struct dc_sink *dc_link_add_remote_sink( struct dc_link *link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data) { struct dc_sink *dc_sink; enum dc_edid_status edid_status; if (len > MAX_EDID_BUFFER_SIZE) { dm_error("Max EDID buffer size breached!\n"); return NULL; } if (!init_data) { BREAK_TO_DEBUGGER(); return NULL; } if (!init_data->link) { BREAK_TO_DEBUGGER(); return NULL; } dc_sink = dc_sink_create(init_data); if (!dc_sink) return NULL; memmove(dc_sink->dc_edid.raw_edid, edid, len); dc_sink->dc_edid.length = len; if (!link_add_remote_sink_helper( link, dc_sink)) goto fail_add_sink; edid_status = dm_helpers_parse_edid_caps( link->ctx, &dc_sink->dc_edid, &dc_sink->edid_caps); if (edid_status != EDID_OK) goto fail; return dc_sink; fail: dc_link_remove_remote_sink(link, dc_sink); fail_add_sink: dc_sink_release(dc_sink); return NULL; }
enum dc_edid_status dm_helpers_read_local_edid( struct dc_context *ctx, struct dc_link *link, struct dc_sink *sink) { struct amdgpu_dm_connector *aconnector = link->priv; struct i2c_adapter *ddc; int retry = 3; enum dc_edid_status edid_status; struct edid *edid; if (link->aux_mode) ddc = &aconnector->dm_dp_aux.aux.ddc; else ddc = &aconnector->i2c->base; /* some dongles read edid incorrectly the first time, * do check sum and retry to make sure read correct edid. */ do { edid = drm_get_edid(&aconnector->base, ddc); if (!edid) return EDID_NO_RESPONSE; 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 */ kfree(edid); edid_status = dm_helpers_parse_edid_caps( ctx, &sink->dc_edid, &sink->edid_caps); } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0); if (edid_status != EDID_OK) DRM_ERROR("EDID err: %d, on connector: %s", edid_status, aconnector->base.name); return edid_status; }