Skip to content

Commit ac1bb49

Browse files
Timur Kristófalexdeucher
authored andcommitted
drm/amd/display: Use DAC load detection on analog connectors (v2)
This feature is useful for analog connections without EDID: - Really old monitors with a VGA connector - Cheap DVI/VGA adapters that don't connect DDC pins When a connection is established through DAC load detection, the driver is supposed to fill in the supported modes for the display, which we already do in amdgpu_dm_connector_get_modes. Also, because the load detection causes visible glitches, do not attempt to poll the connector again after it was detected this way. Note that it will still be polled after sleep/resume or when force is enabled, which is okay. v2: Add dc_connection_dac_load connection type. Properly release sink when no display is connected. Don't print error when EDID isn't read from an analog display. Signed-off-by: Timur Kristóf <timur.kristof@gmail.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent d75e45b commit ac1bb49

3 files changed

Lines changed: 72 additions & 2 deletions

File tree

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7248,6 +7248,16 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
72487248
enum dc_connection_type conn_type = dc_connection_none;
72497249
enum drm_connector_status status = connector_status_disconnected;
72507250

7251+
/* When we determined the connection using DAC load detection,
7252+
* do NOT poll the connector do detect disconnect because
7253+
* that would run DAC load detection again which can cause
7254+
* visible visual glitches.
7255+
*
7256+
* Only allow to poll such a connector again when forcing.
7257+
*/
7258+
if (!force && link->local_sink && link->type == dc_connection_dac_load)
7259+
return connector->status;
7260+
72517261
mutex_lock(&aconnector->hpd_lock);
72527262

72537263
if (dc_link_detect_connection_type(aconnector->dc_link, &conn_type) &&

drivers/gpu/drm/amd/display/dc/dc_types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,8 @@ enum dc_connection_type {
353353
dc_connection_none,
354354
dc_connection_single,
355355
dc_connection_mst_branch,
356-
dc_connection_sst_branch
356+
dc_connection_sst_branch,
357+
dc_connection_dac_load
357358
};
358359

359360
struct dc_csc_adjustments {

drivers/gpu/drm/amd/display/dc/link/link_detection.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,37 @@ static bool link_detect_ddc_probe(struct dc_link *link)
904904
return true;
905905
}
906906

907+
/**
908+
* link_detect_dac_load_detect() - Performs DAC load detection.
909+
*
910+
* Load detection can be used to detect the presence of an
911+
* analog display when we can't read DDC. This causes a visible
912+
* visual glitch so it should be used sparingly.
913+
*/
914+
static bool link_detect_dac_load_detect(struct dc_link *link)
915+
{
916+
struct dc_bios *bios = link->ctx->dc_bios;
917+
struct link_encoder *link_enc = link->link_enc;
918+
enum engine_id engine_id = link_enc->preferred_engine;
919+
enum dal_device_type device_type = DEVICE_TYPE_CRT;
920+
enum bp_result bp_result;
921+
uint32_t enum_id;
922+
923+
switch (engine_id) {
924+
case ENGINE_ID_DACB:
925+
enum_id = 2;
926+
break;
927+
case ENGINE_ID_DACA:
928+
default:
929+
engine_id = ENGINE_ID_DACA;
930+
enum_id = 1;
931+
break;
932+
}
933+
934+
bp_result = bios->funcs->dac_load_detection(bios, engine_id, device_type, enum_id);
935+
return bp_result == BP_RESULT_OK;
936+
}
937+
907938
/*
908939
* detect_link_and_local_sink() - Detect if a sink is attached to a given link
909940
*
@@ -1118,7 +1149,30 @@ static bool detect_link_and_local_sink(struct dc_link *link,
11181149
DC_LOG_ERROR("Partial EDID valid, abandon invalid blocks.\n");
11191150
break;
11201151
case EDID_NO_RESPONSE:
1152+
/* Analog connectors without EDID:
1153+
* - old monitor that actually doesn't have EDID
1154+
* - cheap DVI-A cable or adapter that doesn't connect DDC
1155+
*/
1156+
if (dc_connector_supports_analog(link->link_id.id)) {
1157+
/* If we didn't do DAC load detection yet, do it now
1158+
* to verify there really is a display connected.
1159+
*/
1160+
if (link->type != dc_connection_dac_load &&
1161+
!link_detect_dac_load_detect(link)) {
1162+
if (prev_sink)
1163+
dc_sink_release(prev_sink);
1164+
link_disconnect_sink(link);
1165+
return false;
1166+
}
1167+
1168+
DC_LOG_INFO("%s detected analog display without EDID\n", __func__);
1169+
link->type = dc_connection_dac_load;
1170+
sink->edid_caps.analog = true;
1171+
break;
1172+
}
1173+
11211174
DC_LOG_ERROR("No EDID read.\n");
1175+
11221176
/*
11231177
* Abort detection for non-DP connectors if we have
11241178
* no EDID
@@ -1307,6 +1361,11 @@ static bool link_detect_analog(struct dc_link *link, enum dc_connection_type *ty
13071361
return true;
13081362
}
13091363

1364+
if (link_detect_dac_load_detect(link)) {
1365+
*type = dc_connection_dac_load;
1366+
return true;
1367+
}
1368+
13101369
*type = dc_connection_none;
13111370
return true;
13121371
}
@@ -1328,7 +1387,7 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
13281387
}
13291388

13301389
/* Ignore the HPD pin (if any) for analog connectors.
1331-
* Instead rely on DDC.
1390+
* Instead rely on DDC and DAC.
13321391
*
13331392
* - VGA connectors don't have any HPD at all.
13341393
* - Some DVI-A cables don't connect the HPD pin.

0 commit comments

Comments
 (0)