Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amd/display: Restore analog connector support

[Why]
The analog connector support was accidentally removed,
causing a crash when connecting an analog monitor.

[How]
This patch restores the functions and pointers required for proper analog
and DP bridge encoder support on legacy GPUs.

V2: Restore the external encoder control functions.

V3:
- Restore BIOS parser external encoder DAC load detection
- Restore stream initialization and source selection changes

Fixes: e56e3cff2a1b ("drm/amd/display: Sync dcn42 with DC 3.2.373")
Cc: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Roman Li <Roman.Li@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit cea8349e4494d2892ea57eef3fe4a8987464a876)

authored by

Roman Li and committed by
Alex Deucher
4867cef0 095a8b0a

+71 -37
+10 -1
drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
··· 794 794 795 795 static enum bp_result bios_parser_dac_load_detection( 796 796 struct dc_bios *dcb, 797 - enum engine_id engine_id) 797 + enum engine_id engine_id, 798 + struct graphics_object_id ext_enc_id) 798 799 { 799 800 struct bios_parser *bp = BP_FROM_DCB(dcb); 800 801 struct dc_context *ctx = dcb->ctx; 801 802 struct bp_load_detection_parameters bp_params = {0}; 803 + struct bp_external_encoder_control ext_cntl = {0}; 802 804 enum bp_result bp_result = BP_RESULT_UNSUPPORTED; 803 805 uint32_t bios_0_scratch; 804 806 uint32_t device_id_mask = 0; ··· 826 824 827 825 bp_params.engine_id = engine_id; 828 826 bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); 827 + } else if (ext_enc_id.id) { 828 + if (!bp->cmd_tbl.external_encoder_control) 829 + return BP_RESULT_UNSUPPORTED; 830 + 831 + ext_cntl.action = EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT; 832 + ext_cntl.encoder_id = ext_enc_id; 833 + bp_result = bp->cmd_tbl.external_encoder_control(bp, &ext_cntl); 829 834 } 830 835 831 836 if (bp_result != BP_RESULT_OK)
+2 -1
drivers/gpu/drm/amd/display/dc/dc_bios_types.h
··· 102 102 struct bp_external_encoder_control *cntl); 103 103 enum bp_result (*dac_load_detection)( 104 104 struct dc_bios *bios, 105 - enum engine_id engine_id); 105 + enum engine_id engine_id, 106 + struct graphics_object_id ext_enc_id); 106 107 enum bp_result (*transmitter_control)( 107 108 struct dc_bios *bios, 108 109 struct bp_transmitter_control *cntl);
+59 -35
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
··· 665 665 } 666 666 667 667 static void 668 - dce110_dac_encoder_control(struct pipe_ctx *pipe_ctx, bool enable) 668 + dce110_external_encoder_control(enum bp_external_encoder_control_action action, 669 + struct dc_link *link, 670 + struct dc_crtc_timing *timing) 669 671 { 670 - struct dc_link *link = pipe_ctx->stream->link; 672 + struct dc *dc = link->ctx->dc; 671 673 struct dc_bios *bios = link->ctx->dc_bios; 672 - struct bp_encoder_control encoder_control = {0}; 674 + const struct dc_link_settings *link_settings = &link->cur_link_settings; 675 + enum bp_result bp_result = BP_RESULT_OK; 676 + struct bp_external_encoder_control ext_cntl = { 677 + .action = action, 678 + .connector_obj_id = link->link_enc->connector, 679 + .encoder_id = link->ext_enc_id, 680 + .lanes_number = link_settings->lane_count, 681 + .link_rate = link_settings->link_rate, 673 682 674 - encoder_control.action = enable ? ENCODER_CONTROL_ENABLE : ENCODER_CONTROL_DISABLE; 675 - encoder_control.engine_id = link->link_enc->analog_engine; 676 - encoder_control.pixel_clock = pipe_ctx->stream->timing.pix_clk_100hz / 10; 677 - bios->funcs->encoder_control(bios, &encoder_control); 683 + /* Use signal type of the real link encoder, ie. DP */ 684 + .signal = link->connector_signal, 685 + 686 + /* We don't know the timing yet when executing the SETUP action, 687 + * so use a reasonably high default value. It seems that ENABLE 688 + * can change the actual pixel clock but doesn't work with higher 689 + * pixel clocks than what SETUP was called with. 690 + */ 691 + .pixel_clock = timing ? timing->pix_clk_100hz / 10 : 300000, 692 + .color_depth = timing ? timing->display_color_depth : COLOR_DEPTH_888, 693 + }; 694 + DC_LOGGER_INIT(dc->ctx); 695 + 696 + bp_result = bios->funcs->external_encoder_control(bios, &ext_cntl); 697 + 698 + if (bp_result != BP_RESULT_OK) 699 + DC_LOG_ERROR("Failed to execute external encoder action: 0x%x\n", action); 700 + } 701 + 702 + static void 703 + dce110_prepare_ddc(struct dc_link *link) 704 + { 705 + if (link->ext_enc_id.id) 706 + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_DDC_SETUP, link, NULL); 678 707 } 679 708 680 709 static bool ··· 713 684 struct link_encoder *link_enc = link->link_enc; 714 685 enum bp_result bp_result; 715 686 716 - bp_result = bios->funcs->dac_load_detection(bios, link_enc->analog_engine); 687 + bp_result = bios->funcs->dac_load_detection( 688 + bios, link_enc->analog_engine, link->ext_enc_id); 717 689 return bp_result == BP_RESULT_OK; 718 690 } 719 691 ··· 730 700 uint32_t early_control = 0; 731 701 struct timing_generator *tg = pipe_ctx->stream_res.tg; 732 702 733 - link_hwss->setup_stream_attribute(pipe_ctx); 734 703 link_hwss->setup_stream_encoder(pipe_ctx); 735 704 736 705 dc->hwss.update_info_frame(pipe_ctx); ··· 748 719 749 720 tg->funcs->set_early_control(tg, early_control); 750 721 751 - if (dc_is_rgb_signal(pipe_ctx->stream->signal)) 752 - dce110_dac_encoder_control(pipe_ctx, true); 722 + if (link->ext_enc_id.id) 723 + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_ENABLE, link, timing); 753 724 } 754 725 755 726 static enum bp_result link_transmitter_control( ··· 1248 1219 link_enc->transmitter - TRANSMITTER_UNIPHY_A); 1249 1220 } 1250 1221 1251 - if (dc_is_rgb_signal(pipe_ctx->stream->signal)) 1252 - dce110_dac_encoder_control(pipe_ctx, false); 1222 + if (link->ext_enc_id.id) 1223 + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_DISABLE, link, NULL); 1253 1224 } 1254 1225 1255 1226 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, ··· 1632 1603 1633 1604 return DC_OK; 1634 1605 } 1635 - static void 1636 - dce110_select_crtc_source(struct pipe_ctx *pipe_ctx) 1637 - { 1638 - struct dc_link *link = pipe_ctx->stream->link; 1639 - struct dc_bios *bios = link->ctx->dc_bios; 1640 - struct bp_crtc_source_select crtc_source_select = {0}; 1641 - enum engine_id engine_id = link->link_enc->preferred_engine; 1642 - 1643 - if (dc_is_rgb_signal(pipe_ctx->stream->signal)) 1644 - engine_id = link->link_enc->analog_engine; 1645 - crtc_source_select.controller_id = CONTROLLER_ID_D0 + pipe_ctx->stream_res.tg->inst; 1646 - crtc_source_select.color_depth = pipe_ctx->stream->timing.display_color_depth; 1647 - crtc_source_select.engine_id = engine_id; 1648 - crtc_source_select.sink_signal = pipe_ctx->stream->signal; 1649 - bios->funcs->select_crtc_source(bios, &crtc_source_select); 1650 - } 1651 1606 1652 1607 enum dc_status dce110_apply_single_controller_ctx_to_hw( 1653 1608 struct pipe_ctx *pipe_ctx, ··· 1650 1637 1651 1638 if (hws->funcs.disable_stream_gating) { 1652 1639 hws->funcs.disable_stream_gating(dc, pipe_ctx); 1653 - } 1654 - 1655 - if (pipe_ctx->stream->signal == SIGNAL_TYPE_RGB) { 1656 - dce110_select_crtc_source(pipe_ctx); 1657 1640 } 1658 1641 1659 1642 if (pipe_ctx->stream_res.audio != NULL) { ··· 1731 1722 pipe_ctx->stream_res.tg->funcs->set_static_screen_control( 1732 1723 pipe_ctx->stream_res.tg, event_triggers, 2); 1733 1724 1734 - if (!dc_is_virtual_signal(pipe_ctx->stream->signal) && 1735 - !dc_is_rgb_signal(pipe_ctx->stream->signal)) 1725 + if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) 1736 1726 pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( 1737 1727 pipe_ctx->stream_res.stream_enc, 1738 1728 pipe_ctx->stream_res.tg->inst); ··· 3384 3376 link->phy_state.symclk_state = SYMCLK_ON_TX_ON; 3385 3377 } 3386 3378 3379 + static void dce110_enable_analog_link_output( 3380 + struct dc_link *link, 3381 + uint32_t pix_clk_100hz) 3382 + { 3383 + link->link_enc->funcs->enable_analog_output( 3384 + link->link_enc, 3385 + pix_clk_100hz); 3386 + } 3387 + 3387 3388 void dce110_enable_dp_link_output( 3388 3389 struct dc_link *link, 3389 3390 const struct link_resource *link_res, ··· 3438 3421 &pipes[i].pll_settings); 3439 3422 } 3440 3423 } 3424 + } 3425 + 3426 + if (link->ext_enc_id.id) { 3427 + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_INIT, link, NULL); 3428 + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_SETUP, link, NULL); 3441 3429 } 3442 3430 3443 3431 if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { ··· 3535 3513 .enable_lvds_link_output = dce110_enable_lvds_link_output, 3536 3514 .enable_tmds_link_output = dce110_enable_tmds_link_output, 3537 3515 .enable_dp_link_output = dce110_enable_dp_link_output, 3516 + .enable_analog_link_output = dce110_enable_analog_link_output, 3538 3517 .disable_link_output = dce110_disable_link_output, 3539 3518 .dac_load_detect = dce110_dac_load_detect, 3519 + .prepare_ddc = dce110_prepare_ddc, 3540 3520 }; 3541 3521 3542 3522 static const struct hwseq_private_funcs dce110_private_funcs = {