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@xxxxxxxxxxxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel