drm/modesetting: overhaul the fb create/delete.
authorDave Airlie <airlied@redhat.com>
Wed, 4 Jun 2008 01:59:28 +0000 (11:59 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 4 Jun 2008 01:59:28 +0000 (11:59 +1000)
Move TTM code into the driver

linux-core/drmP.h
linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_crtc_helper.c
linux-core/drm_crtc_helper.h
linux-core/i915_drv.c
linux-core/intel_display.c
linux-core/intel_drv.h
linux-core/intel_fb.c

index 11c0138..6e627cd 100644 (file)
@@ -744,7 +744,6 @@ struct drm_driver {
 
        /* FB routines, if present */
        int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_connector *connector);
-       int (*fb_remove)(struct drm_device *dev, struct drm_framebuffer *fb);
        int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc);
 
        /* Master routines */
index 784c2f7..7f84392 100644 (file)
@@ -208,25 +208,21 @@ struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
  * RETURNS:
  * Pointer to new framebuffer or NULL on error.
  */
-struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev)
+struct drm_framebuffer *drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
+                                            const struct drm_framebuffer_funcs *funcs)
 {
-       struct drm_framebuffer *fb;
-
-       fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL);
-       if (!fb)
-               return NULL;
-       
        drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
        fb->dev = dev;
+       fb->funcs = funcs;
        dev->mode_config.num_fb++;
        list_add(&fb->head, &dev->mode_config.fb_list);
 
        return fb;
 }
-EXPORT_SYMBOL(drm_framebuffer_create);
+EXPORT_SYMBOL(drm_framebuffer_init);
 
 /**
- * drm_framebuffer_destroy - remove a framebuffer object
+ * drm_framebuffer_cleanup - remove a framebuffer object
  * @fb: framebuffer to remove
  *
  * LOCKING:
@@ -235,7 +231,7 @@ EXPORT_SYMBOL(drm_framebuffer_create);
  * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
  * it, setting it to NULL.
  */
-void drm_framebuffer_destroy(struct drm_framebuffer *fb)
+void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 {
        struct drm_device *dev = fb->dev;
        struct drm_crtc *crtc;
@@ -249,10 +245,8 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb)
        drm_mode_object_put(dev, &fb->base);
        list_del(&fb->head);
        dev->mode_config.num_fb--;
-
-       kfree(fb);
 }
-EXPORT_SYMBOL(drm_framebuffer_destroy);
+EXPORT_SYMBOL(drm_framebuffer_cleanup);
 
 /**
  * drm_crtc_init - Initialise a new CRTC object
@@ -705,11 +699,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
        }
 
        list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
-               /* there should only be bo of kernel type left */
-               if (fb->bo->type != drm_bo_type_kernel)
-                       drm_framebuffer_destroy(fb);
-               else
-                       dev->driver->fb_remove(dev, fb);
+               fb->funcs->destroy(fb);
        }
 
        list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
