From 4a2e29bf9982165deeeabb5c585fc0a8a659f380 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 Jun 2008 15:59:01 -0700 Subject: Use GEM in modesetting Use GEM for ring buffer setup and framebuffer allocation. This means reworking the hardware status page stuff a bit (just use the basic range allocator for vram for now) and #ifdef'ing out the TTM & DRI2 code. Works well enough to load/unload several times and display fbcon on my T61 (though there's still some unexplained console corruption). --- linux-core/i915_drv.c | 10 +++--- linux-core/i915_gem.c | 52 ++++++++++++++++-------------- linux-core/intel_display.c | 34 ++++++++++++-------- linux-core/intel_drv.h | 3 +- linux-core/intel_fb.c | 79 +++++++++++++++++++++++++++------------------- 5 files changed, 102 insertions(+), 76 deletions(-) (limited to 'linux-core') diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 8718bd10..574282b2 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -48,11 +48,11 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); unsigned int i915_rightof = 1; module_param_named(i915_rightof, i915_rightof, int, 0400); -#ifdef I915_HAVE_FENCE +#if defined(I915_HAVE_FENCE) && defined(I915_TTM) extern struct drm_fence_driver i915_fence_driver; #endif -#ifdef I915_HAVE_BUFFER +#if defined(I915_HAVE_BUFFER) && defined(I915_TTM) static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL}; static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL}; @@ -71,7 +71,7 @@ static struct drm_bo_driver i915_bo_driver = { .ttm_cache_flush = i915_flush_ttm, .command_stream_barrier = NULL, }; -#endif +#endif /* ttm */ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) { @@ -619,10 +619,10 @@ static struct drm_driver driver = { .probe = probe, .remove = __devexit_p(drm_cleanup_pci), }, -#ifdef I915_HAVE_FENCE +#if defined(I915_HAVE_FENCE) && defined(I915_TTM) .fence_driver = &i915_fence_driver, #endif -#ifdef I915_HAVE_BUFFER +#if defined(I915_HAVE_BUFFER) && defined(I915_TTM) .bo_driver = &i915_bo_driver, #endif .name = DRIVER_NAME, diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 961831c6..47745010 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -41,28 +41,35 @@ i915_gem_object_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain); -int -i915_gem_init_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_gem_do_init(struct drm_device *dev, unsigned long start, + unsigned long end) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_init *args = data; - - mutex_lock(&dev->struct_mutex); - if (args->gtt_start >= args->gtt_end || - (args->gtt_start & (PAGE_SIZE - 1)) != 0 || - (args->gtt_end & (PAGE_SIZE - 1)) != 0) { - mutex_unlock(&dev->struct_mutex); + if (start >= end || + (start & (PAGE_SIZE - 1)) != 0 || + (end & (PAGE_SIZE - 1)) != 0) { return -EINVAL; } - drm_memrange_init(&dev_priv->mm.gtt_space, args->gtt_start, - args->gtt_end - args->gtt_start); + drm_memrange_init(&dev_priv->mm.gtt_space, start, + end - start); + + return 0; +} + +int +i915_gem_init_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_init *args = data; + int ret; + mutex_lock(&dev->struct_mutex); + ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end); mutex_unlock(&dev->struct_mutex); - return 0; + return ret; } static void @@ -1834,17 +1841,16 @@ i915_gem_init_ringbuffer(struct drm_device *dev) dev_priv->ring.virtual_start = dev_priv->ring.map.handle; /* Stop the ring if it's running. */ - I915_WRITE(LP_RING + RING_LEN, 0); - I915_WRITE(LP_RING + RING_HEAD, 0); - I915_WRITE(LP_RING + RING_TAIL, 0); - I915_WRITE(LP_RING + RING_START, 0); + I915_WRITE(PRB0_CTL, 0); + I915_WRITE(PRB0_HEAD, 0); + I915_WRITE(PRB0_TAIL, 0); + I915_WRITE(PRB0_START, 0); /* Initialize the ring. */ - I915_WRITE(LP_RING + RING_START, obj_priv->gtt_offset); - I915_WRITE(LP_RING + RING_LEN, - ((obj->size - 4096) & RING_NR_PAGES) | - RING_NO_REPORT | - RING_VALID); + I915_WRITE(PRB0_START, obj_priv->gtt_offset); + I915_WRITE(PRB0_CTL, (((obj->size - 4096) & RING_NR_PAGES) | + RING_NO_REPORT | + RING_VALID)); /* Update our cache of the ring state */ i915_kernel_lost_context(dev); @@ -1852,7 +1858,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) return 0; } -static void +void i915_gem_cleanup_ringbuffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 0a2854a2..50ad1a27 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -369,6 +369,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; + struct drm_i915_gem_object *obj_priv; int pipe = intel_crtc->pipe; unsigned long Start, Offset; int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); @@ -385,7 +386,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) intel_fb = to_intel_framebuffer(crtc->fb); - Start = intel_fb->bo->offset; + obj_priv = intel_fb->obj->driver_private; + + Start = obj_priv->gtt_offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); I915_WRITE(dspstride, crtc->fb->pitch); @@ -1493,7 +1496,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { }; struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, - struct drm_file *file_priv, + struct drm_file *filp, struct drm_mode_fb_cmd *mode_cmd) { struct intel_framebuffer *intel_fb; @@ -1505,15 +1508,15 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev, drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); - if (file_priv) { - mutex_lock(&dev->struct_mutex); - intel_fb->bo = drm_lookup_buffer_object(file_priv, intel_fb->base.mm_handle, 0); - mutex_unlock(&dev->struct_mutex); - if (!intel_fb->bo) { + if (filp) { + intel_fb->obj = drm_gem_object_lookup(dev, filp, + mode_cmd->handle); + if (!intel_fb->obj) { kfree(intel_fb); return NULL; } } + drm_gem_object_unreference(intel_fb->obj); return &intel_fb->base; } @@ -1521,22 +1524,25 @@ static int intel_insert_new_fb(struct drm_device *dev, struct drm_file *file_pri struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd) { struct intel_framebuffer *intel_fb; - struct drm_buffer_object *bo; + struct drm_gem_object *obj; struct drm_crtc *crtc; intel_fb = to_intel_framebuffer(fb); mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, mode_cmd->handle, 0); - mutex_unlock(&dev->struct_mutex); + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - if (!bo) + if (!obj) { + mutex_unlock(&dev->struct_mutex); return -EINVAL; + } drm_helper_mode_fill_fb_struct(fb, mode_cmd); - - drm_bo_usage_deref_unlocked(&intel_fb->bo); - intel_fb->bo = bo; + drm_gem_object_unreference(intel_fb->obj); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + intel_fb->obj = obj; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb == fb) { diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index 1008e271..bffbeef0 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -50,8 +50,7 @@ struct intel_i2c_chan { struct intel_framebuffer { struct drm_framebuffer base; - struct drm_buffer_object *bo; - struct drm_bo_kmap_obj kmap; + struct drm_gem_object *obj; }; diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 856ec868..d53b22ff 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -590,9 +590,10 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; struct drm_mode_fb_cmd mode_cmd; - struct drm_buffer_object *fbo = NULL; + struct drm_gem_object *fbo = NULL; + struct drm_i915_gem_object *obj_priv; struct device *device = &dev->pdev->dev; - int ret; + int size, aligned_size, ret; mode_cmd.width = surface_width;/* crtc->desired_mode->hdisplay; */ mode_cmd.height = surface_height;/* crtc->desired_mode->vdisplay; */ @@ -601,26 +602,28 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height mode_cmd.pitch = mode_cmd.width * ((mode_cmd.bpp + 1) / 8); mode_cmd.depth = 24; - ret = drm_buffer_object_create(dev, mode_cmd.pitch * mode_cmd.height, - drm_bo_type_kernel, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_MEM_VRAM | - DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, 0, 0, - &fbo); - if (ret || !fbo) { + size = mode_cmd.pitch * mode_cmd.height; + aligned_size = ALIGN(size, PAGE_SIZE); + fbo = drm_gem_object_alloc(dev, aligned_size); + if (!fbo) { printk(KERN_ERR "failed to allocate framebuffer\n"); - return -EINVAL; + ret = -ENOMEM; + goto out; + } + obj_priv = fbo->driver_private; + + mutex_lock(&dev->struct_mutex); + ret = i915_gem_object_pin(fbo, PAGE_SIZE); + if (ret) { + DRM_ERROR("failed to pin fb: %d\n", ret); + goto out_unref; } - fb = intel_user_framebuffer_create(dev, NULL, &mode_cmd); if (!fb) { - drm_bo_usage_deref_unlocked(&fbo); DRM_ERROR("failed to allocate fb.\n"); - return -EINVAL; + ret = -ENOMEM; + goto out_unref; } list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); @@ -628,11 +631,13 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height intel_fb = to_intel_framebuffer(fb); *intel_fb_p = intel_fb; - intel_fb->bo = fbo; + intel_fb->obj = fbo; info = framebuffer_alloc(sizeof(struct intelfb_par), device); - if (!info) - return -EINVAL; + if (!info) { + ret = -ENOMEM; + goto out_unref; + } par = info->par; @@ -651,19 +656,20 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height info->fbops = &intelfb_ops; info->fix.line_length = fb->pitch; - info->fix.smem_start = intel_fb->bo->offset + dev->mode_config.fb_base; - info->fix.smem_len = info->fix.line_length * fb->height; + info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; + info->fix.smem_len = size; info->flags = FBINFO_DEFAULT; - ret = drm_bo_kmap(intel_fb->bo, 0, intel_fb->bo->num_pages, &intel_fb->kmap); - if (ret) - DRM_ERROR("error mapping fb: %d\n", ret); - - info->screen_base = intel_fb->kmap.virtual; - info->screen_size = info->fix.smem_len; /* FIXME */ + info->screen_base = ioremap(dev->agp->base + obj_priv->gtt_offset, + size); + if (!info->screen_base) { + ret = -ENOSPC; + goto out_unref; + } + info->screen_size = size; - memset(intel_fb->kmap.virtual, 0, info->screen_size); + memset(info->screen_base, 0, size); info->pseudo_palette = fb->pseudo_palette; info->var.xres_virtual = fb->width; @@ -754,10 +760,17 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height par->dev = dev; /* To allow resizeing without swapping buffers */ - printk("allocated %dx%d fb: 0x%08lx, bo %p\n", intel_fb->base.width, - intel_fb->base.height, intel_fb->bo->offset, fbo); + printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, + intel_fb->base.height, obj_priv->gtt_offset, fbo); + mutex_unlock(&dev->struct_mutex); return 0; + +out_unref: + drm_gem_object_unreference(fbo); + mutex_unlock(&dev->struct_mutex); +out: + return ret; } static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc) @@ -1001,8 +1014,10 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) if (info) { unregister_framebuffer(info); - drm_bo_kunmap(&intel_fb->kmap); - drm_bo_usage_deref_unlocked(&intel_fb->bo); + iounmap(info->screen_base); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(intel_fb->obj); + mutex_unlock(&dev->struct_mutex); framebuffer_release(info); } return 0; -- cgit v1.2.3