diff options
Diffstat (limited to 'linux-core/drm_crtc.c')
-rw-r--r-- | linux-core/drm_crtc.c | 293 |
1 files changed, 204 insertions, 89 deletions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 6874265e..1899df2d 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -8,39 +8,39 @@ int drm_mode_idr_get(struct drm_device *dev, void *ptr) int new_id = 0; int ret; again: - if (idr_pre_get(&dev->crtc_config.crtc_idr, GFP_KERNEL) == 0) { + if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { DRM_ERROR("Ran out memory getting a mode number\n"); return 0; } - spin_lock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); - ret = idr_get_new_above(&dev->crtc_config.crtc_idr, ptr, 1, &new_id); + ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id); if (ret == -EAGAIN) { - spin_unlock(&dev->crtc_config.config_lock); + spin_unlock(&dev->mode_config.config_lock); goto again; } - spin_unlock(&dev->crtc_config.config_lock); + spin_unlock(&dev->mode_config.config_lock); return new_id; } void drm_mode_idr_put(struct drm_device *dev, int id) { - idr_remove(&dev->crtc_config.crtc_idr, id); + idr_remove(&dev->mode_config.crtc_idr, id); } struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) { struct drm_framebuffer *fb; - spin_lock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); /* Limit to single framebuffer for now */ - if (dev->crtc_config.num_fb > 1) { + if (dev->mode_config.num_fb > 1) { DRM_ERROR("Attempt to add multiple framebuffers failed\n"); return NULL; } - spin_unlock(&dev->crtc_config.config_lock); + spin_unlock(&dev->mode_config.config_lock); fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL); if (!fb) { @@ -50,10 +50,10 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) fb->id = drm_mode_idr_get(dev, fb); fb->dev = dev; - spin_lock(&dev->crtc_config.config_lock); - dev->crtc_config.num_fb++; - list_add(&fb->head, &dev->crtc_config.fb_list); - spin_unlock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); + dev->mode_config.num_fb++; + list_add(&fb->head, &dev->mode_config.fb_list); + spin_unlock(&dev->mode_config.config_lock); return fb; } @@ -62,11 +62,11 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) { drm_device_t *dev = fb->dev; - spin_lock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); drm_mode_idr_put(dev, fb->id); list_del(&fb->head); - dev->crtc_config.num_fb--; - spin_unlock(&dev->crtc_config.config_lock); + dev->mode_config.num_fb--; + spin_unlock(&dev->mode_config.config_lock); kfree(fb); } @@ -86,10 +86,10 @@ struct drm_crtc *drm_crtc_create(drm_device_t *dev, crtc->id = drm_mode_idr_get(dev, crtc); DRM_DEBUG("crtc %p got id %d\n", crtc, crtc->id); - spin_lock(&dev->crtc_config.config_lock); - list_add_tail(&crtc->head, &dev->crtc_config.crtc_list); - dev->crtc_config.num_crtc++; - spin_unlock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); + list_add_tail(&crtc->head, &dev->mode_config.crtc_list); + dev->mode_config.num_crtc++; + spin_unlock(&dev->mode_config.config_lock); return crtc; } @@ -103,11 +103,11 @@ void drm_crtc_destroy(struct drm_crtc *crtc) (*crtc->funcs->cleanup)(crtc); - spin_lock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); drm_mode_idr_put(dev, crtc->id); list_del(&crtc->head); - dev->crtc_config.num_crtc--; - spin_unlock(&dev->crtc_config.config_lock); + dev->mode_config.num_crtc--; + spin_unlock(&dev->mode_config.config_lock); kfree(crtc); } EXPORT_SYMBOL(drm_crtc_destroy); @@ -117,7 +117,7 @@ bool drm_crtc_in_use(struct drm_crtc *crtc) struct drm_output *output; drm_device_t *dev = crtc->dev; /* FIXME: Locking around list access? */ - list_for_each_entry(output, &dev->crtc_config.output_list, head) + list_for_each_entry(output, &dev->mode_config.output_list, head) if (output->crtc == crtc) return true; return false; @@ -132,7 +132,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) //if (maxX == 0 || maxY == 0) // TODO - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { list_for_each_entry_safe(mode, t, &output->modes, head) drm_mode_remove(output, mode); @@ -215,7 +215,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. */ - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc != crtc) continue; @@ -230,7 +230,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, } /* Prepare the outputs and CRTCs before setting the mode. */ - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc != crtc) continue; @@ -245,14 +245,14 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, * on the DPLL. */ crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc == crtc) output->funcs->mode_set(output, mode, adjusted_mode); } /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ crtc->funcs->commit(crtc); - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc == crtc) { output->funcs->commit(output); @@ -288,11 +288,11 @@ bool drm_set_desired_modes(struct drm_device *dev) struct drm_crtc *crtc; struct drm_output *output, *list_output; - list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { output = NULL; DRM_DEBUG("crtc is %d\n", crtc->id); - list_for_each_entry(list_output, &dev->crtc_config.output_list, head) { + list_for_each_entry(list_output, &dev->mode_config.output_list, head) { if (list_output->crtc == crtc) { output = list_output; break; @@ -321,12 +321,12 @@ void drm_disable_unused_functions(struct drm_device *dev) struct drm_output *output; struct drm_crtc *crtc; - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { if (!output->crtc) (*output->funcs->dpms)(output, DPMSModeOff); } - list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->enabled) crtc->funcs->dpms(crtc, DPMSModeOff); } @@ -372,7 +372,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; @@ -390,11 +390,11 @@ struct drm_output *drm_output_create(drm_device_t *dev, /* output_set_monitor(output)? */ /* check for output_ignored(output)? */ - spin_lock(&dev->crtc_config.config_lock); - list_add_tail(&output->head, &dev->crtc_config.output_list); - dev->crtc_config.num_output++; + spin_lock(&dev->mode_config.config_lock); + list_add_tail(&output->head, &dev->mode_config.output_list); + dev->mode_config.num_output++; - spin_unlock(&dev->crtc_config.config_lock); + spin_unlock(&dev->mode_config.config_lock); return output; @@ -415,10 +415,10 @@ void drm_output_destroy(struct drm_output *output) list_for_each_entry_safe(mode, t, &output->modes, head) drm_mode_remove(output, mode); - spin_lock(&dev->crtc_config.config_lock); + spin_lock(&dev->mode_config.config_lock); drm_mode_idr_put(dev, output->id); list_del(&output->head); - spin_unlock(&dev->crtc_config.config_lock); + spin_unlock(&dev->mode_config.config_lock); kfree(output); } EXPORT_SYMBOL(drm_output_destroy); @@ -456,28 +456,29 @@ void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode kfree(mode); } -void drm_crtc_config_init(drm_device_t *dev) +void drm_mode_config_init(drm_device_t *dev) { - spin_lock_init(&dev->crtc_config.config_lock); - INIT_LIST_HEAD(&dev->crtc_config.fb_list); - INIT_LIST_HEAD(&dev->crtc_config.crtc_list); - INIT_LIST_HEAD(&dev->crtc_config.output_list); - idr_init(&dev->crtc_config.crtc_idr); + spin_lock_init(&dev->mode_config.config_lock); + INIT_LIST_HEAD(&dev->mode_config.fb_list); + INIT_LIST_HEAD(&dev->mode_config.crtc_list); + INIT_LIST_HEAD(&dev->mode_config.output_list); + idr_init(&dev->mode_config.crtc_idr); } -EXPORT_SYMBOL(drm_crtc_config_init); +EXPORT_SYMBOL(drm_mode_config_init); -void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle) +static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **bo, unsigned long handle) { - struct drm_framebuffer *fb; drm_user_object_t *uo; drm_hash_item_t *hash; - drm_buffer_object_t *bo; int ret; + *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; goto out_err; } @@ -486,20 +487,13 @@ void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle) ret = -EINVAL; goto out_err; } - - bo = drm_user_object_entry(uo, drm_buffer_object_t, base); - /* get the first fb */ - list_for_each_entry(fb, &dev->crtc_config.fb_list, head) { - fb->offset = bo->offset; - break; - } + *bo = drm_user_object_entry(uo, drm_buffer_object_t, base); ret = 0; out_err: mutex_unlock(&dev->struct_mutex); - return; + return ret; } -EXPORT_SYMBOL(drm_framebuffer_set_object); bool drm_initial_config(drm_device_t *dev, bool can_grow) { @@ -509,6 +503,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) struct drm_framebuffer *fb; struct drm_output *output, *use_output = NULL; +#if 0 fb = drm_framebuffer_create(dev); if (!fb) return false; @@ -518,11 +513,12 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) fb->height = 768; fb->depth = 24; fb->bits_per_pixel = 32; +#endif /* bind both CRTCs to this fb */ /* only initialise one crtc to enabled state */ - list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { - crtc->fb = fb; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + // crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; crtc->enabled = 1; @@ -547,7 +543,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) /* hard bind the CRTCS */ /* bind analog output to one crtc */ - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { struct drm_display_mode *des_mode; /* Get the first preferred moded */ @@ -583,20 +579,20 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } EXPORT_SYMBOL(drm_initial_config); -void drm_crtc_config_cleanup(drm_device_t *dev) +void drm_mode_config_cleanup(drm_device_t *dev) { struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; - list_for_each_entry_safe(output, ot, &dev->crtc_config.output_list, head) { + list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_output_destroy(output); } - list_for_each_entry_safe(crtc, ct, &dev->crtc_config.crtc_list, head) { + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { drm_crtc_destroy(crtc); } } -EXPORT_SYMBOL(drm_crtc_config_cleanup); +EXPORT_SYMBOL(drm_mode_config_cleanup); int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set) { @@ -607,7 +603,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_output *output; int count = 0, ro; - save_crtcs = kzalloc(dev->crtc_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL); + save_crtcs = kzalloc(dev->mode_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL); if (!save_crtcs) return -ENOMEM; @@ -617,7 +613,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, if (crtc->mode.mode_id != new_mode->mode_id) changed = true; - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { save_crtcs[count++] = output->crtc; if (output->crtc == crtc) @@ -645,7 +641,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, crtc_info->y)) { crtc->enabled = save_enabled; count = 0; - list_for_each_entry(output, &dev->crtc_config.output_list, head) + list_for_each_entry(output, &dev->mode_config.output_list, head) output->crtc = save_crtcs[count++]; kfree(save_crtcs); return -EINVAL; @@ -700,15 +696,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->crtc_config.crtc_list) + list_for_each(lh, &dev->mode_config.crtc_list) crtc_count++; - list_for_each_entry(output, &dev->crtc_config.output_list, - head) - { + list_for_each_entry(output, &dev->mode_config.output_list, + head) { output_count++; list_for_each(lh, &output->modes) mode_count++; @@ -717,11 +712,21 @@ 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) { copied = 0; - list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head){ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){ DRM_DEBUG("CRTC ID is %d\n", crtc->id); if (put_user(crtc->id, &card_res.crtc_id[copied++])) { retcode = -EFAULT; @@ -735,7 +740,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, /* Outputs */ if (card_res.count_outputs >= output_count) { copied = 0; - list_for_each_entry(output, &dev->crtc_config.output_list, + list_for_each_entry(output, &dev->mode_config.output_list, head) { DRM_DEBUG("OUTPUT ID is %d\n", output->id); if (put_user(output->id, &card_res.output_id[copied++])) { @@ -749,7 +754,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, /* Modes */ if (card_res.count_modes >= mode_count) { copied = 0; - list_for_each_entry(output, &dev->crtc_config.output_list, + list_for_each_entry(output, &dev->mode_config.output_list, head) { list_for_each_entry(mode, &output->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); @@ -788,7 +793,7 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp))) return -EFAULT; - crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_resp.crtc_id); + crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id); if (!crtc || (crtc->id != crtc_resp.crtc_id)) return -EINVAL; crtc_resp.x = crtc->x; @@ -800,7 +805,7 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, crtc_resp.mode = crtc->mode.mode_id; ocount = 0; - list_for_each_entry(output, &dev->crtc_config.output_list, head) { + list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc == crtc) crtc_resp.outputs |= 1 << (ocount++); } @@ -830,13 +835,19 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, if (copy_from_user(&out_resp, argp, sizeof(out_resp))) return -EFAULT; - output= idr_find(&dev->crtc_config.crtc_idr, out_resp.output); + 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: %s\n", output->name); 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); + strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN); + out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0; + out_resp.mm_width = output->mm_width; out_resp.mm_height = output->mm_height; out_resp.subpixel = output->subpixel_order; @@ -846,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++])) { @@ -881,22 +892,42 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, if (copy_from_user(&crtc_req, argp, sizeof(crtc_req))) return -EFAULT; - crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_req.crtc_id); + 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->crtc_config.crtc_idr, 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; @@ -904,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->crtc_config.crtc_idr, out_id); - if (!output || (out_id != output->id)) + output = idr_find(&dev->mode_config.crtc_idr, out_id); + if (!output || (out_id != output->id)) { + DRM_DEBUG("Output id %d unknown\n", out_id); return -EINVAL; + } output_set[i] = output; } @@ -920,3 +952,86 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set); return retcode; } + +/* Add framebuffer ioctl */ +int drm_mode_addfb(struct inode *inode, struct file *filp, + 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_framebuffer *fb; + struct drm_buffer_object *bo; + int ret; + + if (copy_from_user(&r, argp, sizeof(r))) + return -EFAULT; + + 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; + + /* TODO check buffer is sufficently large */ + /* TODO setup destructor callback */ + + fb = drm_framebuffer_create(dev); + if(!fb) + return -EINVAL;; + + 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; + + 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) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->head->dev; + struct drm_framebuffer *fb = 0; + uint32_t id = arg; + + fb = idr_find(&dev->mode_config.crtc_idr, id); + /* TODO check that we realy get a framebuffer back. */ + if (!fb || (id != fb->id)) { + DRM_ERROR("mode invalid framebuffer id\n"); + return -EINVAL; + } + + /* TODO check if we own the buffer */ + /* TODO release all crtc connected to the framebuffer */ + /* TODO unhock the destructor from the buffer object */ + + drm_framebuffer_destroy(fb); + + return 0; +} |