AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Timur Kristóf" <timur.kristof@gmail.com>
To: amd-gfx@lists.freedesktop.org
Cc: alexander.deucher@amd.com, alex.hung@amd.com,
	harry.wentland@amd.com, siqueira@igalia.com,
	christian.koenig@amd.com,
	"Timur Kristóf" <timur.kristof@gmail.com>
Subject: [PATCH 19/23] drm/amd/display: Add DAC_LoadDetection to BIOS parser (v2)
Date: Fri, 26 Sep 2025 20:01:59 +0200	[thread overview]
Message-ID: <20250926180203.16690-20-timur.kristof@gmail.com> (raw)
In-Reply-To: <20250926180203.16690-1-timur.kristof@gmail.com>

DAC_LoadDetection can be used to determine whether something
is connected to an analog connector by determining if there is
an analog load. This causes visible flickering on displays, so
we only resort to using this when the connected display doesn't
have an EDID.

For reference, see the legacy display code:
amdgpu_atombios_encoder_dac_load_detect

v2:
Only clear corresponding bit from BIOS_SCRATCH_0.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 .../gpu/drm/amd/display/dc/bios/bios_parser.c | 50 ++++++++++
 .../drm/amd/display/dc/bios/command_table.c   | 92 +++++++++++++++++++
 .../drm/amd/display/dc/bios/command_table.h   |  3 +
 .../gpu/drm/amd/display/dc/dc_bios_types.h    |  5 +
 .../amd/display/include/bios_parser_types.h   |  5 +
 5 files changed, 155 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
index a126ca3a53fb..4120d6c4c5e4 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -780,6 +780,54 @@ static enum bp_result bios_parser_encoder_control(
 	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
 }
 
+static enum bp_result bios_parser_dac_load_detection(
+	struct dc_bios *dcb,
+	enum engine_id engine_id,
+	enum dal_device_type device_type,
+	uint32_t enum_id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct dc_context *ctx = dcb->ctx;
+	struct bp_load_detection_parameters bp_params = {0};
+	enum bp_result bp_result;
+	uint32_t bios_0_scratch;
+	uint32_t device_id_mask = 0;
+
+	bp_params.engine_id = engine_id;
+	bp_params.device_id = get_support_mask_for_device_id(device_type, enum_id);
+
+	if (engine_id != ENGINE_ID_DACA &&
+	    engine_id != ENGINE_ID_DACB)
+		return BP_RESULT_UNSUPPORTED;
+
+	if (!bp->cmd_tbl.dac_load_detection)
+		return BP_RESULT_UNSUPPORTED;
+
+	if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT)
+		device_id_mask = ATOM_S0_CRT1_MASK;
+	else if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT)
+		device_id_mask = ATOM_S0_CRT2_MASK;
+	else
+		return BP_RESULT_UNSUPPORTED;
+
+	/* BIOS will write the detected devices to BIOS_SCRATCH_0, clear corresponding bit */
+	bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0);
+	bios_0_scratch &= ~device_id_mask;
+	dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch);
+
+	bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params);
+
+	if (bp_result != BP_RESULT_OK)
+		return bp_result;
+
+	bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0);
+
+	if (bios_0_scratch & device_id_mask)
+		return BP_RESULT_OK;
+
+	return BP_RESULT_FAILURE;
+}
+
 static enum bp_result bios_parser_adjust_pixel_clock(
 	struct dc_bios *dcb,
 	struct bp_adjust_pixel_clock_parameters *bp_params)
