[PATCH/RFC 3/5] drm/edid: Move DisplayID tile parsing to drm_connector.c

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed Aug 21 18:50:03 UTC 2019


The static function that populates the drm_connector tile-related fields
from EDID displayid will be used outside of drm_edid.c. As it logically
belongs to connector code, move it to drm_connector.c and rename it from
drm_get_displayid() to drm_connector_set_displayid().

While at it, fix a few checkpatch warnings in the moved code.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 drivers/gpu/drm/drm_connector.c       | 137 +++++++++++++++++++++++++-
 drivers/gpu/drm/drm_dp_mst_topology.c |   3 +-
 drivers/gpu/drm/drm_edid.c            | 131 +-----------------------
 include/drm/drm_connector.h           |   3 +-
 include/drm/drm_displayid.h           |   2 +
 include/drm/drm_edid.h                |   2 +
 6 files changed, 148 insertions(+), 130 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4c766624b20d..04f72ad0d9b6 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -21,6 +21,7 @@
  */
 
 #include <drm/drm_connector.h>
+#include <drm/drm_displayid.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_utils.h>
@@ -1801,6 +1802,135 @@ int drm_connector_set_path_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_connector_set_path_property);
 
+static int drm_parse_tiled_block(struct drm_connector *connector,
+				 struct displayid_block *block)
+{
+	struct displayid_tiled_block *tile =
+		(struct displayid_tiled_block *)block;
+	struct drm_tile_group *tg;
+	u8 tile_v_loc, tile_h_loc;
+	u8 num_v_tile, num_h_tile;
+	u16 w, h;
+
+	w = tile->tile_size[0] | tile->tile_size[1] << 8;
+	h = tile->tile_size[2] | tile->tile_size[3] << 8;
+
+	num_v_tile = (tile->topo[0] & 0xf) | (tile->topo[2] & 0x30);
+	num_h_tile = (tile->topo[0] >> 4) | ((tile->topo[2] >> 2) & 0x30);
+	tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
+	tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
+
+	connector->has_tile = true;
+	if (tile->tile_cap & 0x80)
+		connector->tile_is_single_monitor = true;
+
+	connector->num_h_tile = num_h_tile + 1;
+	connector->num_v_tile = num_v_tile + 1;
+	connector->tile_h_loc = tile_h_loc;
+	connector->tile_v_loc = tile_v_loc;
+	connector->tile_h_size = w + 1;
+	connector->tile_v_size = h + 1;
+
+	DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
+	DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
+	DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
+		      num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
+	DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0],
+		      tile->topology_id[1], tile->topology_id[2]);
+
+	tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
+	if (!tg)
+		tg = drm_mode_create_tile_group(connector->dev,
+						tile->topology_id);
+	if (!tg)
+		return -ENOMEM;
+
+	if (connector->tile_group != tg) {
+		/*
+		 * If we haven't got a pointer, take the reference, drop ref to
+		 * old tile group.
+		 */
+		if (connector->tile_group)
+			drm_mode_put_tile_group(connector->dev,
+						connector->tile_group);
+		connector->tile_group = tg;
+	} else {
+		/* If same tile group, then release the ref we just took. */
+		drm_mode_put_tile_group(connector->dev, tg);
+	}
+
+	return 0;
+}
+
+static int drm_connector_parse_displayid_tile(struct drm_connector *connector,
+					      u8 *displayid, int length)
+{
+	struct displayid_block *block;
+	int idx;
+	int ret;
+
+	if (!drm_displayid_is_valid(displayid, length))
+		return -EINVAL;
+
+	idx = sizeof(struct displayid_hdr);
+	for_each_displayid_db(displayid, block, idx, length) {
+		DRM_DEBUG_KMS("block id 0x%x, rev %d, len %d\n",
+			      block->tag, block->rev, block->num_bytes);
+
+		switch (block->tag) {
+		case DATA_BLOCK_TILED_DISPLAY:
+			ret = drm_parse_tiled_block(connector, block);
+			if (ret)
+				return ret;
+			break;
+		case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
+			/* handled in mode gathering code. */
+			break;
+		case DATA_BLOCK_CTA:
+			/* handled in the cea parser code. */
+			break;
+		default:
+			DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n",
+				      block->tag);
+			break;
+		}
+	}
+	return 0;
+}
+
+static void drm_connector_set_displayid_tile(struct drm_connector *connector,
+					     void *displayid,
+					     unsigned int length)
+{
+	connector->has_tile = false;
+
+	if (displayid)
+		drm_connector_parse_displayid_tile(connector, displayid,
+						   length);
+
+	if (!connector->has_tile && connector->tile_group) {
+		drm_mode_put_tile_group(connector->dev, connector->tile_group);
+		connector->tile_group = NULL;
+	}
+}
+
+static void drm_connector_set_edid_tile(struct drm_connector *connector,
+					const struct edid *edid)
+{
+	unsigned int length;
+	void *displayid;
+
+	if (edid) {
+		displayid = drm_edid_find_displayid_extension(edid);
+		length = EDID_LENGTH - 1;
+	} else {
+		displayid = NULL;
+		length = 0;
+	}
+
+	drm_connector_set_displayid_tile(connector, displayid, length);
+}
+
 /**
  * drm_connector_set_tile_property - set tile property on connector
  * @connector: connector to set property on.
@@ -1814,12 +1944,15 @@ EXPORT_SYMBOL(drm_connector_set_path_property);
  * Returns:
  * Zero on success, errno on failure.
  */
-int drm_connector_set_tile_property(struct drm_connector *connector)
+int drm_connector_set_tile_property(struct drm_connector *connector,
+				    const struct edid *edid)
 {
 	struct drm_device *dev = connector->dev;
 	char tile[256];
 	int ret;
 
+	drm_connector_set_edid_tile(connector, edid);
+
 	if (!connector->has_tile) {
 		ret  = drm_property_replace_global_blob(dev,
 		                                        &connector->tile_blob_ptr,
@@ -1899,7 +2032,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector,
 	                                       dev->mode_config.edid_property);
 	if (ret)
 		return ret;
-	return drm_connector_set_tile_property(connector);
+	return drm_connector_set_tile_property(connector, edid);
 }
 EXPORT_SYMBOL(drm_connector_update_edid_property);
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 82add736e17d..6edf9bf8fd9b 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1712,7 +1712,8 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
 		    port->port_num >= DP_MST_LOGICAL_PORT_0) {
 			port->cached_edid = drm_get_edid(port->connector,
 							 &port->aux.ddc);
-			drm_connector_set_tile_property(port->connector);
+			drm_connector_set_tile_property(port->connector,
+							port->cached_edid);
 		}
 		(*mstb->mgr->cbs->register_connector)(port->connector);
 	}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index bfcb232b9760..541e50b858e3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2606,7 +2606,7 @@ static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id)
 	return edid_ext;
 }
 
-static bool drm_displayid_is_valid(u8 *displayid, unsigned int length)
+bool drm_displayid_is_valid(u8 *displayid, unsigned int length)
 {
 	struct displayid_hdr *base;
 	u8 csum = 0;
@@ -2631,7 +2631,7 @@ static bool drm_displayid_is_valid(u8 *displayid, unsigned int length)
 	return true;
 }
 
-static u8 *drm_find_displayid_extension(const struct edid *edid)
+u8 *drm_edid_find_displayid_extension(const struct edid *edid)
 {
 	u8 *ext = drm_find_edid_extension(edid, DISPLAYID_EXT);
 
@@ -2659,7 +2659,7 @@ static u8 *drm_find_cea_extension(const struct edid *edid)
 		return cea;
 
 	/* CEA blocks can also be found embedded in a DisplayID block */
-	displayid = drm_find_displayid_extension(edid);
+	displayid = drm_edid_find_displayid_extension(edid);
 	if (!displayid)
 		return NULL;
 
@@ -4501,7 +4501,7 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
 	struct displayid_block *block;
 	int num_modes = 0;
 
-	displayid = drm_find_displayid_extension(edid);
+	displayid = drm_edid_find_displayid_extension(edid);
 	if (!displayid)
 		return 0;
 
@@ -5055,122 +5055,6 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
 }
 EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode);
 
-static int drm_parse_tiled_block(struct drm_connector *connector,
-				 struct displayid_block *block)
-{
-	struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block;
-	u16 w, h;
-	u8 tile_v_loc, tile_h_loc;
-	u8 num_v_tile, num_h_tile;
-	struct drm_tile_group *tg;
-
-	w = tile->tile_size[0] | tile->tile_size[1] << 8;
-	h = tile->tile_size[2] | tile->tile_size[3] << 8;
-
-	num_v_tile = (tile->topo[0] & 0xf) | (tile->topo[2] & 0x30);
-	num_h_tile = (tile->topo[0] >> 4) | ((tile->topo[2] >> 2) & 0x30);
-	tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
-	tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
-
-	connector->has_tile = true;
-	if (tile->tile_cap & 0x80)
-		connector->tile_is_single_monitor = true;
-
-	connector->num_h_tile = num_h_tile + 1;
-	connector->num_v_tile = num_v_tile + 1;
-	connector->tile_h_loc = tile_h_loc;
-	connector->tile_v_loc = tile_v_loc;
-	connector->tile_h_size = w + 1;
-	connector->tile_v_size = h + 1;
-
-	DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
-	DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
-	DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
-		      num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
-	DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
-
-	tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
-	if (!tg) {
-		tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
-	}
-	if (!tg)
-		return -ENOMEM;
-
-	if (connector->tile_group != tg) {
-		/* if we haven't got a pointer,
-		   take the reference, drop ref to old tile group */
-		if (connector->tile_group) {
-			drm_mode_put_tile_group(connector->dev, connector->tile_group);
-		}
-		connector->tile_group = tg;
-	} else
-		/* if same tile group, then release the ref we just took. */
-		drm_mode_put_tile_group(connector->dev, tg);
-	return 0;
-}
-
-static int drm_parse_displayid(struct drm_connector *connector,
-			       u8 *displayid, int length)
-{
-	struct displayid_block *block;
-	int idx;
-	int ret;
-
-	if (!drm_displayid_is_valid(displayid, length))
-		return -EINVAL;
-
-	idx = sizeof(struct displayid_hdr);
-	for_each_displayid_db(displayid, block, idx, length) {
-		DRM_DEBUG_KMS("block id 0x%x, rev %d, len %d\n",
-			      block->tag, block->rev, block->num_bytes);
-
-		switch (block->tag) {
-		case DATA_BLOCK_TILED_DISPLAY:
-			ret = drm_parse_tiled_block(connector, block);
-			if (ret)
-				return ret;
-			break;
-		case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
-			/* handled in mode gathering code. */
-			break;
-		case DATA_BLOCK_CTA:
-			/* handled in the cea parser code. */
-			break;
-		default:
-			DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag);
-			break;
-		}
-	}
-	return 0;
-}
-
-static void drm_get_displayid(struct drm_connector *connector,
-			      struct edid *edid)
-{
-	void *displayid;
-	int ret;
-
-	connector->has_tile = false;
-	displayid = drm_find_displayid_extension(edid);
-	if (!displayid) {
-		/* drop reference to any tile group we had */
-		goto out_drop_ref;
-	}
-
-	ret = drm_parse_displayid(connector, displayid, EDID_LENGTH - 1);
-	if (ret < 0)
-		goto out_drop_ref;
-	if (!connector->has_tile)
-		goto out_drop_ref;
-	return;
-
-out_drop_ref:
-	if (connector->tile_group) {
-		drm_mode_put_tile_group(connector->dev, connector->tile_group);
-		connector->tile_group = NULL;
-	}
-}
-
 #define DDC_SEGMENT_ADDR 0x30
 /**
  * drm_do_probe_ddc_edid() - get EDID information via I2C
@@ -5448,18 +5332,13 @@ EXPORT_SYMBOL(drm_probe_ddc);
 struct edid *drm_get_edid(struct drm_connector *connector,
 			  struct i2c_adapter *adapter)
 {
-	struct edid *edid;
-
 	if (connector->force == DRM_FORCE_OFF)
 		return NULL;
 
 	if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter))
 		return NULL;
 
-	edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
-	if (edid)
-		drm_get_displayid(connector, edid);
-	return edid;
+	return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
 }
 EXPORT_SYMBOL(drm_get_edid);
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 681cb590f952..9ff07f8d6a44 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1532,7 +1532,8 @@ int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
 
 int drm_connector_set_path_property(struct drm_connector *connector,
 				    const char *path);
-int drm_connector_set_tile_property(struct drm_connector *connector);
+int drm_connector_set_tile_property(struct drm_connector *connector,
+				    const struct edid *edid);
 int drm_connector_update_edid_property(struct drm_connector *connector,
 				       const struct edid *edid);
 void drm_connector_set_link_status_property(struct drm_connector *connector,
diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h
index 9d3b745c3107..24f2faf3abf8 100644
--- a/include/drm/drm_displayid.h
+++ b/include/drm/drm_displayid.h
@@ -100,4 +100,6 @@ struct displayid_detailed_timing_block {
 	     (idx) += (block)->num_bytes + sizeof(struct displayid_block), \
 	     (block) = (struct displayid_block *)&(displayid)[idx])
 
+bool drm_displayid_is_valid(u8 *displayid, unsigned int length);
+
 #endif
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index b9719418c3d2..cf58e6c987d1 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -495,6 +495,8 @@ int drm_edid_header_is_valid(const u8 *raw_edid);
 bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
 			  bool *edid_corrupt);
 bool drm_edid_is_valid(struct edid *edid);
+u8 *drm_edid_find_displayid_extension(const struct edid *edid);
+
 void drm_edid_get_monitor_name(struct edid *edid, char *name,
 			       int buflen);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
-- 
Regards,

Laurent Pinchart



More information about the dri-devel mailing list