[RFC][PATCH 07/10] drm: Add MODE_IDS property to connectors
ville.syrjala at linux.intel.com
ville.syrjala at linux.intel.com
Wed Jun 27 03:24:09 PDT 2012
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
Add a new blob property MODE_IDS to connectors. This property contains
a list a mode object IDs attached to the connector (either probed modes,
or user attached modes).
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
drivers/gpu/drm/drm_crtc.c | 77 +++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_crtc_helper.c | 1 +
include/drm/drm_crtc.h | 2 +
3 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 958a4b0..cfef9de 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -508,6 +508,9 @@ int drm_connector_init(struct drm_device *dev,
drm_connector_attach_property(connector,
dev->mode_config.dpms_property, 0);
+ drm_connector_attach_property(connector,
+ dev->mode_config.mode_ids_property, 0);
+
out:
mutex_unlock(&dev->mode_config.mutex);
@@ -713,6 +716,7 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
{
struct drm_property *edid;
struct drm_property *dpms;
+ struct drm_property *mode_ids;
/*
* Standard properties (apply to all connectors)
@@ -727,6 +731,11 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
ARRAY_SIZE(drm_dpms_enum_list));
dev->mode_config.dpms_property = dpms;
+ mode_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+ DRM_MODE_PROP_IMMUTABLE,
+ "MODE_IDS", 0);
+ dev->mode_config.mode_ids_property = mode_ids;
+
return 0;
}
@@ -2648,6 +2657,10 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev,
}
drm_mode_attachmode(dev, connector, mode);
+
+ ret = drm_mode_connector_update_mode_ids_property(connector);
+ if (ret)
+ drm_mode_remove(connector, mode);
out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
@@ -3144,6 +3157,70 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
+int drm_mode_connector_update_mode_ids_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property_blob *blob = NULL;
+ struct drm_property_blob *old_blob = NULL;
+ struct drm_display_mode *mode;
+ uint64_t value;
+ int i = 0;
+ int ret;
+
+ ret = drm_connector_property_get_value(connector,
+ dev->mode_config.mode_ids_property,
+ &value);
+ if (ret)
+ return ret;
+
+ if (value) {
+ struct drm_mode_object *obj = drm_mode_object_find(dev, value, DRM_MODE_OBJECT_BLOB);
+ if (!obj)
+ return -ENOENT;
+
+ old_blob = obj_to_blob(obj);
+ }
+
+ list_for_each_entry(mode, &connector->modes, head)
+ i++;
+ list_for_each_entry(mode, &connector->user_modes, head)
+ i++;
+
+ if (i) {
+ uint32_t *mode_ids = kcalloc(i, sizeof mode_ids[0], GFP_KERNEL);
+ if (!mode_ids)
+ return -ENOMEM;
+
+ i = 0;
+ list_for_each_entry(mode, &connector->modes, head)
+ mode_ids[i++] = mode->base.id;
+ list_for_each_entry(mode, &connector->user_modes, head)
+ mode_ids[i++] = mode->base.id;
+
+ blob = drm_property_create_blob(dev, i * sizeof mode_ids[0], mode_ids);
+
+ kfree(mode_ids);
+
+ if (!blob)
+ return -ENOMEM;
+ }
+
+ ret = drm_connector_property_set_value(connector,
+ dev->mode_config.mode_ids_property,
+ blob ? blob->base.id : 0);
+ if (ret) {
+ if (blob)
+ drm_property_destroy_blob(dev, blob);
+ return ret;
+ }
+
+ if (old_blob)
+ drm_property_destroy_blob(dev, old_blob);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_mode_connector_update_mode_ids_property);
+
static bool range_property_is_signed(const struct drm_property *property)
{
return property->values[0] > property->values[1];
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index ebbfcc6..bc24c0e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -131,6 +131,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
goto prune;
drm_mode_connector_list_update(connector);
+ drm_mode_connector_update_mode_ids_property(connector);
if (maxX && maxY)
drm_mode_validate_size(dev, &connector->modes, maxX,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 99bd489..c8bfdf1 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -790,6 +790,7 @@ struct drm_mode_config {
struct list_head property_blob_list;
struct drm_property *edid_property;
struct drm_property *dpms_property;
+ struct drm_property *mode_ids_property;
/* DVI-I properties */
struct drm_property *dvi_i_subconnector_property;
@@ -910,6 +911,7 @@ extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
extern void drm_mode_connector_list_update(struct drm_connector *connector);
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
struct edid *edid);
+extern int drm_mode_connector_update_mode_ids_property(struct drm_connector *connector);
extern int drm_connector_property_set_value(struct drm_connector *connector,
struct drm_property *property,
uint64_t value);
--
1.7.3.4
More information about the dri-devel
mailing list