summaryrefslogtreecommitdiff
path: root/linux-core/drm_crtc.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2007-12-03 13:42:32 +1000
committerDave Airlie <airlied@redhat.com>2007-12-03 15:30:05 +1000
commit96df9b11ad8974d7a2a0a589114cbbb04a584f18 (patch)
tree1d1abe533919afcdc3530a214eb43fcf78e51dbf /linux-core/drm_crtc.c
parent91cd3e3c097d581ea75ec4bcbc1ba8d23b471a2e (diff)
finish of mode add/remove, just have attach/detach modes
Diffstat (limited to 'linux-core/drm_crtc.c')
-rw-r--r--linux-core/drm_crtc.c202
1 files changed, 39 insertions, 163 deletions
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;
}
}
@@ -1801,86 +1759,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
* @filp: file * from the ioctl
@@ -1899,21 +1777,24 @@ 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)) {
+ output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
+ if (!output || (output->id != mode_cmd->output_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;
+ 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:
@@ -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;