fixup numerous issues with adding framebuffer support
authorDavid Airlie <airlied@asimov.stargames.com.au>
Tue, 10 Apr 2007 04:49:49 +0000 (14:49 +1000)
committerDavid Airlie <airlied@asimov.stargames.com.au>
Tue, 10 Apr 2007 04:49:49 +0000 (14:49 +1000)
This still isn't perfect but it fixes a few oopses and cleans up
some of the tabs and bugs in the original fb limit code

libdrm/xf86drmMode.c
libdrm/xf86drmMode.h
linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_modes.c
shared-core/i915_dma.c

index 5f48089..df8ea8e 100644 (file)
@@ -311,11 +311,9 @@ err_allocs:
 }
 
 
-int drmModeSetCrtc(
-               int fd, uint32_t crtcId, uint32_t bufferId,
-               uint32_t x, uint32_t y, uint32_t modeId,
-               uint32_t *outputs, int count
-       )
+int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+                   uint32_t x, uint32_t y, uint32_t modeId,
+                   uint32_t *outputs, int count)
 {
        struct drm_mode_crtc crtc;
 
index 45b157a..fadfdc5 100644 (file)
@@ -214,14 +214,12 @@ extern drmModeFrameBufferPtr drmModeGetFramebuffer(int fd,
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
  */
-extern uint32_t drmModeNewFrameBuffer(int fd,
-               uint32_t width, uint32_t height,
-               uint8_t bbp, uint32_t pitch, drmBO *bo);
-
+extern int drmModeAddFB(int fd, uint32_t width, uint32_t height,
+                        uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id);
 /**
  * Destroies the given framebuffer.
  */
-extern int drmModeDesFrameBuffer(int fd, uint32_t bufferId);
+extern int drmModeRmFB(int fd, uint32_t bufferId);
 
 /**
  * Changes the scanout buffer to the given buffer object.
index ce2073d..46b7f7a 100644 (file)
@@ -371,7 +371,7 @@ struct drm_output *drm_output_create(drm_device_t *dev,
 {
        struct drm_output *output = NULL;
 
-       output = kmalloc(sizeof(struct drm_output), GFP_KERNEL);
+       output = kzalloc(sizeof(struct drm_output), GFP_KERNEL);
        if (!output)
                return NULL;
                
@@ -471,13 +471,13 @@ static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **b
        drm_hash_item_t *hash;
        int ret;
 
-        *bo = NULL;
+       *bo = NULL;
 
        mutex_lock(&dev->struct_mutex);
        ret = drm_ht_find_item(&dev->object_hash, handle, &hash);
        if (ret) {
                DRM_ERROR("Couldn't find handle.\n");
-                ret = -EINVAL;
+               ret = -EINVAL;
                goto out_err;
        }
 
@@ -486,7 +486,7 @@ static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **b
                ret = -EINVAL;
                goto out_err;
        }
-        
+       
        *bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
        ret = 0;
 out_err:
@@ -517,7 +517,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
        /* bind both CRTCs to this fb */
        /* only initialise one crtc to enabled state */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               crtc->fb = fb;
+               //              crtc->fb = fb;
                if (!vga_crtc) {
                        vga_crtc = crtc;
                        crtc->enabled = 1;
@@ -699,15 +699,14 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
        int output_count = 0;
        int crtc_count = 0;
        int copied = 0;
-
+       
        memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
        list_for_each(lh, &dev->mode_config.crtc_list)
                crtc_count++;
 
        list_for_each_entry(output, &dev->mode_config.output_list,
-                           head)
-       {
+                           head) {
                output_count++;
                list_for_each(lh, &output->modes)
                        mode_count++;
@@ -716,6 +715,16 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
        if (copy_from_user(&card_res, argp, sizeof(card_res)))
                return -EFAULT;
 
+       if (card_res.count_modes == 0) {
+               DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height);
+               drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
+               mode_count = 0;
+               list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                       list_for_each(lh, &output->modes)
+                               mode_count++;
+               }
+       }
+
        /* handle this in 3 parts */
        /* CRTCs */
        if (card_res.count_crtcs >= crtc_count) {
@@ -829,13 +838,16 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
        if (copy_from_user(&out_resp, argp, sizeof(out_resp)))
                return -EFAULT; 
 
+       DRM_DEBUG("output id %d\n", out_resp.output);
        output= idr_find(&dev->mode_config.crtc_idr, out_resp.output);
        if (!output || (output->id != out_resp.output))
                return -EINVAL;
 
+       DRM_DEBUG("about to count modes\n");
        list_for_each_entry(mode, &output->modes, head)
                mode_count++;
 
+       DRM_DEBUG("about to count modes %d %d %p\n", mode_count, out_resp.count_modes, output->crtc);
        out_resp.mm_width = output->mm_width;
        out_resp.mm_height = output->mm_height;
        out_resp.subpixel = output->subpixel_order;
@@ -845,7 +857,7 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
        else
                out_resp.crtc = 0;
 
-       if (out_resp.count_modes >= mode_count) {
+       if ((out_resp.count_modes >= mode_count) && mode_count) {
                copied = 0;
                list_for_each_entry(mode, &output->modes, head) {
                        if (put_user(mode->mode_id, &out_resp.modes[copied++])) {
@@ -882,20 +894,40 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
 
        crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id);
        if (!crtc || (crtc->id != crtc_req.crtc_id))
+       {
+               DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req.crtc_id);
                return -EINVAL;
+       }
 
        if (crtc_req.mode) {
                mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode);
                if (!mode || (mode->mode_id != crtc_req.mode))
+               {
+                       {
+                               struct drm_output *output;
+
+                               list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                                       list_for_each_entry(mode, &output->modes, head) {
+                                               drm_mode_debug_printmodeline(dev, mode);
+                                       }
+                               }
+                       }
+
+                       DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req.mode, mode);
                        return -EINVAL;
+               }
        } else
                mode = NULL;
 
-       if (crtc_req.count_outputs == 0 && mode)
+       if (crtc_req.count_outputs == 0 && mode) {
+               DRM_DEBUG("Count outputs is 0 but mode set\n");
                return -EINVAL;
+       }
 
-       if (crtc_req.count_outputs > 0 && !mode)
+       if (crtc_req.count_outputs > 0 && !mode) {
+               DRM_DEBUG("Count outputs is %d but no mode set\n", crtc_req.count_outputs);
                return -EINVAL;
+       }
 
        if (crtc_req.count_outputs > 0) {
                u32 out_id;
@@ -903,14 +935,15 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
                if (!output_set)
                        return -ENOMEM;
 
-               for (i = 0; i < crtc_req.count_outputs; i++)
-               {
+               for (i = 0; i < crtc_req.count_outputs; i++) {
                        if (get_user(out_id, &crtc_req.set_outputs[i]))
                                return -EFAULT;
 
                        output = idr_find(&dev->mode_config.crtc_idr, out_id);
-                       if (!output || (out_id != output->id))
+                       if (!output || (out_id != output->id)) {
+                               DRM_DEBUG("Output id %d unknown\n", out_id);
                                return -EINVAL;
+                       }
 
                        output_set[i] = output;
                }
@@ -922,16 +955,16 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
 
 /* Add framebuffer ioctl */
 int drm_mode_addfb(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+                  unsigned int cmd, unsigned long arg)
 {
        struct drm_file *priv = filp->private_data;
        struct drm_device *dev = priv->head->dev;
        struct drm_mode_fb_cmd __user *argp = (void __user *)arg;
        struct drm_mode_fb_cmd r;
-        struct drm_mode_config *config = &dev->mode_config;
+       struct drm_mode_config *config = &dev->mode_config;
        struct drm_framebuffer *fb;
        struct drm_buffer_object *bo;
-        int ret;
+       int ret;
 
        if (copy_from_user(&r, argp, sizeof(r)))
                return -EFAULT;
@@ -939,16 +972,16 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
        if ((config->min_width > r.width) || (r.width > config->max_width)) {
                DRM_ERROR("mode new framebuffer width not within limits\n");
                return -EINVAL;
-        }
+       }
        if ((config->min_height > r.height) || (r.height > config->max_height)) {
                DRM_ERROR("mode new framebuffer height not within limits\n");
                return -EINVAL;
        }
 
        /* TODO check limits are okay */
-        ret = drm_get_buffer_object(dev, &bo, r.handle);
-        if (ret || !bo)
-                return -EINVAL;
+       ret = drm_get_buffer_object(dev, &bo, r.handle);
+       if (ret || !bo)
+               return -EINVAL;
 
        /* TODO check buffer is sufficently large */
        /* TODO setup destructor callback */
@@ -957,22 +990,30 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
        if(!fb)
                return -EINVAL;;
 
-       fb->width          = r.width;
-       fb->height         = r.height;
-       fb->pitch          = r.pitch;
+       fb->width         = r.width;
+       fb->height       = r.height;
+       fb->pitch         = r.pitch;
        fb->bits_per_pixel = r.bpp;
-       fb->offset         = bo->offset;
-       fb->bo             = bo;
+       fb->offset       = bo->offset;
+       fb->bo       = bo;
 
-        r.buffer_id = fb->id;
-        if (copy_to_user(argp, &r, sizeof(r)))
-                return -EFAULT;
+       r.buffer_id = fb->id;
+
+       /* bind the fb to the crtc for now */
+       {
+               struct drm_crtc *crtc;
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       crtc->fb = fb;
+               }
+       }
+       if (copy_to_user(argp, &r, sizeof(r)))
+               return -EFAULT;
 
        return 0;
 }
 
 int drm_mode_rmfb(struct inode *inode, struct file *filp,
-                  unsigned int cmd, unsigned long arg)
+                 unsigned int cmd, unsigned long arg)
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->head->dev;
index 19d7cf5..142e0ec 100644 (file)
@@ -178,7 +178,7 @@ struct drm_framebuffer {
        unsigned int depth;
        int bits_per_pixel;
        int flags;
-        struct drm_buffer_object *bo;
+       struct drm_buffer_object *bo;
 };
 struct drm_crtc;
 struct drm_output;
@@ -456,8 +456,8 @@ extern int drm_mode_getoutput(struct inode *inode, struct file *filp,
 extern int drm_mode_setcrtc(struct inode *inode, struct file *filp,
                            unsigned int cmd, unsigned long arg);
 extern int drm_mode_addfb(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
+                         unsigned int cmd, unsigned long arg);
 extern int drm_mode_rmfb(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
+                        unsigned int cmd, unsigned long arg);
 #endif /* __DRM_CRTC_H__ */
 
index bedef16..0f2a612 100644 (file)
@@ -36,8 +36,8 @@
 void drm_mode_debug_printmodeline(struct drm_device *dev,
                                  struct drm_display_mode *mode)
 {
-       DRM_DEBUG("Modeline \"%s\" %d %d %d %d %d %d %d %d %d %d\n",
-                 mode->name, mode->vrefresh / 1000, mode->clock,
+       DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d\n",
+                 mode->mode_id, mode->name, mode->vrefresh / 1000, mode->clock,
                  mode->hdisplay, mode->hsync_start,
                  mode->hsync_end, mode->htotal,
                  mode->vdisplay, mode->vsync_start,
index 811e4bb..2c14cb5 100644 (file)
@@ -171,7 +171,7 @@ static int i915_initialize(drm_device_t * dev,
        I915_WRITE(0x02080, dev_priv->dma_status_page);
        DRM_DEBUG("Enabled hardware status page\n");
 
-       drm_set_desired_modes(dev);
+//drm_set_desired_modes(dev);
 
        return 0;
 }