From 52f9028c84baea81230dc673b756552e8e90aecd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Apr 2007 11:21:06 +1000 Subject: Initial import of modesetting for intel driver in DRM --- linux-core/drm_crtc.c | 540 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 540 insertions(+) create mode 100644 linux-core/drm_crtc.c (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c new file mode 100644 index 00000000..a52d82bc --- /dev/null +++ b/linux-core/drm_crtc.c @@ -0,0 +1,540 @@ +#include +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" + +struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) +{ + struct drm_framebuffer *fb; + + spin_lock(&dev->crtc_config.config_lock); + /* Limit to single framebuffer for now */ + if (dev->crtc_config.num_fb > 1) { + DRM_ERROR("Attempt to add multiple framebuffers failed\n"); + return NULL; + } + spin_unlock(&dev->crtc_config.config_lock); + + fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL); + if (!fb) { + + return NULL; + } + + 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); + + return fb; +} + +void drm_framebuffer_destroy(struct drm_framebuffer *fb) +{ + drm_device_t *dev = fb->dev; + + spin_lock(&dev->crtc_config.config_lock); + list_del(&fb->head); + dev->crtc_config.num_fb--; + spin_unlock(&dev->crtc_config.config_lock); + + kfree(fb); +} + +struct drm_crtc *drm_crtc_create(drm_device_t *dev, + const struct drm_crtc_funcs *funcs) +{ + struct drm_crtc *crtc = NULL; + crtc = kmalloc(sizeof(struct drm_crtc), GFP_KERNEL); + if (!crtc) + return NULL; + + crtc->dev = dev; + crtc->funcs = funcs; + + 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); + + return crtc; +} +EXPORT_SYMBOL(drm_crtc_create); + +void drm_crtc_destroy(struct drm_crtc *crtc) +{ + drm_device_t *dev = crtc->dev; + + if (crtc->funcs->cleanup) + (*crtc->funcs->cleanup)(crtc); + + spin_lock(&dev->crtc_config.config_lock); + list_del(&crtc->head); + dev->crtc_config.num_crtc--; + spin_unlock(&dev->crtc_config.config_lock); + kfree(crtc); +} +EXPORT_SYMBOL(drm_crtc_destroy); + +bool drm_crtc_in_use(struct drm_crtc *crtc) +{ + struct drm_output *output; + drm_device_t *dev = crtc->dev; + list_for_each_entry(output, &dev->crtc_config.output_list, head) + if (output->crtc == crtc) + return true; + return false; +} +EXPORT_SYMBOL(drm_crtc_in_use); + +void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) +{ + struct drm_output *output; + struct drm_display_mode *mode, *t; + int ret; + //if (maxX == 0 || maxY == 0) + // TODO + + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + + list_for_each_entry_safe(mode, t, &output->modes, head) + drm_mode_remove(output, mode); + + output->status = (*output->funcs->detect)(output); + + if (output->status == output_status_disconnected) { + /* TODO set EDID to NULL */ + continue; + } + + ret = (*output->funcs->get_modes)(output); + + if (ret) { + /* move the modes over to the main mode list */ + drm_mode_list_concat(&output->probed_modes, + &output->modes); + } + + if (maxX && maxY) + drm_mode_validate_size(dev, &output->modes, maxX, + maxY, 0); + list_for_each_entry_safe(mode, t, &output->modes, head) { + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output,mode); + } + + + drm_mode_prune_invalid(dev, &output->modes, TRUE); + + if (list_empty(&output->modes)) + continue; + + drm_mode_sort(&output->modes); + + DRM_DEBUG("Probed modes for %s\n", output->name); + list_for_each_entry_safe(mode, t, &output->modes, head) { + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_debug_printmodeline(dev, mode); + } + } +} + +bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, + int x, int y) +{ + drm_device_t *dev = crtc->dev; + struct drm_display_mode *adjusted_mode, saved_mode; + int saved_x, saved_y; + bool didLock = false; + bool ret = false; + struct drm_output *output; + + adjusted_mode = drm_mode_duplicate(mode); + + crtc->enabled = drm_crtc_in_use(crtc); + + if (!crtc->enabled) { + return true; + } + + didLock = crtc->funcs->lock(crtc); + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + + /* Update crtc values up front so the driver can rely on them for mode + * setting. + */ + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + + /* XXX short-circuit changes to base location only */ + + /* Pass our mode to the outputs and the CRTC to give them a chance to + * 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) { + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + goto done; + } + + /* Prepare the outputs and CRTCs before setting the mode. */ + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->prepare(output); + } + + crtc->funcs->prepare(crtc); + + /* Set up the DPLL and any output state that needs to adjust or depend + * on the DPLL. + */ + crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); + list_for_each_entry(output, &dev->crtc_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) { + if (output->crtc == crtc) + { + output->funcs->commit(output); +#if 0 // TODO def RANDR_12_INTERFACE + if (output->randr_output) + RRPostPendingProperties (output->randr_output); +#endif + } + } + + /* XXX free adjustedmode */ + ret = TRUE; + /* TODO */ +// if (scrn->pScreen) +// drm_crtc_set_screen_sub_pixel_order(dev); + +done: + if (!ret) { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->mode = saved_mode; + } + + if (didLock) + crtc->funcs->unlock (crtc); + + return ret; +} + +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) { + output = NULL; + + list_for_each_entry(list_output, &dev->crtc_config.output_list, head) { + if (list_output->crtc == crtc) { + output = list_output; + break; + } + } + /* Skip disabled crtcs */ + if (!output) + continue; + + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desired_mode.crtc_hdisplay) { + + } + if (!drm_crtc_set_mode(crtc, &crtc->desired_mode, + crtc->desired_x, crtc->desired_y)) + return false; + } + + drm_disable_unused_functions(dev); + return true; +} +EXPORT_SYMBOL(drm_set_desired_modes); + +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) { + if (!output->crtc) + (*output->funcs->dpms)(output, DPMSModeOff); + } + + list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { + if (!crtc->enabled) + crtc->funcs->dpms(crtc, DPMSModeOff); + } +} + +/** + * drm_mode_probed_add - add a mode to the specified output's probed mode list + * @output: output the new mode + * @mode: mode data + * + * Add @mode to @output's mode list for later use. + */ +void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode) +{ + printk(KERN_ERR "adding DDC mode %s to output %s\n", mode->name, + output->name); + spin_lock(&output->modes_lock); + list_add(&mode->head, &output->probed_modes); + spin_unlock(&output->modes_lock); +} +EXPORT_SYMBOL(drm_mode_probed_add); + +/** + * drm_mode_remove - remove and free a mode + * @output: output list to modify + * @mode: mode to remove + * + * Remove @mode from @output's mode list, then free it. + */ +void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) +{ + spin_lock(&output->modes_lock); + list_del(&mode->head); + spin_unlock(&output->modes_lock); + kfree(mode); +} +EXPORT_SYMBOL(drm_mode_remove); + +/* + * Probably belongs in the DRM device structure + */ +struct drm_output *drm_output_create(drm_device_t *dev, + const struct drm_output_funcs *funcs, + const char *name) +{ + struct drm_output *output = NULL; + + output = kmalloc(sizeof(struct drm_output), GFP_KERNEL); + if (!output) + return NULL; + + output->dev = dev; + output->funcs = funcs; + if (name) + strncpy(output->name, name, DRM_OUTPUT_LEN); + output->name[DRM_OUTPUT_LEN - 1] = 0; + output->subpixel_order = SubPixelUnknown; + INIT_LIST_HEAD(&output->probed_modes); + INIT_LIST_HEAD(&output->modes); + spin_lock_init(&output->modes_lock); + /* randr_output? */ + /* 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_unlock(&dev->crtc_config.config_lock); + + return output; + +} +EXPORT_SYMBOL(drm_output_create); + +void drm_output_destroy(struct drm_output *output) +{ + struct drm_device *dev = output->dev; + struct drm_display_mode *mode, *t; + + if (*output->funcs->cleanup) + (*output->funcs->cleanup)(output); + + list_for_each_entry_safe(mode, t, &output->probed_modes, head) + drm_mode_remove(output, mode); + + list_for_each_entry_safe(mode, t, &output->modes, head) + drm_mode_remove(output, mode); + + spin_lock(&dev->crtc_config.config_lock); + list_del(&output->head); + spin_unlock(&dev->crtc_config.config_lock); + kfree(output); +} +EXPORT_SYMBOL(drm_output_destroy); + +bool drm_output_rename(struct drm_output *output, const char *name) +{ + if (!name) + return false; + + strncpy(output->name, name, DRM_OUTPUT_LEN); + output->name[DRM_OUTPUT_LEN - 1] = 0; +// drm_output_set_monitor(output); +// if (drm_output_ignored(output)) +// return FALSE; + return TRUE; +} +EXPORT_SYMBOL(drm_output_rename); + +void drm_crtc_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); +} +EXPORT_SYMBOL(drm_crtc_config_init); + +void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle) +{ + struct drm_framebuffer *fb; + drm_user_object_t *uo; + drm_hash_item_t *hash; + drm_buffer_object_t *bo; + int ret; + + mutex_lock(&dev->struct_mutex); + ret = drm_ht_find_item(&dev->object_hash, handle, &hash); + if (ret) { + DRM_ERROR("Couldn't find handle.\n"); + goto out_err; + } + + uo = drm_hash_entry(hash, drm_user_object_t, hash); + if (uo->type != drm_buffer_type) { + 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; + } + ret = 0; +out_err: + mutex_unlock(&dev->struct_mutex); + return ret; +} +EXPORT_SYMBOL(drm_framebuffer_set_object); + +bool drm_initial_config(drm_device_t *dev, bool can_grow) +{ + /* do a hardcoded initial configuration here */ + struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL; + struct drm_framebuffer *fb; + struct drm_output *output, *use_output = NULL; + + fb = drm_framebuffer_create(dev); + if (!fb) + return false; + + fb->pitch = 1024; + fb->width = 1024; + fb->height = 768; + fb->depth = 24; + fb->bits_per_pixel = 32; + + /* 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; + if (!vga_crtc) { + vga_crtc = crtc; + crtc->enabled = 1; + crtc->desired_x = 0; + crtc->desired_y = 0; + } +#if 0 + else if (!dvi_crtc) { + dvi_crtc = crtc; + crtc->enabled = 1; + crtc->desired_x = 0; + crtc->desired_y = 0; + } +#endif + } + + drm_crtc_probe_output_modes(dev, 1024, 768); + + /* hard bind the CRTCS */ + + /* bind analog output to one crtc */ + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + struct drm_display_mode *des_mode; + + if (strncmp(output->name, "VGA", 3)) { + output->crtc = vga_crtc; + /* just pull the first mode out of that hat */ + list_for_each_entry(des_mode, &output->modes, head) + break; + DRM_DEBUG("Setting desired mode for output %s\n", output->name); + drm_mode_debug_printmodeline(dev, des_mode); + output->crtc->desired_mode = *des_mode; + output->initial_x = 0; + output->initial_y = 0; + use_output = output; + } else if (strncmp(output->name, "TMDS", 4)) { + output->crtc = vga_crtc; +#if 0 + /* just pull the first mode out of that hat */ + list_for_each_entry(des_mode, &output->modes, head) + break; + DRM_DEBUG("Setting desired mode for output %s\n", output->name); + drm_mode_debug_printmodeline(dev, des_mode); + output->crtc->desired_mode = *des_mode; +#endif + output->initial_x = 0; + output->initial_y = 0; + } else + output->crtc = NULL; + + } + + return false; +} +EXPORT_SYMBOL(drm_initial_config); + +void drm_crtc_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) { + drm_output_destroy(output); + } + + + list_for_each_entry_safe(crtc, ct, &dev->crtc_config.crtc_list, head) { + drm_crtc_destroy(crtc); + } +} +EXPORT_SYMBOL(drm_crtc_config_cleanup); + -- cgit v1.2.3 From 5bffbd6e275efffbb649c20c528a11412ccf99cd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Apr 2007 13:34:50 +1000 Subject: initial userspace interface to get modes --- linux-core/drm_crtc.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index a52d82bc..1311fa63 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -154,7 +154,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, bool ret = false; struct drm_output *output; - adjusted_mode = drm_mode_duplicate(mode); + adjusted_mode = drm_mode_duplicate(dev, mode); crtc->enabled = drm_crtc_in_use(crtc); @@ -230,6 +230,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, } /* XXX free adjustedmode */ + drm_crtc_mode_destroy(dev, adjusted_mode); ret = TRUE; /* TODO */ // if (scrn->pScreen) @@ -401,12 +402,48 @@ bool drm_output_rename(struct drm_output *output, const char *name) } EXPORT_SYMBOL(drm_output_rename); +struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev) +{ + int ret; + struct drm_display_mode *nmode; + + nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); + if (!nmode) + return NULL; + +again: + if (idr_pre_get(&dev->crtc_config.mode_idr, GFP_KERNEL) == 0) { + DRM_ERROR("Ran out memory getting a mode number\n"); + kfree(nmode); + return NULL; + } + + spin_lock(&dev->crtc_config.config_lock); + + ret = idr_get_new(&dev->crtc_config.mode_idr, nmode, &nmode->mode_id); + if (ret == -EAGAIN) { + udelay(1); + spin_unlock(&dev->crtc_config.config_lock); + goto again; + } + spin_unlock(&dev->crtc_config.config_lock); + return nmode; +} + +void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) +{ + idr_remove(&dev->crtc_config.mode_idr, mode->mode_id); + + kfree(mode); +} + void drm_crtc_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.mode_idr); } EXPORT_SYMBOL(drm_crtc_config_init); @@ -441,7 +478,7 @@ void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle) ret = 0; out_err: mutex_unlock(&dev->struct_mutex); - return ret; + return; } EXPORT_SYMBOL(drm_framebuffer_set_object); @@ -538,3 +575,86 @@ void drm_crtc_config_cleanup(drm_device_t *dev) } EXPORT_SYMBOL(drm_crtc_config_cleanup); +void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in) +{ + + out->id = in->mode_id; + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; + out->hsync_end = in->hsync_end; + out->htotal = in->htotal; + out->hskew = in->hskew; + out->vdisplay = in->vdisplay; + out->vsync_start = in->vsync_start; + out->vsync_end = in->vsync_end; + out->vtotal = in->vtotal; + out->vscan = in->vscan; + + out->flags = in->flags; +} + + +/* IOCTL code from userspace */ +int drm_mode_getresources(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_mode_card_res __user *argp = (void __user *)arg; + struct drm_mode_card_res card_res; + struct list_head *lh; + struct drm_output *output; + struct drm_mode_modeinfo u_mode; + struct drm_display_mode *mode; + int retcode = 0; + int mode_count= 0; + + memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); + list_for_each_entry(output, &dev->crtc_config.output_list, + head) + { + list_for_each(lh, &output->modes) + mode_count++; + } + + if (copy_from_user(&card_res, argp, sizeof(card_res))) + return -EFAULT; + + if (card_res.count_modes >= mode_count) { + int copied = 0; + list_for_each_entry(output, &dev->crtc_config.output_list, + head) { + list_for_each_entry(mode, &output->modes, head) { + drm_crtc_convert_to_umode(&u_mode, mode); + if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { + retcode = -EFAULT; + goto done; + } + } + } + } + + else { + list_for_each(lh, &dev->crtc_config.crtc_list) + card_res.count_crtcs++; + + list_for_each_entry(output, &dev->crtc_config.output_list, + head) + { + list_for_each(lh, &output->modes) + card_res.count_modes++; + card_res.count_outputs++; + } + } + +done: + DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs, + card_res.count_outputs, + card_res.count_modes); + + if (copy_to_user(argp, &card_res, sizeof(card_res))) + return -EFAULT; + + return retcode; +} -- cgit v1.2.3 From 7bb112fecadc6fe42e5828b861600691071ccd91 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Apr 2007 17:06:42 +1000 Subject: checkpoint commit: added getresources, crtc and output This adds the user interfaces from Jakob and hooks them up for 3 ioctls GetResources, GetCrtc and GetOutput. I've made the ids for everything fbs, crtcs, outputs and modes go via idr as per krh's suggestion on irc as it make the code nice and consistent. --- linux-core/drm_crtc.c | 218 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 180 insertions(+), 38 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1311fa63..2dbe6de1 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -3,6 +3,33 @@ #include "drm.h" #include "drm_crtc.h" +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) { + DRM_ERROR("Ran out memory getting a mode number\n"); + return 0; + } + + spin_lock(&dev->crtc_config.config_lock); + + ret = idr_get_new_above(&dev->crtc_config.crtc_idr, ptr, 1, &new_id); + if (ret == -EAGAIN) { + spin_unlock(&dev->crtc_config.config_lock); + goto again; + } + + spin_unlock(&dev->crtc_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); +} + struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) { struct drm_framebuffer *fb; @@ -20,7 +47,8 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) return NULL; } - + + fb->id = drm_mode_idr_get(dev, fb); fb->dev = dev; spin_lock(&dev->crtc_config.config_lock); dev->crtc_config.num_fb++; @@ -35,6 +63,7 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) drm_device_t *dev = fb->dev; spin_lock(&dev->crtc_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); @@ -45,19 +74,21 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) struct drm_crtc *drm_crtc_create(drm_device_t *dev, const struct drm_crtc_funcs *funcs) { - struct drm_crtc *crtc = NULL; - crtc = kmalloc(sizeof(struct drm_crtc), GFP_KERNEL); + struct drm_crtc *crtc; + + crtc = kzalloc(sizeof(struct drm_crtc), GFP_KERNEL); if (!crtc) return NULL; crtc->dev = dev; crtc->funcs = funcs; - spin_lock(&dev->crtc_config.config_lock); + 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); return crtc; @@ -71,7 +102,9 @@ void drm_crtc_destroy(struct drm_crtc *crtc) if (crtc->funcs->cleanup) (*crtc->funcs->cleanup)(crtc); + spin_lock(&dev->crtc_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); @@ -257,6 +290,7 @@ bool drm_set_desired_modes(struct drm_device *dev) list_for_each_entry(crtc, &dev->crtc_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) { if (list_output->crtc == crtc) { output = list_output; @@ -345,6 +379,7 @@ struct drm_output *drm_output_create(drm_device_t *dev, output->dev = dev; output->funcs = funcs; + output->id = drm_mode_idr_get(dev, output); if (name) strncpy(output->name, name, DRM_OUTPUT_LEN); output->name[DRM_OUTPUT_LEN - 1] = 0; @@ -382,6 +417,7 @@ void drm_output_destroy(struct drm_output *output) drm_mode_remove(output, mode); spin_lock(&dev->crtc_config.config_lock); + drm_mode_idr_put(dev, output->id); list_del(&output->head); spin_unlock(&dev->crtc_config.config_lock); kfree(output); @@ -411,28 +447,13 @@ struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev) if (!nmode) return NULL; -again: - if (idr_pre_get(&dev->crtc_config.mode_idr, GFP_KERNEL) == 0) { - DRM_ERROR("Ran out memory getting a mode number\n"); - kfree(nmode); - return NULL; - } - - spin_lock(&dev->crtc_config.config_lock); - - ret = idr_get_new(&dev->crtc_config.mode_idr, nmode, &nmode->mode_id); - if (ret == -EAGAIN) { - udelay(1); - spin_unlock(&dev->crtc_config.config_lock); - goto again; - } - spin_unlock(&dev->crtc_config.config_lock); + nmode->mode_id = drm_mode_idr_get(dev, nmode); return nmode; } void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) { - idr_remove(&dev->crtc_config.mode_idr, mode->mode_id); + drm_mode_idr_put(dev, mode->mode_id); kfree(mode); } @@ -443,7 +464,7 @@ void drm_crtc_config_init(drm_device_t *dev) 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.mode_idr); + idr_init(&dev->crtc_config.crtc_idr); } EXPORT_SYMBOL(drm_crtc_config_init); @@ -502,6 +523,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->crtc_config.crtc_list, head) { + DRM_DEBUG("crtc is %d\n", crtc->id); crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; @@ -568,7 +590,6 @@ void drm_crtc_config_cleanup(drm_device_t *dev) drm_output_destroy(output); } - list_for_each_entry_safe(crtc, ct, &dev->crtc_config.crtc_list, head) { drm_crtc_destroy(crtc); } @@ -592,6 +613,8 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display out->vscan = in->vscan; out->flags = in->flags; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } @@ -605,15 +628,24 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, struct drm_mode_card_res card_res; struct list_head *lh; struct drm_output *output; + struct drm_crtc *crtc; struct drm_mode_modeinfo u_mode; struct drm_display_mode *mode; int retcode = 0; int mode_count= 0; + 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) + crtc_count++; + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + output_count++; list_for_each(lh, &output->modes) mode_count++; } @@ -621,8 +653,38 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, if (copy_from_user(&card_res, argp, sizeof(card_res))) return -EFAULT; + /* 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){ + DRM_DEBUG("CRTC ID is %d\n", crtc->id); + if (put_user(crtc->id, &card_res.crtc_id[copied++])) { + retcode = -EFAULT; + goto done; + } + } + } + card_res.count_crtcs = crtc_count; + + + /* Outputs */ + if (card_res.count_outputs >= output_count) { + copied = 0; + list_for_each_entry(output, &dev->crtc_config.output_list, + head) { + DRM_DEBUG("OUTPUT ID is %d\n", output->id); + if (put_user(output->id, &card_res.output_id[copied++])) { + retcode = -EFAULT; + goto done; + } + } + } + card_res.count_outputs = output_count; + + /* Modes */ if (card_res.count_modes >= mode_count) { - int copied = 0; + copied = 0; list_for_each_entry(output, &dev->crtc_config.output_list, head) { list_for_each_entry(mode, &output->modes, head) { @@ -634,19 +696,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, } } } - - else { - list_for_each(lh, &dev->crtc_config.crtc_list) - card_res.count_crtcs++; - - list_for_each_entry(output, &dev->crtc_config.output_list, - head) - { - list_for_each(lh, &output->modes) - card_res.count_modes++; - card_res.count_outputs++; - } - } + card_res.count_modes = mode_count; done: DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs, @@ -658,3 +708,95 @@ done: return retcode; } + +int drm_mode_getcrtc(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_mode_crtc __user *argp = (void __user *)arg; + struct drm_mode_crtc crtc_resp; + struct drm_crtc *crtc; + struct drm_output *output; + int ocount; + int retcode = 0; + + if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp))) + return -EFAULT; + + crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_resp.crtc_id); + if (!crtc || (crtc->id != crtc_resp.crtc_id)) + return -EINVAL; + crtc_resp.x = crtc->x; + crtc_resp.y = crtc->y; + crtc_resp.fb_id = 1; + + crtc_resp.outputs = 0; + if (crtc->enabled) { + + crtc_resp.mode = crtc->mode.mode_id; + ocount = 0; + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + if (output->crtc == crtc) + crtc_resp.outputs |= 1 << (ocount++); + } + } else { + crtc_resp.mode = 0; + } + + if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp))) + return -EFAULT; + + return retcode; +} + +int drm_mode_getoutput(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_mode_get_output __user *argp = (void __user *)arg; + struct drm_mode_get_output out_resp; + struct drm_crtc *crtc; + struct drm_output *output; + struct drm_display_mode *mode; + int mode_count = 0; + int retcode = 0; + int copied = 0; + + if (copy_from_user(&out_resp, argp, sizeof(out_resp))) + return -EFAULT; + + output= idr_find(&dev->crtc_config.crtc_idr, out_resp.output); + if (!output || (output->id != out_resp.output)) + return -EINVAL; + + list_for_each_entry(mode, &output->modes, head) + mode_count++; + + out_resp.mm_width = output->mm_width; + out_resp.mm_height = output->mm_height; + out_resp.subpixel = output->subpixel_order; + out_resp.connection = output->status; + if (output->crtc) + out_resp.crtc = output->crtc->id; + else + out_resp.crtc = 0; + + if (out_resp.count_modes >= mode_count) { + copied = 0; + list_for_each_entry(mode, &output->modes, head) { + if (put_user(mode->mode_id, &out_resp.modes[copied++])) { + retcode = -EFAULT; + goto done; + } + } + } + out_resp.count_modes = mode_count; + +done: + if (copy_to_user(argp, &out_resp, sizeof(out_resp))) + return -EFAULT; + + return retcode; +} -- cgit v1.2.3 From b4094864f188a1346cc3b51bcb457beeacefbf82 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Apr 2007 18:01:02 +1000 Subject: checkpoint commit: implement SetCrtc so modes can in theory be set from user This hooks up the userspace mode set it "seems" to work. --- linux-core/drm_crtc.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 2dbe6de1..8e03dd5f 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -302,10 +302,10 @@ bool drm_set_desired_modes(struct drm_device *dev) continue; memset(&crtc->mode, 0, sizeof(crtc->mode)); - if (!crtc->desired_mode.crtc_hdisplay) { + if (!crtc->desired_mode->crtc_hdisplay) { } - if (!drm_crtc_set_mode(crtc, &crtc->desired_mode, + if (!drm_crtc_set_mode(crtc, crtc->desired_mode, crtc->desired_x, crtc->desired_y)) return false; } @@ -556,7 +556,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) break; DRM_DEBUG("Setting desired mode for output %s\n", output->name); drm_mode_debug_printmodeline(dev, des_mode); - output->crtc->desired_mode = *des_mode; + output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; use_output = output; @@ -568,7 +568,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) break; DRM_DEBUG("Setting desired mode for output %s\n", output->name); drm_mode_debug_printmodeline(dev, des_mode); - output->crtc->desired_mode = *des_mode; + output->crtc->desired_mode = des_mode; #endif output->initial_x = 0; output->initial_y = 0; @@ -596,6 +596,68 @@ void drm_crtc_config_cleanup(drm_device_t *dev) } EXPORT_SYMBOL(drm_crtc_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) +{ + drm_device_t *dev = crtc->dev; + struct drm_crtc **save_crtcs, *new_crtc; + bool save_enabled = crtc->enabled; + bool changed; + struct drm_output *output; + int count = 0, ro; + + save_crtcs = kzalloc(dev->crtc_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL); + if (!save_crtcs) + return -ENOMEM; + + if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) + changed = true; + + if (crtc->mode.mode_id != new_mode->mode_id) + changed = true; + + list_for_each_entry(output, &dev->crtc_config.output_list, head) { + save_crtcs[count++] = output->crtc; + + if (output->crtc == crtc) + new_crtc = NULL; + else + new_crtc = output->crtc; + + for (ro = 0; ro < crtc_info->count_outputs; ro++) + { + if (output_set[ro] == output) + new_crtc = crtc; + } + if (new_crtc != output->crtc) { + changed = true; + output->crtc = new_crtc; + } + } + + if (changed) { + crtc->enabled = new_mode != NULL; + if (new_mode) { + DRM_DEBUG("attempting to set mode from userspace\n"); + drm_mode_debug_printmodeline(dev, new_mode); + if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x, + crtc_info->y)) { + crtc->enabled = save_enabled; + count = 0; + list_for_each_entry(output, &dev->crtc_config.output_list, head) + output->crtc = save_crtcs[count++]; + kfree(save_crtcs); + return -EINVAL; + } + crtc->desired_x = crtc_info->x; + crtc->desired_y = crtc_info->y; + crtc->desired_mode = new_mode; + } + drm_disable_unused_functions(dev); + } + kfree(save_crtcs); + return 0; +} + void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in) { @@ -757,7 +819,6 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, drm_device_t *dev = priv->head->dev; struct drm_mode_get_output __user *argp = (void __user *)arg; struct drm_mode_get_output out_resp; - struct drm_crtc *crtc; struct drm_output *output; struct drm_display_mode *mode; int mode_count = 0; @@ -800,3 +861,60 @@ done: return retcode; } + + +int drm_mode_setcrtc(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_mode_crtc __user *argp = (void __user *)arg; + struct drm_mode_crtc crtc_req; + struct drm_crtc *crtc; + struct drm_output **output_set = NULL, *output; + struct drm_display_mode *mode; + int retcode = 0; + int i; + + if (copy_from_user(&crtc_req, argp, sizeof(crtc_req))) + return -EFAULT; + + crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_req.crtc_id); + if (!crtc || (crtc->id != crtc_req.crtc_id)) + return -EINVAL; + + if (crtc_req.mode) { + mode = idr_find(&dev->crtc_config.crtc_idr, crtc_req.mode); + if (!mode || (mode->mode_id != crtc_req.mode)) + return -EINVAL; + } else + mode = NULL; + + if (crtc_req.count_outputs == 0 && mode) + return -EINVAL; + + if (crtc_req.count_outputs > 0 && !mode) + return -EINVAL; + + if (crtc_req.count_outputs > 0) { + u32 out_id; + output_set = kmalloc(crtc_req.count_outputs * sizeof(struct drm_output *), GFP_KERNEL); + if (!output_set) + return -ENOMEM; + + 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)) + return -EINVAL; + + output_set[i] = output; + } + } + + retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set); + return retcode; +} -- cgit v1.2.3 From a35ba455b27b72f1ee3e1136ca6659f672ada4fa Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Sat, 7 Apr 2007 19:22:39 -0700 Subject: make drmP.h include drm_crtc.h for CRTC related stuff. fixup drm_crtc.c so it matches VGA and other outputs properly. make drm_crtc.c less verbose. add function declarations in drm_crtc.h for other files. --- linux-core/drm_crtc.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 8e03dd5f..fe27e386 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -340,8 +340,6 @@ void drm_disable_unused_functions(struct drm_device *dev) */ void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode) { - printk(KERN_ERR "adding DDC mode %s to output %s\n", mode->name, - output->name); spin_lock(&output->modes_lock); list_add(&mode->head, &output->probed_modes); spin_unlock(&output->modes_lock); @@ -440,7 +438,6 @@ EXPORT_SYMBOL(drm_output_rename); struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev) { - int ret; struct drm_display_mode *nmode; nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); @@ -506,7 +503,8 @@ EXPORT_SYMBOL(drm_framebuffer_set_object); bool drm_initial_config(drm_device_t *dev, bool can_grow) { /* do a hardcoded initial configuration here */ - struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL; + struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL, + *lvds_crtc = NULL;; struct drm_framebuffer *fb; struct drm_output *output, *use_output = NULL; @@ -523,14 +521,18 @@ 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->crtc_config.crtc_list, head) { - DRM_DEBUG("crtc is %d\n", crtc->id); crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; - } + } else if (!lvds_crtc) { + lvds_crtc = crtc; + crtc->enabled = 1; + crtc->desired_x = 0; + crtc->desired_y = 0; + } #if 0 else if (!dvi_crtc) { dvi_crtc = crtc; @@ -549,29 +551,32 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) list_for_each_entry(output, &dev->crtc_config.output_list, head) { struct drm_display_mode *des_mode; - if (strncmp(output->name, "VGA", 3)) { - output->crtc = vga_crtc; - /* just pull the first mode out of that hat */ - list_for_each_entry(des_mode, &output->modes, head) + /* Get the first preferred moded */ + list_for_each_entry(des_mode, &output->modes, head) { + if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) break; - DRM_DEBUG("Setting desired mode for output %s\n", output->name); + } + if (!strncmp(output->name, "VGA", 3)) { + output->crtc = vga_crtc; drm_mode_debug_printmodeline(dev, des_mode); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; use_output = output; - } else if (strncmp(output->name, "TMDS", 4)) { + } else if (!strncmp(output->name, "TMDS", 4)) { output->crtc = vga_crtc; #if 0 - /* just pull the first mode out of that hat */ - list_for_each_entry(des_mode, &output->modes, head) - break; - DRM_DEBUG("Setting desired mode for output %s\n", output->name); drm_mode_debug_printmodeline(dev, des_mode); output->crtc->desired_mode = des_mode; #endif output->initial_x = 0; output->initial_y = 0; + } else if (!strncmp(output->name, "LVDS", 3)) { + output->crtc = lvds_crtc; + drm_mode_debug_printmodeline(dev, des_mode); + output->crtc->desired_mode = des_mode; + output->initial_x = 0; + output->initial_y = 0; } else output->crtc = NULL; -- cgit v1.2.3 From b50bda002b824efb24e18e8d514ff0ca763c15b9 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 10 Apr 2007 18:44:47 +1000 Subject: add addfb/rmfb ioctls Originally from Jakob, cleaned up by airlied. --- linux-core/drm_crtc.c | 95 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 13 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fe27e386..a02124f3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -465,18 +465,19 @@ void drm_crtc_config_init(drm_device_t *dev) } EXPORT_SYMBOL(drm_crtc_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; } @@ -485,20 +486,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) { @@ -923,3 +917,78 @@ 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_crtc_config *config = &dev->crtc_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"); + return -EINVAL; + } + if (config->min_height > r.height || r.height > config->min_height) { + DRM_ERROR("mode new framebuffer height not within limits"); + 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; + 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->crtc_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; +} -- cgit v1.2.3 From ed0ebd9d3da2e5c4e8053b6e7a7d2898b184f857 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Apr 2007 18:56:02 +1000 Subject: make crtc_config be named mode_config X.org calls this crtc_config but this is a bad name and will confuse ppl later (and me now :-) --- linux-core/drm_crtc.c | 136 +++++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 68 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index a02124f3..4f8af001 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); @@ -116,7 +116,7 @@ bool drm_crtc_in_use(struct drm_crtc *crtc) { struct drm_output *output; drm_device_t *dev = crtc->dev; - 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; @@ -131,7 +131,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); @@ -214,7 +214,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; @@ -229,7 +229,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; @@ -244,14 +244,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); @@ -287,11 +287,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; @@ -320,12 +320,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); } @@ -389,11 +389,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; @@ -414,10 +414,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); @@ -455,15 +455,15 @@ 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); static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **bo, unsigned long handle) { @@ -514,7 +514,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->crtc_config.crtc_list, head) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; @@ -542,7 +542,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 */ @@ -580,20 +580,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) { @@ -604,7 +604,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; @@ -614,7 +614,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) @@ -642,7 +642,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,10 +700,10 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, 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, + list_for_each_entry(output, &dev->mode_config.output_list, head) { output_count++; @@ -718,7 +718,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, /* 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; @@ -732,7 +732,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++])) { @@ -746,7 +746,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); @@ -785,7 +785,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; @@ -797,7 +797,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++); } @@ -827,7 +827,7 @@ 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); + output= idr_find(&dev->mode_config.crtc_idr, out_resp.output); if (!output || (output->id != out_resp.output)) return -EINVAL; @@ -878,12 +878,12 @@ 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)) 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)) return -EINVAL; } else @@ -906,7 +906,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, if (get_user(out_id, &crtc_req.set_outputs[i])) return -EFAULT; - output = idr_find(&dev->crtc_config.crtc_idr, out_id); + output = idr_find(&dev->mode_config.crtc_idr, out_id); if (!output || (out_id != output->id)) return -EINVAL; @@ -926,7 +926,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, 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_crtc_config *config = &dev->crtc_config; + struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; struct drm_buffer_object *bo; int ret; @@ -977,7 +977,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, struct drm_framebuffer *fb = 0; uint32_t id = arg; - fb = idr_find(&dev->crtc_config.crtc_idr, id); + 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"); -- cgit v1.2.3 From eb9bdc27879d1aa307b234bbdb0f81494dcf7095 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 11:51:31 +1000 Subject: mode: fixup problems with framebuffer add function --- linux-core/drm_crtc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 4f8af001..ce2073d1 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -502,6 +502,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; @@ -512,6 +513,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) 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->mode_config.crtc_list, head) { @@ -931,15 +933,15 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, struct drm_buffer_object *bo; int ret; - if (!copy_from_user(&r, argp, sizeof(r))) + 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"); + 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->min_height) { - DRM_ERROR("mode new framebuffer height not within limits"); + if ((config->min_height > r.height) || (r.height > config->max_height)) { + DRM_ERROR("mode new framebuffer height not within limits\n"); return -EINVAL; } @@ -963,7 +965,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, fb->bo = bo; r.buffer_id = fb->id; - if (!copy_to_user(argp, &r, sizeof(r))) + if (copy_to_user(argp, &r, sizeof(r))) return -EFAULT; return 0; -- cgit v1.2.3 From 65f465ed5ad3caf773658bb2832785c963b987f6 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 14:49:49 +1000 Subject: 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 --- linux-core/drm_crtc.c | 101 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 30 deletions(-) (limited to 'linux-core/drm_crtc.c') 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; -- cgit v1.2.3 From 1e39dc43230ba1827eedc29ab422464281ec3e1b Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 16:25:31 +1000 Subject: export output name to userspace --- linux-core/drm_crtc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 46b7f7ae..cc082d91 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -838,16 +838,19 @@ 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); + 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"); + 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; -- cgit v1.2.3 From 8785679f893ef9257c589a70113ac731edba0194 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 10 Apr 2007 09:49:02 -0700 Subject: Remove some debug #if 0 codes and add a reminder to check locking around output enumeration stuff. --- linux-core/drm_crtc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fe27e386..6874265e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -116,6 +116,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) if (output->crtc == crtc) return true; @@ -504,7 +505,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) { /* do a hardcoded initial configuration here */ struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL, - *lvds_crtc = NULL;; + *lvds_crtc = NULL; struct drm_framebuffer *fb; struct drm_output *output, *use_output = NULL; @@ -517,7 +518,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) fb->height = 768; fb->depth = 24; fb->bits_per_pixel = 32; - + /* bind both CRTCs to this fb */ /* only initialise one crtc to enabled state */ list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { @@ -533,14 +534,12 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) crtc->desired_x = 0; crtc->desired_y = 0; } -#if 0 else if (!dvi_crtc) { dvi_crtc = crtc; crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; } -#endif } drm_crtc_probe_output_modes(dev, 1024, 768); @@ -565,10 +564,8 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) use_output = output; } else if (!strncmp(output->name, "TMDS", 4)) { output->crtc = vga_crtc; -#if 0 drm_mode_debug_printmodeline(dev, des_mode); output->crtc->desired_mode = des_mode; -#endif output->initial_x = 0; output->initial_y = 0; } else if (!strncmp(output->name, "LVDS", 3)) { -- cgit v1.2.3 From 44be9c9d5950d3b2ba4d5527189abec8dac0686f Mon Sep 17 00:00:00 2001 From: David Airlie Date: Wed, 11 Apr 2007 13:19:30 +1000 Subject: add an fb count + id get to the get resources code path --- linux-core/drm_crtc.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1899df2d..12705272 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -84,7 +84,6 @@ struct drm_crtc *drm_crtc_create(drm_device_t *dev, crtc->funcs = funcs; crtc->id = drm_mode_idr_get(dev, crtc); - DRM_DEBUG("crtc %p got id %d\n", crtc, crtc->id); spin_lock(&dev->mode_config.config_lock); list_add_tail(&crtc->head, &dev->mode_config.crtc_list); @@ -291,7 +290,6 @@ bool drm_set_desired_modes(struct drm_device *dev) 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->mode_config.output_list, head) { if (list_output->crtc == crtc) { output = list_output; @@ -610,7 +608,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) changed = true; - if (crtc->mode.mode_id != new_mode->mode_id) + if (new_mode && (crtc->mode.mode_id != new_mode->mode_id)) changed = true; list_for_each_entry(output, &dev->mode_config.output_list, head) { @@ -633,8 +631,8 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } if (changed) { - crtc->enabled = new_mode != NULL; - if (new_mode) { + crtc->enabled = (new_mode != NULL); + if (new_mode != NULL) { DRM_DEBUG("attempting to set mode from userspace\n"); drm_mode_debug_printmodeline(dev, new_mode); if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x, @@ -648,7 +646,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } crtc->desired_x = crtc_info->x; crtc->desired_y = crtc_info->y; - crtc->desired_mode = new_mode; + crtc->desired_mode = new_mode; } drm_disable_unused_functions(dev); } @@ -687,6 +685,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, struct drm_mode_card_res __user *argp = (void __user *)arg; struct drm_mode_card_res card_res; struct list_head *lh; + struct drm_framebuffer *fb; struct drm_output *output; struct drm_crtc *crtc; struct drm_mode_modeinfo u_mode; @@ -695,10 +694,14 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, int mode_count= 0; int output_count = 0; int crtc_count = 0; + int fb_count = 0; int copied = 0; memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); + list_for_each(lh, &dev->mode_config.fb_list) + fb_count++; + list_for_each(lh, &dev->mode_config.crtc_list) crtc_count++; @@ -722,7 +725,19 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, } } - /* handle this in 3 parts */ + /* handle this in 4 parts */ + /* FBs */ + if (card_res.count_fbs >= fb_count) { + copied = 0; + list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + if (put_user(fb->id, &card_res.fb_id[copied++])) { + retcode = -EFAULT; + goto done; + } + } + } + card_res.count_fbs = fb_count; + /* CRTCs */ if (card_res.count_crtcs >= crtc_count) { copied = 0; @@ -840,11 +855,9 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, 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; @@ -1029,9 +1042,18 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, /* TODO check if we own the buffer */ /* TODO release all crtc connected to the framebuffer */ + /* bind the fb to the crtc for now */ + { + struct drm_crtc *crtc; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb == fb) + crtc->fb = NULL; + } + } /* TODO unhock the destructor from the buffer object */ drm_framebuffer_destroy(fb); return 0; } + -- cgit v1.2.3 From 32f6a58db216f23a7c71ca9c7eda56aaa8293078 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 11 Apr 2007 16:33:03 +1000 Subject: add initial drm_fb framebuffer So far I can load fbcon, once I use my miniglx to add a framebuffer. fbcon doesn't show anything on screen but baby steps and all that. --- linux-core/drm_crtc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 12705272..83f8e167 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1022,6 +1022,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, if (copy_to_user(argp, &r, sizeof(r))) return -EFAULT; + drmfb_probe(dev, fb); return 0; } @@ -1040,6 +1041,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, return -EINVAL; } + drmfb_remove(dev, fb); /* TODO check if we own the buffer */ /* TODO release all crtc connected to the framebuffer */ /* bind the fb to the crtc for now */ -- cgit v1.2.3 From a6cc6a778f8b2f86300a8ce87441d044fd67f930 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Wed, 11 Apr 2007 17:13:45 +1000 Subject: add support for setting a framebuffer depth --- linux-core/drm_crtc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 83f8e167..1c1c3006 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1003,12 +1003,13 @@ 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->depth = r.depth; + fb->offset = bo->offset; + fb->bo = bo; r.buffer_id = fb->id; -- cgit v1.2.3 From 78598fdaa8b23a199880a63b79f17cfd7f14cb0f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 Apr 2007 07:07:54 -0700 Subject: Various changes for in-kernel modesetting: - allow drm_buffer_object_create to be called w/o dev_mapping - fixup i915 init code to allocate memory, fb and set modes right - pass fb to drm_initial_config for setup - change some debug output to make it easier to spot - fixup lvds code to use DDC probing correctly --- linux-core/drm_crtc.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1c1c3006..b349527d 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -57,6 +57,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) return fb; } +EXPORT_SYMBOL(drm_framebuffer_create); void drm_framebuffer_destroy(struct drm_framebuffer *fb) { @@ -493,30 +494,28 @@ out_err: return ret; } -bool drm_initial_config(drm_device_t *dev, bool can_grow) +/** + * drm_initial_config - setup a sane initial output configuration + * @dev: DRM device + * @fb: framebuffer backing for new setup + * @can_grow: this configuration is growable + * + * Scan the CRTCs and outputs and try to put together an initial setup. + * At the moment, this is a cloned configuration across all heads with + * @fb as the backing store. + */ +bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, + bool can_grow) { /* do a hardcoded initial configuration here */ struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL, *lvds_crtc = NULL; - struct drm_framebuffer *fb; struct drm_output *output, *use_output = NULL; -#if 0 - fb = drm_framebuffer_create(dev); - if (!fb) - return false; - - fb->pitch = 1024; - fb->width = 1024; - 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->mode_config.crtc_list, head) { - // crtc->fb = fb; + crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; crtc->enabled = 1; @@ -527,8 +526,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; - } - else if (!dvi_crtc) { + } else if (!dvi_crtc) { dvi_crtc = crtc; crtc->enabled = 1; crtc->desired_x = 0; @@ -536,7 +534,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } } - drm_crtc_probe_output_modes(dev, 1024, 768); + drm_crtc_probe_output_modes(dev, 2048, 2048); /* hard bind the CRTCS */ @@ -551,20 +549,20 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } if (!strncmp(output->name, "VGA", 3)) { output->crtc = vga_crtc; - drm_mode_debug_printmodeline(dev, des_mode); + DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; use_output = output; } else if (!strncmp(output->name, "TMDS", 4)) { output->crtc = vga_crtc; - drm_mode_debug_printmodeline(dev, des_mode); + DRM_DEBUG("TMDS preferred mode: %s\n", des_mode->name); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; } else if (!strncmp(output->name, "LVDS", 3)) { output->crtc = lvds_crtc; - drm_mode_debug_printmodeline(dev, des_mode); + DRM_DEBUG("LVDS preferred mode: %s\n", des_mode->name); output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; -- cgit v1.2.3 From a81558d8b3ee17fbf46e32b10732e22fcd997858 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 08:45:40 +1000 Subject: add getfb ioctl --- linux-core/drm_crtc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b349527d..d1f3c077 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1058,3 +1058,33 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, return 0; } +int drm_mode_getfb(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_mode_fb_cmd __user *argp = (void __user *)arg; + struct drm_mode_fb_cmd r; + struct drm_framebuffer *fb; + + if (copy_from_user(&r, argp, sizeof(r))) + return -EFAULT; + + fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); + if (!fb || (r.buffer_id != fb->id)) { + DRM_ERROR("invalid framebuffer id\n"); + return -EINVAL; + } + + r.height = fb->height; + r.width = fb->width; + r.depth = fb->depth; + r.bpp = fb->bits_per_pixel; + r.handle = fb->bo->base.hash.key; + r.pitch = fb->pitch; + + if (copy_to_user(argp, &r, sizeof(r))) + return -EFAULT; + + return 0; +} -- cgit v1.2.3 From 981f8156de0c5ec6387f659fbcac031d663d943c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 08:54:31 +1000 Subject: allow framebuffer changes on the crtc setup --- linux-core/drm_crtc.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index d1f3c077..21d7012e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -590,7 +590,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) } 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) +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, struct drm_framebuffer *fb) { drm_device_t *dev = crtc->dev; struct drm_crtc **save_crtcs, *new_crtc; @@ -603,6 +603,9 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, if (!save_crtcs) return -ENOMEM; + if (crtc->fb != fb) + changed = true; + if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) changed = true; @@ -629,6 +632,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } if (changed) { + crtc->fb = fb; crtc->enabled = (new_mode != NULL); if (new_mode != NULL) { DRM_DEBUG("attempting to set mode from userspace\n"); @@ -897,6 +901,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, struct drm_crtc *crtc; struct drm_output **output_set = NULL, *output; struct drm_display_mode *mode; + struct drm_framebuffer *fb = NULL; int retcode = 0; int i; @@ -911,6 +916,15 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, } if (crtc_req.mode) { + + /* if we have a mode we need a framebuffer */ + if (crtc_req.fb_id) { + fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id); + if (!fb || (fb->id != crtc_req.fb_id)) { + DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id); + return -EINVAL; + } + } mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode); if (!mode || (mode->mode_id != crtc_req.mode)) { @@ -935,8 +949,8 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, return -EINVAL; } - if (crtc_req.count_outputs > 0 && !mode) { - DRM_DEBUG("Count outputs is %d but no mode set\n", crtc_req.count_outputs); + if (crtc_req.count_outputs > 0 && !mode && !fb) { + DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req.count_outputs); return -EINVAL; } @@ -960,7 +974,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, } } - retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set); + retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb); return retcode; } -- cgit v1.2.3 From a5cf4cc369fcc2cf7b84bbaef1e458250ecb91ee Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 11:28:55 +1000 Subject: fix unbalanced lock and make sure mode list has modes so lvds code doesn't crash --- linux-core/drm_crtc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 21d7012e..63ad829d 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -37,6 +37,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) spin_lock(&dev->mode_config.config_lock); /* Limit to single framebuffer for now */ if (dev->mode_config.num_fb > 1) { + spin_unlock(&dev->mode_config.config_lock); DRM_ERROR("Attempt to add multiple framebuffers failed\n"); return NULL; } @@ -542,6 +543,9 @@ bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, list_for_each_entry(output, &dev->mode_config.output_list, head) { struct drm_display_mode *des_mode; + if (list_empty(&output->modes)) + continue; + /* Get the first preferred moded */ list_for_each_entry(des_mode, &output->modes, head) { if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) -- cgit v1.2.3 From b49b3ba4c1aad0d3f34f06013f2ffa67fc8d82c9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 11:43:13 +1000 Subject: set bracing style like Linux --- linux-core/drm_crtc.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 63ad829d..259ea1b8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -254,8 +254,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ crtc->funcs->commit(crtc); list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (output->crtc == crtc) - { + if (output->crtc == crtc) { output->funcs->commit(output); #if 0 // TODO def RANDR_12_INTERFACE if (output->randr_output) @@ -624,8 +623,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, else new_crtc = output->crtc; - for (ro = 0; ro < crtc_info->count_outputs; ro++) - { + for (ro = 0; ro < crtc_info->count_outputs; ro++) { if (output_set[ro] == output) new_crtc = crtc; } @@ -913,8 +911,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, return -EFAULT; crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id); - if (!crtc || (crtc->id != 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; } @@ -930,15 +927,12 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, } } 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); - } + 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); } } -- cgit v1.2.3 From 1bba3cb3b37ca9bc302d83377c1e9d5441653d0d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 11:55:10 +1000 Subject: cleanup framebuffers on drm unload --- linux-core/drm_crtc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 259ea1b8..2f140dbd 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -582,7 +582,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) { struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; - + struct drm_crtc *fb, *fbt; list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_output_destroy(output); } @@ -590,6 +590,11 @@ void drm_mode_config_cleanup(drm_device_t *dev) list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { drm_crtc_destroy(crtc); } + + list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { + drmfb_remove(dev, fb); + drm_framebuffer_destroy(fb); + } } EXPORT_SYMBOL(drm_mode_config_cleanup); -- cgit v1.2.3 From cf016891435a0aa74dc4909ed4125c7ed906b7d1 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 12 Apr 2007 15:12:00 +0100 Subject: Use drm_framebuffer instead of drm_crtc for fb & fbt --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 2f140dbd..ef025922 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -582,7 +582,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) { struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; - struct drm_crtc *fb, *fbt; + struct drm_framebuffer *fb, *fbt; list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_output_destroy(output); } -- cgit v1.2.3 From c4e944182db3002101c330453ebb3f454637743e Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 13 Apr 2007 02:23:42 +0200 Subject: Added debug messages so we know which output we are dealing with --- linux-core/drm_crtc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ef025922..adea0309 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -134,13 +134,14 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) // TODO 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); output->status = (*output->funcs->detect)(output); if (output->status == output_status_disconnected) { + DRM_DEBUG("%s is disconnected\n", output->name); /* TODO set EDID to NULL */ continue; } @@ -164,8 +165,10 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) drm_mode_prune_invalid(dev, &output->modes, TRUE); - if (list_empty(&output->modes)) + if (list_empty(&output->modes)) { + DRM_DEBUG("No valid modes found on %s\n", output->name); continue; + } drm_mode_sort(&output->modes); @@ -429,9 +432,12 @@ bool drm_output_rename(struct drm_output *output, const char *name) strncpy(output->name, name, DRM_OUTPUT_LEN); output->name[DRM_OUTPUT_LEN - 1] = 0; + + DRM_DEBUG("Changed name to %s\n", output->name); // drm_output_set_monitor(output); // if (drm_output_ignored(output)) // return FALSE; + return TRUE; } EXPORT_SYMBOL(drm_output_rename); -- cgit v1.2.3 From 79aa1d54746f33c33ffbf98fb96ccbf88c3cb390 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 17 Apr 2007 18:16:38 +1000 Subject: another large overhaul of interactions with userspace... We need to keep a list of user created fbs to nuke on master exit. We also need to use the bo properly. --- linux-core/drm_crtc.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index adea0309..bf019df3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -64,6 +64,15 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) { drm_device_t *dev = fb->dev; + /* remove from any CRTC */ + { + struct drm_crtc *crtc; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb == fb) + crtc->fb = NULL; + } + } + spin_lock(&dev->mode_config.config_lock); drm_mode_idr_put(dev, fb->id); list_del(&fb->head); @@ -1034,6 +1043,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, r.buffer_id = fb->id; + list_add(&fb->filp_head, &priv->fbs); /* bind the fb to the crtc for now */ { struct drm_crtc *crtc; @@ -1049,7 +1059,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, } 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; @@ -1067,13 +1077,6 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, /* TODO check if we own the buffer */ /* TODO release all crtc connected to the framebuffer */ /* bind the fb to the crtc for now */ - { - struct drm_crtc *crtc; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb == fb) - crtc->fb = NULL; - } - } /* TODO unhock the destructor from the buffer object */ drm_framebuffer_destroy(fb); @@ -1111,3 +1114,17 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, return 0; } + +void drm_fb_release(struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->head->dev; + struct drm_framebuffer *fb, *tfb; + + list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { + list_del(&fb->filp_head); + drmfb_remove(dev, fb); + drm_framebuffer_destroy(fb); + + } +} -- cgit v1.2.3 From 4e4d9cbeb3f52b605e46aad8ae1a947ca236079f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 17 Apr 2007 10:00:37 -0700 Subject: Move initial framebuffer allocation and configuration to drm_initial_config, remove i915_driver_load fb related stuff. Add a small helper for setting up outputs. --- linux-core/drm_crtc.c | 73 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 21 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index adea0309..ff989265 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1,6 +1,6 @@ #include -#include "drmP.h" #include "drm.h" +#include "drmP.h" #include "drm_crtc.h" int drm_mode_idr_get(struct drm_device *dev, void *ptr) @@ -500,6 +500,15 @@ out_err: return ret; } +static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + output->crtc = crtc; + output->crtc->desired_mode = mode; + output->initial_x = 0; + output->initial_y = 0; +} + /** * drm_initial_config - setup a sane initial output configuration * @dev: DRM device @@ -510,13 +519,21 @@ out_err: * At the moment, this is a cloned configuration across all heads with * @fb as the backing store. */ -bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, - bool can_grow) +bool drm_initial_config(drm_device_t *dev, bool can_grow) { /* do a hardcoded initial configuration here */ - struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL, + struct drm_crtc *crtc, *vga_crtc = NULL, *tmds_crtc = NULL, *lvds_crtc = NULL; - struct drm_output *output, *use_output = NULL; + struct drm_output *output; + struct drm_framebuffer *fb; + drm_buffer_object_t *fbo; + unsigned long size, bytes_per_pixel; + + fb = drm_framebuffer_create(dev); + if (!fb) { + DRM_ERROR("failed to allocate fb.\n"); + return true; + } /* bind both CRTCs to this fb */ /* only initialise one crtc to enabled state */ @@ -532,8 +549,8 @@ bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; - } else if (!dvi_crtc) { - dvi_crtc = crtc; + } else if (!tmds_crtc) { + tmds_crtc = crtc; crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; @@ -557,29 +574,43 @@ bool drm_initial_config(drm_device_t *dev, struct drm_framebuffer *fb, break; } if (!strncmp(output->name, "VGA", 3)) { - output->crtc = vga_crtc; DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name); - output->crtc->desired_mode = des_mode; - output->initial_x = 0; - output->initial_y = 0; - use_output = output; + drm_setup_output(output, vga_crtc, des_mode); } else if (!strncmp(output->name, "TMDS", 4)) { - output->crtc = vga_crtc; DRM_DEBUG("TMDS preferred mode: %s\n", des_mode->name); - output->crtc->desired_mode = des_mode; - output->initial_x = 0; - output->initial_y = 0; + drm_setup_output(output, tmds_crtc, des_mode); } else if (!strncmp(output->name, "LVDS", 3)) { - output->crtc = lvds_crtc; DRM_DEBUG("LVDS preferred mode: %s\n", des_mode->name); - output->crtc->desired_mode = des_mode; - output->initial_x = 0; - output->initial_y = 0; + drm_setup_output(output, lvds_crtc, des_mode); } else output->crtc = NULL; - + + /* FB config is max of above desired resolutions */ + /* FIXME: per-output FBs/CRTCs */ + if (des_mode->hdisplay > fb->width) { + fb->width = des_mode->hdisplay; + fb->pitch = fb->width; + } + if (des_mode->vdisplay > fb->height) + fb->height = des_mode->vdisplay; } + /* FIXME: multiple depths */ + bytes_per_pixel = 4; + fb->bits_per_pixel = bytes_per_pixel * 8; + fb->depth = bytes_per_pixel * 8; + size = fb->width * fb->height * bytes_per_pixel; + drm_buffer_object_create(dev, size, drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_PRIV0 | DRM_BO_FLAG_NO_MOVE, + 0, 0, 0, + &fbo); + DRM_DEBUG("allocated %dx%d fb: 0x%08lx\n", fb->width, fb->height, + fbo->offset); + fb->offset = fbo->offset; + fb->bo = fbo; + drmfb_probe(dev, fb); + return false; } EXPORT_SYMBOL(drm_initial_config); -- cgit v1.2.3 From 73b031df613b58c4462a65818b88200bed0a97de Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 17 Apr 2007 17:30:46 -0700 Subject: Add framebuffer bo freeing to drm_mode_config_cleanup (seems like the best place for now). --- linux-core/drm_crtc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1adae0d2..0fb5b9ae 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -614,8 +614,8 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) DRM_BO_FLAG_MEM_PRIV0 | DRM_BO_FLAG_NO_MOVE, 0, 0, 0, &fbo); - DRM_DEBUG("allocated %dx%d fb: 0x%08lx\n", fb->width, fb->height, - fbo->offset); + DRM_DEBUG("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width, + fb->height, fbo->offset, fbo); fb->offset = fbo->offset; fb->bo = fbo; drmfb_probe(dev, fb); @@ -639,6 +639,12 @@ void drm_mode_config_cleanup(drm_device_t *dev) list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { drmfb_remove(dev, fb); + /* If this FB was the kernel one, free it */ + if (fb->bo->type == drm_bo_type_kernel) { + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(fb->bo); + mutex_unlock(&dev->struct_mutex); + } drm_framebuffer_destroy(fb); } } -- cgit v1.2.3 From d20aaf485893ed11dd0d68daf63ccadd77b02213 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 18 Apr 2007 10:41:39 +1000 Subject: don't crash if no desired mode --- linux-core/drm_crtc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 0fb5b9ae..437259d5 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -572,7 +572,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) /* bind analog output to one crtc */ list_for_each_entry(output, &dev->mode_config.output_list, head) { - struct drm_display_mode *des_mode; + struct drm_display_mode *des_mode = NULL; if (list_empty(&output->modes)) continue; @@ -582,6 +582,10 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) break; } + + if (!des_mode) + continue; + if (!strncmp(output->name, "VGA", 3)) { DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name); drm_setup_output(output, vga_crtc, des_mode); -- cgit v1.2.3 From 20b2949e3738bc900407d6aeddc6338f05b0b169 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 18 Apr 2007 14:55:43 +1000 Subject: make sure TMDS gets a crtc --- linux-core/drm_crtc.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 437259d5..e8f42feb 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -553,16 +553,19 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; - } else if (!lvds_crtc) { - lvds_crtc = crtc; - crtc->enabled = 1; - crtc->desired_x = 0; - crtc->desired_y = 0; - } else if (!tmds_crtc) { - tmds_crtc = crtc; - crtc->enabled = 1; - crtc->desired_x = 0; - crtc->desired_y = 0; + } else { + if (!lvds_crtc) { + lvds_crtc = crtc; + crtc->enabled = 1; + crtc->desired_x = 0; + crtc->desired_y = 0; + } + if (!tmds_crtc) { + tmds_crtc = crtc; + crtc->enabled = 1; + crtc->desired_x = 0; + crtc->desired_y = 0; + } } } -- cgit v1.2.3 From 191594ebd5fbe3ac3615247c4e2cd50e1b099635 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 12:07:55 +0100 Subject: When no valid EDID modes are available, we bail. This snippet adds a standard 640x480 @ 60Hz mode when that occurs, so we can continue with a basic mode. Should we do this here though ??? --- linux-core/drm_crtc.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e8f42feb..f6c675c5 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -134,6 +134,15 @@ bool drm_crtc_in_use(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_in_use); +/* + * Detailed mode info for a standard 640x480@60Hz monitor + */ +static struct drm_display_mode std_mode[] = { + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, + 752, 800, 0, 480, 490, 492, 525, 0, + V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */ +}; + void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) { struct drm_output *output; @@ -175,8 +184,22 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) drm_mode_prune_invalid(dev, &output->modes, TRUE); if (list_empty(&output->modes)) { + struct drm_display_mode *newmode; + DRM_DEBUG("No valid modes found on %s\n", output->name); - continue; + + /* Should we do this here ??? + * When no valid EDID modes are available we end up + * here and bailed in the past, now we add a standard + * 640x480@60Hz mode and carry on. + */ + newmode = drm_mode_duplicate(dev, &std_mode[0]); + drm_mode_probed_add(output, newmode); + drm_mode_list_concat(&output->probed_modes, + &output->modes); + + DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", + output->name); } drm_mode_sort(&output->modes); @@ -310,13 +333,11 @@ bool drm_set_desired_modes(struct drm_device *dev) } } /* Skip disabled crtcs */ - if (!output) + if (!output) { + DRM_DEBUG("skipping disabled crtc\n"); continue; - - memset(&crtc->mode, 0, sizeof(crtc->mode)); - if (!crtc->desired_mode->crtc_hdisplay) { - } + if (!drm_crtc_set_mode(crtc, crtc->desired_mode, crtc->desired_x, crtc->desired_y)) return false; -- cgit v1.2.3 From 87b46bd436074572b3a62e2fb7ec85a1db8df892 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 12:10:06 +0100 Subject: free the duplicated mode. --- linux-core/drm_crtc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f6c675c5..16bbd9b6 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -184,7 +184,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) drm_mode_prune_invalid(dev, &output->modes, TRUE); if (list_empty(&output->modes)) { - struct drm_display_mode *newmode; + struct drm_display_mode *stdmode; DRM_DEBUG("No valid modes found on %s\n", output->name); @@ -193,10 +193,11 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) * here and bailed in the past, now we add a standard * 640x480@60Hz mode and carry on. */ - newmode = drm_mode_duplicate(dev, &std_mode[0]); + stdmode = drm_mode_duplicate(dev, &std_mode[0]); drm_mode_probed_add(output, newmode); drm_mode_list_concat(&output->probed_modes, &output->modes); + drm_crtc_mode_destroy(dev, stdmode); DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", output->name); -- cgit v1.2.3 From 0207b51acce0382b2e3cf55ed7dbbe02e48c73b2 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 12:19:16 +0100 Subject: Fix build problem --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 16bbd9b6..02325520 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -194,7 +194,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) * 640x480@60Hz mode and carry on. */ stdmode = drm_mode_duplicate(dev, &std_mode[0]); - drm_mode_probed_add(output, newmode); + drm_mode_probed_add(output, stdmode); drm_mode_list_concat(&output->probed_modes, &output->modes); drm_crtc_mode_destroy(dev, stdmode); -- cgit v1.2.3 From dfc02547ff5f35bfa5cffd6a0dcb56402db59f33 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 14:18:56 +0100 Subject: Shouldn't free the mode here. It's done later on. --- linux-core/drm_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 02325520..38d596ba 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -197,7 +197,6 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) drm_mode_probed_add(output, stdmode); drm_mode_list_concat(&output->probed_modes, &output->modes); - drm_crtc_mode_destroy(dev, stdmode); DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", output->name); -- cgit v1.2.3 From 5587961cfeff86d8368ff03867a1f0667e4a64d4 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 18 Apr 2007 11:49:42 -0700 Subject: Document main drm_crtc.c functions, and rename drm_crtc_mode_create to drm_mode_create to be consistent with the other functions. Also document where we need locking fixes and what the locks are for. --- linux-core/drm_crtc.c | 520 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 489 insertions(+), 31 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 38d596ba..a099a6dc 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1,9 +1,55 @@ +/* + * Copyright (c) 2006-2007 Intel Corporation + * Copyright (c) 2007 Dave Airlie + * + * DRM core CRTC related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + * Keith Packard + * Eric Anholt + * Dave Airlie + * Jesse Barnes + */ #include #include "drm.h" #include "drmP.h" #include "drm_crtc.h" -int drm_mode_idr_get(struct drm_device *dev, void *ptr) +/** + * drm_idr_get - allocate a new identifier + * @dev: DRM device + * @ptr: object pointer, used to generate unique ID + * + * LOCKING: + * Process context (either init or calling process). Must take DRM mode_config + * lock around IDR allocation. + * + * Create a unique identifier based on @ptr in @dev's identifier space. Used + * for tracking modes, CRTCs and outputs. + * + * RETURNS: + * New unique (relative to other objects in @dev) integer identifier for the + * object. + */ +int drm_idr_get(struct drm_device *dev, void *ptr) { int new_id = 0; int ret; @@ -25,11 +71,34 @@ again: return new_id; } -void drm_mode_idr_put(struct drm_device *dev, int id) +/** + * drm_idr_put - free an identifer + * @dev: DRM device + * @id: ID to free + * + * LOCKING: + * Caller must hold DRM mode_config lock. + * + * Free @id from @dev's unique identifier pool. + */ +void drm_idr_put(struct drm_device *dev, int id) { idr_remove(&dev->mode_config.crtc_idr, id); } +/** + * drm_framebuffer_create - create a new framebuffer object + * @dev: DRM device + * + * LOCKING: + * Process context (either init or calling process). Must take DRM mode_config + * lock around mode_config manipulation. + * + * Creates a new framebuffer objects and adds it to @dev's DRM mode_config. + * + * RETURNS: + * Pointer to new framebuffer or NULL on error. + */ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) { struct drm_framebuffer *fb; @@ -49,7 +118,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) return NULL; } - fb->id = drm_mode_idr_get(dev, fb); + fb->id = drm_idr_get(dev, fb); fb->dev = dev; spin_lock(&dev->mode_config.config_lock); dev->mode_config.num_fb++; @@ -60,21 +129,30 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) } EXPORT_SYMBOL(drm_framebuffer_create); +/** + * drm_framebuffer_destroy - remove a framebuffer object + * @fb: framebuffer to remove + * + * LOCKING: + * Process context (either init or calling process). Must take DRM mode_config + * lock around mode_config manipulation. + * + * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes + * it, setting it to NULL. + */ void drm_framebuffer_destroy(struct drm_framebuffer *fb) { drm_device_t *dev = fb->dev; + struct drm_crtc *crtc; /* remove from any CRTC */ - { - struct drm_crtc *crtc; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb == fb) - crtc->fb = NULL; - } + spin_lock(&dev->mode_config.config_lock); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb == fb) + crtc->fb = NULL; } - spin_lock(&dev->mode_config.config_lock); - drm_mode_idr_put(dev, fb->id); + drm_idr_put(dev, fb->id); list_del(&fb->head); dev->mode_config.num_fb--; spin_unlock(&dev->mode_config.config_lock); @@ -82,6 +160,20 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) kfree(fb); } +/** + * drm_crtc_create - create a new CRTC object + * @dev: DRM device + * @funcs: callbacks for the new CRTC + * + * LOCKING: + * Process context (either init or calling process). Must take DRM mode_config + * lock around mode_config manipulation. + * + * Creates a new CRTC object and adds it to @dev's mode_config structure. + * + * RETURNS: + * Pointer to new CRTC object or NULL on error. + */ struct drm_crtc *drm_crtc_create(drm_device_t *dev, const struct drm_crtc_funcs *funcs) { @@ -94,7 +186,7 @@ struct drm_crtc *drm_crtc_create(drm_device_t *dev, crtc->dev = dev; crtc->funcs = funcs; - crtc->id = drm_mode_idr_get(dev, crtc); + crtc->id = drm_idr_get(dev, crtc); spin_lock(&dev->mode_config.config_lock); list_add_tail(&crtc->head, &dev->mode_config.crtc_list); @@ -105,6 +197,17 @@ struct drm_crtc *drm_crtc_create(drm_device_t *dev, } EXPORT_SYMBOL(drm_crtc_create); +/** + * drm_crtc_destroy - remove a CRTC object + * @crtc: CRTC to remove + * + * LOCKING: + * Process context (either init or calling process). Must take DRM mode_config + * lock around mode_config traversal. + * + * Cleanup @crtc. Calls @crtc's cleanup function, then removes @crtc from + * its associated DRM device's mode_config. Frees it afterwards. + */ void drm_crtc_destroy(struct drm_crtc *crtc) { drm_device_t *dev = crtc->dev; @@ -112,9 +215,8 @@ void drm_crtc_destroy(struct drm_crtc *crtc) if (crtc->funcs->cleanup) (*crtc->funcs->cleanup)(crtc); - spin_lock(&dev->mode_config.config_lock); - drm_mode_idr_put(dev, crtc->id); + drm_idr_put(dev, crtc->id); list_del(&crtc->head); dev->mode_config.num_crtc--; spin_unlock(&dev->mode_config.config_lock); @@ -122,6 +224,18 @@ void drm_crtc_destroy(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_destroy); +/** + * drm_crtc_in_use - check if a given CRTC is in a mode_config + * @crtc: CRTC to check + * + * LOCKING: + * Caller? (FIXME) + * + * Walk @crtc's DRM device's mode_config and see if it's in use. + * + * RETURNS: + * True if @crtc is part of the mode_config, false otherwise. + */ bool drm_crtc_in_use(struct drm_crtc *crtc) { struct drm_output *output; @@ -143,6 +257,25 @@ static struct drm_display_mode std_mode[] = { V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */ }; +/** + * drm_crtc_probe_output_modes - get complete set of display modes + * @dev: DRM device + * @maxX: max width for modes + * @maxY: max height for modes + * + * LOCKING: + * Caller? (FIXME) + * + * Based on @dev's mode_config layout, scan all the outputs and try to detect + * modes on them. Modes will first be added to the output's probed_modes + * list, then culled (based on validity and the @maxX, @maxY parameters) and + * put into the normal modes list. + * + * Intended to be used either at bootup time or when major configuration + * changes have occurred. + * + * FIXME: take into account monitor limits + */ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) { struct drm_output *output; @@ -186,7 +319,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) if (list_empty(&output->modes)) { struct drm_display_mode *stdmode; - DRM_DEBUG("No valid modes found on %s\n", output->name); + DRM_DEBUG("No valid modes on %s\n", output->name); /* Should we do this here ??? * When no valid EDID modes are available we end up @@ -214,6 +347,22 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) } } +/** + * drm_crtc_set_mode - set a mode + * @crtc: CRTC to program + * @mode: mode to use + * @x: width of mode + * @y: height of mode + * + * LOCKING: + * Caller? (FIXME) + * + * Try to set @mode on @crtc. Give @crtc and its associated outputs a chance + * to fixup or reject the mode prior to trying to set it. + * + * RETURNS: + * True if the mode was set successfully, or false otherwise. + */ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y) { @@ -299,7 +448,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, } /* XXX free adjustedmode */ - drm_crtc_mode_destroy(dev, adjusted_mode); + drm_mode_destroy(dev, adjusted_mode); ret = TRUE; /* TODO */ // if (scrn->pScreen) @@ -318,6 +467,20 @@ done: return ret; } +/** + * drm_set_desired_modes - set a good mode on every CRTC & output + * @dev: DRM device + * + * LOCKING: + * Caller? (FIXME) + * + * Each CRTC may have a desired mode associated with it. This routine simply + * walks @dev's mode_config and sets the desired mode on every CRTC. Intended + * for use at startup time. + * + * RETURNS: + * True if modes were set, false otherwise. + */ bool drm_set_desired_modes(struct drm_device *dev) { struct drm_crtc *crtc; @@ -326,7 +489,8 @@ bool drm_set_desired_modes(struct drm_device *dev) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { output = NULL; - list_for_each_entry(list_output, &dev->mode_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; @@ -348,6 +512,16 @@ bool drm_set_desired_modes(struct drm_device *dev) } EXPORT_SYMBOL(drm_set_desired_modes); +/** + * drm_disable_unused_functions - disable unused objects + * @dev: DRM device + * + * LOCKING: + * Caller? (FIXME) + * + * If an output or CRTC isn't part of @dev's mode_config, it can be disabled + * by calling its dpms function, which should power it off. + */ void drm_disable_unused_functions(struct drm_device *dev) { struct drm_output *output; @@ -369,9 +543,14 @@ void drm_disable_unused_functions(struct drm_device *dev) * @output: output the new mode * @mode: mode data * + * LOCKING: + * Process context (either init or calling process). Must take @output's + * mode_lock around mode list manipulation. + * * Add @mode to @output's mode list for later use. */ -void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode) +void drm_mode_probed_add(struct drm_output *output, + struct drm_display_mode *mode) { spin_lock(&output->modes_lock); list_add(&mode->head, &output->probed_modes); @@ -384,6 +563,10 @@ EXPORT_SYMBOL(drm_mode_probed_add); * @output: output list to modify * @mode: mode to remove * + * LOCKING: + * Process context (either init or calling process). Must take @output's + * mode_lock around mode list manipulation. + * * Remove @mode from @output's mode list, then free it. */ void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) @@ -395,8 +578,21 @@ void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_remove); -/* - * Probably belongs in the DRM device structure +/** + * drm_output_create - create a new output + * @dev: DRM device + * @funcs: callbacks for this output + * @name: user visible name of the output + * + * LOCKING: + * Process context (either init or calling process). Must take @dev's + * mode_config lock around mode list manipulation. + * + * Creates a new drm_output structure and adds it to @dev's mode_config + * structure. + * + * RETURNS: + * Pointer to the new output or NULL on error. */ struct drm_output *drm_output_create(drm_device_t *dev, const struct drm_output_funcs *funcs, @@ -410,7 +606,7 @@ struct drm_output *drm_output_create(drm_device_t *dev, output->dev = dev; output->funcs = funcs; - output->id = drm_mode_idr_get(dev, output); + output->id = drm_idr_get(dev, output); if (name) strncpy(output->name, name, DRM_OUTPUT_LEN); output->name[DRM_OUTPUT_LEN - 1] = 0; @@ -433,6 +629,18 @@ struct drm_output *drm_output_create(drm_device_t *dev, } EXPORT_SYMBOL(drm_output_create); +/** + * drm_output_destroy - remove an output + * @output: output to remove + * + * LOCKING: + * Process context (either init or calling process). Must take @dev's + * mode_config lock around mode list manipulation. Caller must hold + * modes lock? (FIXME) + * + * Call @output's cleanup function, then remove the output from the DRM + * mode_config after freeing @output's modes. + */ void drm_output_destroy(struct drm_output *output) { struct drm_device *dev = output->dev; @@ -448,13 +656,26 @@ void drm_output_destroy(struct drm_output *output) drm_mode_remove(output, mode); spin_lock(&dev->mode_config.config_lock); - drm_mode_idr_put(dev, output->id); + drm_idr_put(dev, output->id); list_del(&output->head); spin_unlock(&dev->mode_config.config_lock); kfree(output); } EXPORT_SYMBOL(drm_output_destroy); +/** + * drm_output_rename - rename an output + * @output: output to rename + * @name: new user visible name + * + * LOCKING: + * None. + * + * Simply stuff a new name into @output's name field, based on @name. + * + * RETURNS: + * True if the name was changed, false otherwise. + */ bool drm_output_rename(struct drm_output *output, const char *name) { if (!name) @@ -472,7 +693,19 @@ bool drm_output_rename(struct drm_output *output, const char *name) } EXPORT_SYMBOL(drm_output_rename); -struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev) +/** + * drm_mode_create - create a new display mode + * @dev: DRM device + * + * LOCKING: + * None. + * + * Create a new drm_display_mode, give it an ID, and return it. + * + * RETURNS: + * Pointer to new mode on success, NULL on error. + */ +struct drm_display_mode *drm_mode_create(struct drm_device *dev) { struct drm_display_mode *nmode; @@ -480,17 +713,37 @@ struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev) if (!nmode) return NULL; - nmode->mode_id = drm_mode_idr_get(dev, nmode); + nmode->mode_id = drm_idr_get(dev, nmode); return nmode; } -void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) +/** + * drm_mode_destroy - remove a mode + * @dev: DRM device + * @mode: mode to remove + * + * LOCKING: + * None. + * + * Free @mode's unique identifier, then free it. + */ +void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) { - drm_mode_idr_put(dev, mode->mode_id); + drm_idr_put(dev, mode->mode_id); kfree(mode); } +/** + * drm_mode_config_init - initialize DRM mode_configuration structure + * @dev: DRM device + * + * LOCKING: + * None, should happen single threaded at init time. + * + * Initialize @dev's mode_config structure, used for tracking the graphics + * configuration of @dev. + */ void drm_mode_config_init(drm_device_t *dev) { spin_lock_init(&dev->mode_config.config_lock); @@ -501,6 +754,21 @@ void drm_mode_config_init(drm_device_t *dev) } EXPORT_SYMBOL(drm_mode_config_init); +/** + * drm_get_buffer_object - find the buffer object for a given handle + * @dev: DRM device + * @bo: pointer to caller's buffer_object pointer + * @handle: handle to lookup + * + * LOCKING: + * Must take @dev's struct_mutex to protect buffer object lookup. + * + * Given @handle, lookup the buffer object in @dev and put it in the caller's + * @bo pointer. + * + * RETURNS: + * Zero on success, -EINVAL if the handle couldn't be found. + */ static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **bo, unsigned long handle) { drm_user_object_t *uo; @@ -530,6 +798,18 @@ out_err: return ret; } +/** + * drm_setup_output - setup an output structure + * @output: output to setup + * @crtc: CRTC this output belongs to + * @mode: desired mode for this output + * + * LOCKING: + * None. + * + * Setup @output with the parameters given, with its initial coordinates set + * at the origin. + */ static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc, struct drm_display_mode *mode) { @@ -542,12 +822,19 @@ static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc, /** * drm_initial_config - setup a sane initial output configuration * @dev: DRM device - * @fb: framebuffer backing for new setup * @can_grow: this configuration is growable * + * LOCKING: + * Must take various locks. (FIXME) + * * Scan the CRTCs and outputs and try to put together an initial setup. * At the moment, this is a cloned configuration across all heads with - * @fb as the backing store. + * a new framebuffer object as the backing store. + * + * FIXME: return value and better initial config. + * + * RETURNS: + * Zero if everything went ok, nonzero otherwise. */ bool drm_initial_config(drm_device_t *dev, bool can_grow) { @@ -652,6 +939,18 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } EXPORT_SYMBOL(drm_initial_config); +/** + * drm_mode_config_cleanup - free up DRM mode_config info + * @dev: DRM device + * + * LOCKING: + * Caller? (FIXME) + * + * Free up all the outputs and CRTCs associated with this DRM device, then + * free up the framebuffers and associated buffer objects. + * + * FIXME: cleanup any dangling user buffer objects too + */ void drm_mode_config_cleanup(drm_device_t *dev) { struct drm_output *output, *ot; @@ -678,6 +977,23 @@ void drm_mode_config_cleanup(drm_device_t *dev) } EXPORT_SYMBOL(drm_mode_config_cleanup); +/** + * drm_crtc_set_config - set a new config from userspace + * @crtc: CRTC to setup + * @crtc_info: user provided configuration + * @new_mode: new mode to set + * @output_set: set of outputs for the new config + * @fb: new framebuffer + * + * LOCKING: + * Caller? (FIXME) + * + * Setup a new configuration, provided by the user in @crtc_info, and enable + * it. + * + * RETURNS: + * Zero. (FIXME) + */ 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, struct drm_framebuffer *fb) { drm_device_t *dev = crtc->dev; @@ -743,6 +1059,17 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, return 0; } +/** + * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo + * @out: drm_mode_modeinfo struct to return to the user + * @in: drm_display_mode to use + * + * LOCKING: + * None. + * + * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to + * the user. + */ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in) { @@ -765,7 +1092,24 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display } -/* IOCTL code from userspace */ +/** + * drm_mode_getresources - get graphics configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Construct a set of configuration description structures and return + * them to the user, including CRTC, output and framebuffer configuration. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_getresources(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -882,6 +1226,23 @@ done: return retcode; } +/** + * drm_mode_getcrtc - get CRTC configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Construct a CRTC configuration structure to return to the user. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_getcrtc(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -923,6 +1284,23 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, return retcode; } +/** + * drm_mode_getoutput - get output configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Construct a output configuration structure to return to the user. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_getoutput(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -977,7 +1355,23 @@ done: return retcode; } - +/** + * drm_mode_setcrtc - set CRTC configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Build a new CRTC configuration based on user request. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_setcrtc(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -1061,7 +1455,23 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, return retcode; } -/* Add framebuffer ioctl */ +/** + * drm_mode_addfb - add an FB to the graphics configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Add a new FB to the specified CRTC, given a user request. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_addfb(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -1123,6 +1533,23 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, return 0; } +/** + * drm_mode_rmfb - remove an FB from the configuration + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Remove the FB specified by the user. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_rmfb(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -1149,6 +1576,23 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, return 0; } +/** + * drm_mode_getfb - get FB info + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Lookup the FB given its ID and return info about it. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ int drm_mode_getfb(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -1180,6 +1624,20 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, return 0; } +/** + * drm_fb_release - remove and free the FBs on this file + * @filp: file * from the ioctl + * + * LOCKING: + * Caller? (FIXME) + * + * Destroy all the FBs associated with @filp. + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ void drm_fb_release(struct file *filp) { drm_file_t *priv = filp->private_data; -- cgit v1.2.3 From 0f3c5148f02bd98411095fdc8059207fa17b4a7d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 23 Apr 2007 09:10:46 +1000 Subject: fixup vrefresh reporting, it should now be *1000 in userspace --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index a099a6dc..f95facce 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1085,7 +1085,7 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display out->vsync_end = in->vsync_end; out->vtotal = in->vtotal; out->vscan = in->vscan; - + out->vrefresh = in->vrefresh; out->flags = in->flags; strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; -- cgit v1.2.3 From ceb44021ad7755721acc3c0307c54009b666442e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 23 Apr 2007 11:42:29 +1000 Subject: drm: make mode numbers no change by comparing probed modes The mode list sets all the output modes to UNVERIFIED, then probes a new list, If a mode is on the new list and not on the old, it adds it to the old, if a mode is on the new list and old, it just updates the status to the new mode status. If a mode is on the old list and not on the new, prune invalid modes should remove all UNVERIFIED modes --- linux-core/drm_crtc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f95facce..16cf62a7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -286,8 +286,9 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) list_for_each_entry(output, &dev->mode_config.output_list, head) { + /* set all modes to the unverified state */ list_for_each_entry_safe(mode, t, &output->modes, head) - drm_mode_remove(output, mode); + mode->status = MODE_UNVERIFIED; output->status = (*output->funcs->detect)(output); @@ -300,9 +301,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) ret = (*output->funcs->get_modes)(output); if (ret) { - /* move the modes over to the main mode list */ - drm_mode_list_concat(&output->probed_modes, - &output->modes); + drm_mode_output_list_update(output); } if (maxX && maxY) -- cgit v1.2.3 From 89231953d108e74ee7b0eb99494ead1dd795d640 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 1 May 2007 13:16:29 +1000 Subject: Add support for user defined modes This allows userspace to specify modes and add them to the modesetting system and attach modes to outputs --- linux-core/drm_crtc.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 254 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 16cf62a7..201137db 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -749,6 +749,7 @@ void drm_mode_config_init(drm_device_t *dev) INIT_LIST_HEAD(&dev->mode_config.fb_list); INIT_LIST_HEAD(&dev->mode_config.crtc_list); INIT_LIST_HEAD(&dev->mode_config.output_list); + INIT_LIST_HEAD(&dev->mode_config.usermode_list); idr_init(&dev->mode_config.crtc_idr); } EXPORT_SYMBOL(drm_mode_config_init); @@ -1090,6 +1091,35 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } +/** + * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode + * @out: drm_display_mode to return to the user + * @in: drm_mode_modeinfo to use + * + * LOCKING: + * None. + * + * Convert a drmo_mode_modeinfo into a drm_display_mode structure to return to + * the caller. + */ +void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modeinfo *in) +{ + out->clock = in->clock; + out->hdisplay = in->hdisplay; + out->hsync_start = in->hsync_start; + out->hsync_end = in->hsync_end; + out->htotal = in->htotal; + out->hskew = in->hskew; + out->vdisplay = in->vdisplay; + out->vsync_start = in->vsync_start; + out->vsync_end = in->vsync_end; + out->vtotal = in->vtotal; + out->vscan = in->vscan; + out->vrefresh = in->vrefresh; + out->flags = in->flags; + strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); + out->name[DRM_DISPLAY_MODE_LEN-1] = 0; +} /** * drm_mode_getresources - get graphics configuration @@ -1143,6 +1173,8 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, list_for_each(lh, &output->modes) mode_count++; } + list_for_each(lh, &dev->mode_config.usermode_list) + mode_count++; if (copy_from_user(&card_res, argp, sizeof(card_res))) return -EFAULT; @@ -1155,6 +1187,8 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, list_for_each(lh, &output->modes) mode_count++; } + list_for_each(lh, &dev->mode_config.usermode_list) + mode_count++; } /* handle this in 4 parts */ @@ -1211,6 +1245,14 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, } } } + /* add in user modes */ + list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { + drm_crtc_convert_to_umode(&u_mode, mode); + if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { + retcode = -EFAULT; + goto done; + } + } } card_res.count_modes = mode_count; @@ -1312,6 +1354,7 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, int mode_count = 0; int retcode = 0; int copied = 0; + int i; if (copy_from_user(&out_resp, argp, sizeof(out_resp))) return -EFAULT; @@ -1323,6 +1366,10 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, 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++; strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN); out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0; @@ -1344,6 +1391,14 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, goto done; } } + for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { + if (output->user_mode_ids[i] != 0) + if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) { + retcode = -EFAULT; + goto done; + } + } + } out_resp.count_modes = mode_count; @@ -1408,9 +1463,13 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, 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); + 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); } } @@ -1650,3 +1709,195 @@ void drm_fb_release(struct file *filp) } } + +/** + * drm_fb_newmode - 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(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_mode_modeinfo __user *argp = (void __user *)arg; + struct drm_mode_modeinfo new_mode; + struct drm_display_mode *user_mode; + + if (copy_from_user(&new_mode, argp, sizeof(new_mode))) + return -EFAULT; + + user_mode = drm_mode_create(dev); + if (!user_mode) + return -ENOMEM; + + drm_crtc_convert_umode(user_mode, &new_mode); + user_mode->type |= DRM_MODE_TYPE_USERDEF; + + user_mode->output_count = 0; + + spin_lock(&dev->mode_config.config_lock); + list_add(&user_mode->head, &dev->mode_config.usermode_list); + spin_unlock(&dev->mode_config.config_lock); + + new_mode.id = user_mode->mode_id; + if (copy_to_user(argp, &new_mode, sizeof(new_mode))) + return -EFAULT; + + return 0; +} + +/** + * 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(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; + uint32_t id = arg; + struct drm_display_mode *mode, *t; + int retcode = -EINVAL; + + mode = idr_find(&dev->mode_config.crtc_idr, id); + if (!mode || (id != mode->mode_id)) + return -EINVAL; + + if (!(mode->type & DRM_MODE_TYPE_USERDEF)) + return -EINVAL; + + if (mode->output_count) + return -EINVAL; + + spin_lock(&dev->mode_config.config_lock); + list_for_each_entry(t, &dev->mode_config.usermode_list, head) { + if (t == mode) { + list_del(&mode->head); + drm_mode_destroy(dev, mode); + retcode = 0; + break; + } + } + spin_unlock(&dev->mode_config.config_lock); + return retcode; +} + +/** + * drm_fb_attachmode - Attach a user mode to an output + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * This attaches a user specified mode to an output. + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_attachmode(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_mode_mode_cmd __user *argp = (void __user *)arg; + struct drm_mode_mode_cmd mode_cmd; + struct drm_output *output; + struct drm_display_mode *mode; + int i; + + if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) + return -EFAULT; + + mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id); + if (!mode || (mode->mode_id != mode_cmd.mode_id)) + return -EINVAL; + + output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id); + if (!output || (output->id != mode_cmd.output_id)) + return -EINVAL; + + 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) + return -ENOSPC; + + return 0; +} + + +/** + * drm_fb_detachmode - Detach a user specified mode from an output + * @inode: inode from the ioctl + * @filp: file * from the ioctl + * @cmd: cmd from ioctl + * @arg: arg from ioctl + * + * Called by the user via ioctl. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_mode_detachmode(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_mode_mode_cmd __user *argp = (void __user *)arg; + struct drm_mode_mode_cmd mode_cmd; + struct drm_output *output; + struct drm_display_mode *mode; + int i, found = 0; + + if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) + return -EFAULT; + + mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id); + if (!mode || (mode->mode_id != mode_cmd.mode_id)) + return -EINVAL; + + output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id); + if (!output || (output->id != mode_cmd.output_id)) + return -EINVAL; + + + 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--; + found = 1; + } + } + + if (!found) + return -EINVAL; + + return 0; +} -- cgit v1.2.3 From 3a69e2484a4a392c8fc8542fc44f9c6552589c46 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 1 May 2007 14:20:22 +1000 Subject: cleanup usermodes on drm mode setting shutdown --- linux-core/drm_crtc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 201137db..a8f14e17 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -956,6 +956,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; struct drm_framebuffer *fb, *fbt; + struct drm_display_mode *mode, *mt; list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_output_destroy(output); } @@ -964,6 +965,10 @@ void drm_mode_config_cleanup(drm_device_t *dev) drm_crtc_destroy(crtc); } + 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) { drmfb_remove(dev, fb); /* If this FB was the kernel one, free it */ -- cgit v1.2.3 From 5ce8aaae7251e60c078eda0a21894aae0e1d7a45 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 17 May 2007 12:46:36 +0100 Subject: Large changes for fbdev support. Change from DIRECTCOLOR to TRUECOLOR, and enable support for PSEUDOCOLOR. DIRECTCOLOR support needs more work. Add the ability to change the mode on the fbdev device. Support depth 8, 15, 16 and 24 (and 32). Add a /dev/fbX device per CRTC, but there's some code which doesn't allocate the fbX device unless the output is actually enabled. Read the code on this as it impacts the fbcon map flags. Pick CRTC's based on the available outputs. More work could be done here to match modes, so cloning could be achieved on outputs. This fits more inline with what the X code does. --- linux-core/drm_crtc.c | 234 +++++++++++++++++++++----------------------------- 1 file changed, 100 insertions(+), 134 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index a8f14e17..d710a4e7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -466,51 +466,6 @@ done: return ret; } -/** - * drm_set_desired_modes - set a good mode on every CRTC & output - * @dev: DRM device - * - * LOCKING: - * Caller? (FIXME) - * - * Each CRTC may have a desired mode associated with it. This routine simply - * walks @dev's mode_config and sets the desired mode on every CRTC. Intended - * for use at startup time. - * - * RETURNS: - * True if modes were set, false otherwise. - */ -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->mode_config.crtc_list, head) { - output = NULL; - - list_for_each_entry(list_output, &dev->mode_config.output_list, - head) { - if (list_output->crtc == crtc) { - output = list_output; - break; - } - } - /* Skip disabled crtcs */ - if (!output) { - DRM_DEBUG("skipping disabled crtc\n"); - continue; - } - - if (!drm_crtc_set_mode(crtc, crtc->desired_mode, - crtc->desired_x, crtc->desired_y)) - return false; - } - - drm_disable_unused_functions(dev); - return true; -} -EXPORT_SYMBOL(drm_set_desired_modes); - /** * drm_disable_unused_functions - disable unused objects * @dev: DRM device @@ -799,26 +754,82 @@ out_err: } /** - * drm_setup_output - setup an output structure - * @output: output to setup - * @crtc: CRTC this output belongs to - * @mode: desired mode for this output + * drm_pick_crtcs - pick crtcs for output devices + * @dev: DRM device * * LOCKING: * None. - * - * Setup @output with the parameters given, with its initial coordinates set - * at the origin. */ -static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc, - struct drm_display_mode *mode) +static void drm_pick_crtcs (drm_device_t *dev) { - output->crtc = crtc; - output->crtc->desired_mode = mode; - output->initial_x = 0; - output->initial_y = 0; + int c, o; + struct drm_output *output, *output_equal; + struct drm_crtc *crtc; + struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; + + list_for_each_entry(output, &dev->mode_config.output_list, head) { + output->crtc = NULL; + + /* Don't hook up outputs that are disconnected ?? + * + * This is debateable. Do we want fixed /dev/fbX or + * dynamic on hotplug (need mode code for that though) ? + * + * If we don't hook up outputs now, then we only create + * /dev/fbX for the output that's enabled, that's good as + * the users console will be on that output. + * + * If we do hook up outputs that are disconnected now, then + * the user may end up having to muck about with the fbcon + * map flags to assign his console to the enabled output. Ugh. + */ + if (output->status != output_status_connected) + continue; + + des_mode = NULL; + list_for_each_entry(des_mode, &output->modes, head) { + if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) + break; + } + + c = -1; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + c++; + if ((output->possible_crtcs & (1 << c)) == 0) + continue; + +#if 0 /* should we try and clone ?? - code not tested - FIXME */ + o = -1; + list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { + o++; + if (output->id == output_equal->id) + continue; + + list_for_each_entry(modes, &output->modes, head) { + list_for_each_entry(modes_equal, &output_equal->modes, head) { + if (drm_mode_equal (modes, modes_equal)) { + if ((output->possible_clones & (1 << o))) { + goto clone; + } + } + } + } + } + +clone: +#endif + /* Found a CRTC to attach to, do it ! */ + output->crtc = crtc; + output->crtc->desired_mode = des_mode; + output->initial_x = 0; + output->initial_y = 0; + DRM_DEBUG("Desired mode for CRTC %d is %dx%x\n",c,des_mode->hdisplay,des_mode->vdisplay); + break; + } + } } + /** * drm_initial_config - setup a sane initial output configuration * @dev: DRM device @@ -831,109 +842,61 @@ static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc, * At the moment, this is a cloned configuration across all heads with * a new framebuffer object as the backing store. * - * FIXME: return value and better initial config. - * * RETURNS: * Zero if everything went ok, nonzero otherwise. */ bool drm_initial_config(drm_device_t *dev, bool can_grow) { /* do a hardcoded initial configuration here */ - struct drm_crtc *crtc, *vga_crtc = NULL, *tmds_crtc = NULL, - *lvds_crtc = NULL; + struct drm_display_mode *des_mode = NULL; struct drm_output *output; struct drm_framebuffer *fb; drm_buffer_object_t *fbo; unsigned long size, bytes_per_pixel; - fb = drm_framebuffer_create(dev); - if (!fb) { - DRM_ERROR("failed to allocate fb.\n"); - return true; - } - - /* 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; - if (!vga_crtc) { - vga_crtc = crtc; - crtc->enabled = 1; - crtc->desired_x = 0; - crtc->desired_y = 0; - } else { - if (!lvds_crtc) { - lvds_crtc = crtc; - crtc->enabled = 1; - crtc->desired_x = 0; - crtc->desired_y = 0; - } - if (!tmds_crtc) { - tmds_crtc = crtc; - crtc->enabled = 1; - crtc->desired_x = 0; - crtc->desired_y = 0; - } - } - } - drm_crtc_probe_output_modes(dev, 2048, 2048); - /* hard bind the CRTCS */ + drm_pick_crtcs(dev); - /* bind analog output to one crtc */ list_for_each_entry(output, &dev->mode_config.output_list, head) { - struct drm_display_mode *des_mode = NULL; - if (list_empty(&output->modes)) + /* can't setup the output if there's no assigned crtc or mode */ + if (!output->crtc || !output->crtc->desired_mode) continue; - /* Get the first preferred moded */ - list_for_each_entry(des_mode, &output->modes, head) { - if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) - break; + fb = drm_framebuffer_create(dev); + if (!fb) { + DRM_ERROR("failed to allocate fb.\n"); + return true; } + output->crtc->fb = fb; + des_mode = output->crtc->desired_mode; - if (!des_mode) - continue; - - if (!strncmp(output->name, "VGA", 3)) { - DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name); - drm_setup_output(output, vga_crtc, des_mode); - } else if (!strncmp(output->name, "TMDS", 4)) { - DRM_DEBUG("TMDS preferred mode: %s\n", des_mode->name); - drm_setup_output(output, tmds_crtc, des_mode); - } else if (!strncmp(output->name, "LVDS", 3)) { - DRM_DEBUG("LVDS preferred mode: %s\n", des_mode->name); - drm_setup_output(output, lvds_crtc, des_mode); - } else - output->crtc = NULL; - - /* FB config is max of above desired resolutions */ - /* FIXME: per-output FBs/CRTCs */ if (des_mode->hdisplay > fb->width) { fb->width = des_mode->hdisplay; fb->pitch = fb->width; } if (des_mode->vdisplay > fb->height) fb->height = des_mode->vdisplay; - } - /* FIXME: multiple depths */ - bytes_per_pixel = 4; - fb->bits_per_pixel = bytes_per_pixel * 8; - fb->depth = bytes_per_pixel * 8; - size = fb->width * fb->height * bytes_per_pixel; - drm_buffer_object_create(dev, size, drm_bo_type_kernel, + /* FIXME: multiple depths */ + bytes_per_pixel = 4; + fb->bits_per_pixel = 32; + fb->depth = 24; + size = fb->pitch * fb->height * bytes_per_pixel; + /* FIXME - what about resizeable objects ??? */ + drm_buffer_object_create(dev, size, drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MEM_PRIV0 | DRM_BO_FLAG_NO_MOVE, 0, 0, 0, &fbo); - DRM_DEBUG("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width, - fb->height, fbo->offset, fbo); - fb->offset = fbo->offset; - fb->bo = fbo; - drmfb_probe(dev, fb); + printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width, + fb->height, fbo->offset, fbo); + fb->offset = fbo->offset; + fb->bo = fbo; + drmfb_probe(dev, output->crtc); + } + drm_disable_unused_functions(dev); return false; } @@ -1582,17 +1545,20 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, r.buffer_id = fb->id; list_add(&fb->filp_head, &priv->fbs); + + if (copy_to_user(argp, &r, sizeof(r))) + return -EFAULT; + /* 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; + + drmfb_probe(dev, crtc); } } - if (copy_to_user(argp, &r, sizeof(r))) - return -EFAULT; - drmfb_probe(dev, fb); return 0; } @@ -1629,6 +1595,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, } drmfb_remove(dev, fb); + /* TODO check if we own the buffer */ /* TODO release all crtc connected to the framebuffer */ /* bind the fb to the crtc for now */ @@ -1711,7 +1678,6 @@ void drm_fb_release(struct file *filp) list_del(&fb->filp_head); drmfb_remove(dev, fb); drm_framebuffer_destroy(fb); - } } -- cgit v1.2.3 From a18b4befb9b76c4b2662ff6caa0e4f0975eb8e9c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 May 2007 09:00:06 -0700 Subject: Fix FB pitch value (we had it wrong and were working around it in a few places). Add new FB hooks to the drm driver structure and make i915 use them for an Intel specific FB driver. This will allow acceleration and better handling of the command stream. --- linux-core/drm_crtc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 16cf62a7..26a1cf2f 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -910,10 +910,8 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) /* FB config is max of above desired resolutions */ /* FIXME: per-output FBs/CRTCs */ - if (des_mode->hdisplay > fb->width) { + if (des_mode->hdisplay > fb->width) fb->width = des_mode->hdisplay; - fb->pitch = fb->width; - } if (des_mode->vdisplay > fb->height) fb->height = des_mode->vdisplay; } @@ -921,6 +919,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) /* FIXME: multiple depths */ bytes_per_pixel = 4; fb->bits_per_pixel = bytes_per_pixel * 8; + fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8); fb->depth = bytes_per_pixel * 8; size = fb->width * fb->height * bytes_per_pixel; drm_buffer_object_create(dev, size, drm_bo_type_kernel, @@ -932,7 +931,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) fb->height, fbo->offset, fbo); fb->offset = fbo->offset; fb->bo = fbo; - drmfb_probe(dev, fb); + dev->driver->fb_probe(dev, fb); return false; } @@ -964,7 +963,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) } list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { - drmfb_remove(dev, fb); + dev->driver->fb_remove(dev, fb); /* If this FB was the kernel one, free it */ if (fb->bo->type == drm_bo_type_kernel) { mutex_lock(&dev->struct_mutex); @@ -1528,7 +1527,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, if (copy_to_user(argp, &r, sizeof(r))) return -EFAULT; - drmfb_probe(dev, fb); + dev->driver->fb_probe(dev, fb); return 0; } @@ -1564,7 +1563,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, return -EINVAL; } - drmfb_remove(dev, fb); + dev->driver->fb_remove(dev, fb); /* TODO check if we own the buffer */ /* TODO release all crtc connected to the framebuffer */ /* bind the fb to the crtc for now */ @@ -1645,7 +1644,7 @@ void drm_fb_release(struct file *filp) list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { list_del(&fb->filp_head); - drmfb_remove(dev, fb); + dev->driver->fb_remove(dev, fb); drm_framebuffer_destroy(fb); } -- cgit v1.2.3 From fd63ea971322246734fca5977a800c3ef51cc3fe Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 17 May 2007 17:00:11 +0100 Subject: Grab the default mode if the preferred mode isn't available. Fix an overflow problem. --- linux-core/drm_crtc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index d710a4e7..13a01fee 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -252,7 +252,7 @@ EXPORT_SYMBOL(drm_crtc_in_use); * Detailed mode info for a standard 640x480@60Hz monitor */ static struct drm_display_mode std_mode[] = { - { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, + { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */ }; @@ -792,6 +792,18 @@ static void drm_pick_crtcs (drm_device_t *dev) break; } + + /* No preferred mode, let's select another which should pick + * the default 640x480 if nothing else is here. + * + */ + if (!des_mode || !(des_mode->flags & DRM_MODE_TYPE_PREFERRED)) { + list_for_each_entry(des_mode, &output->modes, head) { + if (des_mode->flags & DRM_MODE_TYPE_DEFAULT) + break; + } + } + c = -1; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { c++; @@ -823,7 +835,7 @@ clone: output->crtc->desired_mode = des_mode; output->initial_x = 0; output->initial_y = 0; - DRM_DEBUG("Desired mode for CRTC %d is %dx%x\n",c,des_mode->hdisplay,des_mode->vdisplay); + DRM_DEBUG("Desired mode for CRTC %d is %s\n",c,des_mode->name); break; } } -- cgit v1.2.3 From 07a5fbaa612a777de37b5dc0112f6f3f3f84c486 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 17 May 2007 19:28:03 +0100 Subject: Move destruction of crtc as intelfb_remove uses the crtc to locate the fb. --- linux-core/drm_crtc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ab8b4688..7544eac4 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -971,10 +971,6 @@ void drm_mode_config_cleanup(drm_device_t *dev) drm_output_destroy(output); } - list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { - drm_crtc_destroy(crtc); - } - list_for_each_entry_safe(mode, mt, &dev->mode_config.usermode_list, head) { drm_mode_destroy(dev, mode); } @@ -989,6 +985,11 @@ void drm_mode_config_cleanup(drm_device_t *dev) } drm_framebuffer_destroy(fb); } + + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { + drm_crtc_destroy(crtc); + } + } EXPORT_SYMBOL(drm_mode_config_cleanup); -- cgit v1.2.3 From 0c33a2cd2ec81478403d39b1b92aaa4431e7cf0a Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 18 May 2007 14:16:10 +0100 Subject: Move fbo creation to the specified fb driver which gives it a chance to allocate the memory from whichever buffer it wants to. --- linux-core/drm_crtc.c | 45 +-------------------------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 7544eac4..1586eb1a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -184,6 +184,7 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) kfree(fb); } +EXPORT_SYMBOL(drm_framebuffer_destroy); /** * drm_crtc_create - create a new CRTC object @@ -820,10 +821,8 @@ static void drm_pick_crtcs (drm_device_t *dev) break; } - /* No preferred mode, let's select another which should pick * the default 640x480 if nothing else is here. - * */ if (!des_mode || !(des_mode->flags & DRM_MODE_TYPE_PREFERRED)) { list_for_each_entry(des_mode, &output->modes, head) { @@ -887,13 +886,7 @@ clone: */ bool drm_initial_config(drm_device_t *dev, bool can_grow) { - /* do a hardcoded initial configuration here */ - struct drm_display_mode *des_mode = NULL; struct drm_output *output; - struct drm_framebuffer *fb; - drm_buffer_object_t *fbo; - unsigned long size, bytes_per_pixel; - int ret; drm_crtc_probe_output_modes(dev, 2048, 2048); @@ -905,42 +898,6 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) if (!output->crtc || !output->crtc->desired_mode) continue; - fb = drm_framebuffer_create(dev); - if (!fb) { - DRM_ERROR("failed to allocate fb.\n"); - return true; - } - output->crtc->fb = fb; - des_mode = output->crtc->desired_mode; - - if (des_mode->hdisplay > fb->width) - fb->width = des_mode->hdisplay; - if (des_mode->vdisplay > fb->height) - fb->height = des_mode->vdisplay; - - /* FIXME: multiple depths */ - bytes_per_pixel = 4; - fb->bits_per_pixel = 32; - fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8); - fb->depth = 24; - size = fb->width * fb->height * bytes_per_pixel; - /* FIXME - what about resizeable objects ??? */ - ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_PRIV0 | - DRM_BO_FLAG_NO_MOVE, - 0, 0, 0, - &fbo); - if (ret) { - printk(KERN_ERR "failed to allocate framebuffer\n"); - drm_framebuffer_destroy(fb); - continue; - } - fb->offset = fbo->offset; - fb->bo = fbo; - printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width, - fb->height, fbo->offset, fbo); dev->driver->fb_probe(dev, output->crtc); } drm_disable_unused_functions(dev); -- cgit v1.2.3 From f89458722173b364b8c3c27788b6c61889da554c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 18 May 2007 09:40:01 -0700 Subject: Add locking. The main lock is dev->mode_config.config_lock. It should be held across any operations that modify mode lists, crtc config, output config, etc. It should be taken at high level entry points (currently just initial config and user IOCTL). Seems to work ok on my system, but needs more testing (with lockdep) and review from some fresh eyes. --- linux-core/drm_crtc.c | 343 +++++++++++++++++++++++++++++--------------------- 1 file changed, 198 insertions(+), 145 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ab8b4688..e5a4b32b 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -39,8 +39,7 @@ * @ptr: object pointer, used to generate unique ID * * LOCKING: - * Process context (either init or calling process). Must take DRM mode_config - * lock around IDR allocation. + * Caller must hold DRM mode_config lock. * * Create a unique identifier based on @ptr in @dev's identifier space. Used * for tracking modes, CRTCs and outputs. @@ -59,15 +58,12 @@ again: return 0; } - spin_lock(&dev->mode_config.config_lock); - ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id); if (ret == -EAGAIN) { spin_unlock(&dev->mode_config.config_lock); goto again; } - spin_unlock(&dev->mode_config.config_lock); return new_id; } @@ -116,8 +112,7 @@ struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, * @dev: DRM device * * LOCKING: - * Process context (either init or calling process). Must take DRM mode_config - * lock around mode_config manipulation. + * Caller must hold mode config lock. * * Creates a new framebuffer objects and adds it to @dev's DRM mode_config. * @@ -128,27 +123,21 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) { struct drm_framebuffer *fb; - spin_lock(&dev->mode_config.config_lock); /* Limit to single framebuffer for now */ if (dev->mode_config.num_fb > 1) { spin_unlock(&dev->mode_config.config_lock); DRM_ERROR("Attempt to add multiple framebuffers failed\n"); return NULL; } - spin_unlock(&dev->mode_config.config_lock); fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL); - if (!fb) { - + if (!fb) return NULL; - } fb->id = drm_idr_get(dev, fb); fb->dev = dev; - 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; } @@ -159,8 +148,7 @@ EXPORT_SYMBOL(drm_framebuffer_create); * @fb: framebuffer to remove * * LOCKING: - * Process context (either init or calling process). Must take DRM mode_config - * lock around mode_config manipulation. + * Caller must hold mode config lock. * * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes * it, setting it to NULL. @@ -171,7 +159,6 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) struct drm_crtc *crtc; /* remove from any CRTC */ - spin_lock(&dev->mode_config.config_lock); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb == fb) crtc->fb = NULL; @@ -180,7 +167,6 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) drm_idr_put(dev, fb->id); list_del(&fb->head); dev->mode_config.num_fb--; - spin_unlock(&dev->mode_config.config_lock); kfree(fb); } @@ -191,8 +177,7 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) * @funcs: callbacks for the new CRTC * * LOCKING: - * Process context (either init or calling process). Must take DRM mode_config - * lock around mode_config manipulation. + * Caller must hold mode config lock. * * Creates a new CRTC object and adds it to @dev's mode_config structure. * @@ -213,10 +198,8 @@ struct drm_crtc *drm_crtc_create(drm_device_t *dev, crtc->id = drm_idr_get(dev, crtc); - 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; } @@ -227,8 +210,7 @@ EXPORT_SYMBOL(drm_crtc_create); * @crtc: CRTC to remove * * LOCKING: - * Process context (either init or calling process). Must take DRM mode_config - * lock around mode_config traversal. + * Caller must hold mode config lock. * * Cleanup @crtc. Calls @crtc's cleanup function, then removes @crtc from * its associated DRM device's mode_config. Frees it afterwards. @@ -240,11 +222,9 @@ void drm_crtc_destroy(struct drm_crtc *crtc) if (crtc->funcs->cleanup) (*crtc->funcs->cleanup)(crtc); - spin_lock(&dev->mode_config.config_lock); drm_idr_put(dev, crtc->id); list_del(&crtc->head); dev->mode_config.num_crtc--; - spin_unlock(&dev->mode_config.config_lock); kfree(crtc); } EXPORT_SYMBOL(drm_crtc_destroy); @@ -254,7 +234,7 @@ EXPORT_SYMBOL(drm_crtc_destroy); * @crtc: CRTC to check * * LOCKING: - * Caller? (FIXME) + * Caller must hold mode config lock. * * Walk @crtc's DRM device's mode_config and see if it's in use. * @@ -289,7 +269,7 @@ static struct drm_display_mode std_mode[] = { * @maxY: max height for modes * * LOCKING: - * Caller? (FIXME) + * Caller must hold mode config lock. * * Based on @dev's mode_config layout, scan all the outputs and try to detect * modes on them. Modes will first be added to the output's probed_modes @@ -379,7 +359,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) * @y: height of mode * * LOCKING: - * Caller? (FIXME) + * Caller must hold mode config lock. * * Try to set @mode on @crtc. Give @crtc and its associated outputs a chance * to fixup or reject the mode prior to trying to set it. @@ -497,7 +477,7 @@ EXPORT_SYMBOL(drm_crtc_set_mode); * @dev: DRM device * * LOCKING: - * Caller? (FIXME) + * Caller must hold mode config lock. * * If an output or CRTC isn't part of @dev's mode_config, it can be disabled * by calling its dpms function, which should power it off. @@ -524,17 +504,14 @@ void drm_disable_unused_functions(struct drm_device *dev) * @mode: mode data * * LOCKING: - * Process context (either init or calling process). Must take @output's - * mode_lock around mode list manipulation. + * Caller must hold mode config lock. * * Add @mode to @output's mode list for later use. */ void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode) { - spin_lock(&output->modes_lock); list_add(&mode->head, &output->probed_modes); - spin_unlock(&output->modes_lock); } EXPORT_SYMBOL(drm_mode_probed_add); @@ -544,16 +521,13 @@ EXPORT_SYMBOL(drm_mode_probed_add); * @mode: mode to remove * * LOCKING: - * Process context (either init or calling process). Must take @output's - * mode_lock around mode list manipulation. + * Caller must hold mode config lock. * * Remove @mode from @output's mode list, then free it. */ void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) { - spin_lock(&output->modes_lock); list_del(&mode->head); - spin_unlock(&output->modes_lock); kfree(mode); } EXPORT_SYMBOL(drm_mode_remove); @@ -565,8 +539,7 @@ EXPORT_SYMBOL(drm_mode_remove); * @name: user visible name of the output * * LOCKING: - * Process context (either init or calling process). Must take @dev's - * mode_config lock around mode list manipulation. + * Caller must hold @dev's mode_config lock. * * Creates a new drm_output structure and adds it to @dev's mode_config * structure. @@ -593,7 +566,6 @@ struct drm_output *drm_output_create(drm_device_t *dev, output->subpixel_order = SubPixelUnknown; INIT_LIST_HEAD(&output->probed_modes); INIT_LIST_HEAD(&output->modes); - spin_lock_init(&output->modes_lock); /* randr_output? */ /* output_set_monitor(output)? */ /* check for output_ignored(output)? */ @@ -614,9 +586,7 @@ EXPORT_SYMBOL(drm_output_create); * @output: output to remove * * LOCKING: - * Process context (either init or calling process). Must take @dev's - * mode_config lock around mode list manipulation. Caller must hold - * modes lock? (FIXME) + * Caller must hold @dev's mode_config lock. * * Call @output's cleanup function, then remove the output from the DRM * mode_config after freeing @output's modes. @@ -704,7 +674,7 @@ EXPORT_SYMBOL(drm_mode_create); * @mode: mode to remove * * LOCKING: - * None. + * Caller must hold mode config lock. * * Free @mode's unique identifier, then free it. */ @@ -786,7 +756,7 @@ out_err: * @dev: DRM device * * LOCKING: - * None. + * Caller must hold mode config lock. */ static void drm_pick_crtcs (drm_device_t *dev) { @@ -876,7 +846,7 @@ clone: * @can_grow: this configuration is growable * * LOCKING: - * Must take various locks. (FIXME) + * Called at init time, must take mode config lock. * * Scan the CRTCs and outputs and try to put together an initial setup. * At the moment, this is a cloned configuration across all heads with @@ -893,7 +863,9 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) struct drm_framebuffer *fb; drm_buffer_object_t *fbo; unsigned long size, bytes_per_pixel; - int ret; + int ret = false; + + spin_lock(&dev->mode_config.config_lock); drm_crtc_probe_output_modes(dev, 2048, 2048); @@ -908,7 +880,8 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) fb = drm_framebuffer_create(dev); if (!fb) { DRM_ERROR("failed to allocate fb.\n"); - return true; + ret = true; + goto out; } output->crtc->fb = fb; des_mode = output->crtc->desired_mode; @@ -945,7 +918,9 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } drm_disable_unused_functions(dev); - return false; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } EXPORT_SYMBOL(drm_initial_config); @@ -954,7 +929,7 @@ EXPORT_SYMBOL(drm_initial_config); * @dev: DRM device * * LOCKING: - * Caller? (FIXME) + * Caller must hold mode config lock. * * Free up all the outputs and CRTCs associated with this DRM device, then * free up the framebuffers and associated buffer objects. @@ -1001,7 +976,7 @@ EXPORT_SYMBOL(drm_mode_config_cleanup); * @fb: new framebuffer * * LOCKING: - * Caller? (FIXME) + * Caller must hold mode config lock. * * Setup a new configuration, provided by the user in @crtc_info, and enable * it. @@ -1144,7 +1119,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein * @arg: arg from ioctl * * LOCKING: - * Caller? (FIXME) + * Takes mode config lock. * * Construct a set of configuration description structures and return * them to the user, including CRTC, output and framebuffer configuration. @@ -1167,7 +1142,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, struct drm_crtc *crtc; struct drm_mode_modeinfo u_mode; struct drm_display_mode *mode; - int retcode = 0; + int ret = 0; int mode_count= 0; int output_count = 0; int crtc_count = 0; @@ -1176,6 +1151,8 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); + spin_lock(&dev->mode_config.config_lock); + list_for_each(lh, &dev->mode_config.fb_list) fb_count++; @@ -1191,8 +1168,10 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, list_for_each(lh, &dev->mode_config.usermode_list) mode_count++; - if (copy_from_user(&card_res, argp, sizeof(card_res))) - return -EFAULT; + if (copy_from_user(&card_res, argp, sizeof(card_res))) { + ret = -EFAULT; + goto out_unlock; + } if (card_res.count_modes == 0) { DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height); @@ -1212,7 +1191,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, copied = 0; list_for_each_entry(fb, &dev->mode_config.fb_list, head) { if (put_user(fb->id, &card_res.fb_id[copied++])) { - retcode = -EFAULT; + ret = -EFAULT; goto done; } } @@ -1225,7 +1204,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, 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; + ret = -EFAULT; goto done; } } @@ -1240,7 +1219,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, head) { DRM_DEBUG("OUTPUT ID is %d\n", output->id); if (put_user(output->id, &card_res.output_id[copied++])) { - retcode = -EFAULT; + ret = -EFAULT; goto done; } } @@ -1255,7 +1234,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, list_for_each_entry(mode, &output->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { - retcode = -EFAULT; + ret = -EFAULT; goto done; } } @@ -1264,7 +1243,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { drm_crtc_convert_to_umode(&u_mode, mode); if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { - retcode = -EFAULT; + ret = -EFAULT; goto done; } } @@ -1277,9 +1256,11 @@ done: card_res.count_modes); if (copy_to_user(argp, &card_res, sizeof(card_res))) - return -EFAULT; + ret = -EFAULT; - return retcode; +out_unlock: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1309,14 +1290,18 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, struct drm_crtc *crtc; struct drm_output *output; int ocount; - int retcode = 0; + int ret = 0; if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp))) return -EFAULT; + spin_lock(&dev->mode_config.config_lock); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id); - if (!crtc || (crtc->id != crtc_resp.crtc_id)) - return -EINVAL; + if (!crtc || (crtc->id != crtc_resp.crtc_id)) { + ret = -EINVAL; + goto out; + } + crtc_resp.x = crtc->x; crtc_resp.y = crtc->y; crtc_resp.fb_id = 1; @@ -1335,9 +1320,11 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, } if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp))) - return -EFAULT; + ret = -EFAULT; - return retcode; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1367,7 +1354,7 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, struct drm_output *output; struct drm_display_mode *mode; int mode_count = 0; - int retcode = 0; + int ret = 0; int copied = 0; int i; @@ -1375,9 +1362,13 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, return -EFAULT; DRM_DEBUG("output id %d:\n", out_resp.output); + + spin_lock(&dev->mode_config.config_lock); output= idr_find(&dev->mode_config.crtc_idr, out_resp.output); - if (!output || (output->id != out_resp.output)) - return -EINVAL; + if (!output || (output->id != out_resp.output)) { + ret = -EINVAL; + goto out_unlock; + } list_for_each_entry(mode, &output->modes, head) mode_count++; @@ -1402,14 +1393,14 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, copied = 0; list_for_each_entry(mode, &output->modes, head) { if (put_user(mode->mode_id, &out_resp.modes[copied++])) { - retcode = -EFAULT; + ret = -EFAULT; goto done; } } for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { if (output->user_mode_ids[i] != 0) if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) { - retcode = -EFAULT; + ret = -EFAULT; goto done; } } @@ -1419,9 +1410,11 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, done: if (copy_to_user(argp, &out_resp, sizeof(out_resp))) - return -EFAULT; + ret = -EFAULT; - return retcode; +out_unlock: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1452,26 +1445,28 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, struct drm_output **output_set = NULL, *output; struct drm_display_mode *mode; struct drm_framebuffer *fb = NULL; - int retcode = 0; + int ret = 0; int i; if (copy_from_user(&crtc_req, argp, sizeof(crtc_req))) return -EFAULT; + spin_lock(&dev->mode_config.config_lock); 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; + ret = -EINVAL; + goto out; } if (crtc_req.mode) { - /* if we have a mode we need a framebuffer */ if (crtc_req.fb_id) { fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id); if (!fb || (fb->id != crtc_req.fb_id)) { DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id); - return -EINVAL; + ret = -EINVAL; + goto out; } } mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode); @@ -1489,43 +1484,55 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, } DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req.mode, mode); - return -EINVAL; + ret = -EINVAL; + goto out; } } else mode = NULL; if (crtc_req.count_outputs == 0 && mode) { DRM_DEBUG("Count outputs is 0 but mode set\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } if (crtc_req.count_outputs > 0 && !mode && !fb) { DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req.count_outputs); - return -EINVAL; + ret = -EINVAL; + goto out; } if (crtc_req.count_outputs > 0) { u32 out_id; - output_set = kmalloc(crtc_req.count_outputs * sizeof(struct drm_output *), GFP_KERNEL); - if (!output_set) - return -ENOMEM; + output_set = kmalloc(crtc_req.count_outputs * + sizeof(struct drm_output *), GFP_KERNEL); + if (!output_set) { + ret = -ENOMEM; + goto out; + } for (i = 0; i < crtc_req.count_outputs; i++) { - if (get_user(out_id, &crtc_req.set_outputs[i])) - return -EFAULT; + if (get_user(out_id, &crtc_req.set_outputs[i])) { + ret = -EFAULT; + goto out; + } 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; + ret = -EINVAL; + goto out; } output_set[i] = output; } } - retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb); - return retcode; + ret = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb); + +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1536,7 +1543,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, * @arg: arg from ioctl * * LOCKING: - * Caller? (FIXME) + * Takes mode config lock. * * Add a new FB to the specified CRTC, given a user request. * @@ -1555,7 +1562,8 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; struct drm_buffer_object *bo; - int ret; + struct drm_crtc *crtc; + int ret = 0; if (copy_from_user(&r, argp, sizeof(r))) return -EFAULT; @@ -1569,17 +1577,22 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, return -EINVAL; } + spin_lock(&dev->mode_config.config_lock); /* TODO check limits are okay */ ret = drm_get_buffer_object(dev, &bo, r.handle); - if (ret || !bo) - return -EINVAL; + if (ret || !bo) { + ret = -EINVAL; + goto out; + } /* TODO check buffer is sufficently large */ /* TODO setup destructor callback */ fb = drm_framebuffer_create(dev); - if(!fb) - return -EINVAL;; + if (!fb) { + ret = -EINVAL; + goto out; + } fb->width = r.width; fb->height = r.height; @@ -1593,20 +1606,20 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, list_add(&fb->filp_head, &priv->fbs); - if (copy_to_user(argp, &r, sizeof(r))) - return -EFAULT; + if (copy_to_user(argp, &r, sizeof(r))) { + ret = -EFAULT; + goto out; + } - /* 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; - - dev->driver->fb_probe(dev, crtc); - } + /* FIXME: bind the fb to the right crtc */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + crtc->fb = fb; + dev->driver->fb_probe(dev, crtc); } - return 0; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1617,7 +1630,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, * @arg: arg from ioctl * * LOCKING: - * Caller? (FIXME) + * Takes mode config lock. * * Remove the FB specified by the user. * @@ -1633,12 +1646,15 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, drm_device_t *dev = priv->head->dev; struct drm_framebuffer *fb = 0; uint32_t id = arg; + int ret = 0; + spin_lock(&dev->mode_config.config_lock); 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; + ret = -EINVAL; + goto out; } dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); @@ -1650,7 +1666,9 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, drm_framebuffer_destroy(fb); - return 0; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1678,14 +1696,17 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, struct drm_mode_fb_cmd __user *argp = (void __user *)arg; struct drm_mode_fb_cmd r; struct drm_framebuffer *fb; + int ret = 0; if (copy_from_user(&r, argp, sizeof(r))) return -EFAULT; + spin_lock(&dev->mode_config.config_lock); fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); if (!fb || (r.buffer_id != fb->id)) { DRM_ERROR("invalid framebuffer id\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } r.height = fb->height; @@ -1696,9 +1717,11 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, r.pitch = fb->pitch; if (copy_to_user(argp, &r, sizeof(r))) - return -EFAULT; + ret = -EFAULT; - return 0; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1706,7 +1729,7 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, * @filp: file * from the ioctl * * LOCKING: - * Caller? (FIXME) + * Takes mode config lock. * * Destroy all the FBs associated with @filp. * @@ -1721,11 +1744,13 @@ void drm_fb_release(struct file *filp) drm_device_t *dev = priv->head->dev; struct drm_framebuffer *fb, *tfb; + spin_lock(&dev->mode_config.config_lock); list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { list_del(&fb->filp_head); dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); drm_framebuffer_destroy(fb); } + spin_unlock(&dev->mode_config.config_lock); } /** @@ -1751,28 +1776,32 @@ int drm_mode_addmode(struct inode *inode, struct file *filp, struct drm_mode_modeinfo __user *argp = (void __user *)arg; struct drm_mode_modeinfo new_mode; struct drm_display_mode *user_mode; + int ret = 0; if (copy_from_user(&new_mode, argp, sizeof(new_mode))) return -EFAULT; + spin_lock(&dev->mode_config.config_lock); user_mode = drm_mode_create(dev); - if (!user_mode) - return -ENOMEM; + if (!user_mode) { + ret = -ENOMEM; + goto out; + } drm_crtc_convert_umode(user_mode, &new_mode); user_mode->type |= DRM_MODE_TYPE_USERDEF; user_mode->output_count = 0; - spin_lock(&dev->mode_config.config_lock); list_add(&user_mode->head, &dev->mode_config.usermode_list); - spin_unlock(&dev->mode_config.config_lock); new_mode.id = user_mode->mode_id; if (copy_to_user(argp, &new_mode, sizeof(new_mode))) - return -EFAULT; + ret = -EFAULT; - return 0; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } /** @@ -1796,29 +1825,37 @@ int drm_mode_rmmode(struct inode *inode, struct file *filp, drm_device_t *dev = priv->head->dev; uint32_t id = arg; struct drm_display_mode *mode, *t; - int retcode = -EINVAL; + int ret = -EINVAL; + spin_lock(&dev->mode_config.config_lock); mode = idr_find(&dev->mode_config.crtc_idr, id); - if (!mode || (id != mode->mode_id)) - return -EINVAL; + if (!mode || (id != mode->mode_id)) { + ret = -EINVAL; + goto out; + } - if (!(mode->type & DRM_MODE_TYPE_USERDEF)) - return -EINVAL; + if (!(mode->type & DRM_MODE_TYPE_USERDEF)) { + ret = -EINVAL; + goto out; + } - if (mode->output_count) - return -EINVAL; + if (mode->output_count) { + ret = -EINVAL; + goto out; + } - spin_lock(&dev->mode_config.config_lock); list_for_each_entry(t, &dev->mode_config.usermode_list, head) { if (t == mode) { list_del(&mode->head); drm_mode_destroy(dev, mode); - retcode = 0; + ret = 0; break; } } + +out: spin_unlock(&dev->mode_config.config_lock); - return retcode; + return ret; } /** @@ -1843,18 +1880,24 @@ int drm_mode_attachmode(struct inode *inode, struct file *filp, struct drm_mode_mode_cmd mode_cmd; struct drm_output *output; struct drm_display_mode *mode; - int i; + int i, ret = 0; if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) return -EFAULT; + spin_lock(&dev->mode_config.config_lock); + mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id); - if (!mode || (mode->mode_id != mode_cmd.mode_id)) - return -EINVAL; + 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)) - return -EINVAL; + if (!output || (output->id != mode_cmd.output_id)) { + ret = -EINVAL; + goto out; + } for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { if (output->user_mode_ids[i] == 0) { @@ -1865,9 +1908,11 @@ int drm_mode_attachmode(struct inode *inode, struct file *filp, } if (i == DRM_OUTPUT_MAX_UMODES) - return -ENOSPC; + ret = -ENOSPC; - return 0; +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } @@ -1892,18 +1937,24 @@ int drm_mode_detachmode(struct inode *inode, struct file *filp, struct drm_mode_mode_cmd mode_cmd; struct drm_output *output; struct drm_display_mode *mode; - int i, found = 0; + int i, found = 0, ret = 0; if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) return -EFAULT; + spin_lock(&dev->mode_config.config_lock); + mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id); - if (!mode || (mode->mode_id != mode_cmd.mode_id)) - return -EINVAL; + 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)) - return -EINVAL; + if (!output || (output->id != mode_cmd.output_id)) { + ret = -EINVAL; + goto out; + } for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { @@ -1915,7 +1966,9 @@ int drm_mode_detachmode(struct inode *inode, struct file *filp, } if (!found) - return -EINVAL; - - return 0; + ret = -EINVAL; + +out: + spin_unlock(&dev->mode_config.config_lock); + return ret; } -- cgit v1.2.3 From e79e2a58161d44754fd55507e155b7e12a09c4d2 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 28 Jun 2007 21:25:13 +0100 Subject: Fix type/flags usage problem to check for preferred modes. Add more debugging to help diagnose problems. --- linux-core/drm_crtc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 245fe5be..04d3b723 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -436,8 +436,11 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, */ crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (output->crtc == crtc) + if (output->crtc == crtc) { + dev_warn(&output->dev->pdev->dev, "%s: set mode %s\n", + output->name, mode->name); output->funcs->mode_set(output, mode, adjusted_mode); + } } /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ @@ -787,16 +790,14 @@ static void drm_pick_crtcs (drm_device_t *dev) des_mode = NULL; list_for_each_entry(des_mode, &output->modes, head) { - if (des_mode->flags & DRM_MODE_TYPE_PREFERRED) + if (des_mode->type & DRM_MODE_TYPE_PREFERRED) break; } - /* No preferred mode, let's select another which should pick - * the default 640x480 if nothing else is here. - */ - if (!des_mode || !(des_mode->flags & DRM_MODE_TYPE_PREFERRED)) { + /* No preferred mode, let's just select the first available */ + if (!des_mode || !(des_mode->type & DRM_MODE_TYPE_PREFERRED)) { list_for_each_entry(des_mode, &output->modes, head) { - if (des_mode->flags & DRM_MODE_TYPE_DEFAULT) + if (des_mode) break; } } -- cgit v1.2.3 From 14c49df06bb0b1adc0fa2a9bd575c454d39c7cf0 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 29 Jun 2007 20:14:09 +0100 Subject: merge fixes --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 04d3b723..65ccc870 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -912,7 +912,7 @@ void drm_mode_config_cleanup(drm_device_t *dev) /* If this FB was the kernel one, free it */ if (fb->bo->type == drm_bo_type_kernel) { mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(fb->bo); + drm_bo_usage_deref_locked(&fb->bo); mutex_unlock(&dev->struct_mutex); } drm_framebuffer_destroy(fb); -- cgit v1.2.3 From 43c9abdedc88807a40034513de842d6eeb8c3ed2 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 19 Jul 2007 16:58:23 +0200 Subject: Fix unlocking of spinlock when we should not --- linux-core/drm_crtc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 65ccc870..0ede1571 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -59,10 +59,8 @@ again: } ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id); - if (ret == -EAGAIN) { - spin_unlock(&dev->mode_config.config_lock); - goto again; - } + if (ret == -EAGAIN) + goto again; return new_id; } -- cgit v1.2.3 From 9ccb8440f393a395941b211ee87d9addcfa6d69a Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 20 Jul 2007 11:36:57 +0200 Subject: Changed mode config spinlock to mutex --- linux-core/drm_crtc.c | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 0ede1571..df00a7d2 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -123,7 +123,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) /* Limit to single framebuffer for now */ if (dev->mode_config.num_fb > 1) { - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); DRM_ERROR("Attempt to add multiple framebuffers failed\n"); return NULL; } @@ -572,11 +572,11 @@ struct drm_output *drm_output_create(drm_device_t *dev, /* output_set_monitor(output)? */ /* check for output_ignored(output)? */ - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); list_add_tail(&output->head, &dev->mode_config.output_list); dev->mode_config.num_output++; - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return output; @@ -607,10 +607,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->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); drm_idr_put(dev, output->id); list_del(&output->head); - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); kfree(output); } EXPORT_SYMBOL(drm_output_destroy); @@ -700,7 +700,7 @@ EXPORT_SYMBOL(drm_mode_destroy); */ void drm_mode_config_init(drm_device_t *dev) { - spin_lock_init(&dev->mode_config.config_lock); + mutex_init(&dev->mode_config.mutex); INIT_LIST_HEAD(&dev->mode_config.fb_list); INIT_LIST_HEAD(&dev->mode_config.crtc_list); INIT_LIST_HEAD(&dev->mode_config.output_list); @@ -858,7 +858,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) struct drm_output *output; int ret = false; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); drm_crtc_probe_output_modes(dev, 2048, 2048); @@ -874,7 +874,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow) } drm_disable_unused_functions(dev); - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } EXPORT_SYMBOL(drm_initial_config); @@ -1107,7 +1107,7 @@ int drm_mode_getresources(struct inode *inode, struct file *filp, memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); list_for_each(lh, &dev->mode_config.fb_list) fb_count++; @@ -1215,7 +1215,7 @@ done: ret = -EFAULT; out_unlock: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1251,7 +1251,7 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp))) return -EFAULT; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id); if (!crtc || (crtc->id != crtc_resp.crtc_id)) { ret = -EINVAL; @@ -1279,7 +1279,7 @@ int drm_mode_getcrtc(struct inode *inode, struct file *filp, ret = -EFAULT; out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1319,7 +1319,7 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp, DRM_DEBUG("output id %d:\n", out_resp.output); - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); output= idr_find(&dev->mode_config.crtc_idr, out_resp.output); if (!output || (output->id != out_resp.output)) { ret = -EINVAL; @@ -1369,7 +1369,7 @@ done: ret = -EFAULT; out_unlock: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1407,7 +1407,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, if (copy_from_user(&crtc_req, argp, sizeof(crtc_req))) return -EFAULT; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); 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); @@ -1487,7 +1487,7 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp, ret = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb); out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1533,7 +1533,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, return -EINVAL; } - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); /* TODO check limits are okay */ ret = drm_get_buffer_object(dev, &bo, r.handle); if (ret || !bo) { @@ -1574,7 +1574,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp, } out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1604,7 +1604,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, uint32_t id = arg; int ret = 0; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); fb = idr_find(&dev->mode_config.crtc_idr, id); /* TODO check that we realy get a framebuffer back. */ if (!fb || (id != fb->id)) { @@ -1623,7 +1623,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp, drm_framebuffer_destroy(fb); out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1657,7 +1657,7 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, if (copy_from_user(&r, argp, sizeof(r))) return -EFAULT; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); if (!fb || (r.buffer_id != fb->id)) { DRM_ERROR("invalid framebuffer id\n"); @@ -1676,7 +1676,7 @@ int drm_mode_getfb(struct inode *inode, struct file *filp, ret = -EFAULT; out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1700,13 +1700,13 @@ void drm_fb_release(struct file *filp) drm_device_t *dev = priv->head->dev; struct drm_framebuffer *fb, *tfb; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { list_del(&fb->filp_head); dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); drm_framebuffer_destroy(fb); } - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); } /** @@ -1737,7 +1737,7 @@ int drm_mode_addmode(struct inode *inode, struct file *filp, if (copy_from_user(&new_mode, argp, sizeof(new_mode))) return -EFAULT; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); user_mode = drm_mode_create(dev); if (!user_mode) { ret = -ENOMEM; @@ -1756,7 +1756,7 @@ int drm_mode_addmode(struct inode *inode, struct file *filp, ret = -EFAULT; out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1783,7 +1783,7 @@ int drm_mode_rmmode(struct inode *inode, struct file *filp, struct drm_display_mode *mode, *t; int ret = -EINVAL; - spin_lock(&dev->mode_config.config_lock); + mutex_lock(&dev->mode_config.mutex); mode = idr_find(&dev->mode_config.crtc_idr, id); if (!mode || (id != mode->mode_id)) { ret = -EINVAL; @@ -1810,7 +1810,7 @@ int drm_mode_rmmode(struct inode *inode, struct file *filp, } out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1841,7 +1841,7 @@ int drm_mode_attachmode(struct inode *inode, struct file *filp, if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) return -EFAULT; - spin_lock(&dev->mode_config.config_lock); + 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)) { @@ -1867,7 +1867,7 @@ int drm_mode_attachmode(struct inode *inode, struct file *filp, ret = -ENOSPC; out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1898,7 +1898,7 @@ int drm_mode_detachmode(struct inode *inode, struct file *filp, if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) return -EFAULT; - spin_lock(&dev->mode_config.config_lock); + 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)) { @@ -1925,6 +1925,6 @@ int drm_mode_detachmode(struct inode *inode, struct file *filp, ret = -EINVAL; out: - spin_unlock(&dev->mode_config.config_lock); + mutex_unlock(&dev->mode_config.mutex); return ret; } -- cgit v1.2.3 From dfcf9272ce4427d959098b0f9e1748832a47a786 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 26 Sep 2007 15:40:40 +0100 Subject: no need to copy to/from user as the unlocked ioctl does that for us. other small cleanups. --- linux-core/drm_crtc.c | 365 +++++++++++++++++++++++--------------------------- 1 file changed, 164 insertions(+), 201 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ed5f1dfa..fcddc7d9 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -433,24 +433,31 @@ 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->mode_config.output_list, head) { - if (output->crtc == crtc) { - dev_warn(&output->dev->pdev->dev, "%s: set mode %s\n", - output->name, mode->name); - output->funcs->mode_set(output, mode, adjusted_mode); - } + + if (output->crtc != crtc) + continue; + + DRM_INFO("%s: set mode %s\n", output->name, mode->name); + + 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->mode_config.output_list, head) { - if (output->crtc == crtc) { - output->funcs->commit(output); + + if (output->crtc != crtc) + continue; + + output->funcs->commit(output); + #if 0 // TODO def RANDR_12_INTERFACE - if (output->randr_output) - RRPostPendingProperties (output->randr_output); + if (output->randr_output) + RRPostPendingProperties (output->randr_output); #endif - } } /* XXX free adjustedmode */ @@ -762,7 +769,7 @@ out_err: */ static void drm_pick_crtcs (struct drm_device *dev) { - int c, o; + int c, o, assigned; struct drm_output *output, *output_equal; struct drm_crtc *crtc; struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; @@ -802,11 +809,26 @@ static void drm_pick_crtcs (struct drm_device *dev) c = -1; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + assigned = 0; + c++; if ((output->possible_crtcs & (1 << c)) == 0) continue; -#if 0 /* should we try and clone ?? - code not tested - FIXME */ + list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { + if (output->id == output_equal->id) + continue; + + /* Find out if crtc has been assigned before */ + if (output_equal->crtc == crtc) + assigned = 1; + } + +#if 1 /* continue for now */ + if (assigned) + continue; +#endif + o = -1; list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { o++; @@ -816,7 +838,9 @@ static void drm_pick_crtcs (struct drm_device *dev) list_for_each_entry(modes, &output->modes, head) { list_for_each_entry(modes_equal, &output_equal->modes, head) { if (drm_mode_equal (modes, modes_equal)) { - if ((output->possible_clones & (1 << o))) { + if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { + printk("Cloning %s (0x%lx) to %s (0x%lx)\n",output->name,output->possible_clones,output_equal->name,output_equal->possible_clones); + assigned = 0; goto clone; } } @@ -825,7 +849,10 @@ static void drm_pick_crtcs (struct drm_device *dev) } clone: -#endif + /* crtc has been assigned skip it */ + if (assigned) + continue; + /* Found a CRTC to attach to, do it ! */ output->crtc = crtc; output->crtc->desired_mode = des_mode; @@ -856,6 +883,7 @@ clone: bool drm_initial_config(struct drm_device *dev, bool can_grow) { struct drm_output *output; + struct drm_crtc *crtc; int ret = false; mutex_lock(&dev->mode_config.mutex); @@ -864,14 +892,31 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow) drm_pick_crtcs(dev); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + /* can't setup the crtc if there's no assigned mode */ + if (!crtc->desired_mode) + continue; + + /* Now setup the fbdev for attached crtcs */ + dev->driver->fb_probe(dev, crtc); + } + + /* This is a little screwy, as we've already walked the outputs + * above, but it's a little bit of magic too. There's the potential + * for things not to get setup above if an existing device gets + * re-assigned thus confusing the hardware. By walking the outputs + * this fixes up their crtc's. + */ list_for_each_entry(output, &dev->mode_config.output_list, head) { - /* can't setup the output if there's no assigned crtc or mode */ + /* can't setup the output if there's no assigned mode */ if (!output->crtc || !output->crtc->desired_mode) continue; - dev->driver->fb_probe(dev, output->crtc); + drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); } + drm_disable_unused_functions(dev); mutex_unlock(&dev->mode_config.mutex); @@ -1088,8 +1133,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein int drm_mode_getresources(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_card_res __user *argp = (void __user *)data; - struct drm_mode_card_res card_res; + struct drm_mode_card_res *card_res = data; struct list_head *lh; struct drm_framebuffer *fb; struct drm_output *output; @@ -1122,12 +1166,7 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each(lh, &dev->mode_config.usermode_list) mode_count++; - if (copy_from_user(&card_res, argp, sizeof(card_res))) { - ret = -EFAULT; - goto out_unlock; - } - - if (card_res.count_modes == 0) { + 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; @@ -1141,78 +1180,58 @@ int drm_mode_getresources(struct drm_device *dev, /* handle this in 4 parts */ /* FBs */ - if (card_res.count_fbs >= fb_count) { + if (card_res->count_fbs >= fb_count) { copied = 0; list_for_each_entry(fb, &dev->mode_config.fb_list, head) { - if (put_user(fb->id, &card_res.fb_id[copied++])) { - ret = -EFAULT; - goto done; - } + card_res->fb_id[copied++] = fb->id; } } - card_res.count_fbs = fb_count; + card_res->count_fbs = fb_count; /* CRTCs */ - if (card_res.count_crtcs >= crtc_count) { + if (card_res->count_crtcs >= crtc_count) { copied = 0; 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++])) { - ret = -EFAULT; - goto done; - } + card_res->crtc_id[copied++] = crtc->id; } } - card_res.count_crtcs = crtc_count; + card_res->count_crtcs = crtc_count; /* Outputs */ - if (card_res.count_outputs >= output_count) { + if (card_res->count_outputs >= output_count) { copied = 0; 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++])) { - ret = -EFAULT; - goto done; - } + card_res->output_id[copied++] = output->id; } } - card_res.count_outputs = output_count; + card_res->count_outputs = output_count; /* Modes */ - if (card_res.count_modes >= mode_count) { + if (card_res->count_modes >= mode_count) { copied = 0; 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); - if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { - ret = -EFAULT; - goto done; - } + card_res->modes[copied++] = u_mode; } } /* add in user modes */ list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { drm_crtc_convert_to_umode(&u_mode, mode); - if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { - ret = -EFAULT; - goto done; - } + card_res->modes[copied++] = u_mode; } } - card_res.count_modes = mode_count; + card_res->count_modes = mode_count; -done: - DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs, - card_res.count_outputs, - card_res.count_modes); + DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, + card_res->count_outputs, + card_res->count_modes); - if (copy_to_user(argp, &card_res, sizeof(card_res))) - ret = -EFAULT; - -out_unlock: mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1237,43 +1256,36 @@ out_unlock: int drm_mode_getcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_crtc __user *argp = (void __user *)data; - struct drm_mode_crtc crtc_resp; + struct drm_mode_crtc *crtc_resp = data; struct drm_crtc *crtc; struct drm_output *output; int ocount; int ret = 0; - if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp))) - return -EFAULT; - mutex_lock(&dev->mode_config.mutex); - crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id); - if (!crtc || (crtc->id != crtc_resp.crtc_id)) { + crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp->crtc_id); + if (!crtc || (crtc->id != crtc_resp->crtc_id)) { ret = -EINVAL; goto out; } - crtc_resp.x = crtc->x; - crtc_resp.y = crtc->y; - crtc_resp.fb_id = 1; + crtc_resp->x = crtc->x; + crtc_resp->y = crtc->y; + crtc_resp->fb_id = 1; - crtc_resp.outputs = 0; + crtc_resp->outputs = 0; if (crtc->enabled) { - crtc_resp.mode = crtc->mode.mode_id; + crtc_resp->mode = crtc->mode.mode_id; ocount = 0; list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc == crtc) - crtc_resp.outputs |= 1 << (ocount++); + crtc_resp->outputs |= 1 << (ocount++); } } else { - crtc_resp.mode = 0; + crtc_resp->mode = 0; } - if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp))) - ret = -EFAULT; - out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1299,8 +1311,7 @@ out: int drm_mode_getoutput(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_get_output __user *argp = (void __user *)data; - struct drm_mode_get_output out_resp; + struct drm_mode_get_output *out_resp = data; struct drm_output *output; struct drm_display_mode *mode; int mode_count = 0; @@ -1308,16 +1319,13 @@ int drm_mode_getoutput(struct drm_device *dev, int copied = 0; int i; - if (copy_from_user(&out_resp, argp, sizeof(out_resp))) - return -EFAULT; - - DRM_DEBUG("output id %d:\n", out_resp.output); + DRM_DEBUG("output id %d:\n", out_resp->output); mutex_lock(&dev->mode_config.mutex); - output= idr_find(&dev->mode_config.crtc_idr, out_resp.output); - if (!output || (output->id != out_resp.output)) { + output= idr_find(&dev->mode_config.crtc_idr, out_resp->output); + if (!output || (output->id != out_resp->output)) { ret = -EINVAL; - goto out_unlock; + goto done; } list_for_each_entry(mode, &output->modes, head) @@ -1327,42 +1335,32 @@ int drm_mode_getoutput(struct drm_device *dev, if (output->user_mode_ids[i] != 0) mode_count++; - strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN); - out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0; + 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; - out_resp.connection = output->status; + out_resp->mm_width = output->mm_width; + out_resp->mm_height = output->mm_height; + out_resp->subpixel = output->subpixel_order; + out_resp->connection = output->status; if (output->crtc) - out_resp.crtc = output->crtc->id; + out_resp->crtc = output->crtc->id; else - out_resp.crtc = 0; + out_resp->crtc = 0; - if ((out_resp.count_modes >= mode_count) && 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++])) { - ret = -EFAULT; - goto done; - } + out_resp->modes[copied++] = mode->mode_id; } for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { if (output->user_mode_ids[i] != 0) - if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) { - ret = -EFAULT; - goto done; - } + out_resp->modes[copied++] = output->user_mode_ids[i]; } } - out_resp.count_modes = mode_count; + out_resp->count_modes = mode_count; done: - if (copy_to_user(argp, &out_resp, sizeof(out_resp))) - ret = -EFAULT; - -out_unlock: mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1387,8 +1385,7 @@ out_unlock: int drm_mode_setcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_crtc __user *argp = (void __user *)data; - struct drm_mode_crtc crtc_req; + struct drm_mode_crtc *crtc_req = data; struct drm_crtc *crtc; struct drm_output **output_set = NULL, *output; struct drm_display_mode *mode; @@ -1396,29 +1393,26 @@ int drm_mode_setcrtc(struct drm_device *dev, int ret = 0; int i; - if (copy_from_user(&crtc_req, argp, sizeof(crtc_req))) - return -EFAULT; - mutex_lock(&dev->mode_config.mutex); - 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); + 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); ret = -EINVAL; goto out; } - if (crtc_req.mode) { + if (crtc_req->mode) { /* if we have a mode we need a framebuffer */ - if (crtc_req.fb_id) { - fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id); - if (!fb || (fb->id != crtc_req.fb_id)) { - DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id); + if (crtc_req->fb_id) { + fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id); + if (!fb || (fb->id != crtc_req->fb_id)) { + DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id); ret = -EINVAL; goto out; } } - mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode); - if (!mode || (mode->mode_id != 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, @@ -1431,36 +1425,36 @@ int drm_mode_setcrtc(struct drm_device *dev, } } - DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req.mode, mode); + DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req->mode, mode); ret = -EINVAL; goto out; } } 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"); ret = -EINVAL; goto out; } - if (crtc_req.count_outputs > 0 && !mode && !fb) { - DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req.count_outputs); + if (crtc_req->count_outputs > 0 && !mode && !fb) { + DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs); ret = -EINVAL; goto out; } - if (crtc_req.count_outputs > 0) { + if (crtc_req->count_outputs > 0) { u32 out_id; - output_set = kmalloc(crtc_req.count_outputs * + output_set = kmalloc(crtc_req->count_outputs * sizeof(struct drm_output *), GFP_KERNEL); if (!output_set) { ret = -ENOMEM; goto out; } - for (i = 0; i < crtc_req.count_outputs; i++) { - if (get_user(out_id, &crtc_req.set_outputs[i])) { + for (i = 0; i < crtc_req->count_outputs; i++) { + if (get_user(out_id, &crtc_req->set_outputs[i])) { ret = -EFAULT; goto out; } @@ -1476,7 +1470,7 @@ int drm_mode_setcrtc(struct drm_device *dev, } } - ret = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb); + ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); out: mutex_unlock(&dev->mode_config.mutex); @@ -1503,29 +1497,25 @@ out: int drm_mode_addfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_fb_cmd __user *argp = (void __user *)data; - struct drm_mode_fb_cmd r; + struct drm_mode_fb_cmd *r = data; struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; struct drm_buffer_object *bo; struct drm_crtc *crtc; int ret = 0; - if (copy_from_user(&r, argp, sizeof(r))) - return -EFAULT; - - if ((config->min_width > r.width) || (r.width > config->max_width)) { + 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)) { + if ((config->min_height > r->height) || (r->height > config->max_height)) { DRM_ERROR("mode new framebuffer height not within limits\n"); return -EINVAL; } mutex_lock(&dev->mode_config.mutex); /* TODO check limits are okay */ - ret = drm_get_buffer_object(dev, &bo, r.handle); + ret = drm_get_buffer_object(dev, &bo, r->handle); if (ret || !bo) { ret = -EINVAL; goto out; @@ -1540,23 +1530,18 @@ int drm_mode_addfb(struct drm_device *dev, goto out; } - fb->width = r.width; - fb->height = r.height; - fb->pitch = r.pitch; - fb->bits_per_pixel = r.bpp; - fb->depth = r.depth; + fb->width = r->width; + fb->height = r->height; + fb->pitch = r->pitch; + fb->bits_per_pixel = r->bpp; + fb->depth = r->depth; fb->offset = bo->offset; fb->bo = bo; - r.buffer_id = fb->id; + r->buffer_id = fb->id; list_add(&fb->filp_head, &file_priv->fbs); - if (copy_to_user(argp, &r, sizeof(r))) { - ret = -EFAULT; - goto out; - } - /* FIXME: bind the fb to the right crtc */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { crtc->fb = fb; @@ -1589,13 +1574,12 @@ int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_framebuffer *fb = 0; - uint32_t id = data; + uint32_t *id = data; int ret = 0; - mutex_lock(&dev->mode_config.mutex); - fb = idr_find(&dev->mode_config.crtc_idr, id); + fb = idr_find(&dev->mode_config.crtc_idr, *id); /* TODO check that we realy get a framebuffer back. */ - if (!fb || (id != fb->id)) { + if (!fb || (*id != fb->id)) { DRM_ERROR("mode invalid framebuffer id\n"); ret = -EINVAL; goto out; @@ -1635,31 +1619,24 @@ out: int drm_mode_getfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_fb_cmd __user *argp = (void __user *)data; - struct drm_mode_fb_cmd r; + struct drm_mode_fb_cmd *r = data; struct drm_framebuffer *fb; int ret = 0; - if (copy_from_user(&r, argp, sizeof(r))) - return -EFAULT; - mutex_lock(&dev->mode_config.mutex); - fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); - if (!fb || (r.buffer_id != fb->id)) { + fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id); + if (!fb || (r->buffer_id != fb->id)) { DRM_ERROR("invalid framebuffer id\n"); ret = -EINVAL; goto out; } - r.height = fb->height; - r.width = fb->width; - r.depth = fb->depth; - r.bpp = fb->bits_per_pixel; - r.handle = fb->bo->base.hash.key; - r.pitch = fb->pitch; - - if (copy_to_user(argp, &r, sizeof(r))) - ret = -EFAULT; + r->height = fb->height; + r->width = fb->width; + r->depth = fb->depth; + r->bpp = fb->bits_per_pixel; + r->handle = fb->bo->base.hash.key; + r->pitch = fb->pitch; out: mutex_unlock(&dev->mode_config.mutex); @@ -1713,14 +1690,10 @@ void drm_fb_release(struct file *filp) int drm_mode_addmode(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_modeinfo __user *argp = (void __user *)data; - struct drm_mode_modeinfo new_mode; + struct drm_mode_modeinfo *new_mode = data; struct drm_display_mode *user_mode; int ret = 0; - if (copy_from_user(&new_mode, argp, sizeof(new_mode))) - return -EFAULT; - mutex_lock(&dev->mode_config.mutex); user_mode = drm_mode_create(dev); if (!user_mode) { @@ -1728,16 +1701,14 @@ int drm_mode_addmode(struct drm_device *dev, goto out; } - drm_crtc_convert_umode(user_mode, &new_mode); + 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); - new_mode.id = user_mode->mode_id; - if (copy_to_user(argp, &new_mode, sizeof(new_mode))) - ret = -EFAULT; + new_mode->id = user_mode->mode_id; out: mutex_unlock(&dev->mode_config.mutex); @@ -1761,13 +1732,13 @@ out: int drm_mode_rmmode(struct drm_device *dev, void *data, struct drm_file *file_priv) { - uint32_t id = (uint32_t)data; + uint32_t *id = data; struct drm_display_mode *mode, *t; int ret = -EINVAL; mutex_lock(&dev->mode_config.mutex); - mode = idr_find(&dev->mode_config.crtc_idr, id); - if (!mode || (id != mode->mode_id)) { + mode = idr_find(&dev->mode_config.crtc_idr, *id); + if (!mode || (*id != mode->mode_id)) { ret = -EINVAL; goto out; } @@ -1812,25 +1783,21 @@ out: int drm_mode_attachmode(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_mode_cmd __user *argp = (void __user *)data; - struct drm_mode_mode_cmd mode_cmd; + struct drm_mode_mode_cmd *mode_cmd = data; struct drm_output *output; struct drm_display_mode *mode; int i, ret = 0; - if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) - return -EFAULT; - 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)) { + 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)) { + output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); + if (!output || (output->id != mode_cmd->output_id)) { ret = -EINVAL; goto out; } @@ -1867,25 +1834,21 @@ out: int drm_mode_detachmode(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_mode_cmd __user *argp = (void __user *)data; - struct drm_mode_mode_cmd mode_cmd; + struct drm_mode_mode_cmd *mode_cmd = data; struct drm_output *output; struct drm_display_mode *mode; int i, found = 0, ret = 0; - if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) - return -EFAULT; - 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)) { + 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)) { + output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); + if (!output || (output->id != mode_cmd->output_id)) { ret = -EINVAL; goto out; } -- cgit v1.2.3 From cc9be8ac323e47616e48adebc5cc85c654524b45 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Mon, 15 Oct 2007 11:51:19 +0100 Subject: Fix some buffer teardown problems. --- linux-core/drm_crtc.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fcddc7d9..bdea20c9 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -951,14 +951,10 @@ void drm_mode_config_cleanup(struct drm_device *dev) } list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { - dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); - /* If this FB was the kernel one, free it */ - if (fb->bo->type == drm_bo_type_kernel) { - mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(&fb->bo); - mutex_unlock(&dev->struct_mutex); - } - drm_framebuffer_destroy(fb); + if (fb->bo->type != drm_bo_type_kernel) + drm_framebuffer_destroy(fb); + else + dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); } list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { @@ -1585,14 +1581,15 @@ int drm_mode_rmfb(struct drm_device *dev, goto out; } - dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); - /* TODO check if we own the buffer */ /* TODO release all crtc connected to the framebuffer */ /* bind the fb to the crtc for now */ /* TODO unhock the destructor from the buffer object */ - drm_framebuffer_destroy(fb); + if (fb->bo->type != drm_bo_type_kernel) + drm_framebuffer_destroy(fb); + else + dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); out: mutex_unlock(&dev->mode_config.mutex); @@ -1666,8 +1663,10 @@ void drm_fb_release(struct file *filp) mutex_lock(&dev->mode_config.mutex); list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { list_del(&fb->filp_head); - dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); - drm_framebuffer_destroy(fb); + if (fb->bo->type != drm_bo_type_kernel) + drm_framebuffer_destroy(fb); + else + dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); } mutex_unlock(&dev->mode_config.mutex); } -- cgit v1.2.3 From 198170ab97bbf2ca6362bb7100e9ed86d90aa51f Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 23 Oct 2007 15:33:20 +0100 Subject: Need fb attached --- linux-core/drm_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bdea20c9..5bc02206 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -914,7 +914,9 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow) if (!output->crtc || !output->crtc->desired_mode) continue; - drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); + /* and needs an attached fb */ + if (output->crtc->fb) + drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); } drm_disable_unused_functions(dev); -- cgit v1.2.3 From 71385d6f75bb3b551e2f8d9f74a4438f0f3da9df Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Mon, 5 Nov 2007 10:03:26 +0000 Subject: add missing lock --- linux-core/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 5bc02206..cad7cd83 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1575,6 +1575,7 @@ int drm_mode_rmfb(struct drm_device *dev, uint32_t *id = data; int ret = 0; + mutex_lock(&dev->mode_config.mutex); fb = idr_find(&dev->mode_config.crtc_idr, *id); /* TODO check that we realy get a framebuffer back. */ if (!fb || (*id != fb->id)) { -- cgit v1.2.3 From 2520d3fd99636e493060d51b1c3287a5faac22bf Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 15 Nov 2007 16:52:04 +1100 Subject: modes: pass type to userspace for preferred showing --- linux-core/drm_crtc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index cad7cd83..5b00c115 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1076,6 +1076,7 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display out->vscan = in->vscan; out->vrefresh = in->vrefresh; out->flags = in->flags; + out->type = in->type; strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } @@ -1106,6 +1107,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein out->vscan = in->vscan; out->vrefresh = in->vrefresh; out->flags = in->flags; + out->type = in->type; strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } @@ -1345,6 +1347,8 @@ int drm_mode_getoutput(struct drm_device *dev, else out_resp->crtc = 0; + out_resp->crtcs = output->possible_crtcs; + out_resp->clones = output->possible_clones; if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; list_for_each_entry(mode, &output->modes, head) { -- cgit v1.2.3 From 1e8984a3674c89c3b5ef9b6d3747fb75e10774b3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 15 Nov 2007 18:31:23 +1100 Subject: drm: send correct fb id to userspace --- linux-core/drm_crtc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 5b00c115..e40ab6da 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1271,7 +1271,11 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; - crtc_resp->fb_id = 1; + + if (crtc->fb) + crtc_resp->fb_id = crtc->fb->id; + else + crtc_resp->fb_id = 0; crtc_resp->outputs = 0; if (crtc->enabled) { -- cgit v1.2.3 From 7ec4ebe95e7eec6625d68ae6300255901b69d5c7 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 15 Nov 2007 17:14:03 -0800 Subject: Use user copy routines for writing modes & ids back to userspace Since the drm_mode_card_res structure contains user pointers, we have to use put_user and copy_to_user to write stuff out. The DRM ioctl wrapper will only take care of copying the base drm_mode_card_res struct, not the included arrays. --- linux-core/drm_crtc.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e40ab6da..db062c1d 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1146,7 +1146,7 @@ int drm_mode_getresources(struct drm_device *dev, int crtc_count = 0; int fb_count = 0; int copied = 0; - + memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); mutex_lock(&dev->mode_config.mutex); @@ -1183,7 +1183,9 @@ int drm_mode_getresources(struct drm_device *dev, if (card_res->count_fbs >= fb_count) { copied = 0; list_for_each_entry(fb, &dev->mode_config.fb_list, head) { - card_res->fb_id[copied++] = fb->id; + if (put_user(fb->id, card_res->fb_id + copied)) + return -EFAULT; + copied++; } } card_res->count_fbs = fb_count; @@ -1193,7 +1195,9 @@ int drm_mode_getresources(struct drm_device *dev, copied = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){ DRM_DEBUG("CRTC ID is %d\n", crtc->id); - card_res->crtc_id[copied++] = crtc->id; + if (put_user(crtc->id, card_res->crtc_id + copied)) + return -EFAULT; + copied++; } } card_res->count_crtcs = crtc_count; @@ -1205,7 +1209,10 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each_entry(output, &dev->mode_config.output_list, head) { DRM_DEBUG("OUTPUT ID is %d\n", output->id); - card_res->output_id[copied++] = output->id; + if (put_user(output->id, + card_res->output_id + copied)) + return -EFAULT; + copied++; } } card_res->count_outputs = output_count; @@ -1217,13 +1224,19 @@ int drm_mode_getresources(struct drm_device *dev, head) { list_for_each_entry(mode, &output->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); - card_res->modes[copied++] = u_mode; + if (copy_to_user(&card_res->modes + copied, + &u_mode, sizeof(u_mode))) + return -EFAULT; + copied++; } } /* add in user modes */ list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { drm_crtc_convert_to_umode(&u_mode, mode); - card_res->modes[copied++] = u_mode; + if (copy_to_user(&card_res->modes + copied, &u_mode, + sizeof(u_mode))) + return -EFAULT; + copied++; } } card_res->count_modes = mode_count; -- cgit v1.2.3 From 96e136c4794f9f57e18c1f984a27bbad4b5e1500 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 16 Nov 2007 13:57:42 -0800 Subject: Fix typo in copy_to_user calls We want to copy to card_res->modes + copied, not &card_res->modes + copied. --- linux-core/drm_crtc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index db062c1d..df934841 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1209,8 +1209,7 @@ int drm_mode_getresources(struct drm_device *dev, 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)) + if (put_user(output->id, card_res->output_id + copied)) return -EFAULT; copied++; } @@ -1224,7 +1223,7 @@ int drm_mode_getresources(struct drm_device *dev, head) { list_for_each_entry(mode, &output->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); - if (copy_to_user(&card_res->modes + copied, + if (copy_to_user(card_res->modes + copied, &u_mode, sizeof(u_mode))) return -EFAULT; copied++; @@ -1233,9 +1232,9 @@ int drm_mode_getresources(struct drm_device *dev, /* add in user modes */ list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { drm_crtc_convert_to_umode(&u_mode, mode); - if (copy_to_user(&card_res->modes + copied, &u_mode, + if (copy_to_user(card_res->modes + copied, &u_mode, sizeof(u_mode))) - return -EFAULT; + return -EFAULT; copied++; } } -- cgit v1.2.3 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 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 24 deletions(-) (limited to 'linux-core/drm_crtc.c') 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); -- cgit v1.2.3 From 362f4283205a01b2a60a49838721e9fff9ae1a4c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 26 Nov 2007 14:28:48 +1100 Subject: add _ioctl to the end of two more ioctls --- linux-core/drm_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 87302555..d5f3a0ed 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1816,8 +1816,8 @@ out: * RETURNS: * Zero on success, errno on failure. */ -int drm_mode_attachmode(struct drm_device *dev, - void *data, struct drm_file *file_priv) +int drm_mode_attachmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) { struct drm_mode_mode_cmd *mode_cmd = data; struct drm_output *output; @@ -1867,8 +1867,8 @@ out: * RETURNS: * Zero on success, errno on failure. */ -int drm_mode_detachmode(struct drm_device *dev, - void *data, struct drm_file *file_priv) +int drm_mode_detachmode_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) { struct drm_mode_mode_cmd *mode_cmd = data; struct drm_output *output; -- cgit v1.2.3 From f9ac54b0319b273de83a004d6cfdf46a3b9d6ced Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 26 Nov 2007 15:06:42 +1100 Subject: fb: make fb interface use user mode attach/detach for adding modes --- linux-core/drm_crtc.c | 92 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 24 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index d5f3a0ed..bc292703 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1722,6 +1722,70 @@ int drm_mode_rmmode(struct drm_device *dev, struct drm_display_mode *mode) } 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; + + return ret; +} + +int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct drm_output *output; + + list_for_each_entry(output, &dev->mode_config.output_list, head) { + if (output->crtc == crtc) + drm_mode_attachmode(dev, output, mode); + } +} +EXPORT_SYMBOL(drm_mode_attachmode_crtc); + +static int drm_mode_detachmode(struct drm_device *dev, + struct drm_output *output, + struct drm_display_mode *mode) +{ + int found = 0; + int ret = 0, i; + + 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--; + found = 1; + } + } + + if (!found) + ret = -EINVAL; + + return ret; +} + +int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) +{ + struct drm_output *output; + + list_for_each_entry(output, &dev->mode_config.output_list, head) { + drm_mode_detachmode(dev, output, mode); + } +} +EXPORT_SYMBOL(drm_mode_detachmode_crtc); + /** * drm_fb_addmode - adds a user defined mode * @inode: inode from the ioctl @@ -1822,7 +1886,7 @@ 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; - int i, ret = 0; + int ret = 0; mutex_lock(&dev->mode_config.mutex); @@ -1838,17 +1902,7 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, goto out; } - 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; - + ret = drm_mode_attachmode(dev, output, mode); out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1873,7 +1927,7 @@ 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; - int i, found = 0, ret = 0; + int ret = 0; mutex_lock(&dev->mode_config.mutex); @@ -1890,17 +1944,7 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, } - 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--; - found = 1; - } - } - - if (!found) - ret = -EINVAL; - + ret = drm_mode_detachmode(dev, output, mode); out: mutex_unlock(&dev->mode_config.mutex); return ret; -- cgit v1.2.3 From b3af2b59a77a6916ea7151236d3da9bde6a537fc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 27 Nov 2007 14:31:02 +1000 Subject: drm/modesetting: add initial gettable properites code. This allow the user to retrieve a list of properties for an output. Properties can either be 32-bit values or an enum with an associated name. Range properties are to be supported. This API is probably not all correct, I may make properties part of the general resource get when I think about it some more. So basically you can create properties and attached them to whatever outputs you want, so it should be possible to create some generics and just attach them to every output. --- linux-core/drm_crtc.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 201 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bc292703..cd60f522 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -711,6 +711,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.fb_list); 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); } @@ -944,14 +945,20 @@ void drm_mode_config_cleanup(struct drm_device *dev) 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) { drm_output_destroy(output); } + list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, head) { + 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); @@ -1331,6 +1338,7 @@ int drm_mode_getoutput(struct drm_device *dev, struct drm_output *output; struct drm_display_mode *mode; int mode_count = 0; + int props_count = 0; int ret = 0; int copied = 0; int i; @@ -1341,7 +1349,7 @@ int drm_mode_getoutput(struct drm_device *dev, output= idr_find(&dev->mode_config.crtc_idr, out_resp->output); if (!output || (output->id != out_resp->output)) { ret = -EINVAL; - goto done; + goto out; } list_for_each_entry(mode, &output->modes, head) @@ -1351,6 +1359,12 @@ int drm_mode_getoutput(struct drm_device *dev, 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++; + } + } + strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN); out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0; @@ -1365,20 +1379,42 @@ int drm_mode_getoutput(struct drm_device *dev, out_resp->crtcs = output->possible_crtcs; out_resp->clones = output->possible_clones; + if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; list_for_each_entry(mode, &output->modes, head) { out_resp->modes[copied++] = mode->mode_id; } for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { - if (output->user_mode_ids[i] != 0) - out_resp->modes[copied++] = output->user_mode_ids[i]; + if (output->user_mode_ids[i] != 0) { + if (put_user(output->user_mode_ids[i], out_resp->modes + copied)) + return -EFAULT; + copied++; + } } - } out_resp->count_modes = mode_count; -done: + if ((out_resp->count_props >= props_count) && props_count) { + copied = 0; + for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { + if (output->property_ids[i] != 0) { + if (put_user(output->property_ids[i], out_resp->props + copied)) { + ret = -EFAULT; + goto out; + } + + if (put_user(output->property_values[i], out_resp->prop_values + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + } + out_resp->count_props = props_count; + +out: mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1783,6 +1819,7 @@ int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mo list_for_each_entry(output, &dev->mode_config.output_list, head) { drm_mode_detachmode(dev, output, mode); } + return 0; } EXPORT_SYMBOL(drm_mode_detachmode_crtc); @@ -1949,3 +1986,161 @@ out: mutex_unlock(&dev->mode_config.mutex); return ret; } + +struct drm_property *drm_property_create(struct drm_device *dev, int flags, + const char *name, int num_values) +{ + struct drm_property *property = NULL; + + property = kzalloc(sizeof(struct drm_output), GFP_KERNEL); + if (!property) + return NULL; + + property->values = kzalloc(sizeof(uint32_t)*num_values, GFP_KERNEL); + if (!property->values) + goto fail; + + property->id = drm_idr_get(dev, property); + property->flags = flags; + property->num_values = num_values; + INIT_LIST_HEAD(&property->enum_list); + + if (name) + strncpy(property->name, name, DRM_PROP_NAME_LEN); + + list_add_tail(&property->head, &dev->mode_config.property_list); + return property; +fail: + kfree(property); + return NULL; +} +EXPORT_SYMBOL(drm_property_create); + +int drm_property_add_enum(struct drm_property *property, int index, + uint32_t value, const char *name) +{ + struct drm_property_enum *prop_enum; + + if (!(property->flags & DRM_MODE_PROP_ENUM)) + return -EINVAL; + + if (!list_empty(&property->enum_list)) { + list_for_each_entry(prop_enum, &property->enum_list, head) { + if (prop_enum->value == value) { + strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); + prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; + return 0; + } + } + } + + prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL); + if (!prop_enum) + return -ENOMEM; + + strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); + prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; + prop_enum->value = value; + + property->values[index] = value; + list_add_tail(&prop_enum->head, &property->enum_list); + return 0; +} +EXPORT_SYMBOL(drm_property_add_enum); + +void drm_property_destroy(struct drm_device *dev, struct drm_property *property) +{ + struct drm_property_enum *prop_enum, *pt; + + list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) { + list_del(&prop_enum->head); + kfree(prop_enum); + } + + kfree(property->values); + drm_idr_put(dev, property->id); + list_del(&property->head); + kfree(property); +} +EXPORT_SYMBOL(drm_property_destroy); + + +int drm_output_attach_property(struct drm_output *output, + struct drm_property *property, int init_val) +{ + int i; + + for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { + if (output->property_ids[i] == 0) { + output->property_ids[i] = property->id; + output->property_values[i] = init_val; + break; + } + } + + if (i == DRM_OUTPUT_MAX_PROPERTY) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(drm_output_attach_property); + +int drm_mode_getproperty_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_get_property *out_resp = data; + struct drm_property *property; + int enum_count = 0; + int value_count = 0; + int ret = 0, i; + int copied; + struct drm_property_enum *prop_enum; + + mutex_lock(&dev->mode_config.mutex); + property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); + if (!property || (property->id != out_resp->prop_id)) { + ret = -EINVAL; + goto done; + } + + + list_for_each_entry(prop_enum, &property->enum_list, head) + enum_count++; + + value_count = property->num_values; + + strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); + out_resp->name[DRM_PROP_NAME_LEN-1] = 0; + out_resp->flags = property->flags; + + if ((out_resp->count_values >= value_count) && value_count) { + for (i = 0; i < value_count; i++) { + if (put_user(property->values[i], out_resp->values + i)) { + ret = -EFAULT; + goto done; + } + } + } + out_resp->count_values = value_count; + + if ((out_resp->count_enums >= enum_count) && enum_count) { + copied = 0; + list_for_each_entry(prop_enum, &property->enum_list, head) { + if (put_user(prop_enum->value, &out_resp->enums[copied].value)) { + ret = -EFAULT; + goto done; + } + + if (copy_to_user(&out_resp->enums[copied].name, + prop_enum->name, DRM_PROP_NAME_LEN)) { + ret = -EFAULT; + goto done; + } + copied++; + } + } + out_resp->count_enums = enum_count; + +done: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} -- cgit v1.2.3 From 91cd3e3c097d581ea75ec4bcbc1ba8d23b471a2e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 28 Nov 2007 15:18:25 +1000 Subject: modesetting API change for removing mode ids and making modes per output. so really want to get a list of modes per output not the global hammer list. also we remove the mode ids and let the user pass back the full mode description need to fix up add/remove mode for user modes now --- linux-core/drm_crtc.c | 270 +++++++++++++++++++++++--------------------------- 1 file changed, 123 insertions(+), 147 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index cd60f522..44268337 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -280,73 +280,79 @@ static struct drm_display_mode std_mode[] = { * * FIXME: take into account monitor limits */ -void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) +void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int maxY) { - struct drm_output *output; + struct drm_device *dev = output->dev; struct drm_display_mode *mode, *t; int ret; //if (maxX == 0 || maxY == 0) // TODO - list_for_each_entry(output, &dev->mode_config.output_list, head) { - - /* set all modes to the unverified state */ - list_for_each_entry_safe(mode, t, &output->modes, head) - mode->status = MODE_UNVERIFIED; + /* set all modes to the unverified state */ + list_for_each_entry_safe(mode, t, &output->modes, head) + mode->status = MODE_UNVERIFIED; - output->status = (*output->funcs->detect)(output); - - if (output->status == output_status_disconnected) { - DRM_DEBUG("%s is disconnected\n", output->name); - /* TODO set EDID to NULL */ - continue; - } - - ret = (*output->funcs->get_modes)(output); - - if (ret) { - drm_mode_output_list_update(output); - } - - if (maxX && maxY) - drm_mode_validate_size(dev, &output->modes, maxX, - maxY, 0); - list_for_each_entry_safe(mode, t, &output->modes, head) { - if (mode->status == MODE_OK) - mode->status = (*output->funcs->mode_valid)(output,mode); - } + output->status = (*output->funcs->detect)(output); + + if (output->status == output_status_disconnected) { + DRM_DEBUG("%s is disconnected\n", output->name); + /* TODO set EDID to NULL */ + return; + } + + ret = (*output->funcs->get_modes)(output); + + if (ret) { + drm_mode_output_list_update(output); + } + + if (maxX && maxY) + drm_mode_validate_size(dev, &output->modes, maxX, + maxY, 0); + list_for_each_entry_safe(mode, t, &output->modes, head) { + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output,mode); + } + + + drm_mode_prune_invalid(dev, &output->modes, TRUE); + + if (list_empty(&output->modes)) { + struct drm_display_mode *stdmode; + DRM_DEBUG("No valid modes on %s\n", output->name); + + /* Should we do this here ??? + * When no valid EDID modes are available we end up + * here and bailed in the past, now we add a standard + * 640x480@60Hz mode and carry on. + */ + stdmode = drm_mode_duplicate(dev, &std_mode[0]); + drm_mode_probed_add(output, stdmode); + drm_mode_list_concat(&output->probed_modes, + &output->modes); + + DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", + output->name); + } + + drm_mode_sort(&output->modes); + + DRM_DEBUG("Probed modes for %s\n", output->name); + list_for_each_entry_safe(mode, t, &output->modes, head) { + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_debug_printmodeline(dev, mode); + } +} - drm_mode_prune_invalid(dev, &output->modes, TRUE); - - if (list_empty(&output->modes)) { - struct drm_display_mode *stdmode; - - DRM_DEBUG("No valid modes on %s\n", output->name); - - /* Should we do this here ??? - * When no valid EDID modes are available we end up - * here and bailed in the past, now we add a standard - * 640x480@60Hz mode and carry on. - */ - stdmode = drm_mode_duplicate(dev, &std_mode[0]); - drm_mode_probed_add(output, stdmode); - drm_mode_list_concat(&output->probed_modes, - &output->modes); - - DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", - output->name); - } - - drm_mode_sort(&output->modes); - - DRM_DEBUG("Probed modes for %s\n", output->name); - list_for_each_entry_safe(mode, t, &output->modes, head) { - mode->vrefresh = drm_mode_vrefresh(mode); +void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) +{ + struct drm_output *output; - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - drm_mode_debug_printmodeline(dev, mode); - } + list_for_each_entry(output, &dev->mode_config.output_list, head) { + drm_crtc_probe_single_output_modes(output, maxX, maxY); } } @@ -1068,8 +1074,6 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, */ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in) { - - out->id = in->mode_id; out->clock = in->clock; out->hdisplay = in->hdisplay; out->hsync_start = in->hsync_start; @@ -1145,17 +1149,12 @@ int drm_mode_getresources(struct drm_device *dev, struct drm_framebuffer *fb; struct drm_output *output; struct drm_crtc *crtc; - struct drm_mode_modeinfo u_mode; - struct drm_display_mode *mode; int ret = 0; - int mode_count= 0; int output_count = 0; int crtc_count = 0; int fb_count = 0; int copied = 0; - memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); - mutex_lock(&dev->mode_config.mutex); list_for_each(lh, &dev->mode_config.fb_list) @@ -1164,34 +1163,18 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each(lh, &dev->mode_config.crtc_list) crtc_count++; - list_for_each_entry(output, &dev->mode_config.output_list, - head) { + list_for_each(lh, &dev->mode_config.output_list) output_count++; - list_for_each(lh, &output->modes) - mode_count++; - } - list_for_each(lh, &dev->mode_config.usermode_list) - mode_count++; - - 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++; - } - list_for_each(lh, &dev->mode_config.usermode_list) - mode_count++; - } /* handle this in 4 parts */ /* FBs */ if (card_res->count_fbs >= fb_count) { copied = 0; list_for_each_entry(fb, &dev->mode_config.fb_list, head) { - if (put_user(fb->id, card_res->fb_id + copied)) - return -EFAULT; + if (put_user(fb->id, card_res->fb_id + copied)) { + ret = -EFAULT; + goto out; + } copied++; } } @@ -1202,8 +1185,10 @@ int drm_mode_getresources(struct drm_device *dev, copied = 0; 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)) - return -EFAULT; + if (put_user(crtc->id, card_res->crtc_id + copied)) { + ret = -EFAULT; + goto out; + } copied++; } } @@ -1216,41 +1201,20 @@ int drm_mode_getresources(struct drm_device *dev, 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)) - return -EFAULT; + if (put_user(output->id, card_res->output_id + copied)) { + ret = -EFAULT; + goto out; + } copied++; } } card_res->count_outputs = output_count; - /* Modes */ - if (card_res->count_modes >= mode_count) { - copied = 0; - 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); - if (copy_to_user(card_res->modes + copied, - &u_mode, sizeof(u_mode))) - return -EFAULT; - copied++; - } - } - /* add in user modes */ - list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { - drm_crtc_convert_to_umode(&u_mode, mode); - if (copy_to_user(card_res->modes + copied, &u_mode, - sizeof(u_mode))) - return -EFAULT; - copied++; - } - } - card_res->count_modes = mode_count; + DRM_DEBUG("Counted %d %d\n", card_res->count_crtcs, + card_res->count_outputs); - DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, - card_res->count_outputs, - card_res->count_modes); - + +out: mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1299,14 +1263,16 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->outputs = 0; if (crtc->enabled) { - crtc_resp->mode = crtc->mode.mode_id; + drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); + crtc_resp->mode_valid = 1; ocount = 0; list_for_each_entry(output, &dev->mode_config.output_list, head) { if (output->crtc == crtc) crtc_resp->outputs |= 1 << (ocount++); } + } else { - crtc_resp->mode = 0; + crtc_resp->mode_valid = 0; } out: @@ -1342,6 +1308,9 @@ int drm_mode_getoutput(struct drm_device *dev, int ret = 0; int copied = 0; int i; + struct drm_mode_modeinfo u_mode; + + memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); DRM_DEBUG("output id %d:\n", out_resp->output); @@ -1365,6 +1334,10 @@ int drm_mode_getoutput(struct drm_device *dev, } } + if (out_resp->count_modes == 0) { + drm_crtc_probe_single_output_modes(output, dev->mode_config.max_width, dev->mode_config.max_height); + } + strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN); out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0; @@ -1383,12 +1356,26 @@ int drm_mode_getoutput(struct drm_device *dev, if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; list_for_each_entry(mode, &output->modes, head) { - out_resp->modes[copied++] = mode->mode_id; + 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++; + } for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { - if (output->user_mode_ids[i] != 0) { - if (put_user(output->user_mode_ids[i], out_resp->modes + copied)) - return -EFAULT; + 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++; } } @@ -1442,8 +1429,9 @@ int drm_mode_setcrtc(struct drm_device *dev, struct drm_mode_crtc *crtc_req = data; struct drm_crtc *crtc; struct drm_output **output_set = NULL, *output; - struct drm_display_mode *mode; struct drm_framebuffer *fb = NULL; + struct drm_display_mode mode; + int mode_valid = 0; int ret = 0; int i; @@ -1455,7 +1443,7 @@ int drm_mode_setcrtc(struct drm_device *dev, goto out; } - if (crtc_req->mode) { + if (crtc_req->mode_valid) { /* if we have a mode we need a framebuffer */ if (crtc_req->fb_id) { fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id); @@ -1465,34 +1453,19 @@ int drm_mode_setcrtc(struct drm_device *dev, goto out; } } - 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); - ret = -EINVAL; - goto out; - } + mode_valid = 1; + drm_crtc_convert_umode(&mode, &crtc_req->mode); } else - mode = NULL; + mode_valid = 0; - if (crtc_req->count_outputs == 0 && mode) { + if (crtc_req->count_outputs == 0 && mode_valid) { DRM_DEBUG("Count outputs is 0 but mode set\n"); ret = -EINVAL; goto out; } - if (crtc_req->count_outputs > 0 && !mode && !fb) { + if (crtc_req->count_outputs > 0 && !mode_valid && !fb) { DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs); ret = -EINVAL; goto out; @@ -1523,8 +1496,12 @@ int drm_mode_setcrtc(struct drm_device *dev, output_set[i] = output; } } - - ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); + + if (mode_valid) { + ret = drm_crtc_set_config(crtc, crtc_req, &mode, output_set, fb); + } else { + ret = drm_crtc_set_config(crtc, crtc_req, NULL, output_set, fb); + } out: mutex_unlock(&dev->mode_config.mutex); @@ -1855,7 +1832,6 @@ int drm_mode_addmode_ioctl(struct drm_device *dev, drm_crtc_convert_umode(user_mode, new_mode); drm_mode_addmode(dev, user_mode); - new_mode->id = user_mode->mode_id; out: mutex_unlock(&dev->mode_config.mutex); -- cgit v1.2.3 From 96df9b11ad8974d7a2a0a589114cbbb04a584f18 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Dec 2007 13:42:32 +1000 Subject: finish of mode add/remove, just have attach/detach modes --- linux-core/drm_crtc.c | 202 ++++++++++---------------------------------------- 1 file changed, 39 insertions(+), 163 deletions(-) (limited to 'linux-core/drm_crtc.c') 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,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; -- cgit v1.2.3 From 1a6c95ef711fce807659ab5e4fe480d65ac233b6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Dec 2007 16:03:05 +1000 Subject: arrgggh.. make all ioctl structs 32/64-bit compatible hopefully. This also starts to add blob property support. someone needs to check this work for other things like ppc/x86 alignment diffs --- linux-core/drm_crtc.c | 163 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 121 insertions(+), 42 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 26aa5206..c2680319 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -722,7 +722,11 @@ 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.property_blob_list); idr_init(&dev->mode_config.crtc_idr); + dev->mode_config.edid_property = drm_property_create(dev, + DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, + "EDID", 0); } EXPORT_SYMBOL(drm_mode_config_init); @@ -1013,7 +1017,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) changed = true; - if (new_mode && (crtc->mode.mode_id != new_mode->mode_id)) + if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) changed = true; list_for_each_entry(output, &dev->mode_config.output_list, head) { @@ -1152,6 +1156,9 @@ int drm_mode_getresources(struct drm_device *dev, int crtc_count = 0; int fb_count = 0; int copied = 0; + uint32_t __user *fb_id; + uint32_t __user *crtc_id; + uint32_t __user *output_id; mutex_lock(&dev->mode_config.mutex); @@ -1164,12 +1171,18 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each(lh, &dev->mode_config.output_list) output_count++; + card_res->max_height = dev->mode_config.max_height; + card_res->min_height = dev->mode_config.min_height; + card_res->max_width = dev->mode_config.max_width; + card_res->min_width = dev->mode_config.min_width; + /* handle this in 4 parts */ /* FBs */ if (card_res->count_fbs >= fb_count) { copied = 0; + fb_id = (uint32_t *)(unsigned long)card_res->fb_id_ptr; list_for_each_entry(fb, &dev->mode_config.fb_list, head) { - if (put_user(fb->id, card_res->fb_id + copied)) { + if (put_user(fb->id, fb_id + copied)) { ret = -EFAULT; goto out; } @@ -1181,9 +1194,10 @@ int drm_mode_getresources(struct drm_device *dev, /* CRTCs */ if (card_res->count_crtcs >= crtc_count) { copied = 0; + crtc_id = (uint32_t *)(unsigned long)card_res->crtc_id_ptr; 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)) { + if (put_user(crtc->id, crtc_id + copied)) { ret = -EFAULT; goto out; } @@ -1196,10 +1210,11 @@ int drm_mode_getresources(struct drm_device *dev, /* Outputs */ if (card_res->count_outputs >= output_count) { copied = 0; + output_id = (uint32_t *)(unsigned long)card_res->output_id_ptr; 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)) { + if (put_user(output->id, output_id + copied)) { ret = -EFAULT; goto out; } @@ -1211,7 +1226,6 @@ int drm_mode_getresources(struct drm_device *dev, DRM_DEBUG("Counted %d %d\n", card_res->count_crtcs, card_res->count_outputs); - out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1307,6 +1321,9 @@ int drm_mode_getoutput(struct drm_device *dev, int copied = 0; int i; struct drm_mode_modeinfo u_mode; + struct drm_mode_modeinfo __user *mode_ptr; + uint32_t __user *prop_ptr; + uint64_t __user *prop_values; memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); @@ -1349,9 +1366,10 @@ int drm_mode_getoutput(struct drm_device *dev, if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; + mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; list_for_each_entry(mode, &output->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); - if (copy_to_user(out_resp->modes + copied, + if (copy_to_user(mode_ptr + copied, &u_mode, sizeof(u_mode))) { ret = -EFAULT; goto out; @@ -1364,14 +1382,16 @@ int drm_mode_getoutput(struct drm_device *dev, if ((out_resp->count_props >= props_count) && props_count) { copied = 0; + prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); + prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { if (output->property_ids[i] != 0) { - if (put_user(output->property_ids[i], out_resp->props + copied)) { + if (put_user(output->property_ids[i], prop_ptr + copied)) { ret = -EFAULT; goto out; } - if (put_user(output->property_values[i], out_resp->prop_values + copied)) { + if (put_user(output->property_values[i], prop_values + copied)) { ret = -EFAULT; goto out; } @@ -1410,10 +1430,10 @@ int drm_mode_setcrtc(struct drm_device *dev, struct drm_crtc *crtc; struct drm_output **output_set = NULL, *output; struct drm_framebuffer *fb = NULL; - struct drm_display_mode mode; - int mode_valid = 0; + struct drm_display_mode *mode = NULL; int ret = 0; int i; + uint32_t __user *set_outputs_ptr; mutex_lock(&dev->mode_config.mutex); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id); @@ -1434,18 +1454,17 @@ int drm_mode_setcrtc(struct drm_device *dev, } } - mode_valid = 1; - drm_crtc_convert_umode(&mode, &crtc_req->mode); - } else - mode_valid = 0; + mode = drm_mode_create(dev); + drm_crtc_convert_umode(mode, &crtc_req->mode); + } - if (crtc_req->count_outputs == 0 && mode_valid) { + if (crtc_req->count_outputs == 0 && mode) { DRM_DEBUG("Count outputs is 0 but mode set\n"); ret = -EINVAL; goto out; } - if (crtc_req->count_outputs > 0 && !mode_valid && !fb) { + if (crtc_req->count_outputs > 0 && !mode && !fb) { DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs); ret = -EINVAL; goto out; @@ -1461,7 +1480,8 @@ int drm_mode_setcrtc(struct drm_device *dev, } for (i = 0; i < crtc_req->count_outputs; i++) { - if (get_user(out_id, &crtc_req->set_outputs[i])) { + set_outputs_ptr = (uint32_t *)(unsigned long)crtc_req->set_outputs_ptr; + if (get_user(out_id, &set_outputs_ptr[i])) { ret = -EFAULT; goto out; } @@ -1477,11 +1497,7 @@ int drm_mode_setcrtc(struct drm_device *dev, } } - if (mode_valid) { - ret = drm_crtc_set_config(crtc, crtc_req, &mode, output_set, fb); - } else { - ret = drm_crtc_set_config(crtc, crtc_req, NULL, output_set, fb); - } + ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); out: mutex_unlock(&dev->mode_config.mutex); @@ -1847,15 +1863,17 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, property = kzalloc(sizeof(struct drm_output), GFP_KERNEL); if (!property) return NULL; - - property->values = kzalloc(sizeof(uint32_t)*num_values, GFP_KERNEL); - if (!property->values) - goto fail; + + if (num_values) { + property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); + if (!property->values) + goto fail; + } property->id = drm_idr_get(dev, property); property->flags = flags; property->num_values = num_values; - INIT_LIST_HEAD(&property->enum_list); + INIT_LIST_HEAD(&property->enum_blob_list); if (name) strncpy(property->name, name, DRM_PROP_NAME_LEN); @@ -1869,15 +1887,15 @@ fail: EXPORT_SYMBOL(drm_property_create); int drm_property_add_enum(struct drm_property *property, int index, - uint32_t value, const char *name) + uint64_t value, const char *name) { struct drm_property_enum *prop_enum; if (!(property->flags & DRM_MODE_PROP_ENUM)) return -EINVAL; - if (!list_empty(&property->enum_list)) { - list_for_each_entry(prop_enum, &property->enum_list, head) { + if (!list_empty(&property->enum_blob_list)) { + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { if (prop_enum->value == value) { strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; @@ -1895,7 +1913,7 @@ int drm_property_add_enum(struct drm_property *property, int index, prop_enum->value = value; property->values[index] = value; - list_add_tail(&prop_enum->head, &property->enum_list); + list_add_tail(&prop_enum->head, &property->enum_blob_list); return 0; } EXPORT_SYMBOL(drm_property_add_enum); @@ -1904,12 +1922,13 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) { struct drm_property_enum *prop_enum, *pt; - list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) { + list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { list_del(&prop_enum->head); kfree(prop_enum); } - kfree(property->values); + if (property->num_values) + kfree(property->values); drm_idr_put(dev, property->id); list_del(&property->head); kfree(property); @@ -1918,7 +1937,7 @@ EXPORT_SYMBOL(drm_property_destroy); int drm_output_attach_property(struct drm_output *output, - struct drm_property *property, int init_val) + struct drm_property *property, uint64_t init_val) { int i; @@ -1942,10 +1961,14 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, struct drm_mode_get_property *out_resp = data; struct drm_property *property; int enum_count = 0; + int blob_count = 0; int value_count = 0; int ret = 0, i; int copied; struct drm_property_enum *prop_enum; + struct drm_property_enum __user *enum_ptr; + struct drm_property_blob *prop_blob; + uint64_t __user *values_ptr; mutex_lock(&dev->mode_config.mutex); property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); @@ -1954,9 +1977,13 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, goto done; } - - list_for_each_entry(prop_enum, &property->enum_list, head) - enum_count++; + if (property->flags & DRM_MODE_PROP_ENUM) { + list_for_each_entry(prop_enum, &property->enum_blob_list, head) + enum_count++; + } else if (property->flags & DRM_MODE_PROP_BLOB) { + list_for_each_entry(prop_blob, &property->enum_blob_list, head) + blob_count++; + } value_count = property->num_values; @@ -1965,8 +1992,9 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->flags = property->flags; if ((out_resp->count_values >= value_count) && value_count) { + values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; for (i = 0; i < value_count; i++) { - if (put_user(property->values[i], out_resp->values + i)) { + if (put_user(property->values[i], values_ptr + i)) { ret = -EFAULT; goto done; } @@ -1974,10 +2002,30 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } out_resp->count_values = value_count; - if ((out_resp->count_enums >= enum_count) && enum_count) { + if ((out_resp->count_enum_blobs >= enum_count) && enum_count && (property->flags & DRM_MODE_PROP_ENUM)) { + copied = 0; + enum_ptr = (struct drm_property_enum *)(unsigned long)out_resp->enum_blob_ptr; + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { + if (put_user(prop_enum->value, &enum_ptr[copied].value)) { + ret = -EFAULT; + goto done; + } + + if (copy_to_user(&enum_ptr[copied].name, + prop_enum->name, DRM_PROP_NAME_LEN)) { + ret = -EFAULT; + goto done; + } + copied++; + } + } + out_resp->count_enum_blobs = enum_count; + +#if 0 + if ((out_resp->count_blobs >= enum_count) && blob_count && (property->flags & DRM_MODE_PROP_BLOB)) { copied = 0; - list_for_each_entry(prop_enum, &property->enum_list, head) { - if (put_user(prop_enum->value, &out_resp->enums[copied].value)) { + list_for_each_entry(prop_blob, &property->enum_list, head) { + if (put_user(prop_enum->value, &out_resp->blobs[copied].value)) { ret = -EFAULT; goto done; } @@ -1991,8 +2039,39 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } } out_resp->count_enums = enum_count; - +#endif done: mutex_unlock(&dev->mode_config.mutex); return ret; } + +static int drm_property_create_blob(struct drm_device *dev, int length, + void *data) +{ + struct drm_property_blob *blob; + + if (!length || !data) + return -EINVAL; + + blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); + if (!blob) + return -EINVAL; + + blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob)); + blob->length = length; + + memcpy(blob->data, data, length); + + blob->id = drm_idr_get(dev, blob); + + list_add_tail(&blob->head, &dev->mode_config.property_blob_list); + return blob->id; +} + +static void drm_property_destroy_blob(struct drm_device *dev, + struct drm_property_blob *blob) +{ + drm_idr_put(dev, blob->id); + list_del(&blob->head); + kfree(blob); +} -- cgit v1.2.3 From c9cda51af5a8bea1d30ce575ae260de52950fe2f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Dec 2007 16:31:35 +1000 Subject: more WIP on blobs.. I'm going to pass back a list of blob ids and lengths in the getproperty. will need another ioctl to return the blob data as it is variable length. --- linux-core/drm_crtc.c | 67 ++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c2680319..a3aa783b 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1968,7 +1968,9 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, struct drm_property_enum *prop_enum; struct drm_property_enum __user *enum_ptr; struct drm_property_blob *prop_blob; + uint32_t *blob_id_ptr; uint64_t __user *values_ptr; + uint32_t __user *blob_length_ptr; mutex_lock(&dev->mode_config.mutex); property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); @@ -1980,7 +1982,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, if (property->flags & DRM_MODE_PROP_ENUM) { list_for_each_entry(prop_enum, &property->enum_blob_list, head) enum_count++; - } else if (property->flags & DRM_MODE_PROP_BLOB) { + } else if (property->flags & DRM_MODE_PROP_BLOB) { list_for_each_entry(prop_blob, &property->enum_blob_list, head) blob_count++; } @@ -2002,44 +2004,49 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } out_resp->count_values = value_count; - if ((out_resp->count_enum_blobs >= enum_count) && enum_count && (property->flags & DRM_MODE_PROP_ENUM)) { - copied = 0; - enum_ptr = (struct drm_property_enum *)(unsigned long)out_resp->enum_blob_ptr; - list_for_each_entry(prop_enum, &property->enum_blob_list, head) { - if (put_user(prop_enum->value, &enum_ptr[copied].value)) { - ret = -EFAULT; - goto done; - } - - if (copy_to_user(&enum_ptr[copied].name, - prop_enum->name, DRM_PROP_NAME_LEN)) { + if (property->flags & DRM_MODE_PROP_ENUM) { + if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { + copied = 0; + enum_ptr = (struct drm_property_enum *)(unsigned long)out_resp->enum_blob_ptr; + list_for_each_entry(prop_enum, &property->enum_blob_list, head) { + if (put_user(prop_enum->value, &enum_ptr[copied].value)) { + ret = -EFAULT; + goto done; + } + + if (copy_to_user(&enum_ptr[copied].name, + prop_enum->name, DRM_PROP_NAME_LEN)) { ret = -EFAULT; goto done; + } + copied++; } - copied++; } + out_resp->count_enum_blobs = enum_count; } - out_resp->count_enum_blobs = enum_count; -#if 0 - if ((out_resp->count_blobs >= enum_count) && blob_count && (property->flags & DRM_MODE_PROP_BLOB)) { - copied = 0; - list_for_each_entry(prop_blob, &property->enum_list, head) { - if (put_user(prop_enum->value, &out_resp->blobs[copied].value)) { - ret = -EFAULT; - goto done; - } - - if (copy_to_user(&out_resp->enums[copied].name, - prop_enum->name, DRM_PROP_NAME_LEN)) { - ret = -EFAULT; - goto done; + if (property->flags & DRM_MODE_PROP_BLOB) { + if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { + copied = 0; + blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; + blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; + + list_for_each_entry(prop_blob, &property->enum_blob_list, head) { + if (put_user(prop_blob->id, blob_id_ptr + copied)) { + ret = -EFAULT; + goto done; + } + + if (put_user(prop_blob->length, blob_length_ptr + copied)) { + ret = -EFAULT; + goto done; + } + + copied++; } - copied++; } + out_resp->count_enum_blobs = enum_count; } - out_resp->count_enums = enum_count; -#endif done: mutex_unlock(&dev->mode_config.mutex); return ret; -- cgit v1.2.3 From 67f6eb1eb8d3dc5bb5fdb097655d3da326f637c1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 6 Dec 2007 10:44:51 +1000 Subject: add property blobs and edid reporting support --- linux-core/drm_crtc.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index a3aa783b..70844237 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -590,6 +590,8 @@ struct drm_output *drm_output_create(struct drm_device *dev, list_add_tail(&output->head, &dev->mode_config.output_list); dev->mode_config.num_output++; + drm_output_attach_property(output, dev->mode_config.edid_property, 0); + mutex_unlock(&dev->mode_config.mutex); return output; @@ -1935,7 +1937,6 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) } EXPORT_SYMBOL(drm_property_destroy); - int drm_output_attach_property(struct drm_output *output, struct drm_property *property, uint64_t init_val) { @@ -1955,6 +1956,24 @@ int drm_output_attach_property(struct drm_output *output, } EXPORT_SYMBOL(drm_output_attach_property); +int drm_output_property_set_value(struct drm_output *output, + struct drm_property *property, uint64_t value) +{ + int i; + + for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { + if (output->property_ids[i] == property->id) { + output->property_values[i] = value; + break; + } + } + + if (i == DRM_OUTPUT_MAX_PROPERTY) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(drm_output_property_set_value); + int drm_mode_getproperty_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -2052,17 +2071,17 @@ done: return ret; } -static int drm_property_create_blob(struct drm_device *dev, int length, - void *data) +static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, + void *data) { struct drm_property_blob *blob; if (!length || !data) - return -EINVAL; + return NULL; blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); if (!blob) - return -EINVAL; + return NULL; blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob)); blob->length = length; @@ -2072,7 +2091,7 @@ static int drm_property_create_blob(struct drm_device *dev, int length, blob->id = drm_idr_get(dev, blob); list_add_tail(&blob->head, &dev->mode_config.property_blob_list); - return blob->id; + return blob; } static void drm_property_destroy_blob(struct drm_device *dev, @@ -2082,3 +2101,47 @@ static void drm_property_destroy_blob(struct drm_device *dev, list_del(&blob->head); kfree(blob); } + +int drm_mode_getblob_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_get_blob *out_resp = data; + struct drm_property_blob *blob; + int ret = 0; + void *blob_ptr; + + mutex_lock(&dev->mode_config.mutex); + + blob = idr_find(&dev->mode_config.crtc_idr, out_resp->blob_id); + if (!blob || (blob->id != out_resp->blob_id)) { + ret = -EINVAL; + goto done; + } + + if (out_resp->length == blob->length) { + blob_ptr = (void *)(unsigned long)out_resp->data; + if (copy_to_user(blob_ptr, blob->data, blob->length)){ + ret = -EFAULT; + goto done; + } + } + out_resp->length = blob->length; + +done: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_output_update_edid_property(struct drm_output *output, unsigned char *edid) +{ + struct drm_device *dev = output->dev; + int ret = 0; + if (output->edid_blob_ptr) + drm_property_destroy_blob(dev, output->edid_blob_ptr); + + output->edid_blob_ptr = drm_property_create_blob(output->dev, 128, edid); + + ret = drm_output_property_set_value(output, dev->mode_config.edid_property, output->edid_blob_ptr->id); + return ret; +} +EXPORT_SYMBOL(drm_mode_output_update_edid_property); -- cgit v1.2.3 From 1ba2bb3a7e77576333b09f296abac4c01c895c48 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 6 Dec 2007 11:35:37 +1000 Subject: oops initialise variable to false --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 70844237..fba275b7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1005,7 +1005,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_device *dev = crtc->dev; struct drm_crtc **save_crtcs, *new_crtc; bool save_enabled = crtc->enabled; - bool changed; + bool changed = false; struct drm_output *output; int count = 0, ro; -- cgit v1.2.3 From 3b6786e3e6523b1ceca3645ea4c6081f170d2134 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Dec 2007 14:46:51 +1000 Subject: modesetting: add dpms property and initial settable property ioctl --- linux-core/drm_crtc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 7 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fba275b7..871f8994 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -592,6 +592,8 @@ struct drm_output *drm_output_create(struct drm_device *dev, drm_output_attach_property(output, dev->mode_config.edid_property, 0); + drm_output_attach_property(output, dev->mode_config.dpms_property, 0); + mutex_unlock(&dev->mode_config.mutex); return output; @@ -729,6 +731,15 @@ void drm_mode_config_init(struct drm_device *dev) dev->mode_config.edid_property = drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, "EDID", 0); + + dev->mode_config.dpms_property = drm_property_create(dev, + DRM_MODE_PROP_ENUM, + "DPMS", 4); + drm_property_add_enum(dev->mode_config.dpms_property, 0, DPMSModeOn, "On"); + drm_property_add_enum(dev->mode_config.dpms_property, 1, DPMSModeStandby, "Standby"); + drm_property_add_enum(dev->mode_config.dpms_property, 2, DPMSModeSuspend, "Suspend"); + drm_property_add_enum(dev->mode_config.dpms_property, 3, DPMSModeOff, "Off"); + } EXPORT_SYMBOL(drm_mode_config_init); @@ -1985,7 +1996,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, int ret = 0, i; int copied; struct drm_property_enum *prop_enum; - struct drm_property_enum __user *enum_ptr; + struct drm_mode_property_enum __user *enum_ptr; struct drm_property_blob *prop_blob; uint32_t *blob_id_ptr; uint64_t __user *values_ptr; @@ -2015,7 +2026,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, if ((out_resp->count_values >= value_count) && value_count) { values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; for (i = 0; i < value_count; i++) { - if (put_user(property->values[i], values_ptr + i)) { + if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { ret = -EFAULT; goto done; } @@ -2024,19 +2035,21 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_values = value_count; if (property->flags & DRM_MODE_PROP_ENUM) { + if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied = 0; - enum_ptr = (struct drm_property_enum *)(unsigned long)out_resp->enum_blob_ptr; + enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; list_for_each_entry(prop_enum, &property->enum_blob_list, head) { - if (put_user(prop_enum->value, &enum_ptr[copied].value)) { + + if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { ret = -EFAULT; goto done; } if (copy_to_user(&enum_ptr[copied].name, - prop_enum->name, DRM_PROP_NAME_LEN)) { - ret = -EFAULT; - goto done; + &prop_enum->name, DRM_PROP_NAME_LEN)) { + ret = -EFAULT; + goto done; } copied++; } @@ -2145,3 +2158,35 @@ int drm_mode_output_update_edid_property(struct drm_output *output, unsigned cha return ret; } EXPORT_SYMBOL(drm_mode_output_update_edid_property); + +int drm_mode_output_property_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_output_set_property *out_resp = data; + struct drm_output *output; + int ret = -EINVAL; + int i; + + mutex_lock(&dev->mode_config.mutex); + output= idr_find(&dev->mode_config.crtc_idr, out_resp->output_id); + if (!output || (output->id != out_resp->output_id)) { + goto out; + } + + for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { + if (output->property_ids[i] == out_resp->prop_id) + break; + } + + if (i == DRM_OUTPUT_MAX_PROPERTY) { + goto out; + } + + if (output->funcs->set_property) + ret = output->funcs->set_property(output, out_resp->prop_id, out_resp->value); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + -- cgit v1.2.3 From f99dea7db00dd46aa96eaed3a61dff9c956fd86f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Dec 2007 15:56:48 +1000 Subject: modesetting: fixup property setting and add connector property --- linux-core/drm_crtc.c | 102 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 14 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 871f8994..e1b37c0b 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -33,6 +33,33 @@ #include "drmP.h" #include "drm_crtc.h" +struct drm_prop_enum_list { + int type; + char *name; +}; + +static struct drm_prop_enum_list drm_dpms_enum_list[] = +{ { DPMSModeOn, "On" }, + { DPMSModeStandby, "Standby" }, + { DPMSModeSuspend, "Suspend" }, + { DPMSModeOff, "Off" } +}; +static struct drm_prop_enum_list drm_conn_enum_list[] = +{ { ConnectorVGA, "VGA" }, + { ConnectorDVII, "DVI-I" }, + { ConnectorDVID, "DVI-D" }, + { ConnectorDVIA, "DVI-A" }, + { ConnectorComposite, "Composite" }, + { ConnectorSVIDEO, "SVIDEO" }, + { ConnectorLVDS, "LVDS" }, + { ConnectorComponent, "Component" }, + { Connector9PinDIN, "9-pin DIN" }, + { ConnectorDisplayPort, "DisplayPort" }, + { ConnectorHDMIA, "HDMI Type A" }, + { ConnectorHDMIB, "HDMI Type B" }, +}; + + /** * drm_idr_get - allocate a new identifier * @dev: DRM device @@ -709,6 +736,34 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_destroy); +static int drm_mode_create_standard_output_properties(struct drm_device *dev) +{ + int i; + + dev->mode_config.edid_property = + drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, + "EDID", 0); + + dev->mode_config.dpms_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4); + + for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) + drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name); + + dev->mode_config.connector_type_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, + "Connector Type", 10); + for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++) + drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name); + + dev->mode_config.connector_num_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, + "Connector ID", 2); + dev->mode_config.connector_num_property->values[0] = 0; + dev->mode_config.connector_num_property->values[1] = 20; + return 0; +} + /** * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device @@ -728,17 +783,8 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.property_list); INIT_LIST_HEAD(&dev->mode_config.property_blob_list); idr_init(&dev->mode_config.crtc_idr); - dev->mode_config.edid_property = drm_property_create(dev, - DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, - "EDID", 0); - - dev->mode_config.dpms_property = drm_property_create(dev, - DRM_MODE_PROP_ENUM, - "DPMS", 4); - drm_property_add_enum(dev->mode_config.dpms_property, 0, DPMSModeOn, "On"); - drm_property_add_enum(dev->mode_config.dpms_property, 1, DPMSModeStandby, "Standby"); - drm_property_add_enum(dev->mode_config.dpms_property, 2, DPMSModeSuspend, "Suspend"); - drm_property_add_enum(dev->mode_config.dpms_property, 3, DPMSModeOff, "Off"); + + drm_mode_create_standard_output_properties(dev); } EXPORT_SYMBOL(drm_mode_config_init); @@ -2160,15 +2206,16 @@ int drm_mode_output_update_edid_property(struct drm_output *output, unsigned cha EXPORT_SYMBOL(drm_mode_output_update_edid_property); int drm_mode_output_property_set_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv) + void *data, struct drm_file *file_priv) { struct drm_mode_output_set_property *out_resp = data; + struct drm_property *property; struct drm_output *output; int ret = -EINVAL; int i; mutex_lock(&dev->mode_config.mutex); - output= idr_find(&dev->mode_config.crtc_idr, out_resp->output_id); + output = idr_find(&dev->mode_config.crtc_idr, out_resp->output_id); if (!output || (output->id != out_resp->output_id)) { goto out; } @@ -2182,8 +2229,35 @@ int drm_mode_output_property_set_ioctl(struct drm_device *dev, goto out; } + property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); + if (!property || (property->id != out_resp->prop_id)) { + goto out; + } + + if (property->flags & DRM_MODE_PROP_IMMUTABLE) + goto out; + + if (property->flags & DRM_MODE_PROP_RANGE) { + if (out_resp->value < property->values[0]) + goto out; + + if (out_resp->value > property->values[1]) + goto out; + } else { + int found = 0; + for (i = 0; i < property->num_values; i++) { + if (property->values[i] == out_resp->value) { + found = 1; + break; + } + } + if (!found) { + goto out; + } + } + if (output->funcs->set_property) - ret = output->funcs->set_property(output, out_resp->prop_id, out_resp->value); + ret = output->funcs->set_property(output, property, out_resp->value); out: mutex_unlock(&dev->mode_config.mutex); -- cgit v1.2.3 From e239882b1e90cba0297118ec7dc432bea06b0bd0 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 4 Dec 2007 15:36:36 +0100 Subject: Modesetting Hotplug --- linux-core/drm_crtc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e1b37c0b..ac2f1d42 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -382,6 +382,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) drm_crtc_probe_single_output_modes(output, maxX, maxY); } } +EXPORT_SYMBOL(drm_crtc_probe_output_modes); /** * drm_crtc_set_mode - set a mode @@ -539,7 +540,8 @@ void drm_disable_unused_functions(struct drm_device *dev) crtc->funcs->dpms(crtc, DPMSModeOff); } } - +EXPORT_SYMBOL(drm_disable_unused_functions); + /** * drm_mode_probed_add - add a mode to the specified output's probed mode list * @output: output the new mode @@ -936,7 +938,7 @@ clone: } } } - +EXPORT_SYMBOL(drm_pick_crtcs); /** * drm_initial_config - setup a sane initial output configuration @@ -1122,6 +1124,54 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, return 0; } +/** + * drm_hotplug_stage_two + * @dev DRM device + * @output hotpluged output + * + * LOCKING. + * Caller must hold mode config lock, function might grap struct lock. + * + * Stage two of a hotplug. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) +{ + int has_config = 0; + + if (output->crtc && output->crtc->desired_mode) { + DRM_DEBUG("drm thinks that output already has a config\n"); + has_config = 1; + } + + drm_crtc_probe_output_modes(dev, 2048, 2048); + + if (!has_config) + drm_pick_crtcs(dev); + + if (!output->crtc || !output->crtc->desired_mode) { + DRM_DEBUG("could not find a desired mode or crtc for output\n"); + return 1; + } + + /* We should realy check if there is a fb using this crtc */ + if (!has_config) + dev->driver->fb_probe(dev, output->crtc); + else { + dev->driver->fb_resize(dev, output->crtc); + + if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0)) + DRM_ERROR("failed to set mode after hotplug\n"); + } + + drm_disable_unused_functions(dev); + + return 0; +} +EXPORT_SYMBOL(drm_hotplug_stage_two); + /** * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo * @out: drm_mode_modeinfo struct to return to the user -- cgit v1.2.3 From bdbc34e297bd7e4cb036df6244dfb0d816eed36d Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 18 Dec 2007 02:09:48 +0100 Subject: Fix and cleanup of Hotplug --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ac2f1d42..4397b867 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1142,7 +1142,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) int has_config = 0; if (output->crtc && output->crtc->desired_mode) { - DRM_DEBUG("drm thinks that output already has a config\n"); + DRM_DEBUG("drm thinks that the output already has a config\n"); has_config = 1; } -- cgit v1.2.3 From b13dc383df85d75cb1ea422f4d13efc2a4a8a732 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 18 Dec 2007 17:41:20 +1100 Subject: remove output names --- linux-core/drm_crtc.c | 68 ++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e1b37c0b..9a840ea1 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -58,7 +58,22 @@ static struct drm_prop_enum_list drm_conn_enum_list[] = { ConnectorHDMIA, "HDMI Type A" }, { ConnectorHDMIB, "HDMI Type B" }, }; +static struct drm_prop_enum_list drm_output_enum_list[] = +{ { DRM_MODE_OUTPUT_NONE, "None" }, + { DRM_MODE_OUTPUT_DAC, "DAC" }, + { DRM_MODE_OUTPUT_TMDS, "TMDS" }, + { DRM_MODE_OUTPUT_LVDS, "LVDS" }, + { DRM_MODE_OUTPUT_TVDAC, "TV" }, +}; +char *drm_get_output_name(struct drm_output *output) +{ + static char buf[32]; + + snprintf(buf, 32, "%s-%d", drm_output_enum_list[output->output_type].name, + output->output_type_id); + return buf; +} /** * drm_idr_get - allocate a new identifier @@ -322,7 +337,7 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int output->status = (*output->funcs->detect)(output); if (output->status == output_status_disconnected) { - DRM_DEBUG("%s is disconnected\n", output->name); + DRM_DEBUG("%s is disconnected\n", drm_get_output_name(output)); /* TODO set EDID to NULL */ return; } @@ -347,7 +362,7 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int if (list_empty(&output->modes)) { struct drm_display_mode *stdmode; - DRM_DEBUG("No valid modes on %s\n", output->name); + DRM_DEBUG("No valid modes on %s\n", drm_get_output_name(output)); /* Should we do this here ??? * When no valid EDID modes are available we end up @@ -360,12 +375,12 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int &output->modes); DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", - output->name); + drm_get_output_name(output)); } drm_mode_sort(&output->modes); - DRM_DEBUG("Probed modes for %s\n", output->name); + DRM_DEBUG("Probed modes for %s\n", drm_get_output_name(output)); list_for_each_entry_safe(mode, t, &output->modes, head) { mode->vrefresh = drm_mode_vrefresh(mode); @@ -472,7 +487,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 %x\n", output->name, mode->name, mode->mode_id); + DRM_INFO("%s: set mode %s %x\n", drm_get_output_name(output), mode->name, mode->mode_id); output->funcs->mode_set(output, mode, adjusted_mode); } @@ -591,7 +606,7 @@ EXPORT_SYMBOL(drm_mode_remove); */ struct drm_output *drm_output_create(struct drm_device *dev, const struct drm_output_funcs *funcs, - const char *name) + int output_type) { struct drm_output *output = NULL; @@ -602,9 +617,8 @@ struct drm_output *drm_output_create(struct drm_device *dev, output->dev = dev; output->funcs = funcs; output->id = drm_idr_get(dev, output); - if (name) - strncpy(output->name, name, DRM_OUTPUT_LEN); - output->name[DRM_OUTPUT_LEN - 1] = 0; + output->output_type = output_type; + output->output_type_id = 1; /* TODO */ output->subpixel_order = SubPixelUnknown; INIT_LIST_HEAD(&output->user_modes); INIT_LIST_HEAD(&output->probed_modes); @@ -663,35 +677,6 @@ void drm_output_destroy(struct drm_output *output) } EXPORT_SYMBOL(drm_output_destroy); -/** - * drm_output_rename - rename an output - * @output: output to rename - * @name: new user visible name - * - * LOCKING: - * None. - * - * Simply stuff a new name into @output's name field, based on @name. - * - * RETURNS: - * True if the name was changed, false otherwise. - */ -bool drm_output_rename(struct drm_output *output, const char *name) -{ - if (!name) - return false; - - strncpy(output->name, name, DRM_OUTPUT_LEN); - output->name[DRM_OUTPUT_LEN - 1] = 0; - - DRM_DEBUG("Changed name to %s\n", output->name); -// drm_output_set_monitor(output); -// if (drm_output_ignored(output)) -// return FALSE; - - return TRUE; -} -EXPORT_SYMBOL(drm_output_rename); /** * drm_mode_create - create a new display mode @@ -912,7 +897,7 @@ static void drm_pick_crtcs (struct drm_device *dev) list_for_each_entry(modes_equal, &output_equal->modes, head) { if (drm_mode_equal (modes, modes_equal)) { if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { - printk("Cloning %s (0x%lx) to %s (0x%lx)\n",output->name,output->possible_clones,output_equal->name,output_equal->possible_clones); + printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones); assigned = 0; goto clone; } @@ -1408,9 +1393,8 @@ int drm_mode_getoutput(struct drm_device *dev, drm_crtc_probe_single_output_modes(output, dev->mode_config.max_width, dev->mode_config.max_height); } - strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN); - out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0; - + out_resp->output_type = output->output_type; + out_resp->output_type_id = output->output_type_id; out_resp->mm_width = output->mm_width; out_resp->mm_height = output->mm_height; out_resp->subpixel = output->subpixel_order; -- cgit v1.2.3 From 01f905c1779279811d4f0467da4bdf33ff786c86 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 18 Dec 2007 19:16:51 +1100 Subject: we should not be unlocking this here --- linux-core/drm_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 9a840ea1..405b54b7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -165,7 +165,6 @@ struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev) /* Limit to single framebuffer for now */ if (dev->mode_config.num_fb > 1) { - mutex_unlock(&dev->mode_config.mutex); DRM_ERROR("Attempt to add multiple framebuffers failed\n"); return NULL; } -- cgit v1.2.3 From 219ba5cd9aff2dc79e414bbe2e9f90406f7543df Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 21 Dec 2007 18:38:55 +1000 Subject: s/TRUE/true --- linux-core/drm_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fef2700a..bb89cb10 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -356,7 +356,7 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int } - drm_mode_prune_invalid(dev, &output->modes, TRUE); + drm_mode_prune_invalid(dev, &output->modes, true); if (list_empty(&output->modes)) { struct drm_display_mode *stdmode; @@ -510,7 +510,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, /* XXX free adjustedmode */ drm_mode_destroy(dev, adjusted_mode); - ret = TRUE; + ret = true; /* TODO */ // if (scrn->pScreen) // drm_crtc_set_screen_sub_pixel_order(dev); -- cgit v1.2.3 From 10937cf20b6814e4cf68114fab4619fad94eafcb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 4 Jan 2008 16:12:24 +1100 Subject: drm: move drm_head to drm_minor and fix up users --- linux-core/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bb89cb10..dc8b1462 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -356,7 +356,7 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int } - drm_mode_prune_invalid(dev, &output->modes, true); + drm_mode_prune_invalid(dev, &output->modes, TRUE); if (list_empty(&output->modes)) { struct drm_display_mode *stdmode; @@ -510,7 +510,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, /* XXX free adjustedmode */ drm_mode_destroy(dev, adjusted_mode); - ret = true; + ret = TRUE; /* TODO */ // if (scrn->pScreen) // drm_crtc_set_screen_sub_pixel_order(dev); @@ -1781,7 +1781,7 @@ out: void drm_fb_release(struct file *filp) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_framebuffer *fb, *tfb; mutex_lock(&dev->mode_config.mutex); -- cgit v1.2.3 From df9cfeff37d40722df4e8a785478ac41246ca51f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 4 Jan 2008 17:48:42 +1100 Subject: crtc: fixup allocation size --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index dc8b1462..b49fa697 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1952,7 +1952,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, { struct drm_property *property = NULL; - property = kzalloc(sizeof(struct drm_output), GFP_KERNEL); + property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); if (!property) return NULL; -- cgit v1.2.3 From e04d942ee8e74fce90e332446e740a100d782033 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 9 Jan 2008 18:11:17 +1100 Subject: fixup crtcinfo on modes from userspace --- linux-core/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b49fa697..0b71b134 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1548,6 +1548,7 @@ int drm_mode_setcrtc(struct drm_device *dev, mode = drm_mode_create(dev); drm_crtc_convert_umode(mode, &crtc_req->mode); + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); } if (crtc_req->count_outputs == 0 && mode) { -- cgit v1.2.3 From 0b69c1d1d6a09d55d3367296dfdf23269f2721ea Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 11 Jan 2008 02:55:00 +0100 Subject: Added fixed misc framebuffer problems --- linux-core/drm_crtc.c | 53 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 0b71b134..fdf4c70e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -163,12 +163,6 @@ struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev) { struct drm_framebuffer *fb; - /* Limit to single framebuffer for now */ - if (dev->mode_config.num_fb > 1) { - DRM_ERROR("Attempt to add multiple framebuffers failed\n"); - return NULL; - } - fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL); if (!fb) return NULL; @@ -771,7 +765,11 @@ void drm_mode_config_init(struct drm_device *dev) idr_init(&dev->mode_config.crtc_idr); drm_mode_create_standard_output_properties(dev); - + + /* Just to be sure */ + dev->mode_config.num_fb = 0; + dev->mode_config.num_output = 0; + dev->mode_config.num_crtc = 0; } EXPORT_SYMBOL(drm_mode_config_init); @@ -1013,6 +1011,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) } list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { + /* there should only be bo of kernel type left */ if (fb->bo->type != drm_bo_type_kernel) drm_framebuffer_destroy(fb); else @@ -1621,7 +1620,6 @@ int drm_mode_addfb(struct drm_device *dev, struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; struct drm_buffer_object *bo; - struct drm_crtc *crtc; int ret = 0; if ((config->min_width > r->width) || (r->width > config->max_width)) { @@ -1637,6 +1635,7 @@ int drm_mode_addfb(struct drm_device *dev, /* TODO check limits are okay */ ret = drm_get_buffer_object(dev, &bo, r->handle); if (ret || !bo) { + DRM_ERROR("BO handle not valid\n"); ret = -EINVAL; goto out; } @@ -1646,6 +1645,7 @@ int drm_mode_addfb(struct drm_device *dev, fb = drm_framebuffer_create(dev); if (!fb) { + DRM_ERROR("could not create framebuffer\n"); ret = -EINVAL; goto out; } @@ -1662,12 +1662,6 @@ int drm_mode_addfb(struct drm_device *dev, list_add(&fb->filp_head, &file_priv->fbs); - /* FIXME: bind the fb to the right crtc */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - crtc->fb = fb; - dev->driver->fb_probe(dev, crtc); - } - out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1694,8 +1688,10 @@ int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_framebuffer *fb = 0; + struct drm_framebuffer *fbl = 0; uint32_t *id = data; int ret = 0; + int found = 0; mutex_lock(&dev->mode_config.mutex); fb = idr_find(&dev->mode_config.crtc_idr, *id); @@ -1706,15 +1702,24 @@ int drm_mode_rmfb(struct drm_device *dev, goto out; } - /* TODO check if we own the buffer */ + list_for_each_entry(fbl, &file_priv->fbs, filp_head) + if (fb == fbl) + found = 1; + + if (!found) { + DRM_ERROR("tried to remove a fb that we didn't own\n"); + ret = -EINVAL; + goto out; + } + /* TODO release all crtc connected to the framebuffer */ - /* bind the fb to the crtc for now */ /* TODO unhock the destructor from the buffer object */ - if (fb->bo->type != drm_bo_type_kernel) - drm_framebuffer_destroy(fb); - else - dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); + if (fb->bo->type == drm_bo_type_kernel) + DRM_ERROR("the bo type should not be of kernel type\n"); + + list_del(&fb->filp_head); + drm_framebuffer_destroy(fb); out: mutex_unlock(&dev->mode_config.mutex); @@ -1788,10 +1793,10 @@ void drm_fb_release(struct file *filp) mutex_lock(&dev->mode_config.mutex); list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { list_del(&fb->filp_head); - if (fb->bo->type != drm_bo_type_kernel) - drm_framebuffer_destroy(fb); - else - dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); + if (fb->bo->type == drm_bo_type_kernel) + DRM_ERROR("the bo type should not be of kernel_type, the kernel will probably explode, why Dave\n"); + + drm_framebuffer_destroy(fb); } mutex_unlock(&dev->mode_config.mutex); } -- cgit v1.2.3 From f07942f74a08e4c65e3b5e5c46f543686ae30c2b Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 11 Jan 2008 17:13:48 +0100 Subject: Panning now works without modeset --- linux-core/drm_crtc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fdf4c70e..1e69eca3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1048,6 +1048,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_crtc **save_crtcs, *new_crtc; bool save_enabled = crtc->enabled; bool changed = false; + bool flip_or_move = false; struct drm_output *output; int count = 0, ro; @@ -1055,11 +1056,13 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, if (!save_crtcs) return -ENOMEM; + /* We should be able to check here if the fb has the same properties + * and then just flip_or_move it */ if (crtc->fb != fb) changed = true; if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) - changed = true; + flip_or_move = true; if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) changed = true; @@ -1082,6 +1085,10 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } } + /* mode_set_base is not a required function */ + if (flip_or_move && !crtc->funcs->mode_set_base) + changed = true; + if (changed) { crtc->fb = fb; crtc->enabled = (new_mode != NULL); @@ -1102,7 +1109,10 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, crtc->desired_mode = new_mode; } drm_disable_unused_functions(dev); + } else if (flip_or_move) { + crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y); } + kfree(save_crtcs); return 0; } @@ -1564,6 +1574,7 @@ int drm_mode_setcrtc(struct drm_device *dev, if (crtc_req->count_outputs > 0) { u32 out_id; + /* Maybe we should check that count_outputs is a sensible value. */ output_set = kmalloc(crtc_req->count_outputs * sizeof(struct drm_output *), GFP_KERNEL); if (!output_set) { @@ -1589,6 +1600,7 @@ int drm_mode_setcrtc(struct drm_device *dev, } } + /* What happens to output_set, leak? */ ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); out: -- cgit v1.2.3 From a2254c5a9670a3e865f0eb5acd46e905c9b146ce Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Jan 2008 03:12:29 +0100 Subject: Added cursor support --- linux-core/drm_crtc.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1e69eca3..18fa02ce 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1608,6 +1608,63 @@ out: return ret; } +int drm_mode_cursor_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_cursor *req = data; + struct drm_crtc *crtc; + struct drm_buffer_object *bo = NULL; /* must be set */ + int ret = 0; + + DRM_DEBUG("\n"); + + if (!req->flags) { + DRM_ERROR("no operation set\n"); + return -EINVAL; + } + + mutex_lock(&dev->mode_config.mutex); + crtc = idr_find(&dev->mode_config.crtc_idr, req->crtc); + if (!crtc || (crtc->id != req->crtc)) { + DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc); + ret = -EINVAL; + goto out; + } + + if (req->flags & DRM_MODE_CURSOR_BO) { + /* Turn of the cursor if handle is 0 */ + if (req->handle) + ret = drm_get_buffer_object(dev, &bo, req->handle); + + if (ret) { + DRM_ERROR("invalid buffer id\n"); + ret = -EINVAL; + goto out; + } + + if (crtc->funcs->cursor_set) { + ret = crtc->funcs->cursor_set(crtc, bo, req->width, req->height); + } else { + DRM_ERROR("crtc does not support cursor\n"); + ret = -EFAULT; + goto out; + } + } + + if (req->flags & DRM_MODE_CURSOR_MOVE) { + if (crtc->funcs->cursor_move) { + ret = crtc->funcs->cursor_move(crtc, req->x, req->y); + } else { + DRM_ERROR("crtc does not support cursor\n"); + ret = -EFAULT; + goto out; + } + } +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + /** * drm_mode_addfb - add an FB to the graphics configuration * @inode: inode from the ioctl -- cgit v1.2.3 From f2c706e24782940582b75d5286f9bbf2fe37f0cd Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 5 Feb 2008 10:11:01 +0000 Subject: Fix function declaration --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 18fa02ce..03e5ffe9 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2299,7 +2299,7 @@ done: return ret; } -int drm_mode_output_update_edid_property(struct drm_output *output, unsigned char *edid) +int drm_mode_output_update_edid_property(struct drm_output *output, struct edid *edid) { struct drm_device *dev = output->dev; int ret = 0; -- cgit v1.2.3 From 0618ac8a07d834e469cb96818a1dfee6f50662b8 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 7 Feb 2008 19:24:58 +0100 Subject: Added kernel part of hotplug ioctl --- linux-core/drm_crtc.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 03e5ffe9..55390a82 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -770,6 +770,7 @@ void drm_mode_config_init(struct drm_device *dev) dev->mode_config.num_fb = 0; dev->mode_config.num_output = 0; dev->mode_config.num_crtc = 0; + dev->mode_config.hotplug_counter = 0; } EXPORT_SYMBOL(drm_mode_config_init); @@ -1130,10 +1131,18 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, * RETURNS: * Zero on success, errno on failure. */ -int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) +int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, + bool connected) { int has_config = 0; + /* We might want to do something more here */ + if (!connected) { + DRM_DEBUG("not connected\n"); + dev->mode_config.hotplug_counter++; + return 0; + } + if (output->crtc && output->crtc->desired_mode) { DRM_DEBUG("drm thinks that the output already has a config\n"); has_config = 1; @@ -1146,7 +1155,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) if (!output->crtc || !output->crtc->desired_mode) { DRM_DEBUG("could not find a desired mode or crtc for output\n"); - return 1; + goto out_err; } /* We should realy check if there is a fb using this crtc */ @@ -1161,10 +1170,25 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) drm_disable_unused_functions(dev); + dev->mode_config.hotplug_counter++; return 0; + +out_err: + dev->mode_config.hotplug_counter++; + return 1; } EXPORT_SYMBOL(drm_hotplug_stage_two); +int drm_mode_hotplug_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_hotplug *arg = data; + + arg->counter = dev->mode_config.hotplug_counter; + + return 0; +} + /** * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo * @out: drm_mode_modeinfo struct to return to the user -- cgit v1.2.3 From 222092a1a810b67b014ad6881f0c028ec6563329 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 15 Feb 2008 16:15:04 +1000 Subject: various fixes from trying to get userspace started --- linux-core/drm_crtc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 55390a82..3a0dd9c8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1094,7 +1094,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, crtc->fb = fb; crtc->enabled = (new_mode != NULL); if (new_mode != NULL) { - DRM_DEBUG("attempting to set mode from userspace\n"); + DRM_DEBUG("attempting to set mode from userspace %p\n", crtc->fb); drm_mode_debug_printmodeline(dev, new_mode); if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x, crtc_info->y)) { @@ -1577,7 +1577,13 @@ int drm_mode_setcrtc(struct drm_device *dev, ret = -EINVAL; goto out; } + DRM_DEBUG("found fb %p for id %d\n", fb, crtc_req->fb_id); + } else { + DRM_DEBUG("Unknown FB ID %d\n", crtc_req->fb_id); + ret = -EINVAL; + goto out; } + mode = drm_mode_create(dev); drm_crtc_convert_umode(mode, &crtc_req->mode); -- cgit v1.2.3 From 088b38382962a9dccca59a53af2444a1fe8bc18f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 15 Feb 2008 16:42:44 +1000 Subject: fb: fixup the offset by getting it from the right place --- linux-core/drm_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 3a0dd9c8..aceb31b4 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1754,7 +1754,6 @@ int drm_mode_addfb(struct drm_device *dev, fb->pitch = r->pitch; fb->bits_per_pixel = r->bpp; fb->depth = r->depth; - fb->offset = bo->offset; fb->bo = bo; r->buffer_id = fb->id; -- cgit v1.2.3 From 2b1c9cd696049d23845870329d2b61a5873f7b13 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 15 Feb 2008 16:13:21 -0800 Subject: i915: initial (and untested) TV out support Ported from xf86-video-intel. Still need to tie in TV modes somehow, though preferably w/o using the properties mechanism. --- linux-core/drm_crtc.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index aceb31b4..6b8cb9c7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -38,6 +38,9 @@ struct drm_prop_enum_list { char *name; }; +/* + * Global properties + */ static struct drm_prop_enum_list drm_dpms_enum_list[] = { { DPMSModeOn, "On" }, { DPMSModeStandby, "Standby" }, @@ -720,6 +723,9 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) { int i; + /* + * Standard properties (apply to all outputs) + */ dev->mode_config.edid_property = drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, "EDID", 0); @@ -741,6 +747,39 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) "Connector ID", 2); dev->mode_config.connector_num_property->values[0] = 0; dev->mode_config.connector_num_property->values[1] = 20; + + /* + * TV specific properties + */ + dev->mode_config.tv_left_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE | + DRM_MODE_PROP_IMMUTABLE, + "left margin", 2); + dev->mode_config.tv_left_margin_property->values[0] = 0; + dev->mode_config.tv_left_margin_property->values[1] = 100; + + dev->mode_config.tv_right_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE | + DRM_MODE_PROP_IMMUTABLE, + "right margin", 2); + dev->mode_config.tv_right_margin_property->values[0] = 0; + dev->mode_config.tv_right_margin_property->values[1] = 100; + + dev->mode_config.tv_top_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE | + DRM_MODE_PROP_IMMUTABLE, + "top margin", 2); + dev->mode_config.tv_top_margin_property->values[0] = 0; + dev->mode_config.tv_top_margin_property->values[1] = 100; + + dev->mode_config.tv_bottom_margin_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE | + DRM_MODE_PROP_IMMUTABLE, + "bottom margin", 2); + dev->mode_config.tv_bottom_margin_property->values[0] = 0; + dev->mode_config.tv_bottom_margin_property->values[1] = 100; + + return 0; } @@ -1094,7 +1133,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, crtc->fb = fb; crtc->enabled = (new_mode != NULL); if (new_mode != NULL) { - DRM_DEBUG("attempting to set mode from userspace %p\n", crtc->fb); + DRM_DEBUG("attempting to set mode from userspace\n"); drm_mode_debug_printmodeline(dev, new_mode); if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x, crtc_info->y)) { @@ -1577,13 +1616,7 @@ int drm_mode_setcrtc(struct drm_device *dev, ret = -EINVAL; goto out; } - DRM_DEBUG("found fb %p for id %d\n", fb, crtc_req->fb_id); - } else { - DRM_DEBUG("Unknown FB ID %d\n", crtc_req->fb_id); - ret = -EINVAL; - goto out; } - mode = drm_mode_create(dev); drm_crtc_convert_umode(mode, &crtc_req->mode); @@ -1754,6 +1787,7 @@ int drm_mode_addfb(struct drm_device *dev, fb->pitch = r->pitch; fb->bits_per_pixel = r->bpp; fb->depth = r->depth; + fb->offset = bo->offset; fb->bo = bo; r->buffer_id = fb->id; -- cgit v1.2.3 From e484681a43964502bf7e61a1701bb85ab6befab3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 20 Feb 2008 11:44:10 +1000 Subject: remove more offset --- linux-core/drm_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 6b8cb9c7..ebd15c5e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1787,7 +1787,6 @@ int drm_mode_addfb(struct drm_device *dev, fb->pitch = r->pitch; fb->bits_per_pixel = r->bpp; fb->depth = r->depth; - fb->offset = bo->offset; fb->bo = bo; r->buffer_id = fb->id; -- cgit v1.2.3 From fad1db2d73f8dd95f17db10c7ea381c7774e3c29 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 21 Feb 2008 15:58:56 +1000 Subject: modesetting: fix memory leak and misallocation --- linux-core/drm_crtc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ebd15c5e..bf37730b 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1092,7 +1092,8 @@ 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->mode_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL); + /* this is meant to be num_output not num_crtc */ + save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL); if (!save_crtcs) return -ENOMEM; @@ -1663,10 +1664,10 @@ int drm_mode_setcrtc(struct drm_device *dev, } } - /* What happens to output_set, leak? */ ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); out: + kfree(output_set); mutex_unlock(&dev->mode_config.mutex); return ret; } -- cgit v1.2.3 From 879fb12e289e8997ef325dd5b0068d0d4d6c26df Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 26 Feb 2008 17:11:03 +1100 Subject: drm: fix pick crtcs mode selection code --- linux-core/drm_crtc.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bf37730b..73ab10ec 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -870,6 +870,7 @@ static void drm_pick_crtcs (struct drm_device *dev) struct drm_output *output, *output_equal; struct drm_crtc *crtc; struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; + int found; list_for_each_entry(output, &dev->mode_config.output_list, head) { output->crtc = NULL; @@ -890,17 +891,23 @@ static void drm_pick_crtcs (struct drm_device *dev) if (output->status != output_status_connected) continue; + if (list_empty(&output->modes)) + continue; + des_mode = NULL; + found = 0; list_for_each_entry(des_mode, &output->modes, head) { - if (des_mode->type & DRM_MODE_TYPE_PREFERRED) + if (des_mode->type & DRM_MODE_TYPE_PREFERRED) { + found = 1; break; + } } /* No preferred mode, let's just select the first available */ - if (!des_mode || !(des_mode->type & DRM_MODE_TYPE_PREFERRED)) { + if (!found) { + des_mode = NULL; list_for_each_entry(des_mode, &output->modes, head) { - if (des_mode) - break; + break; } } -- cgit v1.2.3 From 2476cb209ebbb11edace4bbce0cfaff4e1599dca Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 22 Feb 2008 11:46:22 +0000 Subject: Implement short circuit for base change only Allow mode to be set with fb_id set to -1, meaning set the mode with the current fb (if we have one bound). Allow intelfb to hook back up it's fb if modesetting clears it (maybe temporary). Move any crtc->fb related register changes to set_base in intel_fb. General intelfb cleanups. --- linux-core/drm_crtc.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 73ab10ec..36d9fc56 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -418,7 +418,6 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, saved_mode; int saved_x, saved_y; bool didLock = false; - bool ret = false; struct drm_output *output; adjusted_mode = drm_mode_duplicate(dev, mode); @@ -442,8 +441,13 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, crtc->x = x; crtc->y = y; - /* XXX short-circuit changes to base location only */ - + if (drm_mode_equal(&saved_mode, &crtc->mode)) { + if (saved_x != crtc->x || saved_y != crtc->y) { + crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); + goto done; + } + } + /* Pass our mode to the outputs and the CRTC to give them a chance to * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. @@ -507,22 +511,15 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, /* XXX free adjustedmode */ drm_mode_destroy(dev, adjusted_mode); - ret = TRUE; /* TODO */ // if (scrn->pScreen) // drm_crtc_set_screen_sub_pixel_order(dev); done: - if (!ret) { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->mode = saved_mode; - } - if (didLock) crtc->funcs->unlock (crtc); - return ret; + return true; } EXPORT_SYMBOL(drm_crtc_set_mode); @@ -1599,13 +1596,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc *crtc_req = data; - struct drm_crtc *crtc; + struct drm_crtc *crtc, *crtcfb; struct drm_output **output_set = NULL, *output; struct drm_framebuffer *fb = NULL; struct drm_display_mode *mode = NULL; + uint32_t __user *set_outputs_ptr; int ret = 0; int i; - uint32_t __user *set_outputs_ptr; mutex_lock(&dev->mode_config.mutex); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id); @@ -1616,8 +1613,16 @@ int drm_mode_setcrtc(struct drm_device *dev, } if (crtc_req->mode_valid) { - /* if we have a mode we need a framebuffer */ - if (crtc_req->fb_id) { + /* If we have a mode we need a framebuffer. */ + /* If we pass -1, set the mode with the currently bound fb */ + if (crtc_req->fb_id == -1) { + list_for_each_entry(crtcfb, &dev->mode_config.crtc_list, head) { + if (crtcfb == crtc) { + DRM_INFO("Using current fb for setmode\n"); + fb = crtc->fb; + } + } + } else { fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id); if (!fb || (fb->id != crtc_req->fb_id)) { DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id); -- cgit v1.2.3 From 191385d51880d5757c8038ff4b46ee5ccb3561c1 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 26 Feb 2008 15:20:59 +0000 Subject: DRM_INFO -> DRM_DEBUG --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 36d9fc56..1a4624c8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1618,7 +1618,7 @@ int drm_mode_setcrtc(struct drm_device *dev, if (crtc_req->fb_id == -1) { list_for_each_entry(crtcfb, &dev->mode_config.crtc_list, head) { if (crtcfb == crtc) { - DRM_INFO("Using current fb for setmode\n"); + DRM_DEBUG("Using current fb for setmode\n"); fb = crtc->fb; } } -- cgit v1.2.3 From 5662934ee467c3a29f9551a40fc7b2f6ee16280a Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:50:59 +0000 Subject: Fix connector description table --- linux-core/drm_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1a4624c8..345569b6 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -48,7 +48,8 @@ static struct drm_prop_enum_list drm_dpms_enum_list[] = { DPMSModeOff, "Off" } }; static struct drm_prop_enum_list drm_conn_enum_list[] = -{ { ConnectorVGA, "VGA" }, +{ { ConnectorUnknown, "Unknown" }, + { ConnectorVGA, "VGA" }, { ConnectorDVII, "DVI-I" }, { ConnectorDVID, "DVI-D" }, { ConnectorDVIA, "DVI-A" }, -- cgit v1.2.3 From 3ea1902be993e88c068ce67355e2b3d253d1c9f2 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:51:56 +0000 Subject: propogate failed fixups back up --- linux-core/drm_crtc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 345569b6..5f93275a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -458,12 +458,12 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, if (output->crtc != crtc) continue; - if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + if (!(ret = output->funcs->mode_fixup(output, mode, adjusted_mode))) { goto done; } } - if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + if (!(ret = crtc->funcs->mode_fixup(crtc, mode, adjusted_mode))) { goto done; } @@ -517,10 +517,16 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, // drm_crtc_set_screen_sub_pixel_order(dev); done: + if (!ret) { + crtc->mode = saved_mode; + crtc->x = saved_x; + crtc->y = saved_y; + } + if (didLock) crtc->funcs->unlock (crtc); - return true; + return ret; } EXPORT_SYMBOL(drm_crtc_set_mode); -- cgit v1.2.3 From 8bfe29d9e44690a3896406acb25ca654dfad054d Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 4 Mar 2008 17:52:37 +0000 Subject: Use ARRAY_SIZE --- linux-core/drm_crtc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 5f93275a..dfa0987f 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -735,20 +735,20 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) "EDID", 0); dev->mode_config.dpms_property = - drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4); - + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name); dev->mode_config.connector_type_property = drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, - "Connector Type", 10); + "Connector Type", ARRAY_SIZE(drm_conn_enum_list)); for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++) drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name); dev->mode_config.connector_num_property = drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, - "Connector ID", 2); + "Connector ID", 2); dev->mode_config.connector_num_property->values[0] = 0; dev->mode_config.connector_num_property->values[1] = 20; @@ -783,7 +783,6 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) dev->mode_config.tv_bottom_margin_property->values[0] = 0; dev->mode_config.tv_bottom_margin_property->values[1] = 100; - return 0; } -- cgit v1.2.3 From fef1c93aa87a1ccbc473749a7e42557fc90a1fca Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 5 Mar 2008 10:33:57 +0000 Subject: build fix --- linux-core/drm_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index dfa0987f..be491908 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -420,14 +420,14 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int saved_x, saved_y; bool didLock = false; struct drm_output *output; + bool ret = true; adjusted_mode = drm_mode_duplicate(dev, mode); crtc->enabled = drm_crtc_in_use(crtc); - if (!crtc->enabled) { + if (!crtc->enabled) return true; - } didLock = crtc->funcs->lock(crtc); -- cgit v1.2.3 From 33cb42a9f7c7c4f4dd91756af55de7352944efa4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Mar 2008 13:03:42 +1100 Subject: make startup of Xorg smoother if the mode doesn't change. just flip the framebuffer in when required. --- linux-core/drm_crtc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index be491908..e0c85cef 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1110,13 +1110,17 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ if (crtc->fb != fb) - changed = true; + flip_or_move = true; if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) flip_or_move = true; - if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) + if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) { + DRM_DEBUG("modes are different\n"); + drm_mode_debug_printmodeline(dev, &crtc->mode); + drm_mode_debug_printmodeline(dev, new_mode); changed = true; + } list_for_each_entry(output, &dev->mode_config.output_list, head) { save_crtcs[count++] = output->crtc; @@ -1161,6 +1165,8 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } drm_disable_unused_functions(dev); } else if (flip_or_move) { + if (crtc->fb != fb) + crtc->fb = fb; crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y); } -- cgit v1.2.3 From 903d9231d6f998657cc80ee6f20ded4df68e691b Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 11 Mar 2008 20:29:37 +0000 Subject: Add support for monitor hotplug signals/waits Also adjust i915 irq handling as it follows the 16bit'ism's of the i8xx series. --- linux-core/drm_crtc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e0c85cef..0cd0ebd0 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -947,6 +947,7 @@ static void drm_pick_crtcs (struct drm_device *dev) if (drm_mode_equal (modes, modes_equal)) { if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones); + des_mode = modes; assigned = 0; goto clone; } @@ -1180,7 +1181,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, * @output hotpluged output * * LOCKING. - * Caller must hold mode config lock, function might grap struct lock. + * Caller must hold mode config lock, function might grab struct lock. * * Stage two of a hotplug. * @@ -1192,10 +1193,11 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, { int has_config = 0; + dev->mode_config.hotplug_counter++; + /* We might want to do something more here */ if (!connected) { DRM_DEBUG("not connected\n"); - dev->mode_config.hotplug_counter++; return 0; } @@ -1211,10 +1213,10 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, if (!output->crtc || !output->crtc->desired_mode) { DRM_DEBUG("could not find a desired mode or crtc for output\n"); - goto out_err; + return 1; } - /* We should realy check if there is a fb using this crtc */ + /* We should really check if there is a fb using this crtc */ if (!has_config) dev->driver->fb_probe(dev, output->crtc); else { @@ -1226,12 +1228,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, drm_disable_unused_functions(dev); - dev->mode_config.hotplug_counter++; return 0; - -out_err: - dev->mode_config.hotplug_counter++; - return 1; } EXPORT_SYMBOL(drm_hotplug_stage_two); -- cgit v1.2.3 From 5a3ce06f3a3dfa9412b9660c1e1f35d24c815dbb Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 8 Apr 2008 12:42:23 -0700 Subject: Improved DRM sysfs support This patch ties outputs, output properties and hotplug events into the DRM core. Each output has a corresponding directory under the primary DRM device (usually card0) containing dpms, edid, modes, and connection status files. New hotplug change events occur when outputs are added or hotplug events are detected. --- linux-core/drm_crtc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 0cd0ebd0..19155e1f 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -47,6 +47,18 @@ static struct drm_prop_enum_list drm_dpms_enum_list[] = { DPMSModeSuspend, "Suspend" }, { DPMSModeOff, "Off" } }; + +char *drm_get_dpms_name(int val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) + if (drm_dpms_enum_list[i].type == val) + return drm_dpms_enum_list[i].name; + + return "unknown"; +} + static struct drm_prop_enum_list drm_conn_enum_list[] = { { ConnectorUnknown, "Unknown" }, { ConnectorVGA, "VGA" }, @@ -79,6 +91,16 @@ char *drm_get_output_name(struct drm_output *output) return buf; } +char *drm_get_output_status_name(enum drm_output_status status) +{ + if (status == output_status_connected) + return "connected"; + else if (status == output_status_disconnected) + return "disconnected"; + else + return "unknown"; +} + /** * drm_idr_get - allocate a new identifier * @dev: DRM device @@ -629,6 +651,8 @@ struct drm_output *drm_output_create(struct drm_device *dev, /* output_set_monitor(output)? */ /* check for output_ignored(output)? */ + drm_sysfs_output_add(output); + mutex_lock(&dev->mode_config.mutex); list_add_tail(&output->head, &dev->mode_config.output_list); dev->mode_config.num_output++; @@ -659,6 +683,8 @@ void drm_output_destroy(struct drm_output *output) struct drm_device *dev = output->dev; struct drm_display_mode *mode, *t; + drm_sysfs_output_remove(output); + if (*output->funcs->cleanup) (*output->funcs->cleanup)(output); @@ -1226,6 +1252,8 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, DRM_ERROR("failed to set mode after hotplug\n"); } + drm_sysfs_hotplug_event(dev); + drm_disable_unused_functions(dev); return 0; @@ -2223,6 +2251,24 @@ int drm_output_property_set_value(struct drm_output *output, } EXPORT_SYMBOL(drm_output_property_set_value); +int drm_output_property_get_value(struct drm_output *output, + struct drm_property *property, uint64_t *val) +{ + int i; + + for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { + if (output->property_ids[i] == property->id) { + *val = output->property_values[i]; + break; + } + } + + if (i == DRM_OUTPUT_MAX_PROPERTY) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL(drm_output_property_get_value); + int drm_mode_getproperty_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { -- cgit v1.2.3 From fa116081a919e716eb95fcfa421d93f10f6f0a4f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 9 Apr 2008 11:30:15 -0700 Subject: Fixup sysfs output registration Put off registering new outputs with sysfs until they're properly configured, or we may get duplicates if the type hasn't been set yet (as is the case with SDVO initialization). This also means moving de-registration into the cleanup function instead of output destroy, since the latter occurs during the normal course of setup when an output isn't found (and therefore not registered with sysfs yet. --- linux-core/drm_crtc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 19155e1f..f54ceb76 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -651,8 +651,6 @@ struct drm_output *drm_output_create(struct drm_device *dev, /* output_set_monitor(output)? */ /* check for output_ignored(output)? */ - drm_sysfs_output_add(output); - mutex_lock(&dev->mode_config.mutex); list_add_tail(&output->head, &dev->mode_config.output_list); dev->mode_config.num_output++; @@ -683,8 +681,6 @@ void drm_output_destroy(struct drm_output *output) struct drm_device *dev = output->dev; struct drm_display_mode *mode, *t; - drm_sysfs_output_remove(output); - if (*output->funcs->cleanup) (*output->funcs->cleanup)(output); @@ -1080,6 +1076,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) struct drm_property *property, *pt; list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { + drm_sysfs_output_remove(output); drm_output_destroy(output); } -- cgit v1.2.3 From 0a6e301e6de3421f116d1b5d8205ca4f442091e2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 11:23:55 -0700 Subject: Keep display info in struct display_info Some fields had snuck into the drm_output structure. Put them back and fill in more stuff from the EDID block. --- linux-core/drm_crtc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f54ceb76..f4377821 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -643,7 +643,6 @@ struct drm_output *drm_output_create(struct drm_device *dev, output->id = drm_idr_get(dev, output); output->output_type = output_type; output->output_type_id = 1; /* TODO */ - output->subpixel_order = SubPixelUnknown; INIT_LIST_HEAD(&output->user_modes); INIT_LIST_HEAD(&output->probed_modes); INIT_LIST_HEAD(&output->modes); @@ -1555,9 +1554,9 @@ int drm_mode_getoutput(struct drm_device *dev, out_resp->output_type = output->output_type; out_resp->output_type_id = output->output_type_id; - out_resp->mm_width = output->mm_width; - out_resp->mm_height = output->mm_height; - out_resp->subpixel = output->subpixel_order; + out_resp->mm_width = output->display_info.width_mm; + out_resp->mm_height = output->display_info.height_mm; + out_resp->subpixel = output->display_info.subpixel_order; out_resp->connection = output->status; if (output->crtc) out_resp->crtc = output->crtc->id; -- cgit v1.2.3 From bee546ad696e3157b878dfa90e563786b5b5c7ac Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 19:02:53 -0700 Subject: Remove structure fields & code Cleanup some random cruft left over from the initial port. --- linux-core/drm_crtc.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f4377821..b33edce7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -440,7 +440,6 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_device *dev = crtc->dev; struct drm_display_mode *adjusted_mode, saved_mode; int saved_x, saved_y; - bool didLock = false; struct drm_output *output; bool ret = true; @@ -451,8 +450,6 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, if (!crtc->enabled) return true; - didLock = crtc->funcs->lock(crtc); - saved_mode = crtc->mode; saved_x = crtc->x; saved_y = crtc->y; @@ -544,9 +541,6 @@ done: crtc->x = saved_x; crtc->y = saved_y; } - - if (didLock) - crtc->funcs->unlock (crtc); return ret; } -- cgit v1.2.3 From 83c3acb7da1043a63d260d5443f7149b2c664b08 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 20:30:12 -0700 Subject: Split TV property creation into its own routine It needs to take arguments from the caller about supported TV formats, so declare it in drm_crtc.h and export it. --- linux-core/drm_crtc.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b33edce7..1e5195db 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -767,9 +767,25 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) dev->mode_config.connector_num_property->values[0] = 0; dev->mode_config.connector_num_property->values[1] = 20; - /* - * TV specific properties - */ + return 0; +} + +/** + * drm_create_tv_properties - create TV specific output properties + * @dev: DRM device + * @num_modes: number of different TV formats (modes) supported + * @modes: array of pointers to strings containing name of each format + * + * Called by a driver's TV initialization routine, this function creates + * the TV specific output properties for a given device. Caller is + * responsible for allocating a list of format names and passing them to + * this routine. + */ +bool drm_create_tv_properties(struct drm_device *dev, int num_modes, + char *modes[]) +{ + int i; + dev->mode_config.tv_left_margin_property = drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, @@ -778,28 +794,33 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) dev->mode_config.tv_left_margin_property->values[1] = 100; dev->mode_config.tv_right_margin_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE | - DRM_MODE_PROP_IMMUTABLE, + drm_property_create(dev, DRM_MODE_PROP_RANGE, "right margin", 2); dev->mode_config.tv_right_margin_property->values[0] = 0; dev->mode_config.tv_right_margin_property->values[1] = 100; dev->mode_config.tv_top_margin_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE | - DRM_MODE_PROP_IMMUTABLE, + drm_property_create(dev, DRM_MODE_PROP_RANGE, "top margin", 2); dev->mode_config.tv_top_margin_property->values[0] = 0; dev->mode_config.tv_top_margin_property->values[1] = 100; dev->mode_config.tv_bottom_margin_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE | - DRM_MODE_PROP_IMMUTABLE, + drm_property_create(dev, DRM_MODE_PROP_RANGE, "bottom margin", 2); dev->mode_config.tv_bottom_margin_property->values[0] = 0; dev->mode_config.tv_bottom_margin_property->values[1] = 100; + dev->mode_config.tv_mode_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "mode", num_modes); + for (i = 0; i < num_modes; i++) + drm_property_add_enum(dev->mode_config.tv_mode_property, i, + i, modes[i]); + return 0; } +EXPORT_SYMBOL(drm_create_tv_properties); /** * drm_mode_config_init - initialize DRM mode_configuration structure -- cgit v1.2.3 From ed072ed075ec431b0746ac1aa8bad5f687d75d8c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 8 May 2008 14:01:24 +1000 Subject: drm_mode: initial replacefb implemenation --- linux-core/drm_crtc.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1e5195db..60255f54 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1879,8 +1879,8 @@ out: int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_framebuffer *fb = 0; - struct drm_framebuffer *fbl = 0; + struct drm_framebuffer *fb = NULL; + struct drm_framebuffer *fbl = NULL; uint32_t *id = data; int ret = 0; int found = 0; @@ -2513,3 +2513,54 @@ out: return ret; } + +int drm_mode_replacefb(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_fb_cmd *r = data; + struct drm_framebuffer *fb; + struct drm_crtc *crtc; + struct drm_buffer_object *bo; + int found = 0; + struct drm_framebuffer *fbl = NULL; + int ret = 0; + /* right replace the current bo attached to this fb with a new bo */ + mutex_lock(&dev->mode_config.mutex); + ret = drm_get_buffer_object(dev, &bo, r->handle); + if (ret || !bo) { + ret = -EINVAL; + goto out; + } + + fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id); + if (!fb || (r->buffer_id != fb->id)) { + ret = -EINVAL; + goto out; + } + + list_for_each_entry(fbl, &file_priv->fbs, filp_head) + if (fb == fbl) + found = 1; + + if (!found) { + DRM_ERROR("tried to replace an fb we didn't own\n"); + ret = -EINVAL; + goto out; + } + + if (fb->bo->type == drm_bo_type_kernel) + DRM_ERROR("the bo should not be a kernel bo\n"); + + fb->bo = bo; + + /* find all crtcs connected to this fb */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (crtc->fb->id == r->buffer_id) { + crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); + } + } +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; + +} -- cgit v1.2.3 From 576cba86b704c0de484ba852b8dce5b24d683f7e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 8 May 2008 16:09:45 +1000 Subject: drm: fix replacefb to change fb properties --- linux-core/drm_crtc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 60255f54..2d1c8064 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2551,6 +2551,11 @@ int drm_mode_replacefb(struct drm_device *dev, if (fb->bo->type == drm_bo_type_kernel) DRM_ERROR("the bo should not be a kernel bo\n"); + fb->width = r->width; + fb->height = r->height; + fb->pitch = r->pitch; + fb->bits_per_pixel = r->bpp; + fb->depth = r->depth; fb->bo = bo; /* find all crtcs connected to this fb */ -- cgit v1.2.3 From ba36d54ad4a3ea52b338d55ca19a864283e7c9ce Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 8 May 2008 15:00:18 +0200 Subject: drm: Made set_config use drm_mode_set as a argument --- linux-core/drm_crtc.c | 74 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 27 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 2d1c8064..bdcf5f9b 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1130,16 +1130,27 @@ EXPORT_SYMBOL(drm_mode_config_cleanup); * RETURNS: * Zero. (FIXME) */ -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, struct drm_framebuffer *fb) +int drm_crtc_set_config(struct drm_mode_set *set) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev; struct drm_crtc **save_crtcs, *new_crtc; - bool save_enabled = crtc->enabled; + bool save_enabled; bool changed = false; bool flip_or_move = false; struct drm_output *output; int count = 0, ro; + if (!set) + return -EINVAL; + + if (!set->crtc) + return -EINVAL; + + dev = set->crtc->dev; + + /* save previous config */ + save_enabled = set->crtc->enabled; + /* this is meant to be num_output not num_crtc */ save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL); if (!save_crtcs) @@ -1147,30 +1158,30 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ - if (crtc->fb != fb) + if (set->crtc->fb != set->fb) flip_or_move = true; - if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) + if (set->x != set->crtc->x || set->y != set->crtc->y) flip_or_move = true; - if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) { + if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { DRM_DEBUG("modes are different\n"); - drm_mode_debug_printmodeline(dev, &crtc->mode); - drm_mode_debug_printmodeline(dev, new_mode); + drm_mode_debug_printmodeline(dev, &set->crtc->mode); + drm_mode_debug_printmodeline(dev, set->mode); changed = true; } list_for_each_entry(output, &dev->mode_config.output_list, head) { save_crtcs[count++] = output->crtc; - if (output->crtc == crtc) + if (output->crtc == set->crtc) new_crtc = NULL; else new_crtc = output->crtc; - for (ro = 0; ro < crtc_info->count_outputs; ro++) { - if (output_set[ro] == output) - new_crtc = crtc; + for (ro = 0; ro < set->num_outputs; ro++) { + if (set->outputs[ro] == output) + new_crtc = set->crtc; } if (new_crtc != output->crtc) { changed = true; @@ -1179,33 +1190,34 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } /* mode_set_base is not a required function */ - if (flip_or_move && !crtc->funcs->mode_set_base) + if (flip_or_move && !set->crtc->funcs->mode_set_base) changed = true; if (changed) { - crtc->fb = fb; - crtc->enabled = (new_mode != NULL); - if (new_mode != NULL) { + set->crtc->fb = set->fb; + set->crtc->enabled = (set->mode != NULL); + if (set->mode != NULL) { DRM_DEBUG("attempting to set mode from userspace\n"); - drm_mode_debug_printmodeline(dev, new_mode); - if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x, - crtc_info->y)) { - crtc->enabled = save_enabled; + drm_mode_debug_printmodeline(dev, set->mode); + if (!drm_crtc_set_mode(set->crtc, set->mode, set->x, + set->y)) { + set->crtc->enabled = save_enabled; count = 0; list_for_each_entry(output, &dev->mode_config.output_list, head) output->crtc = save_crtcs[count++]; kfree(save_crtcs); return -EINVAL; } - crtc->desired_x = crtc_info->x; - crtc->desired_y = crtc_info->y; - crtc->desired_mode = new_mode; + /* TODO are these needed? */ + set->crtc->desired_x = set->x; + set->crtc->desired_y = set->y; + set->crtc->desired_mode = set->mode; } drm_disable_unused_functions(dev); } else if (flip_or_move) { - if (crtc->fb != fb) - crtc->fb = fb; - crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y); + if (set->crtc->fb != set->fb) + set->crtc->fb = set->fb; + set->crtc->funcs->mode_set_base(set->crtc, set->x, set->y); } kfree(save_crtcs); @@ -1648,6 +1660,7 @@ int drm_mode_setcrtc(struct drm_device *dev, struct drm_output **output_set = NULL, *output; struct drm_framebuffer *fb = NULL; struct drm_display_mode *mode = NULL; + struct drm_mode_set set; uint32_t __user *set_outputs_ptr; int ret = 0; int i; @@ -1724,7 +1737,14 @@ int drm_mode_setcrtc(struct drm_device *dev, } } - ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); + set.crtc = crtc; + set.x = crtc_req->x; + set.y = crtc_req->y; + set.mode = mode; + set.outputs = output_set; + set.num_outputs = crtc_req->count_outputs; + set.fb =fb; + ret = drm_crtc_set_config(&set); out: kfree(output_set); -- cgit v1.2.3 From 7bcbc443f4f5161ab1e1a11cb6694e6d6269377c Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 8 May 2008 20:10:18 +0200 Subject: i915: Changed intel_fb to use the new drm_crtc_set_config interface --- linux-core/drm_crtc.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bdcf5f9b..2bc1c4e3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -540,8 +540,8 @@ done: crtc->mode = saved_mode; crtc->x = saved_x; crtc->y = saved_y; - } - + } + return ret; } EXPORT_SYMBOL(drm_crtc_set_mode); @@ -1036,16 +1036,6 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow) drm_pick_crtcs(dev); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - - /* can't setup the crtc if there's no assigned mode */ - if (!crtc->desired_mode) - continue; - - /* Now setup the fbdev for attached crtcs */ - dev->driver->fb_probe(dev, crtc); - } - /* This is a little screwy, as we've already walked the outputs * above, but it's a little bit of magic too. There's the potential * for things not to get setup above if an existing device gets @@ -1058,6 +1048,8 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow) if (!output->crtc || !output->crtc->desired_mode) continue; + dev->driver->fb_probe(dev, output->crtc, output); + /* and needs an attached fb */ if (output->crtc->fb) drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); @@ -1140,12 +1132,15 @@ int drm_crtc_set_config(struct drm_mode_set *set) struct drm_output *output; int count = 0, ro; + DRM_DEBUG("\n"); + if (!set) return -EINVAL; if (!set->crtc) return -EINVAL; + DRM_DEBUG("crtc: %p fb: %p outputs: %p num_outputs: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->outputs, set->num_outputs, set->x, set->y); dev = set->crtc->dev; /* save previous config */ @@ -1223,6 +1218,7 @@ int drm_crtc_set_config(struct drm_mode_set *set) kfree(save_crtcs); return 0; } +EXPORT_SYMBOL(drm_crtc_set_config); /** * drm_hotplug_stage_two @@ -1267,7 +1263,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, /* We should really check if there is a fb using this crtc */ if (!has_config) - dev->driver->fb_probe(dev, output->crtc); + dev->driver->fb_probe(dev, output->crtc, output); else { dev->driver->fb_resize(dev, output->crtc); -- cgit v1.2.3 From a51e38548cfdece2978e9b5f0d6f0467ba7a7272 Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Fri, 9 May 2008 10:06:17 +0800 Subject: fix kernel oops when removing fb drm_crtc->fb may point to NULL, f.e X server will allocate a new fb and assign it to the CRTC at startup, when X server exits, it will destroy the allocated fb, making drm_crtc->fb points to NULL. --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 2bc1c4e3..c011db30 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1095,7 +1095,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) if (fb->bo->type != drm_bo_type_kernel) drm_framebuffer_destroy(fb); else - dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb)); + dev->driver->fb_remove(dev, fb); } list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { -- cgit v1.2.3 From b4d8cda8e6d6ea319ab7c471d6d68b8af8693cfe Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 23 May 2008 18:41:58 -0700 Subject: drm_mode_debug_printmodeline doesn't need struct drm_device * Makes printing modelines from some routines easier. --- linux-core/drm_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c011db30..e05466ee 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -404,7 +404,7 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int mode->vrefresh = drm_mode_vrefresh(mode); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - drm_mode_debug_printmodeline(dev, mode); + drm_mode_debug_printmodeline(mode); } } @@ -1161,8 +1161,8 @@ int drm_crtc_set_config(struct drm_mode_set *set) if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { DRM_DEBUG("modes are different\n"); - drm_mode_debug_printmodeline(dev, &set->crtc->mode); - drm_mode_debug_printmodeline(dev, set->mode); + drm_mode_debug_printmodeline(&set->crtc->mode); + drm_mode_debug_printmodeline(set->mode); changed = true; } @@ -1193,7 +1193,7 @@ int drm_crtc_set_config(struct drm_mode_set *set) set->crtc->enabled = (set->mode != NULL); if (set->mode != NULL) { DRM_DEBUG("attempting to set mode from userspace\n"); - drm_mode_debug_printmodeline(dev, set->mode); + drm_mode_debug_printmodeline(set->mode); if (!drm_crtc_set_mode(set->crtc, set->mode, set->x, set->y)) { set->crtc->enabled = save_enabled; -- cgit v1.2.3 From df8cd54286fbae5903d8ede390ec4a11cb6c4b6c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 29 May 2008 14:02:14 +1000 Subject: modesetting: reorganise code into core and helper functions. This splits a lot of the core modesetting code out into a file of helper functions, that are only called from themselves and/or the driver. The driver gets called into more often or can call these functions from itself if it is a helper using driver. I've broken framebuffer resize doing this but I didn't like the API for that in any case. --- linux-core/drm_crtc.c | 471 +------------------------------------------------- 1 file changed, 7 insertions(+), 464 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e05466ee..a4a51080 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -418,133 +418,6 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) } EXPORT_SYMBOL(drm_crtc_probe_output_modes); -/** - * drm_crtc_set_mode - set a mode - * @crtc: CRTC to program - * @mode: mode to use - * @x: width of mode - * @y: height of mode - * - * LOCKING: - * Caller must hold mode config lock. - * - * Try to set @mode on @crtc. Give @crtc and its associated outputs a chance - * to fixup or reject the mode prior to trying to set it. - * - * RETURNS: - * True if the mode was set successfully, or false otherwise. - */ -bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, - int x, int y) -{ - struct drm_device *dev = crtc->dev; - struct drm_display_mode *adjusted_mode, saved_mode; - int saved_x, saved_y; - struct drm_output *output; - bool ret = true; - - adjusted_mode = drm_mode_duplicate(dev, mode); - - crtc->enabled = drm_crtc_in_use(crtc); - - if (!crtc->enabled) - return true; - - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - - /* Update crtc values up front so the driver can rely on them for mode - * setting. - */ - crtc->mode = *mode; - crtc->x = x; - crtc->y = y; - - if (drm_mode_equal(&saved_mode, &crtc->mode)) { - if (saved_x != crtc->x || saved_y != crtc->y) { - crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); - goto done; - } - } - - /* Pass our mode to the outputs and the CRTC to give them a chance to - * adjust it according to limitations or output properties, and also - * a chance to reject the mode entirely. - */ - list_for_each_entry(output, &dev->mode_config.output_list, head) { - - if (output->crtc != crtc) - continue; - - if (!(ret = output->funcs->mode_fixup(output, mode, adjusted_mode))) { - goto done; - } - } - - if (!(ret = crtc->funcs->mode_fixup(crtc, mode, adjusted_mode))) { - goto done; - } - - /* Prepare the outputs and CRTCs before setting the mode. */ - list_for_each_entry(output, &dev->mode_config.output_list, head) { - - if (output->crtc != crtc) - continue; - - /* Disable the output as the first thing we do. */ - output->funcs->prepare(output); - } - - crtc->funcs->prepare(crtc); - - /* Set up the DPLL and any output state that needs to adjust or depend - * on the DPLL. - */ - crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); - - list_for_each_entry(output, &dev->mode_config.output_list, head) { - - if (output->crtc != crtc) - continue; - - DRM_INFO("%s: set mode %s %x\n", drm_get_output_name(output), mode->name, mode->mode_id); - - 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->mode_config.output_list, head) { - - if (output->crtc != crtc) - continue; - - output->funcs->commit(output); - -#if 0 // TODO def RANDR_12_INTERFACE - if (output->randr_output) - RRPostPendingProperties (output->randr_output); -#endif - } - - /* XXX free adjustedmode */ - drm_mode_destroy(dev, adjusted_mode); - /* TODO */ -// if (scrn->pScreen) -// drm_crtc_set_screen_sub_pixel_order(dev); - -done: - if (!ret) { - crtc->mode = saved_mode; - crtc->x = saved_x; - crtc->y = saved_y; - } - - return ret; -} -EXPORT_SYMBOL(drm_crtc_set_mode); /** * drm_disable_unused_functions - disable unused objects @@ -896,171 +769,8 @@ out_err: return ret; } -/** - * drm_pick_crtcs - pick crtcs for output devices - * @dev: DRM device - * - * LOCKING: - * Caller must hold mode config lock. - */ -static void drm_pick_crtcs (struct drm_device *dev) -{ - int c, o, assigned; - struct drm_output *output, *output_equal; - struct drm_crtc *crtc; - struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; - int found; - - list_for_each_entry(output, &dev->mode_config.output_list, head) { - output->crtc = NULL; - - /* Don't hook up outputs that are disconnected ?? - * - * This is debateable. Do we want fixed /dev/fbX or - * dynamic on hotplug (need mode code for that though) ? - * - * If we don't hook up outputs now, then we only create - * /dev/fbX for the output that's enabled, that's good as - * the users console will be on that output. - * - * If we do hook up outputs that are disconnected now, then - * the user may end up having to muck about with the fbcon - * map flags to assign his console to the enabled output. Ugh. - */ - if (output->status != output_status_connected) - continue; - - if (list_empty(&output->modes)) - continue; - - des_mode = NULL; - found = 0; - list_for_each_entry(des_mode, &output->modes, head) { - if (des_mode->type & DRM_MODE_TYPE_PREFERRED) { - found = 1; - break; - } - } - - /* No preferred mode, let's just select the first available */ - if (!found) { - des_mode = NULL; - list_for_each_entry(des_mode, &output->modes, head) { - break; - } - } - - c = -1; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - assigned = 0; - c++; - if ((output->possible_crtcs & (1 << c)) == 0) - continue; - - list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { - if (output->id == output_equal->id) - continue; - - /* Find out if crtc has been assigned before */ - if (output_equal->crtc == crtc) - assigned = 1; - } - -#if 1 /* continue for now */ - if (assigned) - continue; -#endif - - o = -1; - list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { - o++; - if (output->id == output_equal->id) - continue; - - list_for_each_entry(modes, &output->modes, head) { - list_for_each_entry(modes_equal, &output_equal->modes, head) { - if (drm_mode_equal (modes, modes_equal)) { - if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { - printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones); - des_mode = modes; - assigned = 0; - goto clone; - } - } - } - } - } -clone: - /* crtc has been assigned skip it */ - if (assigned) - continue; - - /* Found a CRTC to attach to, do it ! */ - output->crtc = crtc; - output->crtc->desired_mode = des_mode; - output->initial_x = 0; - output->initial_y = 0; - DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name); - break; - } - } -} -EXPORT_SYMBOL(drm_pick_crtcs); - -/** - * drm_initial_config - setup a sane initial output configuration - * @dev: DRM device - * @can_grow: this configuration is growable - * - * LOCKING: - * Called at init time, must take mode config lock. - * - * Scan the CRTCs and outputs and try to put together an initial setup. - * At the moment, this is a cloned configuration across all heads with - * a new framebuffer object as the backing store. - * - * RETURNS: - * Zero if everything went ok, nonzero otherwise. - */ -bool drm_initial_config(struct drm_device *dev, bool can_grow) -{ - struct drm_output *output; - struct drm_crtc *crtc; - int ret = false; - - mutex_lock(&dev->mode_config.mutex); - - drm_crtc_probe_output_modes(dev, 2048, 2048); - - drm_pick_crtcs(dev); - - /* This is a little screwy, as we've already walked the outputs - * above, but it's a little bit of magic too. There's the potential - * for things not to get setup above if an existing device gets - * re-assigned thus confusing the hardware. By walking the outputs - * this fixes up their crtc's. - */ - list_for_each_entry(output, &dev->mode_config.output_list, head) { - - /* can't setup the output if there's no assigned mode */ - if (!output->crtc || !output->crtc->desired_mode) - continue; - - dev->driver->fb_probe(dev, output->crtc, output); - - /* and needs an attached fb */ - if (output->crtc->fb) - drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0); - } - - drm_disable_unused_functions(dev); - - mutex_unlock(&dev->mode_config.mutex); - return ret; -} -EXPORT_SYMBOL(drm_initial_config); /** * drm_mode_config_cleanup - free up DRM mode_config info @@ -1105,179 +815,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_config_cleanup); -/** - * drm_crtc_set_config - set a new config from userspace - * @crtc: CRTC to setup - * @crtc_info: user provided configuration - * @new_mode: new mode to set - * @output_set: set of outputs for the new config - * @fb: new framebuffer - * - * LOCKING: - * Caller must hold mode config lock. - * - * Setup a new configuration, provided by the user in @crtc_info, and enable - * it. - * - * RETURNS: - * Zero. (FIXME) - */ -int drm_crtc_set_config(struct drm_mode_set *set) -{ - struct drm_device *dev; - struct drm_crtc **save_crtcs, *new_crtc; - bool save_enabled; - bool changed = false; - bool flip_or_move = false; - struct drm_output *output; - int count = 0, ro; - - DRM_DEBUG("\n"); - - if (!set) - return -EINVAL; - - if (!set->crtc) - return -EINVAL; - - DRM_DEBUG("crtc: %p fb: %p outputs: %p num_outputs: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->outputs, set->num_outputs, set->x, set->y); - dev = set->crtc->dev; - - /* save previous config */ - save_enabled = set->crtc->enabled; - - /* this is meant to be num_output not num_crtc */ - save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL); - if (!save_crtcs) - return -ENOMEM; - - /* We should be able to check here if the fb has the same properties - * and then just flip_or_move it */ - if (set->crtc->fb != set->fb) - flip_or_move = true; - if (set->x != set->crtc->x || set->y != set->crtc->y) - flip_or_move = true; - - if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { - DRM_DEBUG("modes are different\n"); - drm_mode_debug_printmodeline(&set->crtc->mode); - drm_mode_debug_printmodeline(set->mode); - changed = true; - } - - list_for_each_entry(output, &dev->mode_config.output_list, head) { - save_crtcs[count++] = output->crtc; - - if (output->crtc == set->crtc) - new_crtc = NULL; - else - new_crtc = output->crtc; - - for (ro = 0; ro < set->num_outputs; ro++) { - if (set->outputs[ro] == output) - new_crtc = set->crtc; - } - if (new_crtc != output->crtc) { - changed = true; - output->crtc = new_crtc; - } - } - - /* mode_set_base is not a required function */ - if (flip_or_move && !set->crtc->funcs->mode_set_base) - changed = true; - - if (changed) { - set->crtc->fb = set->fb; - set->crtc->enabled = (set->mode != NULL); - if (set->mode != NULL) { - DRM_DEBUG("attempting to set mode from userspace\n"); - drm_mode_debug_printmodeline(set->mode); - if (!drm_crtc_set_mode(set->crtc, set->mode, set->x, - set->y)) { - set->crtc->enabled = save_enabled; - count = 0; - list_for_each_entry(output, &dev->mode_config.output_list, head) - output->crtc = save_crtcs[count++]; - kfree(save_crtcs); - return -EINVAL; - } - /* TODO are these needed? */ - set->crtc->desired_x = set->x; - set->crtc->desired_y = set->y; - set->crtc->desired_mode = set->mode; - } - drm_disable_unused_functions(dev); - } else if (flip_or_move) { - if (set->crtc->fb != set->fb) - set->crtc->fb = set->fb; - set->crtc->funcs->mode_set_base(set->crtc, set->x, set->y); - } - - kfree(save_crtcs); - return 0; -} -EXPORT_SYMBOL(drm_crtc_set_config); - -/** - * drm_hotplug_stage_two - * @dev DRM device - * @output hotpluged output - * - * LOCKING. - * Caller must hold mode config lock, function might grab struct lock. - * - * Stage two of a hotplug. - * - * RETURNS: - * Zero on success, errno on failure. - */ -int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, - bool connected) -{ - int has_config = 0; - - dev->mode_config.hotplug_counter++; - - /* We might want to do something more here */ - if (!connected) { - DRM_DEBUG("not connected\n"); - return 0; - } - - if (output->crtc && output->crtc->desired_mode) { - DRM_DEBUG("drm thinks that the output already has a config\n"); - has_config = 1; - } - - drm_crtc_probe_output_modes(dev, 2048, 2048); - - if (!has_config) - drm_pick_crtcs(dev); - - if (!output->crtc || !output->crtc->desired_mode) { - DRM_DEBUG("could not find a desired mode or crtc for output\n"); - return 1; - } - - /* We should really check if there is a fb using this crtc */ - if (!has_config) - dev->driver->fb_probe(dev, output->crtc, output); - else { - dev->driver->fb_resize(dev, output->crtc); - - if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0)) - DRM_ERROR("failed to set mode after hotplug\n"); - } - - drm_sysfs_hotplug_event(dev); - - drm_disable_unused_functions(dev); - - return 0; -} -EXPORT_SYMBOL(drm_hotplug_stage_two); int drm_mode_hotplug_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -1740,7 +1278,7 @@ int drm_mode_setcrtc(struct drm_device *dev, set.outputs = output_set; set.num_outputs = crtc_req->count_outputs; set.fb =fb; - ret = drm_crtc_set_config(&set); + ret = crtc->funcs->set_config(&set); out: kfree(output_set); @@ -2535,7 +2073,6 @@ int drm_mode_replacefb(struct drm_device *dev, { struct drm_mode_fb_cmd *r = data; struct drm_framebuffer *fb; - struct drm_crtc *crtc; struct drm_buffer_object *bo; int found = 0; struct drm_framebuffer *fbl = NULL; @@ -2574,12 +2111,18 @@ int drm_mode_replacefb(struct drm_device *dev, fb->depth = r->depth; fb->bo = bo; + if (dev->mode_config.funcs->resize_fb) + dev->mode_config.funcs->resize_fb(dev, fb); + else + ret = -EINVAL; +#if 0 /* find all crtcs connected to this fb */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb->id == r->buffer_id) { crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); } } +#endif out: mutex_unlock(&dev->mode_config.mutex); return ret; -- cgit v1.2.3 From 98c5cf7f6fc51f1a8f5f90b3895009cd38dd8f22 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 11:25:41 +1000 Subject: modesetting: reorganise out crtc/outputs are allocated. Use subclassing from the drivers to allocate the objects. This saves two objects being allocated for each crtc/output and generally makes exit paths cleaner. --- linux-core/drm_crtc.c | 85 +++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 57 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index a4a51080..faf70df5 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -232,27 +232,19 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) EXPORT_SYMBOL(drm_framebuffer_destroy); /** - * drm_crtc_create - create a new CRTC object + * drm_crtc_init - Initialise a new CRTC object * @dev: DRM device + * @crtc: CRTC object to init * @funcs: callbacks for the new CRTC * * LOCKING: * Caller must hold mode config lock. * - * Creates a new CRTC object and adds it to @dev's mode_config structure. - * - * RETURNS: - * Pointer to new CRTC object or NULL on error. + * Inits a new object created as base part of an driver crtc object. */ -struct drm_crtc *drm_crtc_create(struct drm_device *dev, - const struct drm_crtc_funcs *funcs) +void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + const struct drm_crtc_funcs *funcs) { - struct drm_crtc *crtc; - - crtc = kzalloc(sizeof(struct drm_crtc), GFP_KERNEL); - if (!crtc) - return NULL; - crtc->dev = dev; crtc->funcs = funcs; @@ -260,34 +252,28 @@ struct drm_crtc *drm_crtc_create(struct drm_device *dev, list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++; - - return crtc; } -EXPORT_SYMBOL(drm_crtc_create); +EXPORT_SYMBOL(drm_crtc_init); /** - * drm_crtc_destroy - remove a CRTC object - * @crtc: CRTC to remove + * drm_crtc_cleanup - Cleans up the core crtc usage. + * @crtc: CRTC to cleanup * * LOCKING: * Caller must hold mode config lock. * - * Cleanup @crtc. Calls @crtc's cleanup function, then removes @crtc from - * its associated DRM device's mode_config. Frees it afterwards. + * Cleanup @crtc. Removes from drm modesetting space + * does NOT free object, caller does that. */ -void drm_crtc_destroy(struct drm_crtc *crtc) +void drm_crtc_cleanup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - if (crtc->funcs->cleanup) - (*crtc->funcs->cleanup)(crtc); - drm_idr_put(dev, crtc->id); list_del(&crtc->head); dev->mode_config.num_crtc--; - kfree(crtc); } -EXPORT_SYMBOL(drm_crtc_destroy); +EXPORT_SYMBOL(drm_crtc_cleanup); /** * drm_crtc_in_use - check if a given CRTC is in a mode_config @@ -481,30 +467,23 @@ void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) EXPORT_SYMBOL(drm_mode_remove); /** - * drm_output_create - create a new output + * drm_output_init - Init a preallocated output * @dev: DRM device + * @output: the output to init * @funcs: callbacks for this output * @name: user visible name of the output * * LOCKING: * Caller must hold @dev's mode_config lock. * - * Creates a new drm_output structure and adds it to @dev's mode_config - * structure. - * - * RETURNS: - * Pointer to the new output or NULL on error. + * Initialises a preallocated output. Outputs should be + * subclassed as part of driver output objects. */ -struct drm_output *drm_output_create(struct drm_device *dev, - const struct drm_output_funcs *funcs, - int output_type) +void drm_output_init(struct drm_device *dev, + struct drm_output *output, + const struct drm_output_funcs *funcs, + int output_type) { - struct drm_output *output = NULL; - - output = kzalloc(sizeof(struct drm_output), GFP_KERNEL); - if (!output) - return NULL; - output->dev = dev; output->funcs = funcs; output->id = drm_idr_get(dev, output); @@ -526,30 +505,23 @@ struct drm_output *drm_output_create(struct drm_device *dev, drm_output_attach_property(output, dev->mode_config.dpms_property, 0); mutex_unlock(&dev->mode_config.mutex); - - return output; - } -EXPORT_SYMBOL(drm_output_create); +EXPORT_SYMBOL(drm_output_init); /** - * drm_output_destroy - remove an output - * @output: output to remove + * drm_output_cleanup - cleans up an initialised output + * @output: output to cleanup * * LOCKING: * Caller must hold @dev's mode_config lock. * - * Call @output's cleanup function, then remove the output from the DRM - * mode_config after freeing @output's modes. + * Cleans up the output but doesn't free the object. */ -void drm_output_destroy(struct drm_output *output) +void drm_output_cleanup(struct drm_output *output) { struct drm_device *dev = output->dev; struct drm_display_mode *mode, *t; - if (*output->funcs->cleanup) - (*output->funcs->cleanup)(output); - list_for_each_entry_safe(mode, t, &output->probed_modes, head) drm_mode_remove(output, mode); @@ -563,9 +535,8 @@ void drm_output_destroy(struct drm_output *output) drm_idr_put(dev, output->id); list_del(&output->head); mutex_unlock(&dev->mode_config.mutex); - kfree(output); } -EXPORT_SYMBOL(drm_output_destroy); +EXPORT_SYMBOL(drm_output_cleanup); /** @@ -793,7 +764,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_sysfs_output_remove(output); - drm_output_destroy(output); + output->funcs->destroy(output); } list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, head) { @@ -809,7 +780,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) } list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { - drm_crtc_destroy(crtc); + crtc->funcs->destroy(crtc); } } -- cgit v1.2.3 From 9654c776fda55d6420a14449bf2e274839c444a6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 11:47:57 +1000 Subject: drm/modesetting: add initial encoder structures and setup functions --- linux-core/drm_crtc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index faf70df5..f7e7bfa8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -538,6 +538,31 @@ void drm_output_cleanup(struct drm_output *output) } EXPORT_SYMBOL(drm_output_cleanup); +void drm_encoder_init(struct drm_device *dev, + struct drm_encoder *encoder, + int encoder_type) +{ + encoder->dev = dev; + encoder->id = drm_idr_get(dev, encoder); + encoder->encoder_type = encoder_type; + + mutex_lock(&dev->mode_config.mutex); + list_add_tail(&encoder->head, &dev->mode_config.encoder_list); + dev->mode_config.num_encoder++; + + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_encoder_init); + +void drm_encoder_cleanup(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + mutex_lock(&dev->mode_config.mutex); + drm_idr_put(dev, encoder->id); + list_del(&encoder->head); + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_encoder_cleanup); /** * drm_mode_create - create a new display mode -- cgit v1.2.3 From 8ae82f3a2feb8b8fe56214c4c9e806bf1f87cbf8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 12:03:36 +1000 Subject: drm: add encoder / get encoder to the modesetting resources interface --- linux-core/drm_crtc.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f7e7bfa8..5d5448c5 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -784,6 +784,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) { struct drm_output *output, *ot; struct drm_crtc *crtc, *ct; + struct drm_encoder *encoder, *enct; struct drm_framebuffer *fb, *fbt; struct drm_property *property, *pt; @@ -804,6 +805,10 @@ void drm_mode_config_cleanup(struct drm_device *dev) dev->driver->fb_remove(dev, fb); } + list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, head) { + encoder->funcs->destroy(encoder); + } + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { crtc->funcs->destroy(crtc); } @@ -911,14 +916,17 @@ int drm_mode_getresources(struct drm_device *dev, struct drm_framebuffer *fb; struct drm_output *output; struct drm_crtc *crtc; + struct drm_encoder *encoder; int ret = 0; int output_count = 0; int crtc_count = 0; int fb_count = 0; + int encoder_count = 0; int copied = 0; uint32_t __user *fb_id; uint32_t __user *crtc_id; uint32_t __user *output_id; + uint32_t __user *encoder_id; mutex_lock(&dev->mode_config.mutex); @@ -931,6 +939,9 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each(lh, &dev->mode_config.output_list) output_count++; + list_for_each(lh, &dev->mode_config.encoder_list) + encoder_count++; + card_res->max_height = dev->mode_config.max_height; card_res->min_height = dev->mode_config.min_height; card_res->max_width = dev->mode_config.max_width; @@ -982,9 +993,25 @@ int drm_mode_getresources(struct drm_device *dev, } } card_res->count_outputs = output_count; + + /* Encoders */ + if (card_res->count_encoders >= encoder_count) { + copied = 0; + encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, + head) { + DRM_DEBUG("ENCODER ID is %d\n", encoder->id); + if (put_user(encoder->id, encoder_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + card_res->count_encoders = encoder_count; - DRM_DEBUG("Counted %d %d\n", card_res->count_crtcs, - card_res->count_outputs); + DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, + card_res->count_outputs, card_res->count_encoders); out: mutex_unlock(&dev->mode_config.mutex); @@ -1165,6 +1192,31 @@ out: return ret; } +int drm_mode_getencoder(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_get_encoder *enc_resp = data; + struct drm_encoder *encoder; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + encoder = idr_find(&dev->mode_config.crtc_idr, enc_resp->encoder_id); + if (!encoder || (encoder->id != enc_resp->encoder_id)) { + DRM_DEBUG("Unknown encoder ID %d\n", enc_resp->encoder_id); + ret = -EINVAL; + goto out; + } + + enc_resp->encoder_type = encoder->encoder_type; + enc_resp->encoder_id = encoder->id; + enc_resp->crtcs = encoder->possible_crtcs; + enc_resp->clones = encoder->possible_clones; + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + /** * drm_mode_setcrtc - set CRTC configuration * @inode: inode from the ioctl -- cgit v1.2.3 From b72419a8f74bfb1d3b6a5ca1d8f6dfa3c6a84e86 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 12:19:13 +1000 Subject: drm: add encoder ids to the output handling --- linux-core/drm_crtc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 5d5448c5..fc35c1ab 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1104,6 +1104,7 @@ int drm_mode_getoutput(struct drm_device *dev, struct drm_display_mode *mode; int mode_count = 0; int props_count = 0; + int encoders_count = 0; int ret = 0; int copied = 0; int i; @@ -1111,6 +1112,7 @@ int drm_mode_getoutput(struct drm_device *dev, struct drm_mode_modeinfo __user *mode_ptr; uint32_t __user *prop_ptr; uint64_t __user *prop_values; + uint32_t __user *encoder_ptr; memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); @@ -1132,6 +1134,12 @@ int drm_mode_getoutput(struct drm_device *dev, } } + for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { + if (output->encoder_ids[i] != 0) { + encoders_count++; + } + } + if (out_resp->count_modes == 0) { drm_crtc_probe_single_output_modes(output, dev->mode_config.max_width, dev->mode_config.max_height); } @@ -1187,6 +1195,21 @@ int drm_mode_getoutput(struct drm_device *dev, } out_resp->count_props = props_count; + if ((out_resp->count_encoders >= encoders_count) && encoders_count) { + copied = 0; + encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); + for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { + if (output->encoder_ids[i] != 0) { + if (put_user(output->encoder_ids[i], encoder_ptr + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } + } + out_resp->count_encoders = encoders_count; + out: mutex_unlock(&dev->mode_config.mutex); return ret; -- cgit v1.2.3 From 6b5592790dcaed503bec8f441eab52d22b76d7c1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 12:20:36 +1000 Subject: drm: add red hat copyright. --- linux-core/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fc35c1ab..734850f3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2006-2007 Intel Corporation * Copyright (c) 2007 Dave Airlie + * Copyright (c) 2008 Red Hat Inc. * * DRM core CRTC related functions * -- cgit v1.2.3 From 1542492b797fbdf4970e0213827e2f9887d6174d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 12:24:19 +1000 Subject: drm: init the encoder list/count --- linux-core/drm_crtc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 734850f3..f6937f44 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -708,6 +708,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.fb_list); INIT_LIST_HEAD(&dev->mode_config.crtc_list); INIT_LIST_HEAD(&dev->mode_config.output_list); + INIT_LIST_HEAD(&dev->mode_config.encoder_list); INIT_LIST_HEAD(&dev->mode_config.property_list); INIT_LIST_HEAD(&dev->mode_config.property_blob_list); idr_init(&dev->mode_config.crtc_idr); @@ -718,6 +719,7 @@ void drm_mode_config_init(struct drm_device *dev) dev->mode_config.num_fb = 0; dev->mode_config.num_output = 0; dev->mode_config.num_crtc = 0; + dev->mode_config.num_encoder = 0; dev->mode_config.hotplug_counter = 0; } EXPORT_SYMBOL(drm_mode_config_init); -- cgit v1.2.3 From 9239cf511f65a43eb578fbb6a7c5255e05db2101 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 13:31:16 +1000 Subject: drm: add encoder attach/detach --- linux-core/drm_crtc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f6937f44..400df98e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2202,3 +2202,31 @@ out: return ret; } + +int drm_mode_output_attach_encoder(struct drm_output *output, + struct drm_encoder *encoder) +{ + int i; + + for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { + if (output->encoder_ids[i] == 0) { + output->encoder_ids[i] = encoder->id; + return 0; + } + } + return -ENOMEM; +} +EXPORT_SYMBOL(drm_mode_output_attach_encoder); + +void drm_mode_output_detach_encoder(struct drm_output *output, + struct drm_encoder *encoder) +{ + int i; + for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { + if (output->encoder_ids[i] == encoder->id) { + output->encoder_ids[i] = 0; + break; + } + } +} +EXPORT_SYMBOL(drm_mode_output_detach_encoder); -- cgit v1.2.3 From 6aeef92c0cad784a5019ea90d97ab81f4e51fdd9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 13:57:27 +1000 Subject: drm: attach an encoder. Time to do some renaming on the connectors I think --- linux-core/drm_crtc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 400df98e..bb527413 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -77,7 +77,7 @@ static struct drm_prop_enum_list drm_conn_enum_list[] = }; static struct drm_prop_enum_list drm_output_enum_list[] = { { DRM_MODE_OUTPUT_NONE, "None" }, - { DRM_MODE_OUTPUT_DAC, "DAC" }, + { DRM_MODE_OUTPUT_VGA, "VGA" }, { DRM_MODE_OUTPUT_TMDS, "TMDS" }, { DRM_MODE_OUTPUT_LVDS, "LVDS" }, { DRM_MODE_OUTPUT_TVDAC, "TV" }, @@ -541,11 +541,13 @@ EXPORT_SYMBOL(drm_output_cleanup); void drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, + const struct drm_encoder_funcs *funcs, int encoder_type) { encoder->dev = dev; encoder->id = drm_idr_get(dev, encoder); encoder->encoder_type = encoder_type; + encoder->funcs = funcs; mutex_lock(&dev->mode_config.mutex); list_add_tail(&encoder->head, &dev->mode_config.encoder_list); @@ -791,6 +793,10 @@ void drm_mode_config_cleanup(struct drm_device *dev) struct drm_framebuffer *fb, *fbt; struct drm_property *property, *pt; + list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, head) { + encoder->funcs->destroy(encoder); + } + list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { drm_sysfs_output_remove(output); output->funcs->destroy(output); @@ -808,10 +814,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) dev->driver->fb_remove(dev, fb); } - list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, head) { - encoder->funcs->destroy(encoder); - } - list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { crtc->funcs->destroy(crtc); } -- cgit v1.2.3 From 9d38448ed33aaff324cc4bbe1e0878593e97d07d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 15:03:12 +1000 Subject: modesetting: the great renaming. Okay we have crtc, encoder and connectors. No more outputs exposed beyond driver internals I've broken intel tv connector stuff. Really for TV we should have one TV connector, with a sub property for the type of signal been driven over it --- linux-core/drm_crtc.c | 540 ++++++++++++++++++++++++-------------------------- 1 file changed, 264 insertions(+), 276 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bb527413..c60476a4 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -60,43 +60,43 @@ char *drm_get_dpms_name(int val) return "unknown"; } -static struct drm_prop_enum_list drm_conn_enum_list[] = -{ { ConnectorUnknown, "Unknown" }, - { ConnectorVGA, "VGA" }, - { ConnectorDVII, "DVI-I" }, - { ConnectorDVID, "DVI-D" }, - { ConnectorDVIA, "DVI-A" }, - { ConnectorComposite, "Composite" }, - { ConnectorSVIDEO, "SVIDEO" }, - { ConnectorLVDS, "LVDS" }, - { ConnectorComponent, "Component" }, - { Connector9PinDIN, "9-pin DIN" }, - { ConnectorDisplayPort, "DisplayPort" }, - { ConnectorHDMIA, "HDMI Type A" }, - { ConnectorHDMIB, "HDMI Type B" }, +static struct drm_prop_enum_list drm_connector_enum_list[] = +{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "Composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "Component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, }; -static struct drm_prop_enum_list drm_output_enum_list[] = -{ { DRM_MODE_OUTPUT_NONE, "None" }, - { DRM_MODE_OUTPUT_VGA, "VGA" }, - { DRM_MODE_OUTPUT_TMDS, "TMDS" }, - { DRM_MODE_OUTPUT_LVDS, "LVDS" }, - { DRM_MODE_OUTPUT_TVDAC, "TV" }, +static struct drm_prop_enum_list drm_encoder_enum_list[] = +{ { DRM_MODE_ENCODER_NONE, "None" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TV" }, }; -char *drm_get_output_name(struct drm_output *output) +char *drm_get_connector_name(struct drm_connector *connector) { static char buf[32]; - snprintf(buf, 32, "%s-%d", drm_output_enum_list[output->output_type].name, - output->output_type_id); + snprintf(buf, 32, "%s-%d", drm_connector_enum_list[connector->connector_type].name, + connector->connector_type_id); return buf; } -char *drm_get_output_status_name(enum drm_output_status status) +char *drm_get_connector_status_name(enum drm_connector_status status) { - if (status == output_status_connected) + if (status == connector_status_connected) return "connected"; - else if (status == output_status_disconnected) + else if (status == connector_status_disconnected) return "disconnected"; else return "unknown"; @@ -111,7 +111,7 @@ char *drm_get_output_status_name(enum drm_output_status status) * Caller must hold DRM mode_config lock. * * Create a unique identifier based on @ptr in @dev's identifier space. Used - * for tracking modes, CRTCs and outputs. + * for tracking modes, CRTCs and connectors. * * RETURNS: * New unique (relative to other objects in @dev) integer identifier for the @@ -290,11 +290,11 @@ EXPORT_SYMBOL(drm_crtc_cleanup); */ bool drm_crtc_in_use(struct drm_crtc *crtc) { - struct drm_output *output; + struct drm_connector *connector; struct drm_device *dev = crtc->dev; /* FIXME: Locking around list access? */ - list_for_each_entry(output, &dev->mode_config.output_list, head) - if (output->crtc == crtc) + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->crtc == crtc) return true; return false; } @@ -310,7 +310,7 @@ static struct drm_display_mode std_mode[] = { }; /** - * drm_crtc_probe_output_modes - get complete set of display modes + * drm_crtc_probe_connector_modes - get complete set of display modes * @dev: DRM device * @maxX: max width for modes * @maxY: max height for modes @@ -318,8 +318,8 @@ static struct drm_display_mode std_mode[] = { * LOCKING: * Caller must hold mode config lock. * - * Based on @dev's mode_config layout, scan all the outputs and try to detect - * modes on them. Modes will first be added to the output's probed_modes + * Based on @dev's mode_config layout, scan all the connectors and try to detect + * modes on them. Modes will first be added to the connector's probed_modes * list, then culled (based on validity and the @maxX, @maxY parameters) and * put into the normal modes list. * @@ -328,47 +328,47 @@ static struct drm_display_mode std_mode[] = { * * FIXME: take into account monitor limits */ -void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int maxY) +void drm_crtc_probe_single_connector_modes(struct drm_connector *connector, int maxX, int maxY) { - struct drm_device *dev = output->dev; + struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *t; int ret; //if (maxX == 0 || maxY == 0) // TODO /* set all modes to the unverified state */ - list_for_each_entry_safe(mode, t, &output->modes, head) + list_for_each_entry_safe(mode, t, &connector->modes, head) mode->status = MODE_UNVERIFIED; - output->status = (*output->funcs->detect)(output); + connector->status = (*connector->funcs->detect)(connector); - if (output->status == output_status_disconnected) { - DRM_DEBUG("%s is disconnected\n", drm_get_output_name(output)); + if (connector->status == connector_status_disconnected) { + DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector)); /* TODO set EDID to NULL */ return; } - ret = (*output->funcs->get_modes)(output); + ret = (*connector->funcs->get_modes)(connector); if (ret) { - drm_mode_output_list_update(output); + drm_mode_connector_list_update(connector); } if (maxX && maxY) - drm_mode_validate_size(dev, &output->modes, maxX, + drm_mode_validate_size(dev, &connector->modes, maxX, maxY, 0); - list_for_each_entry_safe(mode, t, &output->modes, head) { + list_for_each_entry_safe(mode, t, &connector->modes, head) { if (mode->status == MODE_OK) - mode->status = (*output->funcs->mode_valid)(output,mode); + mode->status = (*connector->funcs->mode_valid)(connector,mode); } - drm_mode_prune_invalid(dev, &output->modes, TRUE); + drm_mode_prune_invalid(dev, &connector->modes, TRUE); - if (list_empty(&output->modes)) { + if (list_empty(&connector->modes)) { struct drm_display_mode *stdmode; - DRM_DEBUG("No valid modes on %s\n", drm_get_output_name(output)); + DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(connector)); /* Should we do this here ??? * When no valid EDID modes are available we end up @@ -376,18 +376,18 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int * 640x480@60Hz mode and carry on. */ stdmode = drm_mode_duplicate(dev, &std_mode[0]); - drm_mode_probed_add(output, stdmode); - drm_mode_list_concat(&output->probed_modes, - &output->modes); + drm_mode_probed_add(connector, stdmode); + drm_mode_list_concat(&connector->probed_modes, + &connector->modes); DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", - drm_get_output_name(output)); + drm_get_connector_name(connector)); } - drm_mode_sort(&output->modes); + drm_mode_sort(&connector->modes); - DRM_DEBUG("Probed modes for %s\n", drm_get_output_name(output)); - list_for_each_entry_safe(mode, t, &output->modes, head) { + DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector)); + list_for_each_entry_safe(mode, t, &connector->modes, head) { mode->vrefresh = drm_mode_vrefresh(mode); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); @@ -395,15 +395,15 @@ void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int } } -void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) +void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY) { - struct drm_output *output; + struct drm_connector *connector; - list_for_each_entry(output, &dev->mode_config.output_list, head) { - drm_crtc_probe_single_output_modes(output, maxX, maxY); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_crtc_probe_single_connector_modes(connector, maxX, maxY); } } -EXPORT_SYMBOL(drm_crtc_probe_output_modes); +EXPORT_SYMBOL(drm_crtc_probe_connector_modes); /** @@ -413,17 +413,17 @@ EXPORT_SYMBOL(drm_crtc_probe_output_modes); * LOCKING: * Caller must hold mode config lock. * - * If an output or CRTC isn't part of @dev's mode_config, it can be disabled + * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled * by calling its dpms function, which should power it off. */ void drm_disable_unused_functions(struct drm_device *dev) { - struct drm_output *output; + struct drm_connector *connector; struct drm_crtc *crtc; - list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (!output->crtc) - (*output->funcs->dpms)(output, DPMSModeOff); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (!connector->crtc) + (*connector->funcs->dpms)(connector, DPMSModeOff); } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -434,33 +434,33 @@ void drm_disable_unused_functions(struct drm_device *dev) EXPORT_SYMBOL(drm_disable_unused_functions); /** - * drm_mode_probed_add - add a mode to the specified output's probed mode list - * @output: output the new mode + * drm_mode_probed_add - add a mode to the specified connector's probed mode list + * @connector: connector the new mode * @mode: mode data * * LOCKING: * Caller must hold mode config lock. * - * Add @mode to @output's mode list for later use. + * Add @mode to @connector's mode list for later use. */ -void drm_mode_probed_add(struct drm_output *output, +void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode) { - list_add(&mode->head, &output->probed_modes); + list_add(&mode->head, &connector->probed_modes); } EXPORT_SYMBOL(drm_mode_probed_add); /** * drm_mode_remove - remove and free a mode - * @output: output list to modify + * @connector: connector list to modify * @mode: mode to remove * * LOCKING: * Caller must hold mode config lock. * - * Remove @mode from @output's mode list, then free it. + * Remove @mode from @connector's mode list, then free it. */ -void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) +void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode) { list_del(&mode->head); kfree(mode); @@ -468,76 +468,76 @@ void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode) EXPORT_SYMBOL(drm_mode_remove); /** - * drm_output_init - Init a preallocated output + * drm_connector_init - Init a preallocated connector * @dev: DRM device - * @output: the output to init - * @funcs: callbacks for this output - * @name: user visible name of the output + * @connector: the connector to init + * @funcs: callbacks for this connector + * @name: user visible name of the connector * * LOCKING: * Caller must hold @dev's mode_config lock. * - * Initialises a preallocated output. Outputs should be - * subclassed as part of driver output objects. + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. */ -void drm_output_init(struct drm_device *dev, - struct drm_output *output, - const struct drm_output_funcs *funcs, - int output_type) +void drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type) { - output->dev = dev; - output->funcs = funcs; - output->id = drm_idr_get(dev, output); - output->output_type = output_type; - output->output_type_id = 1; /* TODO */ - INIT_LIST_HEAD(&output->user_modes); - INIT_LIST_HEAD(&output->probed_modes); - INIT_LIST_HEAD(&output->modes); - /* randr_output? */ - /* output_set_monitor(output)? */ - /* check for output_ignored(output)? */ + connector->dev = dev; + connector->funcs = funcs; + connector->id = drm_idr_get(dev, connector); + connector->connector_type = connector_type; + connector->connector_type_id = 1; /* TODO */ + INIT_LIST_HEAD(&connector->user_modes); + INIT_LIST_HEAD(&connector->probed_modes); + INIT_LIST_HEAD(&connector->modes); + /* randr_connector? */ + /* connector_set_monitor(connector)? */ + /* check for connector_ignored(connector)? */ mutex_lock(&dev->mode_config.mutex); - list_add_tail(&output->head, &dev->mode_config.output_list); - dev->mode_config.num_output++; + list_add_tail(&connector->head, &dev->mode_config.connector_list); + dev->mode_config.num_connector++; - drm_output_attach_property(output, dev->mode_config.edid_property, 0); + drm_connector_attach_property(connector, dev->mode_config.edid_property, 0); - drm_output_attach_property(output, dev->mode_config.dpms_property, 0); + drm_connector_attach_property(connector, dev->mode_config.dpms_property, 0); mutex_unlock(&dev->mode_config.mutex); } -EXPORT_SYMBOL(drm_output_init); +EXPORT_SYMBOL(drm_connector_init); /** - * drm_output_cleanup - cleans up an initialised output - * @output: output to cleanup + * drm_connector_cleanup - cleans up an initialised connector + * @connector: connector to cleanup * * LOCKING: * Caller must hold @dev's mode_config lock. * - * Cleans up the output but doesn't free the object. + * Cleans up the connector but doesn't free the object. */ -void drm_output_cleanup(struct drm_output *output) +void drm_connector_cleanup(struct drm_connector *connector) { - struct drm_device *dev = output->dev; + struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *t; - list_for_each_entry_safe(mode, t, &output->probed_modes, head) - drm_mode_remove(output, mode); + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) + drm_mode_remove(connector, mode); - list_for_each_entry_safe(mode, t, &output->modes, head) - drm_mode_remove(output, mode); + list_for_each_entry_safe(mode, t, &connector->modes, head) + drm_mode_remove(connector, mode); - list_for_each_entry_safe(mode, t, &output->user_modes, head) - drm_mode_remove(output, mode); + list_for_each_entry_safe(mode, t, &connector->user_modes, head) + drm_mode_remove(connector, mode); mutex_lock(&dev->mode_config.mutex); - drm_idr_put(dev, output->id); - list_del(&output->head); + drm_idr_put(dev, connector->id); + list_del(&connector->head); mutex_unlock(&dev->mode_config.mutex); } -EXPORT_SYMBOL(drm_output_cleanup); +EXPORT_SYMBOL(drm_connector_cleanup); void drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, @@ -610,12 +610,12 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_destroy); -static int drm_mode_create_standard_output_properties(struct drm_device *dev) +static int drm_mode_create_standard_connector_properties(struct drm_device *dev) { int i; /* - * Standard properties (apply to all outputs) + * Standard properties (apply to all connectors) */ dev->mode_config.edid_property = drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, @@ -627,29 +627,17 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev) for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name); - dev->mode_config.connector_type_property = - drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, - "Connector Type", ARRAY_SIZE(drm_conn_enum_list)); - for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++) - drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name); - - dev->mode_config.connector_num_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, - "Connector ID", 2); - dev->mode_config.connector_num_property->values[0] = 0; - dev->mode_config.connector_num_property->values[1] = 20; - return 0; } /** - * drm_create_tv_properties - create TV specific output properties + * drm_create_tv_properties - create TV specific connector properties * @dev: DRM device * @num_modes: number of different TV formats (modes) supported * @modes: array of pointers to strings containing name of each format * * Called by a driver's TV initialization routine, this function creates - * the TV specific output properties for a given device. Caller is + * the TV specific connector properties for a given device. Caller is * responsible for allocating a list of format names and passing them to * this routine. */ @@ -709,17 +697,17 @@ void drm_mode_config_init(struct drm_device *dev) mutex_init(&dev->mode_config.mutex); INIT_LIST_HEAD(&dev->mode_config.fb_list); INIT_LIST_HEAD(&dev->mode_config.crtc_list); - INIT_LIST_HEAD(&dev->mode_config.output_list); + INIT_LIST_HEAD(&dev->mode_config.connector_list); INIT_LIST_HEAD(&dev->mode_config.encoder_list); INIT_LIST_HEAD(&dev->mode_config.property_list); INIT_LIST_HEAD(&dev->mode_config.property_blob_list); idr_init(&dev->mode_config.crtc_idr); - drm_mode_create_standard_output_properties(dev); + drm_mode_create_standard_connector_properties(dev); /* Just to be sure */ dev->mode_config.num_fb = 0; - dev->mode_config.num_output = 0; + dev->mode_config.num_connector = 0; dev->mode_config.num_crtc = 0; dev->mode_config.num_encoder = 0; dev->mode_config.hotplug_counter = 0; @@ -780,14 +768,14 @@ out_err: * LOCKING: * Caller must hold mode config lock. * - * Free up all the outputs and CRTCs associated with this DRM device, then + * Free up all the connectors and CRTCs associated with this DRM device, then * free up the framebuffers and associated buffer objects. * * FIXME: cleanup any dangling user buffer objects too */ void drm_mode_config_cleanup(struct drm_device *dev) { - struct drm_output *output, *ot; + struct drm_connector *connector, *ot; struct drm_crtc *crtc, *ct; struct drm_encoder *encoder, *enct; struct drm_framebuffer *fb, *fbt; @@ -797,9 +785,9 @@ void drm_mode_config_cleanup(struct drm_device *dev) encoder->funcs->destroy(encoder); } - list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) { - drm_sysfs_output_remove(output); - output->funcs->destroy(output); + list_for_each_entry_safe(connector, ot, &dev->mode_config.connector_list, head) { + drm_sysfs_connector_remove(connector); + connector->funcs->destroy(connector); } list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, head) { @@ -906,7 +894,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein * Takes mode config lock. * * Construct a set of configuration description structures and return - * them to the user, including CRTC, output and framebuffer configuration. + * them to the user, including CRTC, connector and framebuffer configuration. * * Called by the user via ioctl. * @@ -919,18 +907,18 @@ int drm_mode_getresources(struct drm_device *dev, struct drm_mode_card_res *card_res = data; struct list_head *lh; struct drm_framebuffer *fb; - struct drm_output *output; + struct drm_connector *connector; struct drm_crtc *crtc; struct drm_encoder *encoder; int ret = 0; - int output_count = 0; + int connector_count = 0; int crtc_count = 0; int fb_count = 0; int encoder_count = 0; int copied = 0; uint32_t __user *fb_id; uint32_t __user *crtc_id; - uint32_t __user *output_id; + uint32_t __user *connector_id; uint32_t __user *encoder_id; mutex_lock(&dev->mode_config.mutex); @@ -941,8 +929,8 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each(lh, &dev->mode_config.crtc_list) crtc_count++; - list_for_each(lh, &dev->mode_config.output_list) - output_count++; + list_for_each(lh, &dev->mode_config.connector_list) + connector_count++; list_for_each(lh, &dev->mode_config.encoder_list) encoder_count++; @@ -983,21 +971,21 @@ int drm_mode_getresources(struct drm_device *dev, card_res->count_crtcs = crtc_count; - /* Outputs */ - if (card_res->count_outputs >= output_count) { + /* Connectors */ + if (card_res->count_connectors >= connector_count) { copied = 0; - output_id = (uint32_t *)(unsigned long)card_res->output_id_ptr; - list_for_each_entry(output, &dev->mode_config.output_list, + connector_id = (uint32_t *)(unsigned long)card_res->connector_id_ptr; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - DRM_DEBUG("OUTPUT ID is %d\n", output->id); - if (put_user(output->id, output_id + copied)) { + DRM_DEBUG("CONNECTOR ID is %d\n", connector->id); + if (put_user(connector->id, connector_id + copied)) { ret = -EFAULT; goto out; } copied++; } } - card_res->count_outputs = output_count; + card_res->count_connectors = connector_count; /* Encoders */ if (card_res->count_encoders >= encoder_count) { @@ -1016,7 +1004,7 @@ int drm_mode_getresources(struct drm_device *dev, card_res->count_encoders = encoder_count; DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, - card_res->count_outputs, card_res->count_encoders); + card_res->count_connectors, card_res->count_encoders); out: mutex_unlock(&dev->mode_config.mutex); @@ -1045,7 +1033,7 @@ int drm_mode_getcrtc(struct drm_device *dev, { struct drm_mode_crtc *crtc_resp = data; struct drm_crtc *crtc; - struct drm_output *output; + struct drm_connector *connector; int ocount; int ret = 0; @@ -1064,15 +1052,15 @@ int drm_mode_getcrtc(struct drm_device *dev, else crtc_resp->fb_id = 0; - crtc_resp->outputs = 0; + crtc_resp->connectors = 0; if (crtc->enabled) { drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); crtc_resp->mode_valid = 1; ocount = 0; - list_for_each_entry(output, &dev->mode_config.output_list, head) { - if (output->crtc == crtc) - crtc_resp->outputs |= 1 << (ocount++); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->crtc == crtc) + crtc_resp->connectors |= 1 << (ocount++); } } else { @@ -1085,7 +1073,7 @@ out: } /** - * drm_mode_getoutput - get output configuration + * drm_mode_getconnector - get connector configuration * @inode: inode from the ioctl * @filp: file * from the ioctl * @cmd: cmd from ioctl @@ -1094,18 +1082,18 @@ out: * LOCKING: * Caller? (FIXME) * - * Construct a output configuration structure to return to the user. + * Construct a connector configuration structure to return to the user. * * Called by the user via ioctl. * * RETURNS: * Zero on success, errno on failure. */ -int drm_mode_getoutput(struct drm_device *dev, +int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_get_output *out_resp = data; - struct drm_output *output; + struct drm_mode_get_connector *out_resp = data; + struct drm_connector *connector; struct drm_display_mode *mode; int mode_count = 0; int props_count = 0; @@ -1121,52 +1109,52 @@ int drm_mode_getoutput(struct drm_device *dev, memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); - DRM_DEBUG("output id %d:\n", out_resp->output); + DRM_DEBUG("connector id %d:\n", out_resp->connector); mutex_lock(&dev->mode_config.mutex); - output= idr_find(&dev->mode_config.crtc_idr, out_resp->output); - if (!output || (output->id != out_resp->output)) { + connector= idr_find(&dev->mode_config.crtc_idr, out_resp->connector); + if (!connector || (connector->id != out_resp->connector)) { ret = -EINVAL; goto out; } - list_for_each_entry(mode, &output->modes, head) + list_for_each_entry(mode, &connector->modes, head) mode_count++; - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { - if (output->property_ids[i] != 0) { + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] != 0) { props_count++; } } - for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { - if (output->encoder_ids[i] != 0) { + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] != 0) { encoders_count++; } } if (out_resp->count_modes == 0) { - drm_crtc_probe_single_output_modes(output, dev->mode_config.max_width, dev->mode_config.max_height); + drm_crtc_probe_single_connector_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height); } - out_resp->output_type = output->output_type; - out_resp->output_type_id = output->output_type_id; - out_resp->mm_width = output->display_info.width_mm; - out_resp->mm_height = output->display_info.height_mm; - out_resp->subpixel = output->display_info.subpixel_order; - out_resp->connection = output->status; - if (output->crtc) - out_resp->crtc = output->crtc->id; + out_resp->connector_type = connector->connector_type; + out_resp->connector_type_id = connector->connector_type_id; + out_resp->mm_width = connector->display_info.width_mm; + out_resp->mm_height = connector->display_info.height_mm; + out_resp->subpixel = connector->display_info.subpixel_order; + out_resp->connection = connector->status; + if (connector->crtc) + out_resp->crtc = connector->crtc->id; else out_resp->crtc = 0; - out_resp->crtcs = output->possible_crtcs; - out_resp->clones = output->possible_clones; + out_resp->crtcs = connector->possible_crtcs; + out_resp->clones = connector->possible_clones; if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; - list_for_each_entry(mode, &output->modes, head) { + list_for_each_entry(mode, &connector->modes, head) { drm_crtc_convert_to_umode(&u_mode, mode); if (copy_to_user(mode_ptr + copied, &u_mode, sizeof(u_mode))) { @@ -1183,14 +1171,14 @@ int drm_mode_getoutput(struct drm_device *dev, copied = 0; prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { - if (output->property_ids[i] != 0) { - if (put_user(output->property_ids[i], prop_ptr + copied)) { + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] != 0) { + if (put_user(connector->property_ids[i], prop_ptr + copied)) { ret = -EFAULT; goto out; } - if (put_user(output->property_values[i], prop_values + copied)) { + if (put_user(connector->property_values[i], prop_values + copied)) { ret = -EFAULT; goto out; } @@ -1203,9 +1191,9 @@ int drm_mode_getoutput(struct drm_device *dev, if ((out_resp->count_encoders >= encoders_count) && encoders_count) { copied = 0; encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); - for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { - if (output->encoder_ids[i] != 0) { - if (put_user(output->encoder_ids[i], encoder_ptr + copied)) { + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] != 0) { + if (put_user(connector->encoder_ids[i], encoder_ptr + copied)) { ret = -EFAULT; goto out; } @@ -1267,11 +1255,11 @@ int drm_mode_setcrtc(struct drm_device *dev, { struct drm_mode_crtc *crtc_req = data; struct drm_crtc *crtc, *crtcfb; - struct drm_output **output_set = NULL, *output; + struct drm_connector **connector_set = NULL, *connector; struct drm_framebuffer *fb = NULL; struct drm_display_mode *mode = NULL; struct drm_mode_set set; - uint32_t __user *set_outputs_ptr; + uint32_t __user *set_connectors_ptr; int ret = 0; int i; @@ -1307,43 +1295,43 @@ int drm_mode_setcrtc(struct drm_device *dev, drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); } - if (crtc_req->count_outputs == 0 && mode) { - DRM_DEBUG("Count outputs is 0 but mode set\n"); + if (crtc_req->count_connectors == 0 && mode) { + DRM_DEBUG("Count connectors is 0 but mode set\n"); ret = -EINVAL; goto out; } - if (crtc_req->count_outputs > 0 && !mode && !fb) { - DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs); + if (crtc_req->count_connectors > 0 && !mode && !fb) { + DRM_DEBUG("Count connectors is %d but no mode or fb set\n", crtc_req->count_connectors); ret = -EINVAL; goto out; } - if (crtc_req->count_outputs > 0) { + if (crtc_req->count_connectors > 0) { u32 out_id; - /* Maybe we should check that count_outputs is a sensible value. */ - output_set = kmalloc(crtc_req->count_outputs * - sizeof(struct drm_output *), GFP_KERNEL); - if (!output_set) { + /* Maybe we should check that count_connectors is a sensible value. */ + connector_set = kmalloc(crtc_req->count_connectors * + sizeof(struct drm_connector *), GFP_KERNEL); + if (!connector_set) { ret = -ENOMEM; goto out; } - for (i = 0; i < crtc_req->count_outputs; i++) { - set_outputs_ptr = (uint32_t *)(unsigned long)crtc_req->set_outputs_ptr; - if (get_user(out_id, &set_outputs_ptr[i])) { + for (i = 0; i < crtc_req->count_connectors; i++) { + set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr; + if (get_user(out_id, &set_connectors_ptr[i])) { ret = -EFAULT; goto out; } - 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); + connector = idr_find(&dev->mode_config.crtc_idr, out_id); + if (!connector || (out_id != connector->id)) { + DRM_DEBUG("Connector id %d unknown\n", out_id); ret = -EINVAL; goto out; } - output_set[i] = output; + connector_set[i] = connector; } } @@ -1351,13 +1339,13 @@ int drm_mode_setcrtc(struct drm_device *dev, set.x = crtc_req->x; set.y = crtc_req->y; set.mode = mode; - set.outputs = output_set; - set.num_outputs = crtc_req->count_outputs; + set.connectors = connector_set; + set.num_connectors = crtc_req->count_connectors; set.fb =fb; ret = crtc->funcs->set_config(&set); out: - kfree(output_set); + kfree(connector_set); mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -1628,29 +1616,29 @@ void drm_fb_release(struct file *filp) */ static int drm_mode_attachmode(struct drm_device *dev, - struct drm_output *output, + struct drm_connector *connector, struct drm_display_mode *mode) { int ret = 0; - list_add_tail(&mode->head, &output->user_modes); + list_add_tail(&mode->head, &connector->user_modes); return ret; } int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, struct drm_display_mode *mode) { - struct drm_output *output; + struct drm_connector *connector; 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) { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->crtc == crtc) { if (need_dup) dup_mode = drm_mode_duplicate(dev, mode); else dup_mode = mode; - ret = drm_mode_attachmode(dev, output, dup_mode); + ret = drm_mode_attachmode(dev, connector, dup_mode); if (ret) return ret; need_dup = 1; @@ -1661,14 +1649,14 @@ int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, EXPORT_SYMBOL(drm_mode_attachmode_crtc); static int drm_mode_detachmode(struct drm_device *dev, - struct drm_output *output, + struct drm_connector *connector, struct drm_display_mode *mode) { int found = 0; int ret = 0; struct drm_display_mode *match_mode, *t; - list_for_each_entry_safe(match_mode, t, &output->user_modes, head) { + list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) { if (drm_mode_equal(match_mode, mode)) { list_del(&match_mode->head); drm_mode_destroy(dev, match_mode); @@ -1685,23 +1673,23 @@ static int drm_mode_detachmode(struct drm_device *dev, int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode) { - struct drm_output *output; + struct drm_connector *connector; - list_for_each_entry(output, &dev->mode_config.output_list, head) { - drm_mode_detachmode(dev, output, mode); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_mode_detachmode(dev, connector, mode); } return 0; } EXPORT_SYMBOL(drm_mode_detachmode_crtc); /** - * drm_fb_attachmode - Attach a user mode to an output + * drm_fb_attachmode - Attach a user mode to an connector * @inode: inode from the ioctl * @filp: file * from the ioctl * @cmd: cmd from ioctl * @arg: arg from ioctl * - * This attaches a user specified mode to an output. + * This attaches a user specified mode to an connector. * Called by the user via ioctl. * * RETURNS: @@ -1711,15 +1699,15 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_mode_cmd *mode_cmd = data; - struct drm_output *output; + struct drm_connector *connector; struct drm_display_mode *mode; struct drm_mode_modeinfo *umode = &mode_cmd->mode; int ret = 0; mutex_lock(&dev->mode_config.mutex); - output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); - if (!output || (output->id != mode_cmd->output_id)) { + connector = idr_find(&dev->mode_config.crtc_idr, mode_cmd->connector_id); + if (!connector || (connector->id != mode_cmd->connector_id)) { ret = -EINVAL; goto out; } @@ -1732,7 +1720,7 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, drm_crtc_convert_umode(mode, umode); - ret = drm_mode_attachmode(dev, output, mode); + ret = drm_mode_attachmode(dev, connector, mode); out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1740,7 +1728,7 @@ out: /** - * drm_fb_detachmode - Detach a user specified mode from an output + * drm_fb_detachmode - Detach a user specified mode from an connector * @inode: inode from the ioctl * @filp: file * from the ioctl * @cmd: cmd from ioctl @@ -1755,21 +1743,21 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_mode_cmd *mode_cmd = data; - struct drm_output *output; + struct drm_connector *connector; struct drm_display_mode mode; struct drm_mode_modeinfo *umode = &mode_cmd->mode; int ret = 0; mutex_lock(&dev->mode_config.mutex); - output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); - if (!output || (output->id != mode_cmd->output_id)) { + connector = idr_find(&dev->mode_config.crtc_idr, mode_cmd->connector_id); + if (!connector || (connector->id != mode_cmd->connector_id)) { ret = -EINVAL; goto out; } drm_crtc_convert_umode(&mode, umode); - ret = drm_mode_detachmode(dev, output, &mode); + ret = drm_mode_detachmode(dev, connector, &mode); out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1855,60 +1843,60 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) } EXPORT_SYMBOL(drm_property_destroy); -int drm_output_attach_property(struct drm_output *output, +int drm_connector_attach_property(struct drm_connector *connector, struct drm_property *property, uint64_t init_val) { int i; - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { - if (output->property_ids[i] == 0) { - output->property_ids[i] = property->id; - output->property_values[i] = init_val; + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == 0) { + connector->property_ids[i] = property->id; + connector->property_values[i] = init_val; break; } } - if (i == DRM_OUTPUT_MAX_PROPERTY) + if (i == DRM_CONNECTOR_MAX_PROPERTY) return -EINVAL; return 0; } -EXPORT_SYMBOL(drm_output_attach_property); +EXPORT_SYMBOL(drm_connector_attach_property); -int drm_output_property_set_value(struct drm_output *output, +int drm_connector_property_set_value(struct drm_connector *connector, struct drm_property *property, uint64_t value) { int i; - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { - if (output->property_ids[i] == property->id) { - output->property_values[i] = value; + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == property->id) { + connector->property_values[i] = value; break; } } - if (i == DRM_OUTPUT_MAX_PROPERTY) + if (i == DRM_CONNECTOR_MAX_PROPERTY) return -EINVAL; return 0; } -EXPORT_SYMBOL(drm_output_property_set_value); +EXPORT_SYMBOL(drm_connector_property_set_value); -int drm_output_property_get_value(struct drm_output *output, +int drm_connector_property_get_value(struct drm_connector *connector, struct drm_property *property, uint64_t *val) { int i; - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { - if (output->property_ids[i] == property->id) { - *val = output->property_values[i]; + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == property->id) { + *val = connector->property_values[i]; break; } } - if (i == DRM_OUTPUT_MAX_PROPERTY) + if (i == DRM_CONNECTOR_MAX_PROPERTY) return -EINVAL; return 0; } -EXPORT_SYMBOL(drm_output_property_get_value); +EXPORT_SYMBOL(drm_connector_property_get_value); int drm_mode_getproperty_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -2070,41 +2058,41 @@ done: return ret; } -int drm_mode_output_update_edid_property(struct drm_output *output, struct edid *edid) +int drm_mode_connector_update_edid_property(struct drm_connector *connector, struct edid *edid) { - struct drm_device *dev = output->dev; + struct drm_device *dev = connector->dev; int ret = 0; - if (output->edid_blob_ptr) - drm_property_destroy_blob(dev, output->edid_blob_ptr); + if (connector->edid_blob_ptr) + drm_property_destroy_blob(dev, connector->edid_blob_ptr); - output->edid_blob_ptr = drm_property_create_blob(output->dev, 128, edid); + connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); - ret = drm_output_property_set_value(output, dev->mode_config.edid_property, output->edid_blob_ptr->id); + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->id); return ret; } -EXPORT_SYMBOL(drm_mode_output_update_edid_property); +EXPORT_SYMBOL(drm_mode_connector_update_edid_property); -int drm_mode_output_property_set_ioctl(struct drm_device *dev, +int drm_mode_connector_property_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_mode_output_set_property *out_resp = data; + struct drm_mode_connector_set_property *out_resp = data; struct drm_property *property; - struct drm_output *output; + struct drm_connector *connector; int ret = -EINVAL; int i; mutex_lock(&dev->mode_config.mutex); - output = idr_find(&dev->mode_config.crtc_idr, out_resp->output_id); - if (!output || (output->id != out_resp->output_id)) { + connector = idr_find(&dev->mode_config.crtc_idr, out_resp->connector_id); + if (!connector || (connector->id != out_resp->connector_id)) { goto out; } - for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) { - if (output->property_ids[i] == out_resp->prop_id) + for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { + if (connector->property_ids[i] == out_resp->prop_id) break; } - if (i == DRM_OUTPUT_MAX_PROPERTY) { + if (i == DRM_CONNECTOR_MAX_PROPERTY) { goto out; } @@ -2135,8 +2123,8 @@ int drm_mode_output_property_set_ioctl(struct drm_device *dev, } } - if (output->funcs->set_property) - ret = output->funcs->set_property(output, property, out_resp->value); + if (connector->funcs->set_property) + ret = connector->funcs->set_property(connector, property, out_resp->value); out: mutex_unlock(&dev->mode_config.mutex); @@ -2205,30 +2193,30 @@ out: } -int drm_mode_output_attach_encoder(struct drm_output *output, +int drm_mode_connector_attach_encoder(struct drm_connector *connector, struct drm_encoder *encoder) { int i; - for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { - if (output->encoder_ids[i] == 0) { - output->encoder_ids[i] = encoder->id; + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) { + connector->encoder_ids[i] = encoder->id; return 0; } } return -ENOMEM; } -EXPORT_SYMBOL(drm_mode_output_attach_encoder); +EXPORT_SYMBOL(drm_mode_connector_attach_encoder); -void drm_mode_output_detach_encoder(struct drm_output *output, +void drm_mode_connector_detach_encoder(struct drm_connector *connector, struct drm_encoder *encoder) { int i; - for (i = 0; i < DRM_OUTPUT_MAX_ENCODER; i++) { - if (output->encoder_ids[i] == encoder->id) { - output->encoder_ids[i] = 0; + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == encoder->id) { + connector->encoder_ids[i] = 0; break; } } } -EXPORT_SYMBOL(drm_mode_output_detach_encoder); +EXPORT_SYMBOL(drm_mode_connector_detach_encoder); -- cgit v1.2.3 From 5d47185eb69d73dd7e6ee3ddde4d0c7642c2d5b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 15:32:58 +1000 Subject: drm: switch possible crtc/clones over to encoders --- linux-core/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c60476a4..bf6afd6a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1148,9 +1148,6 @@ int drm_mode_getconnector(struct drm_device *dev, else out_resp->crtc = 0; - out_resp->crtcs = connector->possible_crtcs; - out_resp->clones = connector->possible_clones; - if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; @@ -2201,6 +2198,9 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector, for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == 0) { connector->encoder_ids[i] = encoder->id; + /* pick the first added encoder as the current */ + if (i == 0) + connector->current_encoder_id = encoder->id; return 0; } } -- cgit v1.2.3 From e439e74776b215d70d8e34e8aa9cea22179dcbc6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 10:05:54 +1000 Subject: drm/modesetting: another re-org of some internals. Move dpms into the helper functions. Move crtc into the encoder. Move disable unused functions into the helper. --- linux-core/drm_crtc.c | 62 +++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 36 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bf6afd6a..27bf7c27 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -83,6 +83,15 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] = { DRM_MODE_ENCODER_TVDAC, "TV" }, }; +char *drm_get_encoder_name(struct drm_encoder *encoder) +{ + static char buf[32]; + + snprintf(buf, 32, "%s-%d", drm_encoder_enum_list[encoder->encoder_type].name, + encoder->id); + return buf; +} + char *drm_get_connector_name(struct drm_connector *connector) { static char buf[32]; @@ -290,11 +299,11 @@ EXPORT_SYMBOL(drm_crtc_cleanup); */ bool drm_crtc_in_use(struct drm_crtc *crtc) { - struct drm_connector *connector; + struct drm_encoder *encoder; struct drm_device *dev = crtc->dev; /* FIXME: Locking around list access? */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - if (connector->crtc == crtc) + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + if (encoder->crtc == crtc) return true; return false; } @@ -406,33 +415,6 @@ void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY) EXPORT_SYMBOL(drm_crtc_probe_connector_modes); -/** - * drm_disable_unused_functions - disable unused objects - * @dev: DRM device - * - * LOCKING: - * Caller must hold mode config lock. - * - * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled - * by calling its dpms function, which should power it off. - */ -void drm_disable_unused_functions(struct drm_device *dev) -{ - struct drm_connector *connector; - struct drm_crtc *crtc; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (!connector->crtc) - (*connector->funcs->dpms)(connector, DPMSModeOff); - } - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (!crtc->enabled) - crtc->funcs->dpms(crtc, DPMSModeOff); - } -} -EXPORT_SYMBOL(drm_disable_unused_functions); - /** * drm_mode_probed_add - add a mode to the specified connector's probed mode list * @connector: connector the new mode @@ -1059,7 +1041,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->mode_valid = 1; ocount = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->crtc == crtc) + if (connector->encoder->crtc == crtc) crtc_resp->connectors |= 1 << (ocount++); } @@ -1143,10 +1125,10 @@ int drm_mode_getconnector(struct drm_device *dev, out_resp->mm_height = connector->display_info.height_mm; out_resp->subpixel = connector->display_info.subpixel_order; out_resp->connection = connector->status; - if (connector->crtc) - out_resp->crtc = connector->crtc->id; + if (connector->encoder) + out_resp->encoder = connector->encoder->id; else - out_resp->crtc = 0; + out_resp->encoder = 0; if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; @@ -1220,6 +1202,10 @@ int drm_mode_getencoder(struct drm_device *dev, goto out; } + if (encoder->crtc) + enc_resp->crtc = encoder->crtc->id; + else + enc_resp->crtc = 0; enc_resp->encoder_type = encoder->encoder_type; enc_resp->encoder_id = encoder->id; enc_resp->crtcs = encoder->possible_crtcs; @@ -1630,7 +1616,9 @@ int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, struct drm_display_mode *dup_mode; int need_dup = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->crtc == crtc) { + if (!connector->encoder) + break; + if (connector->encoder->crtc == crtc) { if (need_dup) dup_mode = drm_mode_duplicate(dev, mode); else @@ -2200,7 +2188,7 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector, connector->encoder_ids[i] = encoder->id; /* pick the first added encoder as the current */ if (i == 0) - connector->current_encoder_id = encoder->id; + connector->encoder = encoder; return 0; } } @@ -2215,6 +2203,8 @@ void drm_mode_connector_detach_encoder(struct drm_connector *connector, for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == encoder->id) { connector->encoder_ids[i] = 0; + if (connector->encoder == encoder) + connector->encoder = NULL; break; } } -- cgit v1.2.3 From dba95ec34315d62934ff0e493e085aa6a03cde7c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 10:41:12 +1000 Subject: drm: fixup some interfaces so test code works again --- linux-core/drm_crtc.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 27bf7c27..c4210fd4 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1015,8 +1015,6 @@ int drm_mode_getcrtc(struct drm_device *dev, { struct drm_mode_crtc *crtc_resp = data; struct drm_crtc *crtc; - struct drm_connector *connector; - int ocount; int ret = 0; mutex_lock(&dev->mode_config.mutex); @@ -1039,11 +1037,6 @@ int drm_mode_getcrtc(struct drm_device *dev, drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); crtc_resp->mode_valid = 1; - ocount = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder->crtc == crtc) - crtc_resp->connectors |= 1 << (ocount++); - } } else { crtc_resp->mode_valid = 0; -- cgit v1.2.3 From 0dd000b578adec6ff101c957bce7dc9a32b76713 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 11:12:28 +1000 Subject: drm/modesetting: move some connector functions to helper. Migrated the output mode collection into the helper. --- linux-core/drm_crtc.c | 132 +------------------------------------------------- 1 file changed, 1 insertion(+), 131 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c4210fd4..74e526bd 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -285,136 +285,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_cleanup); -/** - * drm_crtc_in_use - check if a given CRTC is in a mode_config - * @crtc: CRTC to check - * - * LOCKING: - * Caller must hold mode config lock. - * - * Walk @crtc's DRM device's mode_config and see if it's in use. - * - * RETURNS: - * True if @crtc is part of the mode_config, false otherwise. - */ -bool drm_crtc_in_use(struct drm_crtc *crtc) -{ - struct drm_encoder *encoder; - struct drm_device *dev = crtc->dev; - /* FIXME: Locking around list access? */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->crtc == crtc) - return true; - return false; -} -EXPORT_SYMBOL(drm_crtc_in_use); - -/* - * Detailed mode info for a standard 640x480@60Hz monitor - */ -static struct drm_display_mode std_mode[] = { - { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656, - 752, 800, 0, 480, 490, 492, 525, 0, - V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */ -}; - -/** - * drm_crtc_probe_connector_modes - get complete set of display modes - * @dev: DRM device - * @maxX: max width for modes - * @maxY: max height for modes - * - * LOCKING: - * Caller must hold mode config lock. - * - * Based on @dev's mode_config layout, scan all the connectors and try to detect - * modes on them. Modes will first be added to the connector's probed_modes - * list, then culled (based on validity and the @maxX, @maxY parameters) and - * put into the normal modes list. - * - * Intended to be used either at bootup time or when major configuration - * changes have occurred. - * - * FIXME: take into account monitor limits - */ -void drm_crtc_probe_single_connector_modes(struct drm_connector *connector, int maxX, int maxY) -{ - struct drm_device *dev = connector->dev; - struct drm_display_mode *mode, *t; - int ret; - //if (maxX == 0 || maxY == 0) - // TODO - - /* set all modes to the unverified state */ - list_for_each_entry_safe(mode, t, &connector->modes, head) - mode->status = MODE_UNVERIFIED; - - connector->status = (*connector->funcs->detect)(connector); - - if (connector->status == connector_status_disconnected) { - DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector)); - /* TODO set EDID to NULL */ - return; - } - - ret = (*connector->funcs->get_modes)(connector); - - if (ret) { - drm_mode_connector_list_update(connector); - } - - if (maxX && maxY) - drm_mode_validate_size(dev, &connector->modes, maxX, - maxY, 0); - list_for_each_entry_safe(mode, t, &connector->modes, head) { - if (mode->status == MODE_OK) - mode->status = (*connector->funcs->mode_valid)(connector,mode); - } - - - drm_mode_prune_invalid(dev, &connector->modes, TRUE); - - if (list_empty(&connector->modes)) { - struct drm_display_mode *stdmode; - - DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(connector)); - - /* Should we do this here ??? - * When no valid EDID modes are available we end up - * here and bailed in the past, now we add a standard - * 640x480@60Hz mode and carry on. - */ - stdmode = drm_mode_duplicate(dev, &std_mode[0]); - drm_mode_probed_add(connector, stdmode); - drm_mode_list_concat(&connector->probed_modes, - &connector->modes); - - DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", - drm_get_connector_name(connector)); - } - - drm_mode_sort(&connector->modes); - - DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector)); - list_for_each_entry_safe(mode, t, &connector->modes, head) { - mode->vrefresh = drm_mode_vrefresh(mode); - - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - drm_mode_debug_printmodeline(mode); - } -} - -void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY) -{ - struct drm_connector *connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_crtc_probe_single_connector_modes(connector, maxX, maxY); - } -} -EXPORT_SYMBOL(drm_crtc_probe_connector_modes); - - /** * drm_mode_probed_add - add a mode to the specified connector's probed mode list * @connector: connector the new mode @@ -1109,7 +979,7 @@ int drm_mode_getconnector(struct drm_device *dev, } if (out_resp->count_modes == 0) { - drm_crtc_probe_single_connector_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height); + connector->funcs->fill_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height); } out_resp->connector_type = connector->connector_type; -- cgit v1.2.3 From 46c78a2223802b9105a87b7125fd4872ab69c4ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 11:44:35 +1000 Subject: drm/modesetting: add best encoder finding for modesetting This asks the driver to suggest the best encoder for the connector during the pick crtcs stage. Need to also do this during mode setting stages --- linux-core/drm_crtc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 74e526bd..73c7f2a3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2042,16 +2042,13 @@ out: } int drm_mode_connector_attach_encoder(struct drm_connector *connector, - struct drm_encoder *encoder) + struct drm_encoder *encoder) { int i; for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == 0) { connector->encoder_ids[i] = encoder->id; - /* pick the first added encoder as the current */ - if (i == 0) - connector->encoder = encoder; return 0; } } -- cgit v1.2.3 From 4e7b24639808e5e1e2c05143028db1a3bc2812e9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 14:04:41 +1000 Subject: drm: add functions to get/set gamma ramps --- linux-core/drm_crtc.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 73c7f2a3..7746fd50 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -279,6 +279,11 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + if (crtc->gamma_store) { + kfree(crtc->gamma_store); + crtc->gamma_store = NULL; + } + drm_idr_put(dev, crtc->id); list_del(&crtc->head); dev->mode_config.num_crtc--; @@ -896,6 +901,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; + crtc_resp->gamma_size = crtc->gamma_size; if (crtc->fb) crtc_resp->fb_id = crtc->fb->id; @@ -2070,3 +2076,112 @@ void drm_mode_connector_detach_encoder(struct drm_connector *connector, } } EXPORT_SYMBOL(drm_mode_connector_detach_encoder); + +bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, + int gamma_size) +{ + crtc->gamma_size = gamma_size; + + crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); + if (!crtc->gamma_store) { + crtc->gamma_size = 0; + return false; + } + + return true; +} +EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); + +int drm_mode_gamma_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc_lut *crtc_lut = data; + struct drm_crtc *crtc; + void *r_base, *g_base, *b_base; + int size; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + crtc = idr_find(&dev->mode_config.crtc_idr, crtc_lut->crtc_id); + if (!crtc || (crtc->id != crtc_lut->crtc_id)) { + ret = -EINVAL; + goto out; + } + + /* memcpy into gamma store */ + if (crtc_lut->gamma_size != crtc->gamma_size) { + ret = -EINVAL; + goto out; + } + + size = crtc_lut->gamma_size * (sizeof(uint16_t)); + r_base = crtc->gamma_store; + if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) { + ret = -EFAULT; + goto out; + } + + g_base = r_base + size; + if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) { + ret = -EFAULT; + goto out; + } + + b_base = g_base + size; + if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) { + ret = -EFAULT; + goto out; + } + + crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; + +} + +int drm_mode_gamma_get_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc_lut *crtc_lut = data; + struct drm_crtc *crtc; + void *r_base, *g_base, *b_base; + int size; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + crtc = idr_find(&dev->mode_config.crtc_idr, crtc_lut->crtc_id); + if (!crtc || (crtc->id != crtc_lut->crtc_id)) { + ret = -EINVAL; + goto out; + } + + /* memcpy into gamma store */ + if (crtc_lut->gamma_size != crtc->gamma_size) { + ret = -EINVAL; + goto out; + } + + size = crtc_lut->gamma_size * (sizeof(uint16_t)); + r_base = crtc->gamma_store; + if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) { + ret = -EFAULT; + goto out; + } + + g_base = r_base + size; + if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) { + ret = -EFAULT; + goto out; + } + + b_base = g_base + size; + if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) { + ret = -EFAULT; + goto out; + } +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} -- cgit v1.2.3 From c321bc4f9280fe93e2df2b1c47e13cba7499e486 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 14:33:42 +1000 Subject: drm: only report framebuffers available on this fd. Not 100% sure this is a good idea, but I think I'd rather things communicate with bo handles not fb ids. --- linux-core/drm_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 7746fd50..d82d8390 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -780,7 +780,7 @@ int drm_mode_getresources(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); - list_for_each(lh, &dev->mode_config.fb_list) + list_for_each(lh, &file_priv->fbs) fb_count++; list_for_each(lh, &dev->mode_config.crtc_list) @@ -802,7 +802,7 @@ int drm_mode_getresources(struct drm_device *dev, if (card_res->count_fbs >= fb_count) { copied = 0; fb_id = (uint32_t *)(unsigned long)card_res->fb_id_ptr; - list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + list_for_each_entry(fb, &file_priv->fbs, head) { if (put_user(fb->id, fb_id + copied)) { ret = -EFAULT; goto out; -- cgit v1.2.3 From 50d3e5bd020d0b6877a5fef441408f16e31121cd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 16:19:21 +1000 Subject: drm/modesetting: redo object handles around a core object. handle crtc/encoders/connectors/fb/mode/property/blob using this system. --- linux-core/drm_crtc.c | 211 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 82 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index d82d8390..79dc137e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -88,7 +88,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder) static char buf[32]; snprintf(buf, 32, "%s-%d", drm_encoder_enum_list[encoder->encoder_type].name, - encoder->id); + encoder->base.id); return buf; } @@ -126,25 +126,27 @@ char *drm_get_connector_status_name(enum drm_connector_status status) * New unique (relative to other objects in @dev) integer identifier for the * object. */ -int drm_idr_get(struct drm_device *dev, void *ptr) +static int drm_mode_object_get(struct drm_device *dev, struct drm_mode_object *obj, uint32_t obj_type) { int new_id = 0; int ret; again: if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { DRM_ERROR("Ran out memory getting a mode number\n"); - return 0; + return -EINVAL; } - ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id); + ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); if (ret == -EAGAIN) goto again; - return new_id; + obj->id = new_id; + obj->type = obj_type; + return 0; } /** - * drm_idr_put - free an identifer + * drm_mode_object_put - free an identifer * @dev: DRM device * @id: ID to free * @@ -153,9 +155,20 @@ again: * * Free @id from @dev's unique identifier pool. */ -void drm_idr_put(struct drm_device *dev, int id) +static void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object *object) +{ + idr_remove(&dev->mode_config.crtc_idr, object->id); +} + +static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) { - idr_remove(&dev->mode_config.crtc_idr, id); + struct drm_mode_object *obj; + + obj = idr_find(&dev->mode_config.crtc_idr, id); + if (!obj || (obj->type != type) || (obj->id != id)) + return NULL; + + return obj; } /** @@ -203,7 +216,7 @@ struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev) if (!fb) return NULL; - fb->id = drm_idr_get(dev, fb); + drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); fb->dev = dev; dev->mode_config.num_fb++; list_add(&fb->head, &dev->mode_config.fb_list); @@ -233,7 +246,7 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) crtc->fb = NULL; } - drm_idr_put(dev, fb->id); + drm_mode_object_put(dev, &fb->base); list_del(&fb->head); dev->mode_config.num_fb--; @@ -258,7 +271,7 @@ void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, crtc->dev = dev; crtc->funcs = funcs; - crtc->id = drm_idr_get(dev, crtc); + drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++; @@ -284,7 +297,7 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) crtc->gamma_store = NULL; } - drm_idr_put(dev, crtc->id); + drm_mode_object_put(dev, &crtc->base); list_del(&crtc->head); dev->mode_config.num_crtc--; } @@ -344,7 +357,7 @@ void drm_connector_init(struct drm_device *dev, { connector->dev = dev; connector->funcs = funcs; - connector->id = drm_idr_get(dev, connector); + drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); connector->connector_type = connector_type; connector->connector_type_id = 1; /* TODO */ INIT_LIST_HEAD(&connector->user_modes); @@ -390,7 +403,7 @@ void drm_connector_cleanup(struct drm_connector *connector) drm_mode_remove(connector, mode); mutex_lock(&dev->mode_config.mutex); - drm_idr_put(dev, connector->id); + drm_mode_object_put(dev, &connector->base); list_del(&connector->head); mutex_unlock(&dev->mode_config.mutex); } @@ -402,7 +415,8 @@ void drm_encoder_init(struct drm_device *dev, int encoder_type) { encoder->dev = dev; - encoder->id = drm_idr_get(dev, encoder); + + drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); encoder->encoder_type = encoder_type; encoder->funcs = funcs; @@ -418,7 +432,7 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; mutex_lock(&dev->mode_config.mutex); - drm_idr_put(dev, encoder->id); + drm_mode_object_put(dev, &encoder->base); list_del(&encoder->head); mutex_unlock(&dev->mode_config.mutex); } @@ -444,7 +458,7 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev) if (!nmode) return NULL; - nmode->mode_id = drm_idr_get(dev, nmode); + drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE); return nmode; } EXPORT_SYMBOL(drm_mode_create); @@ -461,7 +475,7 @@ EXPORT_SYMBOL(drm_mode_create); */ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) { - drm_idr_put(dev, mode->mode_id); + drm_mode_object_put(dev, &mode->base); kfree(mode); } @@ -803,7 +817,7 @@ int drm_mode_getresources(struct drm_device *dev, copied = 0; fb_id = (uint32_t *)(unsigned long)card_res->fb_id_ptr; list_for_each_entry(fb, &file_priv->fbs, head) { - if (put_user(fb->id, fb_id + copied)) { + if (put_user(fb->base.id, fb_id + copied)) { ret = -EFAULT; goto out; } @@ -817,8 +831,8 @@ int drm_mode_getresources(struct drm_device *dev, copied = 0; crtc_id = (uint32_t *)(unsigned long)card_res->crtc_id_ptr; 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, crtc_id + copied)) { + DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); + if (put_user(crtc->base.id, crtc_id + copied)) { ret = -EFAULT; goto out; } @@ -834,8 +848,8 @@ int drm_mode_getresources(struct drm_device *dev, connector_id = (uint32_t *)(unsigned long)card_res->connector_id_ptr; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - DRM_DEBUG("CONNECTOR ID is %d\n", connector->id); - if (put_user(connector->id, connector_id + copied)) { + DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id); + if (put_user(connector->base.id, connector_id + copied)) { ret = -EFAULT; goto out; } @@ -850,8 +864,8 @@ int drm_mode_getresources(struct drm_device *dev, encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - DRM_DEBUG("ENCODER ID is %d\n", encoder->id); - if (put_user(encoder->id, encoder_id + copied)) { + DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id); + if (put_user(encoder->base.id, encoder_id + copied)) { ret = -EFAULT; goto out; } @@ -890,21 +904,24 @@ int drm_mode_getcrtc(struct drm_device *dev, { struct drm_mode_crtc *crtc_resp = data; struct drm_crtc *crtc; + struct drm_mode_object *obj; int ret = 0; mutex_lock(&dev->mode_config.mutex); - crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp->crtc_id); - if (!crtc || (crtc->id != crtc_resp->crtc_id)) { + + obj = drm_mode_object_find(dev, crtc_resp->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { ret = -EINVAL; goto out; } + crtc = obj_to_crtc(obj); crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; crtc_resp->gamma_size = crtc->gamma_size; if (crtc->fb) - crtc_resp->fb_id = crtc->fb->id; + crtc_resp->fb_id = crtc->fb->base.id; else crtc_resp->fb_id = 0; @@ -944,6 +961,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_get_connector *out_resp = data; + struct drm_mode_object *obj; struct drm_connector *connector; struct drm_display_mode *mode; int mode_count = 0; @@ -963,11 +981,13 @@ int drm_mode_getconnector(struct drm_device *dev, DRM_DEBUG("connector id %d:\n", out_resp->connector); mutex_lock(&dev->mode_config.mutex); - connector= idr_find(&dev->mode_config.crtc_idr, out_resp->connector); - if (!connector || (connector->id != out_resp->connector)) { + + obj = drm_mode_object_find(dev, out_resp->connector, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { ret = -EINVAL; goto out; } + connector = obj_to_connector(obj); list_for_each_entry(mode, &connector->modes, head) mode_count++; @@ -995,7 +1015,7 @@ int drm_mode_getconnector(struct drm_device *dev, out_resp->subpixel = connector->display_info.subpixel_order; out_resp->connection = connector->status; if (connector->encoder) - out_resp->encoder = connector->encoder->id; + out_resp->encoder = connector->encoder->base.id; else out_resp->encoder = 0; @@ -1060,23 +1080,24 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_get_encoder *enc_resp = data; + struct drm_mode_object *obj; struct drm_encoder *encoder; int ret = 0; mutex_lock(&dev->mode_config.mutex); - encoder = idr_find(&dev->mode_config.crtc_idr, enc_resp->encoder_id); - if (!encoder || (encoder->id != enc_resp->encoder_id)) { - DRM_DEBUG("Unknown encoder ID %d\n", enc_resp->encoder_id); + obj = drm_mode_object_find(dev, enc_resp->encoder_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) { ret = -EINVAL; goto out; } + encoder = obj_to_encoder(obj); if (encoder->crtc) - enc_resp->crtc = encoder->crtc->id; + enc_resp->crtc = encoder->crtc->base.id; else enc_resp->crtc = 0; enc_resp->encoder_type = encoder->encoder_type; - enc_resp->encoder_id = encoder->id; + enc_resp->encoder_id = encoder->base.id; enc_resp->crtcs = encoder->possible_crtcs; enc_resp->clones = encoder->possible_clones; @@ -1106,6 +1127,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc *crtc_req = data; + struct drm_mode_object *obj; struct drm_crtc *crtc, *crtcfb; struct drm_connector **connector_set = NULL, *connector; struct drm_framebuffer *fb = NULL; @@ -1116,13 +1138,14 @@ int drm_mode_setcrtc(struct drm_device *dev, int i; mutex_lock(&dev->mode_config.mutex); - crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id); - if (!crtc || (crtc->id != crtc_req->crtc_id)) { + obj = drm_mode_object_find(dev, crtc_req->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id); ret = -EINVAL; goto out; } - + crtc = obj_to_crtc(obj); + if (crtc_req->mode_valid) { /* If we have a mode we need a framebuffer. */ /* If we pass -1, set the mode with the currently bound fb */ @@ -1134,12 +1157,13 @@ int drm_mode_setcrtc(struct drm_device *dev, } } } else { - fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id); - if (!fb || (fb->id != crtc_req->fb_id)) { + obj = drm_mode_object_find(dev, crtc_req->fb_id, DRM_MODE_OBJECT_FB); + if (!obj) { DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id); ret = -EINVAL; goto out; } + fb = obj_to_fb(obj); } mode = drm_mode_create(dev); @@ -1176,12 +1200,13 @@ int drm_mode_setcrtc(struct drm_device *dev, goto out; } - connector = idr_find(&dev->mode_config.crtc_idr, out_id); - if (!connector || (out_id != connector->id)) { + obj = drm_mode_object_find(dev, out_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { DRM_DEBUG("Connector id %d unknown\n", out_id); ret = -EINVAL; goto out; } + connector = obj_to_connector(obj); connector_set[i] = connector; } @@ -1206,6 +1231,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_cursor *req = data; + struct drm_mode_object *obj; struct drm_crtc *crtc; struct drm_buffer_object *bo = NULL; /* must be set */ int ret = 0; @@ -1218,12 +1244,13 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, } mutex_lock(&dev->mode_config.mutex); - crtc = idr_find(&dev->mode_config.crtc_idr, req->crtc); - if (!crtc || (crtc->id != req->crtc)) { + obj = drm_mode_object_find(dev, req->crtc, DRM_MODE_OBJECT_CRTC); + if (!obj) { DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc); ret = -EINVAL; goto out; } + crtc = obj_to_crtc(obj); if (req->flags & DRM_MODE_CURSOR_BO) { /* Turn of the cursor if handle is 0 */ @@ -1320,7 +1347,7 @@ int drm_mode_addfb(struct drm_device *dev, fb->depth = r->depth; fb->bo = bo; - r->buffer_id = fb->id; + r->buffer_id = fb->base.id; list_add(&fb->filp_head, &file_priv->fbs); @@ -1349,6 +1376,7 @@ out: int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_mode_object *obj; struct drm_framebuffer *fb = NULL; struct drm_framebuffer *fbl = NULL; uint32_t *id = data; @@ -1356,13 +1384,14 @@ int drm_mode_rmfb(struct drm_device *dev, int found = 0; mutex_lock(&dev->mode_config.mutex); - fb = idr_find(&dev->mode_config.crtc_idr, *id); + obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); /* TODO check that we realy get a framebuffer back. */ - if (!fb || (*id != fb->id)) { + if (!obj) { DRM_ERROR("mode invalid framebuffer id\n"); ret = -EINVAL; goto out; } + fb = obj_to_fb(obj); list_for_each_entry(fbl, &file_priv->fbs, filp_head) if (fb == fbl) @@ -1409,16 +1438,18 @@ int drm_mode_getfb(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_fb_cmd *r = data; + struct drm_mode_object *obj; struct drm_framebuffer *fb; int ret = 0; mutex_lock(&dev->mode_config.mutex); - fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id); - if (!fb || (r->buffer_id != fb->id)) { + obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); + if (!obj) { DRM_ERROR("invalid framebuffer id\n"); ret = -EINVAL; goto out; } + fb = obj_to_fb(obj); r->height = fb->height; r->width = fb->width; @@ -1555,16 +1586,18 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, struct drm_mode_mode_cmd *mode_cmd = data; struct drm_connector *connector; struct drm_display_mode *mode; + struct drm_mode_object *obj; struct drm_mode_modeinfo *umode = &mode_cmd->mode; int ret = 0; mutex_lock(&dev->mode_config.mutex); - connector = idr_find(&dev->mode_config.crtc_idr, mode_cmd->connector_id); - if (!connector || (connector->id != mode_cmd->connector_id)) { + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { ret = -EINVAL; goto out; } + connector = obj_to_connector(obj); mode = drm_mode_create(dev); if (!mode) { @@ -1596,6 +1629,7 @@ out: int drm_mode_detachmode_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_mode_object *obj; struct drm_mode_mode_cmd *mode_cmd = data; struct drm_connector *connector; struct drm_display_mode mode; @@ -1604,11 +1638,12 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, mutex_lock(&dev->mode_config.mutex); - connector = idr_find(&dev->mode_config.crtc_idr, mode_cmd->connector_id); - if (!connector || (connector->id != mode_cmd->connector_id)) { + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { ret = -EINVAL; goto out; } + connector = obj_to_connector(obj); drm_crtc_convert_umode(&mode, umode); ret = drm_mode_detachmode(dev, connector, &mode); @@ -1632,7 +1667,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, goto fail; } - property->id = drm_idr_get(dev, property); + drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); property->flags = flags; property->num_values = num_values; INIT_LIST_HEAD(&property->enum_blob_list); @@ -1691,7 +1726,7 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) if (property->num_values) kfree(property->values); - drm_idr_put(dev, property->id); + drm_mode_object_put(dev, &property->base); list_del(&property->head); kfree(property); } @@ -1704,7 +1739,7 @@ int drm_connector_attach_property(struct drm_connector *connector, for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { if (connector->property_ids[i] == 0) { - connector->property_ids[i] = property->id; + connector->property_ids[i] = property->base.id; connector->property_values[i] = init_val; break; } @@ -1722,7 +1757,7 @@ int drm_connector_property_set_value(struct drm_connector *connector, int i; for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { - if (connector->property_ids[i] == property->id) { + if (connector->property_ids[i] == property->base.id) { connector->property_values[i] = value; break; } @@ -1740,7 +1775,7 @@ int drm_connector_property_get_value(struct drm_connector *connector, int i; for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { - if (connector->property_ids[i] == property->id) { + if (connector->property_ids[i] == property->base.id) { *val = connector->property_values[i]; break; } @@ -1755,6 +1790,7 @@ EXPORT_SYMBOL(drm_connector_property_get_value); int drm_mode_getproperty_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_mode_object *obj; struct drm_mode_get_property *out_resp = data; struct drm_property *property; int enum_count = 0; @@ -1770,11 +1806,12 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, uint32_t __user *blob_length_ptr; mutex_lock(&dev->mode_config.mutex); - property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); - if (!property || (property->id != out_resp->prop_id)) { + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); + if (!obj) { ret = -EINVAL; goto done; } + property = obj_to_property(obj); if (property->flags & DRM_MODE_PROP_ENUM) { list_for_each_entry(prop_enum, &property->enum_blob_list, head) @@ -1831,7 +1868,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; list_for_each_entry(prop_blob, &property->enum_blob_list, head) { - if (put_user(prop_blob->id, blob_id_ptr + copied)) { + if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { ret = -EFAULT; goto done; } @@ -1868,7 +1905,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev memcpy(blob->data, data, length); - blob->id = drm_idr_get(dev, blob); + drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); list_add_tail(&blob->head, &dev->mode_config.property_blob_list); return blob; @@ -1877,7 +1914,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev static void drm_property_destroy_blob(struct drm_device *dev, struct drm_property_blob *blob) { - drm_idr_put(dev, blob->id); + drm_mode_object_put(dev, &blob->base); list_del(&blob->head); kfree(blob); } @@ -1885,18 +1922,19 @@ static void drm_property_destroy_blob(struct drm_device *dev, int drm_mode_getblob_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_mode_object *obj; struct drm_mode_get_blob *out_resp = data; struct drm_property_blob *blob; int ret = 0; void *blob_ptr; mutex_lock(&dev->mode_config.mutex); - - blob = idr_find(&dev->mode_config.crtc_idr, out_resp->blob_id); - if (!blob || (blob->id != out_resp->blob_id)) { + obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { ret = -EINVAL; goto done; } + blob = obj_to_blob(obj); if (out_resp->length == blob->length) { blob_ptr = (void *)(unsigned long)out_resp->data; @@ -1921,7 +1959,7 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, str connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); - ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->id); + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->base.id); return ret; } EXPORT_SYMBOL(drm_mode_connector_update_edid_property); @@ -1930,16 +1968,19 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_connector_set_property *out_resp = data; + struct drm_mode_object *obj; struct drm_property *property; struct drm_connector *connector; int ret = -EINVAL; int i; mutex_lock(&dev->mode_config.mutex); - connector = idr_find(&dev->mode_config.crtc_idr, out_resp->connector_id); - if (!connector || (connector->id != out_resp->connector_id)) { + + obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); + if (!obj) { goto out; } + connector = obj_to_connector(obj); for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { if (connector->property_ids[i] == out_resp->prop_id) @@ -1950,10 +1991,11 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, goto out; } - property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); - if (!property || (property->id != out_resp->prop_id)) { + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); + if (!obj) { goto out; } + property = obj_to_property(obj); if (property->flags & DRM_MODE_PROP_IMMUTABLE) goto out; @@ -1990,6 +2032,7 @@ int drm_mode_replacefb(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_fb_cmd *r = data; + struct drm_mode_object *obj; struct drm_framebuffer *fb; struct drm_buffer_object *bo; int found = 0; @@ -2002,12 +2045,12 @@ int drm_mode_replacefb(struct drm_device *dev, ret = -EINVAL; goto out; } - - fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id); - if (!fb || (r->buffer_id != fb->id)) { + obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); + if (!obj) { ret = -EINVAL; goto out; } + fb = obj_to_fb(obj); list_for_each_entry(fbl, &file_priv->fbs, filp_head) if (fb == fbl) @@ -2036,7 +2079,7 @@ int drm_mode_replacefb(struct drm_device *dev, #if 0 /* find all crtcs connected to this fb */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb->id == r->buffer_id) { + if (crtc->fb->base.id == r->buffer_id) { crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); } } @@ -2054,7 +2097,7 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector, for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == 0) { - connector->encoder_ids[i] = encoder->id; + connector->encoder_ids[i] = encoder->base.id; return 0; } } @@ -2067,7 +2110,7 @@ void drm_mode_connector_detach_encoder(struct drm_connector *connector, { int i; for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - if (connector->encoder_ids[i] == encoder->id) { + if (connector->encoder_ids[i] == encoder->base.id) { connector->encoder_ids[i] = 0; if (connector->encoder == encoder) connector->encoder = NULL; @@ -2096,17 +2139,19 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; + struct drm_mode_object *obj; struct drm_crtc *crtc; void *r_base, *g_base, *b_base; int size; int ret = 0; mutex_lock(&dev->mode_config.mutex); - crtc = idr_find(&dev->mode_config.crtc_idr, crtc_lut->crtc_id); - if (!crtc || (crtc->id != crtc_lut->crtc_id)) { + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { ret = -EINVAL; goto out; } + crtc = obj_to_crtc(obj); /* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) { @@ -2145,17 +2190,19 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; + struct drm_mode_object *obj; struct drm_crtc *crtc; void *r_base, *g_base, *b_base; int size; int ret = 0; mutex_lock(&dev->mode_config.mutex); - crtc = idr_find(&dev->mode_config.crtc_idr, crtc_lut->crtc_id); - if (!crtc || (crtc->id != crtc_lut->crtc_id)) { + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { ret = -EINVAL; goto out; } + crtc = obj_to_crtc(obj); /* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) { -- cgit v1.2.3 From 149b17311ad5f117e8f53a7a8cc032e369b95ed2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 16:45:44 +1000 Subject: drm: initial mode object groups. This creates a default group attached to the legacy drm minor nodes. It covers all the objects in the set. make set resources only return objects for this set. Need to fix up other functions to only work on objects in their allowed set. --- linux-core/drm_crtc.c | 154 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 119 insertions(+), 35 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 79dc137e..784c2f74 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -585,6 +585,45 @@ void drm_mode_config_init(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_config_init); +int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) +{ + uint32_t total_objects = 0; + + total_objects += dev->mode_config.num_crtc; + total_objects += dev->mode_config.num_connector; + total_objects += dev->mode_config.num_encoder; + + group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); + if (!group->id_list) + return -ENOMEM; + + group->num_crtcs = 0; + group->num_connectors = 0; + group->num_encoders = 0; + return 0; +} + +int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group) +{ + struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_connector *connector; + + if (drm_mode_group_init(dev, group)) + return -ENOMEM; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + group->id_list[group->num_crtcs++] = crtc->base.id; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + group->id_list[group->num_crtcs + group->num_encoders++] = encoder->base.id; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + group->id_list[group->num_crtcs + group->num_encoders + group->num_connectors++] = connector->base.id; + + return 0; +} + /** * drm_get_buffer_object - find the buffer object for a given handle * @dev: DRM device @@ -786,25 +825,37 @@ int drm_mode_getresources(struct drm_device *dev, int crtc_count = 0; int fb_count = 0; int encoder_count = 0; - int copied = 0; + int copied = 0, i; uint32_t __user *fb_id; uint32_t __user *crtc_id; uint32_t __user *connector_id; uint32_t __user *encoder_id; + struct drm_mode_group *mode_group; mutex_lock(&dev->mode_config.mutex); + /* for the non-control nodes we need to limit the list of resources by IDs in the + group list for this node */ list_for_each(lh, &file_priv->fbs) fb_count++; - list_for_each(lh, &dev->mode_config.crtc_list) - crtc_count++; + mode_group = &file_priv->master->minor->mode_group; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + + list_for_each(lh, &dev->mode_config.crtc_list) + crtc_count++; - list_for_each(lh, &dev->mode_config.connector_list) - connector_count++; + list_for_each(lh, &dev->mode_config.connector_list) + connector_count++; - list_for_each(lh, &dev->mode_config.encoder_list) - encoder_count++; + list_for_each(lh, &dev->mode_config.encoder_list) + encoder_count++; + } else { + + crtc_count = mode_group->num_crtcs; + connector_count = mode_group->num_connectors; + encoder_count = mode_group->num_encoders; + } card_res->max_height = dev->mode_config.max_height; card_res->min_height = dev->mode_config.min_height; @@ -830,49 +881,82 @@ int drm_mode_getresources(struct drm_device *dev, if (card_res->count_crtcs >= crtc_count) { copied = 0; crtc_id = (uint32_t *)(unsigned long)card_res->crtc_id_ptr; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){ - DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); - if (put_user(crtc->base.id, crtc_id + copied)) { - ret = -EFAULT; - goto out; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); + if (put_user(crtc->base.id, crtc_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + for (i = 0; i < mode_group->num_crtcs; i++) { + if (put_user(mode_group->id_list[i], crtc_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; } - copied++; } } card_res->count_crtcs = crtc_count; + /* Encoders */ + if (card_res->count_encoders >= encoder_count) { + copied = 0; + encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(encoder, &dev->mode_config.encoder_list, + head) { + DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id); + if (put_user(encoder->base.id, encoder_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) { + if (put_user(mode_group->id_list[i], encoder_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + + } + } + card_res->count_encoders = encoder_count; /* Connectors */ if (card_res->count_connectors >= connector_count) { copied = 0; connector_id = (uint32_t *)(unsigned long)card_res->connector_id_ptr; - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { - DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id); - if (put_user(connector->base.id, connector_id + copied)) { - ret = -EFAULT; - goto out; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { + DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id); + if (put_user(connector->base.id, connector_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + int start = mode_group->num_crtcs + mode_group->num_encoders; + for (i = start; i < start + mode_group->num_connectors; i++) { + if (put_user(mode_group->id_list[i], connector_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; } - copied++; } } card_res->count_connectors = connector_count; + - /* Encoders */ - if (card_res->count_encoders >= encoder_count) { - copied = 0; - encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, - head) { - DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id); - if (put_user(encoder->base.id, encoder_id + copied)) { - ret = -EFAULT; - goto out; - } - copied++; - } - } - card_res->count_encoders = encoder_count; DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, card_res->count_connectors, card_res->count_encoders); -- cgit v1.2.3 From 76a44f14d6339e5bc0c936ef4a360f6c152511bd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 11:59:28 +1000 Subject: drm/modesetting: overhaul the fb create/delete. Move TTM code into the driver --- linux-core/drm_crtc.c | 68 +++++++++++---------------------------------------- 1 file changed, 14 insertions(+), 54 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 784c2f74..7f843925 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -208,25 +208,21 @@ struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, * RETURNS: * Pointer to new framebuffer or NULL on error. */ -struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev) +struct drm_framebuffer *drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, + const struct drm_framebuffer_funcs *funcs) { - struct drm_framebuffer *fb; - - fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL); - if (!fb) - return NULL; - drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); fb->dev = dev; + fb->funcs = funcs; dev->mode_config.num_fb++; list_add(&fb->head, &dev->mode_config.fb_list); return fb; } -EXPORT_SYMBOL(drm_framebuffer_create); +EXPORT_SYMBOL(drm_framebuffer_init); /** - * drm_framebuffer_destroy - remove a framebuffer object + * drm_framebuffer_cleanup - remove a framebuffer object * @fb: framebuffer to remove * * LOCKING: @@ -235,7 +231,7 @@ EXPORT_SYMBOL(drm_framebuffer_create); * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes * it, setting it to NULL. */ -void drm_framebuffer_destroy(struct drm_framebuffer *fb) +void drm_framebuffer_cleanup(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; struct drm_crtc *crtc; @@ -249,10 +245,8 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb) drm_mode_object_put(dev, &fb->base); list_del(&fb->head); dev->mode_config.num_fb--; - - kfree(fb); } -EXPORT_SYMBOL(drm_framebuffer_destroy); +EXPORT_SYMBOL(drm_framebuffer_cleanup); /** * drm_crtc_init - Initialise a new CRTC object @@ -705,11 +699,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) } list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { - /* there should only be bo of kernel type left */ - if (fb->bo->type != drm_bo_type_kernel) - drm_framebuffer_destroy(fb); - else - dev->driver->fb_remove(dev, fb); + fb->funcs->destroy(fb); } list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { @@ -1393,7 +1383,6 @@ int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *r = data; struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; - struct drm_buffer_object *bo; int ret = 0; if ((config->min_width > r->width) || (r->width > config->max_width)) { @@ -1406,33 +1395,18 @@ int drm_mode_addfb(struct drm_device *dev, } mutex_lock(&dev->mode_config.mutex); - /* TODO check limits are okay */ - ret = drm_get_buffer_object(dev, &bo, r->handle); - if (ret || !bo) { - DRM_ERROR("BO handle not valid\n"); - ret = -EINVAL; - goto out; - } /* TODO check buffer is sufficently large */ /* TODO setup destructor callback */ - fb = drm_framebuffer_create(dev); + fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); if (!fb) { DRM_ERROR("could not create framebuffer\n"); ret = -EINVAL; goto out; } - fb->width = r->width; - fb->height = r->height; - fb->pitch = r->pitch; - fb->bits_per_pixel = r->bpp; - fb->depth = r->depth; - fb->bo = bo; - r->buffer_id = fb->base.id; - list_add(&fb->filp_head, &file_priv->fbs); out: @@ -1490,11 +1464,8 @@ int drm_mode_rmfb(struct drm_device *dev, /* TODO release all crtc connected to the framebuffer */ /* TODO unhock the destructor from the buffer object */ - if (fb->bo->type == drm_bo_type_kernel) - DRM_ERROR("the bo type should not be of kernel type\n"); - list_del(&fb->filp_head); - drm_framebuffer_destroy(fb); + fb->funcs->destroy(fb); out: mutex_unlock(&dev->mode_config.mutex); @@ -1539,7 +1510,7 @@ int drm_mode_getfb(struct drm_device *dev, r->width = fb->width; r->depth = fb->depth; r->bpp = fb->bits_per_pixel; - r->handle = fb->bo->base.hash.key; + r->handle = fb->mm_handle; r->pitch = fb->pitch; out: @@ -1570,10 +1541,7 @@ void drm_fb_release(struct file *filp) mutex_lock(&dev->mode_config.mutex); list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { list_del(&fb->filp_head); - if (fb->bo->type == drm_bo_type_kernel) - DRM_ERROR("the bo type should not be of kernel_type, the kernel will probably explode, why Dave\n"); - - drm_framebuffer_destroy(fb); + fb->funcs->destroy(fb); } mutex_unlock(&dev->mode_config.mutex); } @@ -2118,17 +2086,12 @@ int drm_mode_replacefb(struct drm_device *dev, struct drm_mode_fb_cmd *r = data; struct drm_mode_object *obj; struct drm_framebuffer *fb; - struct drm_buffer_object *bo; int found = 0; struct drm_framebuffer *fbl = NULL; int ret = 0; + /* right replace the current bo attached to this fb with a new bo */ mutex_lock(&dev->mode_config.mutex); - ret = drm_get_buffer_object(dev, &bo, r->handle); - if (ret || !bo) { - ret = -EINVAL; - goto out; - } obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); if (!obj) { ret = -EINVAL; @@ -2146,15 +2109,12 @@ int drm_mode_replacefb(struct drm_device *dev, goto out; } - if (fb->bo->type == drm_bo_type_kernel) - DRM_ERROR("the bo should not be a kernel bo\n"); - fb->width = r->width; fb->height = r->height; fb->pitch = r->pitch; fb->bits_per_pixel = r->bpp; fb->depth = r->depth; - fb->bo = bo; + fb->mm_handle = r->handle; if (dev->mode_config.funcs->resize_fb) dev->mode_config.funcs->resize_fb(dev, fb); -- cgit v1.2.3 From fd27591c6cadd2a868f4110b8993a86c37837d3e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:00:31 +1000 Subject: drm/modesetting: pass object handle to driver !bo --- linux-core/drm_crtc.c | 58 +-------------------------------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 7f843925..4f2297a2 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -618,53 +618,6 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_gro return 0; } -/** - * drm_get_buffer_object - find the buffer object for a given handle - * @dev: DRM device - * @bo: pointer to caller's buffer_object pointer - * @handle: handle to lookup - * - * LOCKING: - * Must take @dev's struct_mutex to protect buffer object lookup. - * - * Given @handle, lookup the buffer object in @dev and put it in the caller's - * @bo pointer. - * - * RETURNS: - * Zero on success, -EINVAL if the handle couldn't be found. - */ -static int drm_get_buffer_object(struct drm_device *dev, struct drm_buffer_object **bo, unsigned long handle) -{ - struct drm_user_object *uo; - struct drm_hash_item *hash; - 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; - } - - uo = drm_hash_entry(hash, struct drm_user_object, hash); - if (uo->type != drm_buffer_type) { - ret = -EINVAL; - goto out_err; - } - - *bo = drm_user_object_entry(uo, struct drm_buffer_object, base); - ret = 0; -out_err: - mutex_unlock(&dev->struct_mutex); - return ret; -} - - - - /** * drm_mode_config_cleanup - free up DRM mode_config info * @dev: DRM device @@ -1328,17 +1281,8 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (req->flags & DRM_MODE_CURSOR_BO) { /* Turn of the cursor if handle is 0 */ - if (req->handle) - ret = drm_get_buffer_object(dev, &bo, req->handle); - - if (ret) { - DRM_ERROR("invalid buffer id\n"); - ret = -EINVAL; - goto out; - } - if (crtc->funcs->cursor_set) { - ret = crtc->funcs->cursor_set(crtc, bo, req->width, req->height); + ret = crtc->funcs->cursor_set(crtc, req->handle, req->width, req->height); } else { DRM_ERROR("crtc does not support cursor\n"); ret = -EFAULT; -- cgit v1.2.3 From 58aca7485a4cd9fcccc6e4044325048abcc2f9c7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:03:23 +1000 Subject: drm: remove sysfs in driver for now.. should probably be in helper --- linux-core/drm_crtc.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 4f2297a2..73ad317a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -643,7 +643,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) } list_for_each_entry_safe(connector, ot, &dev->mode_config.connector_list, head) { - drm_sysfs_connector_remove(connector); connector->funcs->destroy(connector); } @@ -662,8 +661,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_config_cleanup); - - int drm_mode_hotplug_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { -- cgit v1.2.3 From 8690ad8ae0778f2ccd8b428e1c6a8614ebc51707 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:09:05 +1000 Subject: drm/modesetting: bo not used anymore --- linux-core/drm_crtc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 73ad317a..d2060fd1 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1257,7 +1257,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, struct drm_mode_cursor *req = data; struct drm_mode_object *obj; struct drm_crtc *crtc; - struct drm_buffer_object *bo = NULL; /* must be set */ int ret = 0; DRM_DEBUG("\n"); -- cgit v1.2.3 From 382aa3ceeb79165a9bdddc8f944de131c8cbf2dd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:49:43 +1000 Subject: drm: introduce generation counter to interface. Idea being if you want to add new crtc/output/encoder dynamically later, you just increase the generation counter and userspace should re-read all the resources --- linux-core/drm_crtc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index d2060fd1..4c6afd16 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -571,6 +571,7 @@ void drm_mode_config_init(struct drm_device *dev) drm_mode_create_standard_connector_properties(dev); /* Just to be sure */ + dev->mode_config.current_generation = 0; dev->mode_config.num_fb = 0; dev->mode_config.num_connector = 0; dev->mode_config.num_crtc = 0; @@ -801,6 +802,7 @@ int drm_mode_getresources(struct drm_device *dev, card_res->min_height = dev->mode_config.min_height; card_res->max_width = dev->mode_config.max_width; card_res->min_width = dev->mode_config.min_width; + card_res->generation = dev->mode_config.current_generation; /* handle this in 4 parts */ /* FBs */ @@ -943,7 +945,7 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; crtc_resp->gamma_size = crtc->gamma_size; - + crtc_resp->generation = dev->mode_config.current_generation; if (crtc->fb) crtc_resp->fb_id = crtc->fb->base.id; else @@ -1032,6 +1034,7 @@ int drm_mode_getconnector(struct drm_device *dev, connector->funcs->fill_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height); } + out_resp->generation = dev->mode_config.current_generation; out_resp->connector_type = connector->connector_type; out_resp->connector_type_id = connector->connector_type_id; out_resp->mm_width = connector->display_info.width_mm; @@ -1120,6 +1123,7 @@ int drm_mode_getencoder(struct drm_device *dev, enc_resp->crtc = encoder->crtc->base.id; else enc_resp->crtc = 0; + enc_resp->generation = dev->mode_config.current_generation; enc_resp->encoder_type = encoder->encoder_type; enc_resp->encoder_id = encoder->base.id; enc_resp->crtcs = encoder->possible_crtcs; -- cgit v1.2.3 From 52183fb05b8f8db0705e230fc0b8a436512759a1 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 4 Jun 2008 09:38:44 -0700 Subject: Fix crash in drm_mode_connector_update_edid_property We need to initialize the edid_blob_ptr to NULL when we init a connector, otherwise drm_mode_connector_update_edid_property may think there's a valid EDID lying around and try to destroy it, causing a crash. --- linux-core/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 4c6afd16..7a049da8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -357,6 +357,7 @@ void drm_connector_init(struct drm_device *dev, INIT_LIST_HEAD(&connector->user_modes); INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); + connector->edid_blob_ptr = NULL; /* randr_connector? */ /* connector_set_monitor(connector)? */ /* check for connector_ignored(connector)? */ -- cgit v1.2.3 From efcf066eff690887ace33c0f1192168a31115805 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Jun 2008 15:21:07 +1000 Subject: drm/modesetting: attempt to make fb code more sane --- linux-core/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 4c6afd16..92a7d513 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -561,6 +561,7 @@ void drm_mode_config_init(struct drm_device *dev) { mutex_init(&dev->mode_config.mutex); INIT_LIST_HEAD(&dev->mode_config.fb_list); + INIT_LIST_HEAD(&dev->mode_config.fb_kernel_list); INIT_LIST_HEAD(&dev->mode_config.crtc_list); INIT_LIST_HEAD(&dev->mode_config.connector_list); INIT_LIST_HEAD(&dev->mode_config.encoder_list); -- cgit v1.2.3 From 6d4ffd12cd8d3713067adf5fa3bdcb023b0745f1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 6 Jun 2008 16:24:27 +1000 Subject: drm: fix up fb resize again --- linux-core/drm_crtc.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index d49834b9..e1b371cc 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2055,25 +2055,10 @@ int drm_mode_replacefb(struct drm_device *dev, goto out; } - fb->width = r->width; - fb->height = r->height; - fb->pitch = r->pitch; - fb->bits_per_pixel = r->bpp; - fb->depth = r->depth; - fb->mm_handle = r->handle; - if (dev->mode_config.funcs->resize_fb) - dev->mode_config.funcs->resize_fb(dev, fb); + ret = dev->mode_config.funcs->resize_fb(dev, file_priv, fb, r); else - ret = -EINVAL; -#if 0 - /* find all crtcs connected to this fb */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb->base.id == r->buffer_id) { - crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y); - } - } -#endif + ret = -EINVAL; out: mutex_unlock(&dev->mode_config.mutex); return ret; -- cgit v1.2.3 From 473a1997ace1a9fb545d0457549e50d17eb36175 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 22 Jun 2008 16:29:00 +0200 Subject: NV50: Initial import of kernel modesetting. --- linux-core/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e1b371cc..c8cfaef4 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -100,6 +100,7 @@ char *drm_get_connector_name(struct drm_connector *connector) connector->connector_type_id); return buf; } +EXPORT_SYMBOL(drm_get_connector_name); char *drm_get_connector_status_name(enum drm_connector_status status) { -- cgit v1.2.3 From 246b41fea462a3b1669c0e3f9fe7f6077a479832 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Mon, 23 Jun 2008 22:59:17 +0200 Subject: [modesetting-101] update mode count after fill_modes. - This avoids returning with a mode count of 0, thus not allocating space for the 2nd ioctl. --- linux-core/drm_crtc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c8cfaef4..aab936c2 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1018,9 +1018,6 @@ int drm_mode_getconnector(struct drm_device *dev, } connector = obj_to_connector(obj); - list_for_each_entry(mode, &connector->modes, head) - mode_count++; - for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { if (connector->property_ids[i] != 0) { props_count++; @@ -1037,6 +1034,10 @@ int drm_mode_getconnector(struct drm_device *dev, connector->funcs->fill_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height); } + /* delayed so we get modes regardless of pre-fill_modes state */ + list_for_each_entry(mode, &connector->modes, head) + mode_count++; + out_resp->generation = dev->mode_config.current_generation; out_resp->connector_type = connector->connector_type; out_resp->connector_type_id = connector->connector_type_id; @@ -1049,6 +1050,7 @@ int drm_mode_getconnector(struct drm_device *dev, else out_resp->encoder = 0; + /* this ioctl is called twice, once to determine how much space is needed, and the 2nd time to fill it */ if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; @@ -1060,7 +1062,6 @@ int drm_mode_getconnector(struct drm_device *dev, goto out; } copied++; - } } out_resp->count_modes = mode_count; -- cgit v1.2.3 From 13943fe5823c45759091c1a1f487a4abe377421e Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Thu, 26 Jun 2008 21:28:29 +0200 Subject: modesetting-101: Make dpms property optional + misc cleanup. - intel_crt seems the only one to provide it, so init it there. --- linux-core/drm_crtc.c | 77 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 29 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index aab936c2..b6e636e0 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -43,10 +43,10 @@ struct drm_prop_enum_list { * Global properties */ static struct drm_prop_enum_list drm_dpms_enum_list[] = -{ { DPMSModeOn, "On" }, - { DPMSModeStandby, "Standby" }, - { DPMSModeSuspend, "Suspend" }, - { DPMSModeOff, "Off" } +{ { DPMSModeOn, "On" }, + { DPMSModeStandby, "Standby" }, + { DPMSModeSuspend, "Suspend" }, + { DPMSModeOff, "Off" } }; char *drm_get_dpms_name(int val) @@ -61,26 +61,26 @@ char *drm_get_dpms_name(int val) } static struct drm_prop_enum_list drm_connector_enum_list[] = -{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "Composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "Component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, +{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "Composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "Component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, }; static struct drm_prop_enum_list drm_encoder_enum_list[] = -{ { DRM_MODE_ENCODER_NONE, "None" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TV" }, +{ { DRM_MODE_ENCODER_NONE, "None" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TV" }, }; char *drm_get_encoder_name(struct drm_encoder *encoder) @@ -164,7 +164,7 @@ static void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object * static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) { struct drm_mode_object *obj; - + obj = idr_find(&dev->mode_config.crtc_idr, id); if (!obj || (obj->type != type) || (obj->id != id)) return NULL; @@ -369,8 +369,6 @@ void drm_connector_init(struct drm_device *dev, drm_connector_attach_property(connector, dev->mode_config.edid_property, 0); - drm_connector_attach_property(connector, dev->mode_config.dpms_property, 0); - mutex_unlock(&dev->mode_config.mutex); } EXPORT_SYMBOL(drm_connector_init); @@ -479,8 +477,6 @@ EXPORT_SYMBOL(drm_mode_destroy); static int drm_mode_create_standard_connector_properties(struct drm_device *dev) { - int i; - /* * Standard properties (apply to all connectors) */ @@ -488,6 +484,24 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, "EDID", 0); + return 0; +} + +/** + * drm_mode_create_dpms_property - create dpms connector property + * @dev: DRM device + * + * Called by a driver wanting to support the dpms property. + * Caller is responsible for attaching it to the appropriate connector. + */ +bool drm_mode_create_dpms_property(struct drm_device *dev) +{ + int i; + + /* already allocated */ + if (dev->mode_config.dpms_property) + return 0; + dev->mode_config.dpms_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); @@ -496,6 +510,7 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) return 0; } +EXPORT_SYMBOL(drm_mode_create_dpms_property); /** * drm_create_tv_properties - create TV specific connector properties @@ -508,11 +523,15 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) * responsible for allocating a list of format names and passing them to * this routine. */ -bool drm_create_tv_properties(struct drm_device *dev, int num_modes, +bool drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, char *modes[]) { int i; + /* already allocated */ + if (dev->mode_config.tv_mode_property) + return 0; + dev->mode_config.tv_left_margin_property = drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, @@ -547,7 +566,7 @@ bool drm_create_tv_properties(struct drm_device *dev, int num_modes, return 0; } -EXPORT_SYMBOL(drm_create_tv_properties); +EXPORT_SYMBOL(drm_mode_create_tv_properties); /** * drm_mode_config_init - initialize DRM mode_configuration structure -- cgit v1.2.3 From 087e3f577d795bcd007619514bb2977eede70c16 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Thu, 26 Jun 2008 23:12:04 +0200 Subject: Revert "modesetting-101: Make dpms property optional + misc cleanup." This reverts commit 13943fe5823c45759091c1a1f487a4abe377421e. --- linux-core/drm_crtc.c | 77 +++++++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 48 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b6e636e0..aab936c2 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -43,10 +43,10 @@ struct drm_prop_enum_list { * Global properties */ static struct drm_prop_enum_list drm_dpms_enum_list[] = -{ { DPMSModeOn, "On" }, - { DPMSModeStandby, "Standby" }, - { DPMSModeSuspend, "Suspend" }, - { DPMSModeOff, "Off" } +{ { DPMSModeOn, "On" }, + { DPMSModeStandby, "Standby" }, + { DPMSModeSuspend, "Suspend" }, + { DPMSModeOff, "Off" } }; char *drm_get_dpms_name(int val) @@ -61,26 +61,26 @@ char *drm_get_dpms_name(int val) } static struct drm_prop_enum_list drm_connector_enum_list[] = -{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "Composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "Component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, +{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "Composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "Component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, }; static struct drm_prop_enum_list drm_encoder_enum_list[] = -{ { DRM_MODE_ENCODER_NONE, "None" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TV" }, +{ { DRM_MODE_ENCODER_NONE, "None" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TV" }, }; char *drm_get_encoder_name(struct drm_encoder *encoder) @@ -164,7 +164,7 @@ static void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object * static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) { struct drm_mode_object *obj; - + obj = idr_find(&dev->mode_config.crtc_idr, id); if (!obj || (obj->type != type) || (obj->id != id)) return NULL; @@ -369,6 +369,8 @@ void drm_connector_init(struct drm_device *dev, drm_connector_attach_property(connector, dev->mode_config.edid_property, 0); + drm_connector_attach_property(connector, dev->mode_config.dpms_property, 0); + mutex_unlock(&dev->mode_config.mutex); } EXPORT_SYMBOL(drm_connector_init); @@ -477,6 +479,8 @@ EXPORT_SYMBOL(drm_mode_destroy); static int drm_mode_create_standard_connector_properties(struct drm_device *dev) { + int i; + /* * Standard properties (apply to all connectors) */ @@ -484,24 +488,6 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, "EDID", 0); - return 0; -} - -/** - * drm_mode_create_dpms_property - create dpms connector property - * @dev: DRM device - * - * Called by a driver wanting to support the dpms property. - * Caller is responsible for attaching it to the appropriate connector. - */ -bool drm_mode_create_dpms_property(struct drm_device *dev) -{ - int i; - - /* already allocated */ - if (dev->mode_config.dpms_property) - return 0; - dev->mode_config.dpms_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); @@ -510,7 +496,6 @@ bool drm_mode_create_dpms_property(struct drm_device *dev) return 0; } -EXPORT_SYMBOL(drm_mode_create_dpms_property); /** * drm_create_tv_properties - create TV specific connector properties @@ -523,15 +508,11 @@ EXPORT_SYMBOL(drm_mode_create_dpms_property); * responsible for allocating a list of format names and passing them to * this routine. */ -bool drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, +bool drm_create_tv_properties(struct drm_device *dev, int num_modes, char *modes[]) { int i; - /* already allocated */ - if (dev->mode_config.tv_mode_property) - return 0; - dev->mode_config.tv_left_margin_property = drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, @@ -566,7 +547,7 @@ bool drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, return 0; } -EXPORT_SYMBOL(drm_mode_create_tv_properties); +EXPORT_SYMBOL(drm_create_tv_properties); /** * drm_mode_config_init - initialize DRM mode_configuration structure -- cgit v1.2.3 From d88616555d2d3abc118f77d5556e14dd1512272b Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Thu, 26 Jun 2008 23:21:01 +0200 Subject: [modesetting-101] tab-cleanup --- linux-core/drm_crtc.c | 96 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 49 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index aab936c2..4f21d09e 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -43,10 +43,10 @@ struct drm_prop_enum_list { * Global properties */ static struct drm_prop_enum_list drm_dpms_enum_list[] = -{ { DPMSModeOn, "On" }, - { DPMSModeStandby, "Standby" }, - { DPMSModeSuspend, "Suspend" }, - { DPMSModeOff, "Off" } +{ { DPMSModeOn, "On" }, + { DPMSModeStandby, "Standby" }, + { DPMSModeSuspend, "Suspend" }, + { DPMSModeOff, "Off" } }; char *drm_get_dpms_name(int val) @@ -61,26 +61,26 @@ char *drm_get_dpms_name(int val) } static struct drm_prop_enum_list drm_connector_enum_list[] = -{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "Composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "Component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, +{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "Composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "Component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, }; static struct drm_prop_enum_list drm_encoder_enum_list[] = -{ { DRM_MODE_ENCODER_NONE, "None" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TV" }, +{ { DRM_MODE_ENCODER_NONE, "None" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TV" }, }; char *drm_get_encoder_name(struct drm_encoder *encoder) @@ -139,7 +139,7 @@ again: ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); if (ret == -EAGAIN) - goto again; + goto again; obj->id = new_id; obj->type = obj_type; @@ -164,7 +164,7 @@ static void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object * static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) { struct drm_mode_object *obj; - + obj = idr_find(&dev->mode_config.crtc_idr, id); if (!obj || (obj->type != type) || (obj->id != id)) return NULL; @@ -411,7 +411,7 @@ void drm_encoder_init(struct drm_device *dev, int encoder_type) { encoder->dev = dev; - + drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); encoder->encoder_type = encoder_type; encoder->funcs = funcs; @@ -590,7 +590,7 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) total_objects += dev->mode_config.num_crtc; total_objects += dev->mode_config.num_connector; total_objects += dev->mode_config.num_encoder; - + group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); if (!group->id_list) return -ENOMEM; @@ -736,7 +736,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); out->name[DRM_DISPLAY_MODE_LEN-1] = 0; } - + /** * drm_mode_getresources - get graphics configuration * @inode: inode from the ioctl @@ -795,7 +795,7 @@ int drm_mode_getresources(struct drm_device *dev, list_for_each(lh, &dev->mode_config.encoder_list) encoder_count++; } else { - + crtc_count = mode_group->num_crtcs; connector_count = mode_group->num_connectors; encoder_count = mode_group->num_encoders; @@ -900,13 +900,11 @@ int drm_mode_getresources(struct drm_device *dev, } } card_res->count_connectors = connector_count; - - DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, card_res->count_connectors, card_res->count_encoders); -out: +out: mutex_unlock(&dev->mode_config.mutex); return ret; } @@ -959,7 +957,7 @@ int drm_mode_getcrtc(struct drm_device *dev, drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); crtc_resp->mode_valid = 1; - + } else { crtc_resp->mode_valid = 0; } @@ -1114,7 +1112,7 @@ int drm_mode_getencoder(struct drm_device *dev, struct drm_mode_object *obj; struct drm_encoder *encoder; int ret = 0; - + mutex_lock(&dev->mode_config.mutex); obj = drm_mode_object_find(dev, enc_resp->encoder_id, DRM_MODE_OBJECT_ENCODER); if (!obj) { @@ -1132,7 +1130,7 @@ int drm_mode_getencoder(struct drm_device *dev, enc_resp->encoder_id = encoder->base.id; enc_resp->crtcs = encoder->possible_crtcs; enc_resp->clones = encoder->possible_clones; - + out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -1177,7 +1175,7 @@ int drm_mode_setcrtc(struct drm_device *dev, goto out; } crtc = obj_to_crtc(obj); - + if (crtc_req->mode_valid) { /* If we have a mode we need a framebuffer. */ /* If we pass -1, set the mode with the currently bound fb */ @@ -1185,7 +1183,7 @@ int drm_mode_setcrtc(struct drm_device *dev, list_for_each_entry(crtcfb, &dev->mode_config.crtc_list, head) { if (crtcfb == crtc) { DRM_DEBUG("Using current fb for setmode\n"); - fb = crtc->fb; + fb = crtc->fb; } } } else { @@ -1604,7 +1602,7 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, ret = -ENOMEM; goto out; } - + drm_crtc_convert_umode(mode, umode); ret = drm_mode_attachmode(dev, connector, mode); @@ -1644,7 +1642,7 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, goto out; } connector = obj_to_connector(obj); - + drm_crtc_convert_umode(&mode, umode); ret = drm_mode_detachmode(dev, connector, &mode); out: @@ -1728,7 +1726,7 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) kfree(property->values); drm_mode_object_put(dev, &property->base); list_del(&property->head); - kfree(property); + kfree(property); } EXPORT_SYMBOL(drm_property_destroy); @@ -1844,12 +1842,12 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, copied = 0; enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; list_for_each_entry(prop_enum, &property->enum_blob_list, head) { - + if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { ret = -EFAULT; goto done; } - + if (copy_to_user(&enum_ptr[copied].name, &prop_enum->name, DRM_PROP_NAME_LEN)) { ret = -EFAULT; @@ -1866,18 +1864,18 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, copied = 0; blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; - + list_for_each_entry(prop_blob, &property->enum_blob_list, head) { if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { ret = -EFAULT; goto done; } - + if (put_user(prop_blob->length, blob_length_ptr + copied)) { ret = -EFAULT; goto done; } - + copied++; } } @@ -1906,7 +1904,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev memcpy(blob->data, data, length); drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); - + list_add_tail(&blob->head, &dev->mode_config.property_blob_list); return blob; } @@ -1958,7 +1956,7 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, str drm_property_destroy_blob(dev, connector->edid_blob_ptr); connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); - + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->base.id); return ret; } @@ -1990,7 +1988,7 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, if (i == DRM_CONNECTOR_MAX_PROPERTY) { goto out; } - + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); if (!obj) { goto out; @@ -2129,7 +2127,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, goto out; } crtc = obj_to_crtc(obj); - + /* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) { ret = -EINVAL; @@ -2180,7 +2178,7 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, goto out; } crtc = obj_to_crtc(obj); - + /* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) { ret = -EINVAL; -- cgit v1.2.3 From 71906e86e81440037aa08b6f23f36e9fd3835639 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 27 Jun 2008 16:30:25 +0200 Subject: [modesetting-101] Actually store properties when being changed. --- linux-core/drm_crtc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 4f21d09e..b9276c3a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2017,6 +2017,9 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, } } + /* store the property value */ + drm_connector_property_set_value(connector, property, out_resp->value); + if (connector->funcs->set_property) ret = connector->funcs->set_property(connector, property, out_resp->value); -- cgit v1.2.3 From 9f28da80f6cc8e45670b217a2483983f2838095d Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 27 Jun 2008 18:45:08 +0200 Subject: Change some obviously wrong things about property blobs, still broken though. - I do not fully understand these blobs, so i'm leaving it at this for the moment. --- linux-core/drm_crtc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b9276c3a..23ae7d83 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1837,7 +1837,6 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_values = value_count; if (property->flags & DRM_MODE_PROP_ENUM) { - if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied = 0; enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; @@ -1879,7 +1878,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, copied++; } } - out_resp->count_enum_blobs = enum_count; + out_resp->count_enum_blobs = blob_count; } done: mutex_unlock(&dev->mode_config.mutex); -- cgit v1.2.3 From 59a9a756e238dd73f3051434545b2d3bf225da87 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 3 Jul 2008 08:05:51 +1000 Subject: modesetting: lookup blob using correct identifier. blob is a blob not a connector --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 23ae7d83..c20dacd8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1926,7 +1926,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, void *blob_ptr; mutex_lock(&dev->mode_config.mutex); - obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_CONNECTOR); + obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); if (!obj) { ret = -EINVAL; goto done; -- cgit v1.2.3 From 142a309604b65c26ca95594943ee91dde8688697 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 4 Jul 2008 09:34:24 +1000 Subject: modesetting: rip out all of the generation code. not needed, hotplug will work just as well hopefully. --- linux-core/drm_crtc.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c20dacd8..ca5e75a4 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -574,7 +574,6 @@ void drm_mode_config_init(struct drm_device *dev) drm_mode_create_standard_connector_properties(dev); /* Just to be sure */ - dev->mode_config.current_generation = 0; dev->mode_config.num_fb = 0; dev->mode_config.num_connector = 0; dev->mode_config.num_crtc = 0; @@ -805,7 +804,6 @@ int drm_mode_getresources(struct drm_device *dev, card_res->min_height = dev->mode_config.min_height; card_res->max_width = dev->mode_config.max_width; card_res->min_width = dev->mode_config.min_width; - card_res->generation = dev->mode_config.current_generation; /* handle this in 4 parts */ /* FBs */ @@ -946,7 +944,6 @@ int drm_mode_getcrtc(struct drm_device *dev, crtc_resp->x = crtc->x; crtc_resp->y = crtc->y; crtc_resp->gamma_size = crtc->gamma_size; - crtc_resp->generation = dev->mode_config.current_generation; if (crtc->fb) crtc_resp->fb_id = crtc->fb->base.id; else @@ -1036,7 +1033,6 @@ int drm_mode_getconnector(struct drm_device *dev, list_for_each_entry(mode, &connector->modes, head) mode_count++; - out_resp->generation = dev->mode_config.current_generation; out_resp->connector_type = connector->connector_type; out_resp->connector_type_id = connector->connector_type_id; out_resp->mm_width = connector->display_info.width_mm; @@ -1125,7 +1121,6 @@ int drm_mode_getencoder(struct drm_device *dev, enc_resp->crtc = encoder->crtc->base.id; else enc_resp->crtc = 0; - enc_resp->generation = dev->mode_config.current_generation; enc_resp->encoder_type = encoder->encoder_type; enc_resp->encoder_id = encoder->base.id; enc_resp->crtcs = encoder->possible_crtcs; -- cgit v1.2.3 From b29578103f57a8d684b4a3a79f220e6cc626605e Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 4 Jul 2008 17:17:11 +0200 Subject: [modesetting-101] Add subconnector and select_subconnector properties. - These facilitate DVI-I and tv-out that can drive multiple types of signals. --- linux-core/drm_crtc.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ca5e75a4..1a381abe 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -60,6 +60,48 @@ char *drm_get_dpms_name(int val) return "unknown"; } +static struct drm_prop_enum_list drm_select_subconnector_enum_list[] = +{ + { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ + { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ + { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ +}; + +char *drm_get_select_subconnector_name(int val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(drm_select_subconnector_enum_list); i++) + if (drm_select_subconnector_enum_list[i].type == val) + return drm_select_subconnector_enum_list[i].name; + + return "unknown"; +} + +static struct drm_prop_enum_list drm_subconnector_enum_list[] = +{ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ + { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ + { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ + { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ +}; + +char *drm_get_subconnector_name(int val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(drm_subconnector_enum_list); i++) + if (drm_subconnector_enum_list[i].type == val) + return drm_subconnector_enum_list[i].name; + + return "unknown"; +} + static struct drm_prop_enum_list drm_connector_enum_list[] = { { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, { DRM_MODE_CONNECTOR_VGA, "VGA" }, @@ -497,6 +539,38 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) return 0; } +/** + * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties + * @dev: DRM device + * + * Called by a driver the first time a DVI-I connector is made. + */ +int drm_mode_create_dvi_i_properties(struct drm_device *dev) +{ + int i; + + if (dev->mode_config.dvi_i_select_subconnector_property) + return 0; + + dev->mode_config.dvi_i_select_subconnector_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "select subconnector", 3); + /* add enum element 0-2 */ + for (i = 0; i < 3; i++) + drm_property_add_enum(dev->mode_config.dvi_i_select_subconnector_property, i, drm_select_subconnector_enum_list[i].type, + drm_select_subconnector_enum_list[i].name); + + /* This is a property which indicates the most likely thing to be connected. */ + dev->mode_config.dvi_i_subconnector_property = drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, + "subconnector", 3); + /* add enum element 0-2 */ + for (i = 0; i < 3; i++) + drm_property_add_enum(dev->mode_config.dvi_i_subconnector_property, i, drm_subconnector_enum_list[i].type, + drm_subconnector_enum_list[i].name); + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); + /** * drm_create_tv_properties - create TV specific connector properties * @dev: DRM device @@ -508,11 +582,29 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) * responsible for allocating a list of format names and passing them to * this routine. */ -bool drm_create_tv_properties(struct drm_device *dev, int num_modes, +int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, char *modes[]) { int i; + if (dev->mode_config.tv_select_subconnector_property) /* already done */ + return 0; + + dev->mode_config.tv_select_subconnector_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "select subconnector", 4); + /* add enum element 3-5 */ + for (i = 1; i < 4; i++) + drm_property_add_enum(dev->mode_config.tv_select_subconnector_property, i, drm_select_subconnector_enum_list[i + 2].type, + drm_select_subconnector_enum_list[i + 2].name); + + /* This is a property which indicates the most likely thing to be connected. */ + dev->mode_config.tv_subconnector_property = drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, + "subconnector", 4); + /* add enum element 3-5 */ + for (i = 1; i < 4; i++) + drm_property_add_enum(dev->mode_config.tv_subconnector_property, i, drm_subconnector_enum_list[i + 2].type, + drm_subconnector_enum_list[i + 2].name); + dev->mode_config.tv_left_margin_property = drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, @@ -547,7 +639,7 @@ bool drm_create_tv_properties(struct drm_device *dev, int num_modes, return 0; } -EXPORT_SYMBOL(drm_create_tv_properties); +EXPORT_SYMBOL(drm_mode_create_tv_properties); /** * drm_mode_config_init - initialize DRM mode_configuration structure -- cgit v1.2.3 From 0028ca33e90d3405bd47a554e9398e0c2aa6099b Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 4 Jul 2008 17:37:45 +0200 Subject: Forgot the 0'th element for the tv property. --- linux-core/drm_crtc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1a381abe..095d44fa 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -592,6 +592,9 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, dev->mode_config.tv_select_subconnector_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, "select subconnector", 4); + /* add enum element 0 */ + drm_property_add_enum(dev->mode_config.tv_select_subconnector_property, 0, drm_select_subconnector_enum_list[0].type, + drm_select_subconnector_enum_list[0].name); /* add enum element 3-5 */ for (i = 1; i < 4; i++) drm_property_add_enum(dev->mode_config.tv_select_subconnector_property, i, drm_select_subconnector_enum_list[i + 2].type, @@ -600,6 +603,9 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, /* This is a property which indicates the most likely thing to be connected. */ dev->mode_config.tv_subconnector_property = drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, "subconnector", 4); + /* add enum element 0 */ + drm_property_add_enum(dev->mode_config.tv_subconnector_property, 0, drm_subconnector_enum_list[0].type, + drm_subconnector_enum_list[0].name); /* add enum element 3-5 */ for (i = 1; i < 4; i++) drm_property_add_enum(dev->mode_config.tv_subconnector_property, i, drm_subconnector_enum_list[i + 2].type, -- cgit v1.2.3 From be31a0fa73272b9c727668096ba652ea748a9735 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 4 Jul 2008 18:47:59 +0200 Subject: modesetting-101: tv_left_margin_property shouldn't be immutable. --- linux-core/drm_crtc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 095d44fa..3ee0f86c 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -612,8 +612,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, drm_subconnector_enum_list[i + 2].name); dev->mode_config.tv_left_margin_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE | - DRM_MODE_PROP_IMMUTABLE, + drm_property_create(dev, DRM_MODE_PROP_RANGE, "left margin", 2); dev->mode_config.tv_left_margin_property->values[0] = 0; dev->mode_config.tv_left_margin_property->values[1] = 100; -- cgit v1.2.3 From 7cbc5f6145046f3775e3b3ca2862bfb71831ec44 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sat, 5 Jul 2008 12:04:07 +0200 Subject: modesetting-101: Make the interface variable names a little more consistent + modeprint changes. - All things are now called _id when they are id's. - modeprint now accepts driver name as first argument. --- linux-core/drm_crtc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 3ee0f86c..f8e09a8c 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1046,7 +1046,6 @@ int drm_mode_getcrtc(struct drm_device *dev, else crtc_resp->fb_id = 0; - crtc_resp->connectors = 0; if (crtc->enabled) { drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); @@ -1099,11 +1098,11 @@ int drm_mode_getconnector(struct drm_device *dev, memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); - DRM_DEBUG("connector id %d:\n", out_resp->connector); + DRM_DEBUG("connector id %d:\n", out_resp->connector_id); mutex_lock(&dev->mode_config.mutex); - obj = drm_mode_object_find(dev, out_resp->connector, DRM_MODE_OBJECT_CONNECTOR); + obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); if (!obj) { ret = -EINVAL; goto out; @@ -1130,6 +1129,7 @@ int drm_mode_getconnector(struct drm_device *dev, list_for_each_entry(mode, &connector->modes, head) mode_count++; + out_resp->connector_id = connector->base.id; out_resp->connector_type = connector->connector_type; out_resp->connector_type_id = connector->connector_type_id; out_resp->mm_width = connector->display_info.width_mm; @@ -1137,9 +1137,9 @@ int drm_mode_getconnector(struct drm_device *dev, out_resp->subpixel = connector->display_info.subpixel_order; out_resp->connection = connector->status; if (connector->encoder) - out_resp->encoder = connector->encoder->base.id; + out_resp->encoder_id = connector->encoder->base.id; else - out_resp->encoder = 0; + out_resp->encoder_id = 0; /* this ioctl is called twice, once to determine how much space is needed, and the 2nd time to fill it */ if ((out_resp->count_modes >= mode_count) && mode_count) { @@ -1215,13 +1215,13 @@ int drm_mode_getencoder(struct drm_device *dev, encoder = obj_to_encoder(obj); if (encoder->crtc) - enc_resp->crtc = encoder->crtc->base.id; + enc_resp->crtc_id = encoder->crtc->base.id; else - enc_resp->crtc = 0; + enc_resp->crtc_id = 0; enc_resp->encoder_type = encoder->encoder_type; enc_resp->encoder_id = encoder->base.id; - enc_resp->crtcs = encoder->possible_crtcs; - enc_resp->clones = encoder->possible_clones; + enc_resp->possible_crtcs = encoder->possible_crtcs; + enc_resp->possible_clones = encoder->possible_clones; out: mutex_unlock(&dev->mode_config.mutex); -- cgit v1.2.3 From e1cd21bcc8747fcc573708bd4d74df39b60c476a Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sat, 5 Jul 2008 20:17:49 +0200 Subject: NV50: remove edid when monitor is gone, improve fbcon, misc fixes - This should avoid switching crtc's when going to fbcon. --- linux-core/drm_crtc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f8e09a8c..47885a07 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2046,6 +2046,13 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, str if (connector->edid_blob_ptr) drm_property_destroy_blob(dev, connector->edid_blob_ptr); + /* Delete edid, when there is none. */ + if (!edid) { + connector->edid_blob_ptr = NULL; + ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0); + return ret; + } + connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->base.id); -- cgit v1.2.3 From 6738e7b00bf05529303ed690873495db6d83337c Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 6 Jul 2008 11:08:49 +0200 Subject: modesetting-101: Rename DPMS modes to avoid compatibility issues with xorg definitions. --- linux-core/drm_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 47885a07..fc8d1fe8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -43,10 +43,10 @@ struct drm_prop_enum_list { * Global properties */ static struct drm_prop_enum_list drm_dpms_enum_list[] = -{ { DPMSModeOn, "On" }, - { DPMSModeStandby, "Standby" }, - { DPMSModeSuspend, "Suspend" }, - { DPMSModeOff, "Off" } +{ { DRM_MODE_DPMS_ON, "On" }, + { DRM_MODE_DPMS_STANDBY, "Standby" }, + { DRM_MODE_DPMS_SUSPEND, "Suspend" }, + { DRM_MODE_DPMS_OFF, "Off" } }; char *drm_get_dpms_name(int val) -- cgit v1.2.3 From 65803e53a696347e38d7f6c2c8dc186c6764ff03 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 20 Jul 2008 13:49:18 +0200 Subject: modesetting-101: implement optional scaling and dithering properties --- linux-core/drm_crtc.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fc8d1fe8..c984209a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -60,6 +60,26 @@ char *drm_get_dpms_name(int val) return "unknown"; } +/* + * Optional properties + */ +static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = +{ + { DRM_MODE_SCALE_NON_GPU, "Non-GPU" }, + { DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" }, + { DRM_MODE_SCALE_NO_SCALE, "No scale" }, + { DRM_MODE_SCALE_ASPECT, "Aspect" }, +}; + +static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = +{ + { DRM_MODE_DITHERING_OFF, "Off" }, + { DRM_MODE_DITHERING_ON, "On" }, +}; + +/* + * Non-global properties, but "required" for certain connectors. + */ static struct drm_prop_enum_list drm_select_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ @@ -102,6 +122,9 @@ char *drm_get_subconnector_name(int val) return "unknown"; } +/* + * Connector and encoder types. + */ static struct drm_prop_enum_list drm_connector_enum_list[] = { { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, { DRM_MODE_CONNECTOR_VGA, "VGA" }, @@ -646,6 +669,52 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, } EXPORT_SYMBOL(drm_mode_create_tv_properties); +/** + * drm_mode_create_scaling_mode_property - create scaling mode property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired connectors. + */ +int drm_mode_create_scaling_mode_property(struct drm_device *dev) +{ + int i; + + if (dev->mode_config.scaling_mode_property) /* already done */ + return 0; + + dev->mode_config.scaling_mode_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "scaling mode", ARRAY_SIZE(drm_scaling_mode_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) + drm_property_add_enum(dev->mode_config.scaling_mode_property, i, drm_scaling_mode_enum_list[i].type, drm_scaling_mode_enum_list[i].name); + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); + +/** + * drm_mode_create_dithering_property - create dithering property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired connectors. + */ +int drm_mode_create_dithering_property(struct drm_device *dev) +{ + int i; + + if (dev->mode_config.dithering_mode_property) /* already done */ + return 0; + + dev->mode_config.dithering_mode_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, + "dithering", ARRAY_SIZE(drm_dithering_mode_enum_list)); + for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++) + drm_property_add_enum(dev->mode_config.dithering_mode_property, i, drm_dithering_mode_enum_list[i].type, drm_dithering_mode_enum_list[i].name); + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_dithering_property); + /** * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device -- cgit v1.2.3 From e51cd78cac24df15e32e23d8db73614524e6ff0d Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 20 Jul 2008 14:58:46 +0200 Subject: modesetting-101: Only store property value when set_property was successful. --- linux-core/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c984209a..91bff1f6 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2184,12 +2184,12 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, } } - /* store the property value */ - drm_connector_property_set_value(connector, property, out_resp->value); - if (connector->funcs->set_property) ret = connector->funcs->set_property(connector, property, out_resp->value); + /* store the property value if succesful */ + if (!ret) + drm_connector_property_set_value(connector, property, out_resp->value); out: mutex_unlock(&dev->mode_config.mutex); return ret; -- cgit v1.2.3 From 11d30750873260fe19498d90831f07079dfad5d8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 26 Jul 2008 08:41:01 +1000 Subject: modesetting: pass file_priv into cursor set functions --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 91bff1f6..7ee33219 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1445,7 +1445,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (req->flags & DRM_MODE_CURSOR_BO) { /* Turn of the cursor if handle is 0 */ if (crtc->funcs->cursor_set) { - ret = crtc->funcs->cursor_set(crtc, req->handle, req->width, req->height); + ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, req->width, req->height); } else { DRM_ERROR("crtc does not support cursor\n"); ret = -EFAULT; -- cgit v1.2.3 From df9871064e8b564d9ae2e56d561b64434fd004af Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 26 Jul 2008 08:56:23 +1000 Subject: radeon: add initial atombios modesetting and GEM -> TTM translation layer. This is an initial import of the atom bios parser with modesetting support for r500 hw using atombios. It also includes a simple memory manager layer that translates a radeon GEM style interface onto TTM internally. So far this memory manager has only been used for pinned object allocation for the DDX to test modesetting. --- linux-core/drm_crtc.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 7ee33219..8375bf9a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -122,24 +122,31 @@ char *drm_get_subconnector_name(int val) return "unknown"; } +struct drm_conn_prop_enum_list { + int type; + char *name; + int count; +}; + /* * Connector and encoder types. */ -static struct drm_prop_enum_list drm_connector_enum_list[] = -{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "Composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "Component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" }, +static struct drm_conn_prop_enum_list drm_connector_enum_list[] = +{ { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 }, + { DRM_MODE_CONNECTOR_VGA, "VGA", 0 }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 }, + { DRM_MODE_CONNECTOR_Composite, "Composite", 0 }, + { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, + { DRM_MODE_CONNECTOR_Component, "Component", 0 }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 }, + { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, }; + static struct drm_prop_enum_list drm_encoder_enum_list[] = { { DRM_MODE_ENCODER_NONE, "None" }, { DRM_MODE_ENCODER_DAC, "DAC" }, @@ -226,7 +233,7 @@ static void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object * idr_remove(&dev->mode_config.crtc_idr, object->id); } -static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) +void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) { struct drm_mode_object *obj; @@ -236,6 +243,7 @@ static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t return obj; } +EXPORT_SYMBOL(drm_mode_object_find); /** * drm_crtc_from_fb - find the CRTC structure associated with an fb @@ -419,7 +427,7 @@ void drm_connector_init(struct drm_device *dev, connector->funcs = funcs; drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); connector->connector_type = connector_type; - connector->connector_type_id = 1; /* TODO */ + connector->connector_type_id = ++drm_connector_enum_list[connector_type].count; /* TODO */ INIT_LIST_HEAD(&connector->user_modes); INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); @@ -756,6 +764,9 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) total_objects += dev->mode_config.num_connector; total_objects += dev->mode_config.num_encoder; + if (total_objects == 0) + return -EINVAL; + group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); if (!group->id_list) return -ENOMEM; @@ -771,9 +782,10 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_gro struct drm_crtc *crtc; struct drm_encoder *encoder; struct drm_connector *connector; + int ret; - if (drm_mode_group_init(dev, group)) - return -ENOMEM; + if ((ret = drm_mode_group_init(dev, group))) + return ret; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) group->id_list[group->num_crtcs++] = crtc->base.id; -- cgit v1.2.3 From 085df6491e4975681a6e17ff9a67d01268aa7553 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 12 Aug 2008 18:23:58 -0700 Subject: Add error checking to framebuffer creation Make the Intel routine return an error if needed and make the core check for it. --- linux-core/drm_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 8375bf9a..aa6749d6 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -285,7 +285,9 @@ struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, struct drm_framebuffer *drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, const struct drm_framebuffer_funcs *funcs) { - drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); + if(drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB)) + return NULL; + fb->dev = dev; fb->funcs = funcs; dev->mode_config.num_fb++; -- cgit v1.2.3 From 5fdfbee22acb8eaaa834457c30e6f68883ab1353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 23 Sep 2008 16:47:34 +1000 Subject: Store the buffer object backing the fb as a void pointer, not a handle. This lets us defer handle creation until userspace acutally asks for one, at which point we also have a drm_file to associate it with. --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index aa6749d6..2fefd1d2 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1631,8 +1631,8 @@ int drm_mode_getfb(struct drm_device *dev, r->width = fb->width; r->depth = fb->depth; r->bpp = fb->bits_per_pixel; - r->handle = fb->mm_handle; r->pitch = fb->pitch; + fb->funcs->create_handle(fb, file_priv, &r->handle); out: mutex_unlock(&dev->mode_config.mutex); -- cgit v1.2.3 From 34a3ebffc369575412a4ff2c05c50264e83c6d3e Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 24 Oct 2008 18:43:55 +0200 Subject: mode: Try to settle on a standard for struct fields --- linux-core/drm_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 2fefd1d2..2f80ec07 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1448,9 +1448,9 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, } mutex_lock(&dev->mode_config.mutex); - obj = drm_mode_object_find(dev, req->crtc, DRM_MODE_OBJECT_CRTC); + obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); if (!obj) { - DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc); + DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc_id); ret = -EINVAL; goto out; } -- cgit v1.2.3 From 195cc0d817f99e25a1e961deeabbb15a40b789ed Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 10 Nov 2008 15:37:16 +1000 Subject: drm/radeon: add dpms connector functions --- linux-core/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 2f80ec07..bc385dce 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1423,7 +1423,7 @@ int drm_mode_setcrtc(struct drm_device *dev, set.mode = mode; set.connectors = connector_set; set.num_connectors = crtc_req->count_connectors; - set.fb =fb; + set.fb = fb; ret = crtc->funcs->set_config(&set); out: -- cgit v1.2.3 From 1ead45c8f02e7c51cfe977383726d20479385688 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 12 Nov 2008 18:40:04 +0100 Subject: mode: Remove hotplug support from ioctl interface --- linux-core/drm_crtc.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index bc385dce..255cc8c2 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -844,16 +844,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_config_cleanup); -int drm_mode_hotplug_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv) -{ - struct drm_mode_hotplug *arg = data; - - arg->counter = dev->mode_config.hotplug_counter; - - return 0; -} - /** * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo * @out: drm_mode_modeinfo struct to return to the user -- cgit v1.2.3 From 9a4cb7eab4f74747cc777a3fef31dbb46e1191e5 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 12 Nov 2008 19:17:18 +0100 Subject: mode: Minor reodering and renaming --- linux-core/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_crtc.c') diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 255cc8c2..aa0c4a95 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1517,7 +1517,7 @@ int drm_mode_addfb(struct drm_device *dev, goto out; } - r->buffer_id = fb->base.id; + r->fb_id = fb->base.id; list_add(&fb->filp_head, &file_priv->fbs); out: @@ -1609,7 +1609,7 @@ int drm_mode_getfb(struct drm_device *dev, int ret = 0; mutex_lock(&dev->mode_config.mutex); - obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); + obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); if (!obj) { DRM_ERROR("invalid framebuffer id\n"); ret = -EINVAL; @@ -2212,7 +2212,7 @@ int drm_mode_replacefb(struct drm_device *dev, /* right replace the current bo attached to this fb with a new bo */ mutex_lock(&dev->mode_config.mutex); - obj = drm_mode_object_find(dev, r->buffer_id, DRM_MODE_OBJECT_FB); + obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); if (!obj) { ret = -EINVAL; goto out; -- cgit v1.2.3