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