@@ -1393,7 +1383,6 @@ int drm_mode_addfb(struct drm_device *dev,
        struct drm_mode_fb_cmd *r = data;
        struct drm_mode_config *config = &dev->mode_config;
        struct drm_framebuffer *fb;
-       struct drm_buffer_object *bo;
        int ret = 0;
 
        if ((config->min_width > r->width) || (r->width > config->max_width)) {
@@ -1406,33 +1395,18 @@ int drm_mode_addfb(struct drm_device *dev,
        }
 
        mutex_lock(&dev->mode_config.mutex);
-       /* TODO check limits are okay */
-       ret = drm_get_buffer_object(dev, &bo, r->handle);
-       if (ret || !bo) {
-               DRM_ERROR("BO handle not valid\n");
-               ret = -EINVAL;
-               goto out;
-       }
 
        /* TODO check buffer is sufficently large */
        /* TODO setup destructor callback */
 
-       fb = drm_framebuffer_create(dev);
+       fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
        if (!fb) {
                DRM_ERROR("could not create framebuffer\n");
                ret = -EINVAL;
                goto out;
        }
 
-       fb->width = r->width;
-       fb->height = r->height;
-       fb->pitch = r->pitch;
-       fb->bits_per_pixel = r->bpp;
-       fb->depth = r->depth;
-       fb->bo = bo;
-
        r->buffer_id = fb->base.id;
-
        list_add(&fb->filp_head, &file_priv->fbs);
 
 out:
@@ -1490,11 +1464,8 @@ int drm_mode_rmfb(struct drm_device *dev,
        /* TODO release all crtc connected to the framebuffer */
        /* TODO unhock the destructor from the buffer object */
 
-       if (fb->bo->type == drm_bo_type_kernel)
-               DRM_ERROR("the bo type should not be of kernel type\n");
-
        list_del(&fb->filp_head);
-       drm_framebuffer_destroy(fb);
+       fb->funcs->destroy(fb);
 
 out:
        mutex_unlock(&dev->mode_config.mutex);
@@ -1539,7 +1510,7 @@ int drm_mode_getfb(struct drm_device *dev,
        r->width = fb->width;
        r->depth = fb->depth;
        r->bpp = fb->bits_per_pixel;
-       r->handle = fb->bo->base.hash.key;
+       r->handle = fb->mm_handle;
        r->pitch = fb->pitch;
 
 out:
@@ -1570,10 +1541,7 @@ void drm_fb_release(struct file *filp)
        mutex_lock(&dev->mode_config.mutex);
        list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
                list_del(&fb->filp_head);
-               if (fb->bo->type == drm_bo_type_kernel)
-                       DRM_ERROR("the bo type should not be of kernel_type, the kernel will probably explode, why Dave\n");
-
-               drm_framebuffer_destroy(fb);
+               fb->funcs->destroy(fb);
        }
        mutex_unlock(&dev->mode_config.mutex);
 }
@@ -2118,17 +2086,12 @@ int drm_mode_replacefb(struct drm_device *dev,
        struct drm_mode_fb_cmd *r = data;
        struct drm_mode_object *obj;
        struct drm_framebuffer *fb;
-       struct drm_buffer_object *bo;
        int found = 0;
        struct drm_framebuffer *fbl = NULL;
        int ret = 0;
+
        /* right replace the current bo attached to this fb with a new bo */
        mutex_lock(&dev->mode_config.mutex);
-       ret = drm_get_buffer_object(dev, &bo, r->handle);
-       if (ret || !bo) {
-               ret = -EINVAL;
-               goto out;
-       }
        obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
                ret = -EINVAL;
@@ -2146,15 +2109,12 @@ int drm_mode_replacefb(struct drm_device *dev,
                goto out;
        }
 
-       if (fb->bo->type == drm_bo_type_kernel)
-               DRM_ERROR("the bo should not be a kernel bo\n");
-
        fb->width = r->width;
        fb->height = r->height;
        fb->pitch = r->pitch;
        fb->bits_per_pixel = r->bpp;
        fb->depth = r->depth;
-       fb->bo = bo;
+       fb->mm_handle = r->handle;
 
        if (dev->mode_config.funcs->resize_fb)
          dev->mode_config.funcs->resize_fb(dev, fb);
index 01cf9af..5c2d0b3 100644 (file)
@@ -15,6 +15,7 @@
 
 struct drm_device;
 struct drm_mode_set;
+struct drm_framebuffer;
 
 
 #define DRM_MODE_OBJECT_CRTC 0xcccccccc
@@ -250,10 +251,15 @@ struct drm_display_info {
        char *raw_edid; /* if any */
 };
 
+struct drm_framebuffer_funcs {
+       void (*destroy)(struct drm_framebuffer *framebuffer);
+};
+
 struct drm_framebuffer {
        struct drm_device *dev;
        struct list_head head;
        struct drm_mode_object base;
+       const struct drm_framebuffer_funcs *funcs;
        unsigned int pitch;
        unsigned int width;
        unsigned int height;
@@ -261,11 +267,10 @@ struct drm_framebuffer {
        unsigned int depth;
        int bits_per_pixel;
        int flags;
-       struct drm_buffer_object *bo;
        void *fbdev;
        u32 pseudo_palette[17];
-       struct drm_bo_kmap_obj kmap;
        struct list_head filp_head;
+       uint32_t mm_handle;
 };
 
 struct drm_property_blob {
@@ -517,6 +522,7 @@ struct drm_mode_set
  */
 struct drm_mode_config_funcs {
        bool (*resize_fb)(struct drm_device *dev, struct drm_framebuffer *fb);
+       struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd);
 };
 
 struct drm_mode_group {
@@ -645,8 +651,9 @@ extern int drm_connector_property_get_value(struct drm_connector *connector,
 extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
 extern void drm_framebuffer_set_object(struct drm_device *dev,
                                       unsigned long handle);
-extern struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev);
-extern void drm_framebuffer_destroy(struct drm_framebuffer *fb);
+extern struct drm_framebuffer *drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
+                                                   const struct drm_framebuffer_funcs *funcs);
+extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
 extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
 extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
 extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY);
index fcb1243..f35c0a4 100644 (file)
@@ -749,3 +749,17 @@ int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_connector *c
 }
 EXPORT_SYMBOL(drm_helper_hotplug_stage_two);
 
+
+int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+                                  struct drm_mode_fb_cmd *mode_cmd)
+{
+       fb->width = mode_cmd->width;
+       fb->height = mode_cmd->height;
+       fb->pitch = mode_cmd->pitch;
+       fb->bits_per_pixel = mode_cmd->bpp;
+       fb->depth = mode_cmd->depth;
+       fb->mm_handle = mode_cmd->handle;
+       
+       return 0;
+}
+EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
index 3a3a4d4..460fd0d 100644 (file)
@@ -72,6 +72,10 @@ extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
 extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
                                     int x, int y);
 extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
