]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Implement BIOS parser external encoder control
authorTimur Kristóf <timur.kristof@gmail.com>
Mon, 26 Jan 2026 21:08:29 +0000 (22:08 +0100)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 23 Feb 2026 19:28:32 +0000 (14:28 -0500)
The VBIOS has a function called ExternalEncoderControl which
controls the DP bridge encoders that some GPUs use for analog
and LVDS output. Fixup this old functionality.

For reference, see the legacy non-DC amdgpu display code:
amdgpu_atombios_encoder_setup_external_encoder()

- Set same parameters for the ENABLE action as the SETUP action
- Add missing enum values for DDC setup and DAC load detection
- Fix the bits per color field
- Clarify the code that sets the link rate
- Expose the function so that it can be called by rest of DC

A subsequent commit will call this function from DCE HWSS.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
drivers/gpu/drm/amd/display/dc/bios/command_table.c
drivers/gpu/drm/amd/display/dc/dc_bios_types.h
drivers/gpu/drm/amd/display/include/bios_parser_types.h

index 234a7f137cf5ade5b81d3ad35dc4d87bbcb21fc5..f947f82013c66616396d45eb4caac337c8b6e617 100644 (file)
@@ -780,6 +780,18 @@ static enum bp_result bios_parser_encoder_control(
        return bp->cmd_tbl.dig_encoder_control(bp, cntl);
 }
 
+static enum bp_result bios_parser_external_encoder_control(
+       struct dc_bios *dcb,
+       struct bp_external_encoder_control *cntl)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.external_encoder_control)
+               return BP_RESULT_UNSUPPORTED;
+
+       return bp->cmd_tbl.external_encoder_control(bp, cntl);
+}
+
 static enum bp_result bios_parser_dac_load_detection(
        struct dc_bios *dcb,
        enum engine_id engine_id)
@@ -2909,6 +2921,8 @@ static const struct dc_vbios_funcs vbios_funcs = {
 
        .encoder_control = bios_parser_encoder_control,
 
+       .external_encoder_control = bios_parser_external_encoder_control,
+
        .dac_load_detection = bios_parser_dac_load_detection,
 
        .transmitter_control = bios_parser_transmitter_control,
index fdc699b8c7a5621f6fc2cd259a1dd87fb431c1e8..f6e22dcecf29eec8bd159a8b0a9ebde8b0440279 100644 (file)
@@ -2520,6 +2520,7 @@ static enum bp_result external_encoder_control_v3(
                                cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
                break;
        case EXTERNAL_ENCODER_CONTROL_SETUP:
+       case EXTERNAL_ENCODER_CONTROL_ENABLE:
                /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
                 * 10KHz
                 * output display device pixel clock frequency in unit of 10KHz.
@@ -2536,26 +2537,24 @@ static enum bp_result external_encoder_control_v3(
                if (is_input_signal_dp) {
                        /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
                         * only valid in encoder setup with DP mode. */
-                       if (LINK_RATE_HIGH == cntl->link_rate)
-                               cntl_params->ucConfig |= 1;
+                       if (cntl->link_rate == LINK_RATE_LOW)
+                               cntl_params->ucConfig |=
+                                       EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ;
+                       else if (cntl->link_rate == LINK_RATE_HIGH)
+                               cntl_params->ucConfig |=
+                                       EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+                       else
+                               dm_error("Link rate not supported by external encoder");
+
                        /* output color depth Indicate encoder data bpc format
                         * in DP mode, only valid in encoder setup in DP mode.
                         */
-                       cntl_params->ucBitPerColor =
-                                       (uint8_t)(cntl->color_depth);
+                       cntl_params->ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth);
                }
                /* Indicate how many lanes used by external encoder, only valid
                 * in encoder setup and enableoutput. */
                cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
                break;
-       case EXTERNAL_ENCODER_CONTROL_ENABLE:
-               cntl_params->usPixelClock =
-                               cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
-               cntl_params->ucEncoderMode =
-                               (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
-                                               cntl->signal, false);
-               cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
-               break;
        default:
                break;
        }
index 06fdde281a0c3bdc3974ac3eaf450d89eb8b4ef8..6f96c5cf39fe8dc096cb20a6e91b9074ab77cb6b 100644 (file)
@@ -97,6 +97,9 @@ struct dc_vbios_funcs {
        enum bp_result (*encoder_control)(
                struct dc_bios *bios,
                struct bp_encoder_control *cntl);
+       enum bp_result (*external_encoder_control)(
+               struct dc_bios *bios,
+               struct bp_external_encoder_control *cntl);
        enum bp_result (*dac_load_detection)(
                struct dc_bios *bios,
                enum engine_id engine_id);
index f40dc612ec73b655507ff805db5bbe9aa3fe22a7..b5d97b394131b1a416c10551b7a112c2ea3d4df2 100644 (file)
@@ -93,6 +93,8 @@ enum bp_external_encoder_control_action {
        EXTERNAL_ENCODER_CONTROL_SETUP = 0xf,
        EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10,
        EXTERNAL_ENCODER_CONTROL_BLANK = 0x11,
+       EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12,
+       EXTERNAL_ENCODER_CONTROL_DDC_SETUP = 0x14,
 };
 
 enum bp_pipe_control_action {