From 65f465ed5ad3caf773658bb2832785c963b987f6 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 14:49:49 +1000 Subject: [PATCH] fixup numerous issues with adding framebuffer support 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 | 8 ++-- libdrm/xf86drmMode.h | 8 ++-- linux-core/drm_crtc.c | 101 ++++++++++++++++++++++++++++++++++--------------- linux-core/drm_crtc.h | 6 +-- linux-core/drm_modes.c | 4 +- shared-core/i915_dma.c | 2 +- 6 files changed, 83 insertions(+), 46 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 5f480890..df8ea8ee 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -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; diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 45b157a8..fadfdc5d 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -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. diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ce2073d1..46b7f7ae 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -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; diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 19d7cf51..142e0ecb 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -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__ */ diff --git a/linux-core/drm_modes.c b/linux-core/drm_modes.c index bedef163..0f2a612a 100644 --- a/linux-core/drm_modes.c +++ b/linux-core/drm_modes.c @@ -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, diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 811e4bb9..2c14cb5d 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -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; } -- 2.11.0