[Intel-gfx] [PATCH] drm: Add a generic function to change connector type/id of connector dynamically

yakui.zhao at intel.com yakui.zhao at intel.com
Wed Jan 27 08:16:07 CET 2010


From: Zhao Yakui <yakui.zhao at intel.com>

Sometimes one connector can support more than one connector type. And it
will switch the connector type/id dynamically according to the external
connected device.

Add a generic function to change connector type/id of the connector
dynamically.

Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
---
One multi-function SDVO card device can support SDVO-VGA/SDVO-TV(S-Video/
Composite). We should give them the correct connector type according
to the external connected device. For example: VGA/TV. The connector id
should be re-initialized when connector type is changed. Otherwise we will
get one conflict connector id.
 
One list is added to save the connector type/id that is already used by the
connector. If the target type is already in the list, we can change the
connector type/ide directly by using the saved result. 
If the new connector type is not in the list, we will dynamically
allocate the connector id for it and then save the connector type/id to the
list.

 drivers/gpu/drm/drm_crtc.c |   81 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h     |    5 +++
 2 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5124401..a64e389 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -39,6 +39,11 @@ struct drm_prop_enum_list {
 	char *name;
 };
 
+struct connector_type_id {
+	struct list_head head;
+	int connector_type;
+	int connector_id;
+};
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list)				\
 	char *fnname(int val)					\
@@ -443,6 +448,13 @@ void drm_connector_init(struct drm_device *dev,
 		     const struct drm_connector_funcs *funcs,
 		     int connector_type)
 {
+	struct connector_type_id *p_type_id = NULL;
+
+	p_type_id = kzalloc(sizeof(*p_type_id), GFP_KERNEL);
+
+	if (!p_type_id)
+		DRM_DEBUG_KMS("Can't allocate the memory\n");
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	connector->dev = dev;
@@ -465,11 +477,73 @@ void drm_connector_init(struct drm_device *dev,
 	drm_connector_attach_property(connector,
 				      dev->mode_config.dpms_property, 0);
 
+	INIT_LIST_HEAD(&connector->connector_type_list);
+	if (p_type_id) {
+		p_type_id->connector_type = connector_type;
+		p_type_id->connector_id = connector->connector_type_id;
+		list_add_tail(&p_type_id->head,
+					&connector->connector_type_list);
+	}
 	mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_connector_init);
 
 /**
+ * drm_rename_connector_type - Rename the connector type for one connector
+ * @connector: the connector to be named
+ * @target_type: the renamed target connector type
+ *
+ * Rename the connector type for one connector. Sometimes we will
+ * need get a new connector type id.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+
+int drm_rename_connector_type(struct drm_connector *connector,
+		     int target_type)
+{
+	struct connector_type_id *type_id, *temp;
+	int connector_id, found = 0;
+	struct drm_device *dev = connector->dev;
+
+	if (connector->connector_type == target_type)
+		return 0;
+
+	list_for_each_entry_safe(type_id, temp,
+			&connector->connector_type_list, head) {
+		if (type_id->connector_type == target_type) {
+			connector_id = type_id->connector_id;
+			found = 1;
+			break;
+		}
+	}
+	if (found) {
+		connector->connector_type = target_type;
+		connector->connector_type_id = connector_id;
+		return 0;
+	}
+
+	type_id = kzalloc(sizeof(*type_id), GFP_KERNEL);
+
+	if (!type_id) {
+		DRM_DEBUG_KMS("Can't allocate the memory\n");
+		return -ENOMEM;
+	}
+
+	connector->connector_type = target_type;
+	connector->connector_type_id =
+		++drm_connector_enum_list[target_type].count;
+
+	type_id->connector_type = target_type;
+	type_id->connector_id = connector->connector_type_id;
+	list_add_tail(&type_id->head, &connector->connector_type_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_rename_connector_type);
+
+/**
  * drm_connector_cleanup - cleans up an initialised connector
  * @connector: connector to cleanup
  *
@@ -482,6 +556,7 @@ void drm_connector_cleanup(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_display_mode *mode, *t;
+	struct connector_type_id *type_id, *temp;
 
 	list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
 		drm_mode_remove(connector, mode);
@@ -492,6 +567,12 @@ void drm_connector_cleanup(struct drm_connector *connector)
 	list_for_each_entry_safe(mode, t, &connector->user_modes, head)
 		drm_mode_remove(connector, mode);
 
+	list_for_each_entry_safe(type_id, temp,
+			&connector->connector_type_list, head) {
+		list_del(&type_id->head);
+		kfree(type_id);
+	}
+
 	kfree(connector->fb_helper_private);
 	mutex_lock(&dev->mode_config.mutex);
 	drm_mode_object_put(dev, &connector->base);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index fdf43ab..3862e32 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -521,6 +521,8 @@ struct drm_connector {
 	uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
 	uint32_t force_encoder_id;
 	struct drm_encoder *encoder; /* currently active encoder */
+	/* the list of possible connector type/id for this connector */
+	struct list_head connector_type_list;
 	void *fb_helper_private;
 };
 
@@ -647,6 +649,9 @@ extern void drm_connector_init(struct drm_device *dev,
 			    const struct drm_connector_funcs *funcs,
 			    int connector_type);
 
+extern int drm_rename_connector_type(struct drm_connector *connector,
+			    int target_type);
+
 extern void drm_connector_cleanup(struct drm_connector *connector);
 
 extern void drm_encoder_init(struct drm_device *dev,
-- 
1.5.4.5




More information about the Intel-gfx mailing list