[PATCH v4 14/14] drm/amd/display: move dc_sink from dc_edid to drm_edid
Melissa Wen
mwen at igalia.com
Mon Jun 16 19:09:18 UTC 2025
On 13/06/2025 15:26, Mario Limonciello wrote:
> On 6/13/2025 9:58 AM, Melissa Wen wrote:
>> Reduce direct handling of edid data by resorting to drm helpers that
>> deal with this info inside drm_edid infrastructure.
>>
>> v3:
>> - use dc_edid_sink_edid_free in link_detection
>>
>> Signed-off-by: Melissa Wen <mwen at igalia.com>
>> ---
>> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 +++++++------------
>> .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 24 +++++------------
>> .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 21 +++++----------
>> .../gpu/drm/amd/display/amdgpu_dm/dc_edid.c | 26 +++++++++----------
>> .../gpu/drm/amd/display/amdgpu_dm/dc_edid.h | 1 +
>> .../drm/amd/display/dc/link/link_detection.c | 3 ++-
>> 6 files changed, 40 insertions(+), 61 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index c7efeb9f38b6..ec33a6236e37 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -68,6 +68,7 @@
>> #endif
>> #include "amdgpu_dm_psr.h"
>> #include "amdgpu_dm_replay.h"
>> +#include "dc_edid.h"
>> #include "ivsrcid/ivsrcid_vislands30.h"
>> @@ -3708,6 +3709,8 @@ void amdgpu_dm_update_connector_after_detect(
>> * 2. Send an event and let userspace tell us what to do
>> */
>> if (sink) {
>> + const struct drm_edid *drm_edid = sink->drm_edid;
>> +
>> /*
>> * TODO: check if we still need the S3 mode update workaround.
>> * If yes, put it here.
>> @@ -3719,16 +3722,15 @@ void amdgpu_dm_update_connector_after_detect(
>> aconnector->dc_sink = sink;
>> dc_sink_retain(aconnector->dc_sink);
>> - if (sink->dc_edid.length == 0) {
>> +
>> + if (!drm_edid_valid(drm_edid)) {
>> aconnector->drm_edid = NULL;
>> hdmi_cec_unset_edid(aconnector);
>> if (aconnector->dc_link->aux_mode) {
>> drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
>> }
>> } else {
>> - const struct edid *edid = (const struct edid
>> *)sink->dc_edid.raw_edid;
>> -
>> - aconnector->drm_edid = drm_edid_alloc(edid,
>> sink->dc_edid.length);
>> + aconnector->drm_edid = drm_edid_dup(sink->drm_edid);
>> drm_edid_connector_update(connector,
>> aconnector->drm_edid);
>> hdmi_cec_set_edid(aconnector);
>> @@ -7378,12 +7380,8 @@ static void
>> amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
>> aconnector->drm_edid = drm_edid;
>> /* Update emulated (virtual) sink's EDID */
>> if (dc_em_sink && dc_link) {
>> - // FIXME: Get rid of drm_edid_raw()
>> - const struct edid *edid = drm_edid_raw(drm_edid);
>> -
>> memset(&dc_em_sink->edid_caps, 0, sizeof(struct
>> dc_edid_caps));
>> - memmove(dc_em_sink->dc_edid.raw_edid, edid,
>> - (edid->extensions + 1) * EDID_LENGTH);
>> + dc_edid_copy_edid_to_dc(dc_em_sink, drm_edid, 0);
>> dm_helpers_parse_edid_caps(dc_link, dc_em_sink);
>> }
>> }
>> @@ -7416,7 +7414,6 @@ static void create_eml_sink(struct
>> amdgpu_dm_connector *aconnector)
>> .sink_signal = SIGNAL_TYPE_VIRTUAL
>> };
>> const struct drm_edid *drm_edid;
>> - const struct edid *edid;
>> struct i2c_adapter *ddc;
>> if (dc_link && dc_link->aux_mode)
>> @@ -7436,12 +7433,9 @@ static void create_eml_sink(struct
>> amdgpu_dm_connector *aconnector)
>> aconnector->drm_edid = drm_edid;
>> - edid = drm_edid_raw(drm_edid); // FIXME: Get rid of
>> drm_edid_raw()
>> - aconnector->dc_em_sink = dc_link_add_remote_sink(
>> - aconnector->dc_link,
>> - (uint8_t *)edid,
>> - (edid->extensions + 1) * EDID_LENGTH,
>> - &init_params);
>> + aconnector->dc_em_sink =
>> dc_link_add_remote_sink(aconnector->dc_link,
>> + drm_edid, 0,
>> + &init_params);
>> if (aconnector->base.force == DRM_FORCE_ON) {
>> aconnector->dc_sink = aconnector->dc_link->local_sink ?
>> diff --git
>> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
>> index abfce44dcee7..3e9d04760c21 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
>> @@ -48,6 +48,7 @@
>> #include "dm_helpers.h"
>> #include "ddc_service_types.h"
>> #include "clk_mgr.h"
>> +#include "dc_edid.h"
>> static void apply_edid_quirks(struct drm_device *dev,
>> const struct drm_edid *drm_edid,
>> @@ -100,20 +101,16 @@ enum dc_edid_status
>> dm_helpers_parse_edid_caps(struct dc_link *link,
>> struct amdgpu_dm_connector *aconnector = link->priv;
>> struct drm_connector *connector = &aconnector->base;
>> struct drm_device *dev = connector->dev;
>> - struct edid *edid_buf;
>> - const struct drm_edid *drm_edid;
>> + const struct drm_edid *drm_edid = sink->drm_edid;
>> struct drm_edid_product_id product_id;
>> struct dc_edid_caps *edid_caps = &sink->edid_caps;
>> int sad_count;
>> int i = 0;
>> enum dc_edid_status result = EDID_OK;
>> - edid_buf = (struct edid *) &sink->dc_edid.raw_edid;
>> - if (!edid_caps || !edid_buf)
>> + if (!edid_caps || !drm_edid)
>> return EDID_BAD_INPUT;
>> - drm_edid = drm_edid_alloc(edid_buf, EDID_LENGTH *
>> (edid_buf->extensions + 1));
>> -
>> if (!drm_edid_valid(drm_edid))
>> result = EDID_BAD_CHECKSUM;
>> @@ -135,10 +132,8 @@ enum dc_edid_status
>> dm_helpers_parse_edid_caps(struct dc_link *link,
>> apply_edid_quirks(dev, drm_edid, edid_caps);
>> sad_count = drm_eld_sad_count(connector->eld);
>> - if (sad_count <= 0) {
>> - drm_edid_free(drm_edid);
>> + if (sad_count <= 0)
>> return result;
>> - }
>> edid_caps->audio_mode_count = min(sad_count,
>> DC_MAX_AUDIO_DESC_COUNT);
>> for (i = 0; i < edid_caps->audio_mode_count; ++i) {
>> @@ -158,8 +153,6 @@ enum dc_edid_status
>> dm_helpers_parse_edid_caps(struct dc_link *link,
>> else
>> edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
>> - drm_edid_free(drm_edid);
>> -
>> return result;
>> }
>> @@ -991,7 +984,6 @@ enum dc_edid_status dm_helpers_read_local_edid(
>> int retry = 3;
>> enum dc_edid_status edid_status;
>> const struct drm_edid *drm_edid;
>> - const struct edid *edid;
>> if (link->aux_mode)
>> ddc = &aconnector->dm_dp_aux.aux.ddc;
>> @@ -1021,11 +1013,7 @@ enum dc_edid_status dm_helpers_read_local_edid(
>> if (!drm_edid)
>> return EDID_NO_RESPONSE;
>> - edid = drm_edid_raw(drm_edid); // FIXME: Get rid of
>> drm_edid_raw()
>> - sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1);
>> - memmove(sink->dc_edid.raw_edid, (uint8_t *)edid,
>> sink->dc_edid.length);
>> -
>> - /* We don't need the original edid anymore */
>> + sink->drm_edid = drm_edid_dup(drm_edid);
>> drm_edid_free(drm_edid);
>
> Is the duplication actually necessary? Can you "steal" the pointer by
> just assigning directly?
Now you pointed it out and I realized there is a memory leak here if the
loop continues.
I'll fix that.
Thanks for reviewing.
Melissa
>
>
>> edid_status = dm_helpers_parse_edid_caps(link, sink);
>> @@ -1051,6 +1039,8 @@ enum dc_edid_status dm_helpers_read_local_edid(
>> test_response.bits.EDID_CHECKSUM_WRITE = 1;
>> + // TODO: drm_edid doesn't have a helper for dp_write_dpcd yet
>> + dc_edid_copy_edid_to_sink(sink);
>> dm_helpers_dp_write_dpcd(ctx,
>> link,
>> DP_TEST_EDID_CHECKSUM,
>> diff --git
>> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> index 7187d5aedf0a..5ca3e668c8aa 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> @@ -359,12 +359,10 @@ static int dm_dp_mst_get_modes(struct
>> drm_connector *connector)
>> .link = aconnector->dc_link,
>> .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
>> - dc_sink = dc_link_add_remote_sink(
>> - aconnector->dc_link,
>> - NULL,
>> - 0,
>> - &init_params);
>> -
>> + dc_sink = dc_link_add_remote_sink(aconnector->dc_link,
>> + NULL,
>> + 0,
>> + &init_params);
>> if (!dc_sink) {
>> DRM_ERROR("Unable to add a remote sink\n");
>> return 0;
>> @@ -397,15 +395,10 @@ static int dm_dp_mst_get_modes(struct
>> drm_connector *connector)
>> struct dc_sink_init_data init_params = {
>> .link = aconnector->dc_link,
>> .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
>> - const struct edid *edid;
>> -
>> - edid = drm_edid_raw(aconnector->drm_edid); // FIXME: Get rid
>> of drm_edid_raw()
>> - dc_sink = dc_link_add_remote_sink(
>> - aconnector->dc_link,
>> - (uint8_t *)edid,
>> - (edid->extensions + 1) * EDID_LENGTH,
>> - &init_params);
>> + dc_sink = dc_link_add_remote_sink(aconnector->dc_link,
>> + aconnector->drm_edid, 0,
>> + &init_params);
>> if (!dc_sink) {
>> DRM_ERROR("Unable to add a remote sink\n");
>> return 0;
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.c
>> index 9e86dc15557b..ce4a7f9e268a 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.c
>> @@ -6,25 +6,25 @@
>> bool dc_edid_is_same_edid(struct dc_sink *prev_sink,
>> struct dc_sink *current_sink)
>> {
>> - struct dc_edid *old_edid = &prev_sink->dc_edid;
>> - struct dc_edid *new_edid = ¤t_sink->dc_edid;
>> -
>> - if (old_edid->length != new_edid->length)
>> - return false;
>> -
>> - if (new_edid->length == 0)
>> - return false;
>> -
>> - return (memcmp(old_edid->raw_edid,
>> - new_edid->raw_edid, new_edid->length) == 0);
>> + return drm_edid_eq(prev_sink->drm_edid, current_sink->drm_edid);
>> }
>> void dc_edid_copy_edid_to_dc(struct dc_sink *dc_sink,
>> const void *edid,
>> int len)
>> {
>> - memmove(dc_sink->dc_edid.raw_edid, edid, len);
>> - dc_sink->dc_edid.length = len;
>> + dc_sink->drm_edid = drm_edid_dup((const struct drm_edid *) edid);
>> +}
>> +
>> +void dc_edid_copy_edid_to_sink(struct dc_sink *sink)
>> +{
>> + const struct edid *edid;
>> + uint32_t edid_length;
>> +
>> + edid = drm_edid_raw(sink->drm_edid); // FIXME: Get rid of
>> drm_edid_raw()
>> + edid_length = EDID_LENGTH * (edid->extensions + 1);
>> + memcpy(sink->dc_edid.raw_edid, (uint8_t *) edid, edid_length);
>> + sink->dc_edid.length = edid_length;
>> }
>> void dc_edid_sink_edid_free(struct dc_sink *sink)
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.h
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.h
>> index 2c76768be459..a95cc6ccc743 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.h
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_edid.h
>> @@ -9,6 +9,7 @@ bool dc_edid_is_same_edid(struct dc_sink *prev_sink,
>> struct dc_sink *current_sink);
>> void dc_edid_copy_edid_to_dc(struct dc_sink *dc_sink,
>> const void *edid, int len);
>> +void dc_edid_copy_edid_to_sink(struct dc_sink *sink);
>> void dc_edid_sink_edid_free(struct dc_sink *sink);
>> #endif /* __DC_EDID_H__ */
>> diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
>> b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
>> index c28072f980cc..bddcfd8f02ba 100644
>> --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
>> +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
>> @@ -1133,6 +1133,7 @@ static bool detect_link_and_local_sink(struct
>> dc_link *link,
>> dp_trace_init(link);
>> /* Connectivity log: detection */
>> + dc_edid_copy_edid_to_sink(sink);
>> for (i = 0; i < sink->dc_edid.length / DC_EDID_BLOCK_SIZE;
>> i++) {
>> CONN_DATA_DETECT(link,
>> &sink->dc_edid.raw_edid[i * DC_EDID_BLOCK_SIZE],
>> @@ -1415,7 +1416,7 @@ struct dc_sink *link_add_remote_sink(
>> * parsing fails
>> */
>> if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) {
>> - dc_sink->dc_edid.length = 0;
>> + dc_edid_sink_edid_free(dc_sink);
>> dm_error("Bad EDID, status%d!\n", edid_status);
>> }
>
More information about the amd-gfx
mailing list