+
+extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+                                         struct drm_mode_fb_cmd *mode_cmd);
+
 static inline void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs)
 {
        crtc->helper_private = (void *)funcs;
index 51262d7..2aac492 100644 (file)
@@ -589,7 +589,6 @@ static struct drm_driver driver = {
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
        .fb_probe = intelfb_probe,
-       .fb_remove = intelfb_remove,
        .fb_resize = intelfb_resize,
        .master_create = i915_master_create,
        .master_destroy = i915_master_destroy,
index 8a8f4ed..529cae1 100644 (file)
@@ -368,6 +368,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_framebuffer *intel_fb;
        int pipe = intel_crtc->pipe;
        unsigned long Start, Offset;
        int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR);
@@ -382,7 +383,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
                return;
        }
 
-       Start = crtc->fb->bo->offset;
+       intel_fb = to_intel_framebuffer(crtc->fb);
+
+       Start = intel_fb->bo->offset;
        Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 
        I915_WRITE(dspstride, crtc->fb->pitch);
@@ -1459,8 +1462,50 @@ static void intel_setup_outputs(struct drm_device *dev)
        }
 }
 
+static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_device *dev = fb->dev;
+       if (fb->fbdev)
+               intelfb_remove(dev, fb);
+
+       drm_framebuffer_cleanup(fb);
+
+       kfree(intel_fb);
+}
+      
+static const struct drm_framebuffer_funcs intel_fb_funcs = {
+       .destroy = intel_user_framebuffer_destroy,
+};
+
+struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev,
+                                                     struct drm_file *file_priv,
+                                                     struct drm_mode_fb_cmd *mode_cmd)
+{
+       struct intel_framebuffer *intel_fb;
+
+       intel_fb = kmalloc(sizeof(*intel_fb), GFP_KERNEL);
+       if (!intel_fb)
+               return NULL;
+
+       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) {
+                       kfree(intel_fb);
+                       return NULL;
+               }
+       }
+       return &intel_fb->base;
+}
+
 static const struct drm_mode_config_funcs intel_mode_funcs = {
        .resize_fb = NULL,
+       .fb_create = intel_user_framebuffer_create,
 };
 
 void intel_modeset_init(struct drm_device *dev)
index 210ed99..46f0fbe 100644 (file)
@@ -46,6 +46,12 @@ struct intel_i2c_chan {
         u8 slave_addr;
 };
 
+struct intel_framebuffer {
+       struct drm_framebuffer base;
+       struct drm_buffer_object *bo;
+       struct drm_bo_kmap_obj kmap;
+};
+
 struct intel_output {
        struct drm_connector base;
 
@@ -69,6 +75,7 @@ struct intel_crtc {
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_output(x) container_of(x, struct intel_output, base)
 #define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
+#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 
 struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
                                        const char *name);
@@ -106,4 +113,8 @@ extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
 extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
 extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                                    u16 blue, int regno);
+
+extern struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev,
+                                                            struct drm_file *file_priv,
+                                                            struct drm_mode_fb_cmd *mode_cmd);
 #endif /* __INTEL_DRV_H__ */
index d490880..1107cbf 100644 (file)
@@ -573,7 +573,10 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_conn
        struct intelfb_par *par;
        struct device *device = &dev->pdev->dev; 
        struct drm_framebuffer *fb;
+       struct intel_framebuffer *intel_fb;
        struct drm_display_mode *mode = crtc->desired_mode;
+       struct drm_mode_fb_cmd mode_cmd;
+
        struct drm_buffer_object *fbo = NULL;
        int ret;
 
@@ -585,22 +588,14 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_conn
        if (!connector)
                return -EINVAL;
 
-       fb = drm_framebuffer_create(dev);
-       if (!fb) {
-               framebuffer_release(info);
-               DRM_ERROR("failed to allocate fb.\n");
-               return -EINVAL;
-       }
-       crtc->fb = fb;
-
-       /* To allow resizeing without swapping buffers */
-       fb->width = 2048;/* crtc->desired_mode->hdisplay; */
-       fb->height = 2048;/* crtc->desired_mode->vdisplay; */
+       mode_cmd.width = 2048;/* crtc->desired_mode->hdisplay; */
+       mode_cmd.height = 2048;/* crtc->desired_mode->vdisplay; */
+       
+       mode_cmd.bpp = 32;
+       mode_cmd.pitch = mode_cmd.width * ((mode_cmd.bpp + 1) / 8);
+       mode_cmd.depth = 24;
 
-       fb->bits_per_pixel = 32;
-       fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
-       fb->depth = 24;
-       ret = drm_buffer_object_create(dev, fb->pitch * fb->height, 
+       ret = drm_buffer_object_create(dev, mode_cmd.pitch * mode_cmd.height, 
                                        drm_bo_type_kernel,
                                        DRM_BO_FLAG_READ |
                                        DRM_BO_FLAG_WRITE |
@@ -611,14 +606,27 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_conn
                                        &fbo);
        if (ret || !fbo) {
                printk(KERN_ERR "failed to allocate framebuffer\n");
-               drm_framebuffer_destroy(fb);
                framebuffer_release(info);
                return -EINVAL;
        }
+       
 
-       fb->bo = fbo;
-       printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
-                       fb->height, fbo->offset, fbo);
+       fb = intel_user_framebuffer_create(dev, NULL, &mode_cmd);
+       if (!fb) {
+               framebuffer_release(info);
+               drm_bo_usage_deref_unlocked(&fbo);
+               DRM_ERROR("failed to allocate fb.\n");
+               return -EINVAL;
+       }
+
+       intel_fb = to_intel_framebuffer(fb);
+
+       intel_fb->bo = fbo;
+       crtc->fb = fb;
+
+       /* 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);
 
 
        fb->fbdev = info;
@@ -653,16 +661,16 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_conn
        }
 
        info->fix.line_length = fb->pitch;
-       info->fix.smem_start = fb->bo->offset + dev->mode_config.fb_base;
+       info->fix.smem_start = intel_fb->bo->offset + dev->mode_config.fb_base;
        info->fix.smem_len = info->fix.line_length * fb->height;
 
        info->flags = FBINFO_DEFAULT;
 
-       ret = drm_bo_kmap(fb->bo, 0, fb->bo->num_pages, &fb->kmap);
+       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 = fb->kmap.virtual;
+       info->screen_base = intel_fb->kmap.virtual;
        info->screen_size = info->fix.smem_len; /* FIXME */
        info->pseudo_palette = fb->pseudo_palette;
        info->var.xres_virtual = fb->width;
@@ -771,6 +779,7 @@ EXPORT_SYMBOL(intelfb_probe);
 int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
 {
        struct fb_info *info;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
        if (!fb)
                return -EINVAL;
@@ -779,9 +788,8 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
        
        if (info) {
                unregister_framebuffer(info);
-               drm_bo_kunmap(&fb->kmap);
-               drm_bo_usage_deref_unlocked(&fb->bo);
-               drm_framebuffer_destroy(fb);
+               drm_bo_kunmap(&intel_fb->kmap);
+               drm_bo_usage_deref_unlocked(&intel_fb->bo);
                framebuffer_release(info);
        }
        return 0;