@@ -2864,6 +2912,8 @@ static const struct dc_vbios_funcs vbios_funcs = {
 
 	.encoder_control = bios_parser_encoder_control,
 
+	.dac_load_detection = bios_parser_dac_load_detection,
+
 	.transmitter_control = bios_parser_transmitter_control,
 
 	.enable_crtc = bios_parser_enable_crtc,
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
index dbd84477ceb7..22457f417e65 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
@@ -54,6 +54,7 @@ static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
 static void init_adjust_display_pll(struct bios_parser *bp);
 static void init_select_crtc_source(struct bios_parser *bp);
 static void init_dac_encoder_control(struct bios_parser *bp);
+static void init_dac_load_detection(struct bios_parser *bp);
 static void init_dac_output_control(struct bios_parser *bp);
 static void init_set_crtc_timing(struct bios_parser *bp);
 static void init_enable_crtc(struct bios_parser *bp);
@@ -72,6 +73,7 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
 	init_adjust_display_pll(bp);
 	init_select_crtc_source(bp);
 	init_dac_encoder_control(bp);
+	init_dac_load_detection(bp);
 	init_dac_output_control(bp);
 	init_set_crtc_timing(bp);
 	init_enable_crtc(bp);
@@ -1902,6 +1904,96 @@ static enum bp_result dac2_encoder_control_v1(
 	return result;
 }
 
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC LOAD DETECTION
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result dac_load_detection_v1(
+	struct bios_parser *bp,
+	struct bp_load_detection_parameters *bp_params);
+
+static enum bp_result dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct bp_load_detection_parameters *bp_params);
+
+static void init_dac_load_detection(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) {
+	case 1:
+	case 2:
+		bp->cmd_tbl.dac_load_detection = dac_load_detection_v1;
+		break;
+	case 3:
+	default:
+		bp->cmd_tbl.dac_load_detection = dac_load_detection_v3;
+		break;
+	}
+}
+
+static void dac_load_detect_prepare_params(
+	struct _DAC_LOAD_DETECTION_PS_ALLOCATION *params,
+	enum engine_id engine_id,
+	uint16_t device_id,
+	uint8_t misc)
+{
+	uint8_t dac_type = ENGINE_ID_DACA;
+
+	if (engine_id == ENGINE_ID_DACB)
+		dac_type = ATOM_DAC_B;
+
+	params->sDacload.usDeviceID = cpu_to_le16(device_id);
+	params->sDacload.ucDacType = dac_type;
+	params->sDacload.ucMisc = misc;
+}
+
+static enum bp_result dac_load_detection_v1(
+	struct bios_parser *bp,
+	struct bp_load_detection_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_LOAD_DETECTION_PS_ALLOCATION params;
+
+	dac_load_detect_prepare_params(
+		&params,
+		bp_params->engine_id,
+		bp_params->device_id,
+		0);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct bp_load_detection_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_LOAD_DETECTION_PS_ALLOCATION params;
+
+	uint8_t misc = 0;
+
+	if (bp_params->device_id == ATOM_DEVICE_CV_SUPPORT ||
+	    bp_params->device_id == ATOM_DEVICE_TV1_SUPPORT)
+		misc = DAC_LOAD_MISC_YPrPb;
+
+	dac_load_detect_prepare_params(
+		&params,
+		bp_params->engine_id,
+		bp_params->device_id,
+		misc);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
 /*******************************************************************************
  ********************************************************************************
  **
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h
index 8b04b903e93d..e89b1ba0048b 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h
@@ -71,6 +71,9 @@ struct cmd_tbl {
 	enum bp_result (*dac2_output_control)(
 		struct bios_parser *bp,
 		bool enable);
+	enum bp_result (*dac_load_detection)(
+		struct bios_parser *bp,
+		struct bp_load_detection_parameters *bp_params);
 	enum bp_result (*set_crtc_timing)(
 		struct bios_parser *bp,
 		struct bp_hw_crtc_timing_parameters *bp_params);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
index 50c8906b74c5..40d7a7d83c40 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
@@ -97,6 +97,11 @@ struct dc_vbios_funcs {
 	enum bp_result (*encoder_control)(
 		struct dc_bios *bios,
 		struct bp_encoder_control *cntl);
+	enum bp_result (*dac_load_detection)(
+		struct dc_bios *bios,
+		enum engine_id engine_id,
+		enum dal_device_type device_type,
+		uint32_t enum_id);
 	enum bp_result (*transmitter_control)(
 		struct dc_bios *bios,
 		struct bp_transmitter_control *cntl);
diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
index d9e58a6a0d36..973b6bdbac63 100644
--- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h
+++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
@@ -162,6 +162,11 @@ struct bp_transmitter_control {
 	bool single_pll_mode;
 };
 
+struct bp_load_detection_parameters {
+	enum engine_id engine_id;
+	uint16_t device_id;
+};
+
 struct bp_hw_crtc_timing_parameters {
 	enum controller_id controller_id;
 	/* horizontal part */
-- 
2.51.0


  parent reply	other threads:[~2025-09-26 18:03 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-26 18:01 [PATCH 00/23] Analog connector support in DC (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 01/23] drm/amd/display: Determine DVI-I connector type (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 02/23] drm/amd/display: Add analog bit to edid_caps (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 03/23] drm/amd/display: Introduce MAX_LINK_ENCODERS (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 04/23] drm/amd/display: Hook up DAC to bios_parser_encoder_control Timur Kristóf
2025-09-26 18:01 ` [PATCH 05/23] drm/amd/display: Add SelectCRTC_Source to BIOS parser Timur Kristóf
2025-09-26 18:01 ` [PATCH 06/23] drm/amd/display: Get maximum pixel clock from VBIOS Timur Kristóf
2025-09-26 18:01 ` [PATCH 07/23] drm/amd/display: Don't use stereo sync and audio on RGB signals (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 08/23] drm/amd/display: Don't try to enable/disable HPD when unavailable Timur Kristóf
2025-09-26 18:01 ` [PATCH 09/23] drm/amd/display: Determine early if a link has supported encoders (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 10/23] drm/amd/display: Add concept of analog " Timur Kristóf
2025-09-26 18:01 ` [PATCH 11/23] drm/amd/display: Implement DCE analog stream encoders Timur Kristóf
2025-09-26 18:01 ` [PATCH 12/23] drm/amd/display: Implement DCE analog link encoders (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 13/23] drm/amd/display: Support DAC in dce110_hwseq Timur Kristóf
2025-10-08 21:01   ` Harry Wentland
2025-09-26 18:01 ` [PATCH 14/23] drm/amd/display: Add analog link detection (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 15/23] drm/amd/display: Refactor amdgpu_dm_connector_detect (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 16/23] drm/amd/display: Poll analog connectors (v2) Timur Kristóf
2025-09-26 18:01 ` [PATCH 17/23] drm/amd/display: Add DCE BIOS_SCRATCH_0 register Timur Kristóf
2025-09-26 18:01 ` [PATCH 18/23] drm/amd/display: Make get_support_mask_for_device_id reusable Timur Kristóf
2025-09-26 18:01 ` Timur Kristóf [this message]
2025-09-26 18:02 ` [PATCH 20/23] drm/amd/display: Use DAC load detection on analog connectors (v2) Timur Kristóf
2025-09-26 18:02 ` [PATCH 21/23] drm/amd/display: Add common modes to analog displays without EDID Timur Kristóf
2025-09-26 18:02 ` [PATCH 22/23] drm/amd/display: Don't add freesync modes to analog displays (v2) Timur Kristóf
2025-09-26 18:02 ` [PATCH 23/23] drm/amdgpu: Use DC by default for Bonaire Timur Kristóf
2025-10-08 21:11 ` [PATCH 00/23] Analog connector support in DC (v2) Harry Wentland
2025-10-09 17:26   ` Harry Wentland
2025-10-09 17:49     ` Wheeler, Daniel
2025-10-09 18:27       ` Harry Wentland
2025-10-21 16:15         ` Timur Kristóf
2025-10-21 16:44           ` Alex Deucher
2025-10-21 17:32           ` Wheeler, Daniel
2025-10-24 19:07             ` timur.kristof
2025-10-24 21:28               ` Wheeler, Daniel
2025-10-31  8:19                 ` Timur Kristóf
2025-10-31 13:07                   ` Wheeler, Daniel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250926180203.16690-20-timur.kristof@gmail.com \
    --to=timur.kristof@gmail.com \
    --cc=alex.hung@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=christian.koenig@amd.com \
    --cc=harry.wentland@amd.com \
    --cc=siqueira@igalia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox