From 53b4e0cb789151164a0a43b55058319667847aaf Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 26 Nov 2007 14:05:49 +1100 Subject: drm: make fb modes use usermode add/remove interface this stops usermode from getting a mode in the crtc it can't make sense off. --- linux-core/drm_crtc.c | 62 +++++++++++++++++++++++++++++++-------------------- linux-core/drm_crtc.h | 11 +++++---- linux-core/drm_drv.c | 4 ++-- linux-core/intel_fb.c | 15 ++++++------- 4 files changed, 54 insertions(+), 38 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index df934841..87302555 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -439,7 +439,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, if (output->crtc != crtc) continue; - DRM_INFO("%s: set mode %s\n", output->name, mode->name); + DRM_INFO("%s: set mode %s %x\n", output->name, mode->name, mode->mode_id); output->funcs->mode_set(output, mode, adjusted_mode); } @@ -858,7 +858,7 @@ clone: output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; - DRM_DEBUG("Desired mode for CRTC %d is %s\n",c,des_mode->name); + DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name); break; } } @@ -1694,8 +1694,36 @@ void drm_fb_release(struct file *filp) mutex_unlock(&dev->mode_config.mutex); } +/* + * + */ +void drm_mode_addmode(struct drm_device *dev, struct drm_display_mode *user_mode) +{ + user_mode->type |= DRM_MODE_TYPE_USERDEF; + + user_mode->output_count = 0; + list_add(&user_mode->head, &dev->mode_config.usermode_list); +} +EXPORT_SYMBOL(drm_mode_addmode); + +int drm_mode_rmmode(struct drm_device *dev, struct drm_display_mode *mode) +{ + struct drm_display_mode *t; + int ret = -EINVAL; + list_for_each_entry(t, &dev->mode_config.usermode_list, head) { + if (t == mode) { + list_del(&mode->head); + drm_mode_destroy(dev, mode); + ret = 0; + break; + } + } + return ret; +} +EXPORT_SYMBOL(drm_mode_rmmode); + /** - * drm_fb_newmode - adds a user defined mode + * drm_fb_addmode - adds a user defined mode * @inode: inode from the ioctl * @filp: file * from the ioctl * @cmd: cmd from ioctl @@ -1709,8 +1737,8 @@ void drm_fb_release(struct file *filp) * writes new mode id into arg. * Zero on success, errno on failure. */ -int drm_mode_addmode(struct drm_device *dev, - void *data, struct drm_file *file_priv) +int drm_mode_addmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) { struct drm_mode_modeinfo *new_mode = data; struct drm_display_mode *user_mode; @@ -1724,12 +1752,8 @@ int drm_mode_addmode(struct drm_device *dev, } drm_crtc_convert_umode(user_mode, new_mode); - user_mode->type |= DRM_MODE_TYPE_USERDEF; - - user_mode->output_count = 0; - - list_add(&user_mode->head, &dev->mode_config.usermode_list); + drm_mode_addmode(dev, user_mode); new_mode->id = user_mode->mode_id; out: @@ -1751,38 +1775,28 @@ out: * RETURNS: * Zero on success, errno on failure. */ -int drm_mode_rmmode(struct drm_device *dev, - void *data, struct drm_file *file_priv) +int drm_mode_rmmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) { uint32_t *id = data; - struct drm_display_mode *mode, *t; + struct drm_display_mode *mode; int ret = -EINVAL; mutex_lock(&dev->mode_config.mutex); mode = idr_find(&dev->mode_config.crtc_idr, *id); if (!mode || (*id != mode->mode_id)) { - ret = -EINVAL; goto out; } if (!(mode->type & DRM_MODE_TYPE_USERDEF)) { - ret = -EINVAL; goto out; } if (mode->output_count) { - ret = -EINVAL; goto out; } - list_for_each_entry(t, &dev->mode_config.usermode_list, head) { - if (t == mode) { - list_del(&mode->head); - drm_mode_destroy(dev, mode); - ret = 0; - break; - } - } + ret = drm_mode_rmmode(dev, mode); out: mutex_unlock(&dev->mode_config.mutex); diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 0645dd6a..f555b6bb 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -494,6 +494,9 @@ extern void drm_mode_set_name(struct drm_display_mode *mode); extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2); extern void drm_disable_unused_functions(struct drm_device *dev); +extern void drm_mode_addmode(struct drm_device *dev, struct drm_display_mode *user_mode); +extern int drm_mode_rmmode(struct drm_device *dev, struct drm_display_mode *mode); + extern struct drm_display_mode *drm_mode_create(struct drm_device *dev); extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); extern void drm_mode_list_concat(struct list_head *head, @@ -536,10 +539,10 @@ extern int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getfb(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_mode_addmode(struct drm_device *dev, - void *data, struct drm_file *file_priv); -extern int drm_mode_rmmode(struct drm_device *dev, - void *data, struct drm_file *file_priv); +extern int drm_mode_addmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_rmmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern int drm_mode_attachmode(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_detachmode(struct drm_device *dev, diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 8cd7afb1..5156d15d 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -124,8 +124,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDMODE, drm_mode_addmode, DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMMODE, drm_mode_rmmode, DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDMODE, drm_mode_addmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMMODE, drm_mode_rmmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode, DRM_MASTER|DRM_ROOT_ONLY), diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 564a913e..3a4ffc7f 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -47,6 +47,7 @@ struct intelfb_par { struct drm_device *dev; struct drm_crtc *crtc; + struct drm_display_mode *fb_mode; }; static int @@ -107,7 +108,6 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, struct intelfb_par *par = info->par; struct drm_device *dev = par->dev; struct drm_framebuffer *fb = par->crtc->fb; - struct drm_display_mode *drm_mode; struct drm_output *output; int depth, found = 0; @@ -275,6 +275,7 @@ static int intelfb_set_par(struct fb_info *info) return -EINVAL; } #else + drm_mode = drm_mode_create(dev); drm_mode->hdisplay = var->xres; drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin; @@ -290,18 +291,16 @@ static int intelfb_set_par(struct fb_info *info) drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V); #endif + drm_mode_addmode(dev, drm_mode); + if (par->fb_mode) + drm_mode_rmmode(dev, par->fb_mode); + + par->fb_mode = drm_mode; drm_mode_debug_printmodeline(dev, drm_mode); if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0)) return -EINVAL; - /* Have to destroy our created mode if we're not searching the mode - * list for it. - */ -#if 1 - drm_mode_destroy(dev, drm_mode); -#endif - return 0; } -- cgit v1.2.3