[RFC][PATCH 07/10] drm: Add MODE_IDS property to connectors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>

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@xxxxxxxxxxxxxxx>
---
 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

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux