From 96df9b11ad8974d7a2a0a589114cbbb04a584f18 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Dec 2007 13:42:32 +1000 Subject: [PATCH] finish of mode add/remove, just have attach/detach modes --- libdrm/xf86drmMode.c | 24 +---- libdrm/xf86drmMode.h | 15 +--- linux-core/drm_crtc.c | 204 +++++++++--------------------------------- linux-core/drm_crtc.h | 7 +- linux-core/drm_drv.c | 3 +- linux-core/intel_fb.c | 2 - shared-core/drm.h | 4 +- tests/mode/modetest.c | 19 +--- 8 files changed, 51 insertions(+), 227 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 8b701381..cf596730 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -372,38 +372,22 @@ err_allocs: return r; } -#if 0 -uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *mode_info) +int drmModeAttachMode(int fd, uint32_t output_id, struct drm_mode_modeinfo *mode_info) { - if (ioctl(fd, DRM_IOCTL_MODE_ADDMODE, mode_info)) - return 0; - - return mode_info->id; -} - -int drmModeRmMode(int fd, uint32_t mode_id) -{ - return ioctl(fd, DRM_IOCTL_MODE_RMMODE, &mode_id); -} -#endif - -int drmModeAttachMode(int fd, uint32_t output_id, uint32_t mode_id) -{ - struct drm_mode_mode_cmd res; + memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); res.output_id = output_id; - res.mode_id = mode_id; return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); } -int drmModeDetachMode(int fd, uint32_t output_id, uint32_t mode_id) +int drmModeDetachMode(int fd, uint32_t output_id, struct drm_mode_modeinfo *mode_info) { struct drm_mode_mode_cmd res; + memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); res.output_id = output_id; - res.mode_id = mode_id; return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res); } diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 0777c596..a1d717f9 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -198,27 +198,16 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, extern drmModeOutputPtr drmModeGetOutput(int fd, uint32_t outputId); -/** - * Adds a new mode from the given mode info. - * Name must be unique. - */ -extern uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *modeInfo); - -/** - * Removes a mode created with AddMode, must be unused. - */ -extern int drmModeRmMode(int fd, uint32_t modeId); - /** * Attaches the given mode to an output. */ -extern int drmModeAttachMode(int fd, uint32_t outputId, uint32_t modeId); +extern int drmModeAttachMode(int fd, uint32_t outputId, struct drm_mode_modeinfo *mode_info); /** * Detaches a mode from the output * must be unused, by the given mode. */ -extern int drmModeDetachMode(int fd, uint32_t outputId, uint32_t modeId); +extern int drmModeDetachMode(int fd, uint32_t outputId, struct drm_mode_modeinfo *mode_info); extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId); extern void drmModeFreeProperty(drmModePropertyPtr ptr); diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 44268337..26aa5206 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -579,6 +579,7 @@ struct drm_output *drm_output_create(struct drm_device *dev, strncpy(output->name, name, DRM_OUTPUT_LEN); output->name[DRM_OUTPUT_LEN - 1] = 0; output->subpixel_order = SubPixelUnknown; + INIT_LIST_HEAD(&output->user_modes); INIT_LIST_HEAD(&output->probed_modes); INIT_LIST_HEAD(&output->modes); /* randr_output? */ @@ -620,6 +621,9 @@ void drm_output_destroy(struct drm_output *output) list_for_each_entry_safe(mode, t, &output->modes, head) drm_mode_remove(output, mode); + list_for_each_entry_safe(mode, t, &output->user_modes, head) + drm_mode_remove(output, mode); + mutex_lock(&dev->mode_config.mutex); drm_idr_put(dev, output->id); list_del(&output->head); @@ -718,7 +722,6 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.crtc_list); INIT_LIST_HEAD(&dev->mode_config.output_list); INIT_LIST_HEAD(&dev->mode_config.property_list); - INIT_LIST_HEAD(&dev->mode_config.usermode_list); idr_init(&dev->mode_config.crtc_idr); } EXPORT_SYMBOL(drm_mode_config_init); @@ -950,7 +953,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; struct drm_framebuffer *fb, *fbt; - struct drm_display_mode *mode, *mt; struct drm_property *property, *pt; list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { @@ -961,10 +963,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) drm_property_destroy(dev, property); } - list_for_each_entry_safe(mode, mt, &dev->mode_config.usermode_list, head) { - drm_mode_destroy(dev, mode); - } - list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { if (fb->bo->type != drm_bo_type_kernel) drm_framebuffer_destroy(fb); @@ -1324,10 +1322,6 @@ int drm_mode_getoutput(struct drm_device *dev, list_for_each_entry(mode, &output->modes, head) mode_count++; - for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) - if (output->user_mode_ids[i] != 0) - mode_count++; - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { if (output->property_ids[i] != 0) { props_count++; @@ -1365,20 +1359,6 @@ int drm_mode_getoutput(struct drm_device *dev, copied++; } - for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { - if (!output->user_mode_ids[i]) - continue; - mode = idr_find(&dev->mode_config.crtc_idr, output->user_mode_ids[i]); - if (mode && (mode->mode_id == output->user_mode_ids[i])) { - drm_crtc_convert_to_umode(&u_mode, mode); - if (copy_to_user(out_resp->modes + copied, - &u_mode, sizeof(u_mode))) { - ret = -EFAULT; - goto out; - } - copied++; - } - } } out_resp->count_modes = mode_count; @@ -1710,49 +1690,14 @@ void drm_fb_release(struct file *filp) /* * */ -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); static int drm_mode_attachmode(struct drm_device *dev, struct drm_output *output, struct drm_display_mode *mode) { int ret = 0; - int i; - - for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { - if (output->user_mode_ids[i] == 0) { - output->user_mode_ids[i] = mode->mode_id; - mode->output_count++; - break; - } - } - - if (i == DRM_OUTPUT_MAX_UMODES) - ret = -ENOSPC; + list_add_tail(&mode->head, &output->user_modes); return ret; } @@ -1760,11 +1705,22 @@ int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_output *output; - + int ret = 0; + struct drm_display_mode *dup_mode; + int need_dup = 0; list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (output->crtc == crtc) - drm_mode_attachmode(dev, output, mode); + if (output->crtc == crtc) { + if (need_dup) + dup_mode = drm_mode_duplicate(dev, mode); + else + dup_mode = mode; + ret = drm_mode_attachmode(dev, output, dup_mode); + if (ret) + return ret; + need_dup = 1; + } } + return 0; } EXPORT_SYMBOL(drm_mode_attachmode_crtc); @@ -1773,13 +1729,15 @@ static int drm_mode_detachmode(struct drm_device *dev, struct drm_display_mode *mode) { int found = 0; - int ret = 0, i; + int ret = 0; + struct drm_display_mode *match_mode, *t; - for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { - if (output->user_mode_ids[i] == mode->mode_id) { - output->user_mode_ids[i] = 0; - mode->output_count--; + list_for_each_entry_safe(match_mode, t, &output->user_modes, head) { + if (drm_mode_equal(match_mode, mode)) { + list_del(&match_mode->head); + drm_mode_destroy(dev, match_mode); found = 1; + break; } } @@ -1800,86 +1758,6 @@ int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mo } EXPORT_SYMBOL(drm_mode_detachmode_crtc); -/** - * drm_fb_addmode - adds a user defined mode - * @inode: inode from the ioctl - * @filp: file * from the ioctl - * @cmd: cmd from ioctl - * @arg: arg from ioctl - * - * Adds a user specified mode to the kernel. - * - * Called by the user via ioctl. - * - * RETURNS: - * writes new mode id into arg. - * Zero on success, errno on failure. - */ -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; - int ret = 0; - - mutex_lock(&dev->mode_config.mutex); - user_mode = drm_mode_create(dev); - if (!user_mode) { - ret = -ENOMEM; - goto out; - } - - drm_crtc_convert_umode(user_mode, new_mode); - - drm_mode_addmode(dev, user_mode); - -out: - mutex_unlock(&dev->mode_config.mutex); - return ret; -} - -/** - * drm_fb_rmmode - removes a user defined mode - * @inode: inode from the ioctl - * @filp: file * from the ioctl - * @cmd: cmd from ioctl - * @arg: arg from ioctl - * - * Remove the user defined mode specified by the user. - * - * Called by the user via ioctl - * - * RETURNS: - * Zero on success, errno on failure. - */ -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; - int ret = -EINVAL; - - mutex_lock(&dev->mode_config.mutex); - mode = idr_find(&dev->mode_config.crtc_idr, *id); - if (!mode || (*id != mode->mode_id)) { - goto out; - } - - if (!(mode->type & DRM_MODE_TYPE_USERDEF)) { - goto out; - } - - if (mode->output_count) { - goto out; - } - - ret = drm_mode_rmmode(dev, mode); - -out: - mutex_unlock(&dev->mode_config.mutex); - return ret; -} - /** * drm_fb_attachmode - Attach a user mode to an output * @inode: inode from the ioctl @@ -1899,22 +1777,25 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, struct drm_mode_mode_cmd *mode_cmd = data; struct drm_output *output; struct drm_display_mode *mode; + struct drm_mode_modeinfo *umode = &mode_cmd->mode; int ret = 0; mutex_lock(&dev->mode_config.mutex); - mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd->mode_id); - if (!mode || (mode->mode_id != mode_cmd->mode_id)) { - ret = -EINVAL; - goto out; - } - output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); if (!output || (output->id != mode_cmd->output_id)) { ret = -EINVAL; goto out; } + mode = drm_mode_create(dev); + if (!mode) { + ret = -ENOMEM; + goto out; + } + + drm_crtc_convert_umode(mode, umode); + ret = drm_mode_attachmode(dev, output, mode); out: mutex_unlock(&dev->mode_config.mutex); @@ -1939,25 +1820,20 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, { struct drm_mode_mode_cmd *mode_cmd = data; struct drm_output *output; - struct drm_display_mode *mode; + struct drm_display_mode mode; + struct drm_mode_modeinfo *umode = &mode_cmd->mode; int ret = 0; mutex_lock(&dev->mode_config.mutex); - mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd->mode_id); - if (!mode || (mode->mode_id != mode_cmd->mode_id)) { - ret = -EINVAL; - goto out; - } - output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); if (!output || (output->id != mode_cmd->output_id)) { ret = -EINVAL; goto out; } - - - ret = drm_mode_detachmode(dev, output, mode); + + drm_crtc_convert_umode(&mode, umode); + ret = drm_mode_detachmode(dev, output, &mode); out: mutex_unlock(&dev->mode_config.mutex); return ret; diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 011903ce..90d6104f 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -448,7 +448,7 @@ struct drm_output { const struct drm_output_funcs *funcs; void *driver_private; - u32 user_mode_ids[DRM_OUTPUT_MAX_UMODES]; + struct list_head user_modes; u32 property_ids[DRM_OUTPUT_MAX_PROPERTY]; u32 property_values[DRM_OUTPUT_MAX_PROPERTY]; @@ -484,8 +484,6 @@ struct drm_mode_config { int num_crtc; struct list_head crtc_list; - struct list_head usermode_list; - struct list_head property_list; int min_width, min_height; @@ -518,9 +516,6 @@ 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); - /* for us by fb module */ extern int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index b3e00e84..6a3e7041 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -124,8 +124,7 @@ 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_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_ioctl, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_ROOT_ONLY), diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 5f43f291..a8c9188d 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -281,10 +281,8 @@ static int intelfb_set_par(struct fb_info *info) } if (!found) { - drm_mode_addmode(dev, drm_mode); if (par->fb_mode) { drm_mode_detachmode_crtc(dev, par->fb_mode); - drm_mode_rmmode(dev, par->fb_mode); } par->fb_mode = drm_mode; diff --git a/shared-core/drm.h b/shared-core/drm.h index 5c24e0af..f4f75cf5 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1008,7 +1008,7 @@ struct drm_mode_fb_cmd { struct drm_mode_mode_cmd { unsigned int output_id; - unsigned int mode_id; + struct drm_mode_modeinfo mode; }; /** @@ -1111,8 +1111,6 @@ struct drm_mode_mode_cmd { #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int) #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd) -#define DRM_IOCTL_MODE_ADDMODE DRM_IOWR(0xA7, struct drm_mode_modeinfo) -#define DRM_IOCTL_MODE_RMMODE DRM_IOWR(0xA8, unsigned int) #define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) #define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd) diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c index 2871fde4..1d5002b0 100644 --- a/tests/mode/modetest.c +++ b/tests/mode/modetest.c @@ -201,45 +201,30 @@ int testMode(int fd, drmModeResPtr res) int ret = 0; int error = 0; -#if 0 printf("Test: adding mode to output %i\n", output); /* printMode(&mode); */ - printf("\tAdding mode\n"); - newMode = drmModeAddMode(fd, &mode); - if (!newMode) - goto err; - printf("\tAttaching mode %i to output %i\n", newMode, output); - ret = drmModeAttachMode(fd, output, newMode); + ret = drmModeAttachMode(fd, output, &mode); if (ret) goto err_mode; printf("\tDetaching mode %i from output %i\n", newMode, output); - ret = drmModeDetachMode(fd, output, newMode); + ret = drmModeDetachMode(fd, output, &mode); if (ret) goto err_mode; - - printf("\tRemoveing new mode %i\n", newMode); - ret = drmModeRmMode(fd, newMode); - if (ret) - goto err; - return 0; err_mode: - error = drmModeRmMode(fd, newMode); -err: printf("\tFailed\n"); if (error) printf("\tFailed to delete mode %i\n", newMode); -#endif return 1; }