DAC_LoadDetection can be used to determine whether something
is connected to an analog connector, primarily when the connected
display doesn't have an EDID.

As a reference, I used the following function:
amdgpu_atombios_encoder_dac_load_detect

Signed-off-by: Timur Kristóf <timur.kris...@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 44f71757508f..58a7f6012936 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -783,6 +783,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;
+
+       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;
+
+       /* BIOS will write the detected devices to BIOS_SCRATCH_0, clear the 
register */
+       dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, 0);
+
+       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);
+
+       switch (bp_params.device_id) {
+       case ATOM_DEVICE_CRT1_SUPPORT:
+               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+                       return BP_RESULT_OK;
+               break;
+       case ATOM_DEVICE_CRT2_SUPPORT:
+               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+                       return BP_RESULT_OK;
+               break;
+       default:
+               break;
+       }
+
+       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)
@@ -2867,6 +2915,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 8983220d2a4b..7899e952b68a 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.50.1

Reply via email to