[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