Skip to content

Commit 19e43f1

Browse files
Nicholas Kazlauskasalexdeucher
authored andcommitted
drm/amd/display: Add version check before using DP alt query interface
[Why] To maintain compatibility with firmware older than 4.0.11. Those firmware may have interrmittent hangs with RDCSPIPE or the PHY, but we shouldn't regress their previous behavior. [How] Use the new path if firmware is development or 4.0.11 or newer. Use the legacy path otherwise. Fixes: 41f9131 ("drm/amd/display: Query DMCUB for dp alt status") Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 214993e commit 19e43f1

1 file changed

Lines changed: 94 additions & 20 deletions

File tree

drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,35 @@ static uint8_t phy_id_from_transmitter(enum transmitter t)
100100
return phy_id;
101101
}
102102

103+
static bool has_query_dp_alt(struct link_encoder *enc)
104+
{
105+
struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
106+
107+
/* Supports development firmware and firmware >= 4.0.11 */
108+
return dc_dmub_srv &&
109+
!(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) &&
110+
dc_dmub_srv->dmub->fw_version <= DMUB_FW_VERSION(4, 0, 10));
111+
}
112+
113+
static bool query_dp_alt_from_dmub(struct link_encoder *enc,
114+
union dmub_rb_cmd *cmd)
115+
{
116+
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
117+
struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
118+
119+
memset(cmd, 0, sizeof(*cmd));
120+
cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS;
121+
cmd->query_dp_alt.header.sub_type =
122+
DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT;
123+
cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data);
124+
cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
125+
126+
if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, cmd))
127+
return false;
128+
129+
return true;
130+
}
131+
103132
void dcn31_link_encoder_set_dio_phy_mux(
104133
struct link_encoder *enc,
105134
enum encoder_type_select sel,
@@ -569,45 +598,90 @@ void dcn31_link_encoder_disable_output(
569598
bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc)
570599
{
571600
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
572-
struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
573601
union dmub_rb_cmd cmd;
574-
bool is_usb_c_alt_mode = false;
602+
uint32_t dp_alt_mode_disable;
575603

576-
if (enc->features.flags.bits.DP_IS_USB_C && dc_dmub_srv) {
577-
memset(&cmd, 0, sizeof(cmd));
578-
cmd.query_dp_alt.header.type = DMUB_CMD__VBIOS;
579-
cmd.query_dp_alt.header.sub_type = DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT;
580-
cmd.query_dp_alt.header.payload_bytes = sizeof(cmd.panel_cntl.data);
581-
cmd.query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
604+
/* Only applicable to USB-C PHY. */
605+
if (!enc->features.flags.bits.DP_IS_USB_C)
606+
return false;
582607

583-
if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, &cmd))
608+
/*
609+
* Use the new interface from DMCUB if available.
610+
* Avoids hanging the RDCPSPIPE if DMCUB wasn't already running.
611+
*/
612+
if (has_query_dp_alt(enc)) {
613+
if (!query_dp_alt_from_dmub(enc, &cmd))
584614
return false;
585615

586-
is_usb_c_alt_mode = (cmd.query_dp_alt.data.is_dp_alt_disable == 0);
616+
return (cmd.query_dp_alt.data.is_dp_alt_disable == 0);
587617
}
588618

589-
return is_usb_c_alt_mode;
619+
/* Legacy path, avoid if possible. */
620+
if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) {
621+
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE,
622+
&dp_alt_mode_disable);
623+
} else {
624+
/*
625+
* B0 phys use a new set of registers to check whether alt mode is disabled.
626+
* if value == 1 alt mode is disabled, otherwise it is enabled.
627+
*/
628+
if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) ||
629+
(enc10->base.transmitter == TRANSMITTER_UNIPHY_B) ||
630+
(enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) {
631+
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE,
632+
&dp_alt_mode_disable);
633+
} else {
634+
REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE,
635+
&dp_alt_mode_disable);
636+
}
637+
}
638+
639+
return (dp_alt_mode_disable == 0);
590640
}
591641

592642
void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings)
593643
{
594644
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
595-
struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
596645
union dmub_rb_cmd cmd;
646+
uint32_t is_in_usb_c_dp4_mode = 0;
597647

598648
dcn10_link_encoder_get_max_link_cap(enc, link_settings);
599649

600-
if (enc->features.flags.bits.DP_IS_USB_C && dc_dmub_srv) {
601-
memset(&cmd, 0, sizeof(cmd));
602-
cmd.query_dp_alt.header.type = DMUB_CMD__VBIOS;
603-
cmd.query_dp_alt.header.sub_type = DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT;
604-
cmd.query_dp_alt.header.payload_bytes = sizeof(cmd.panel_cntl.data);
605-
cmd.query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
650+
/* Take the link cap directly if not USB */
651+
if (!enc->features.flags.bits.DP_IS_USB_C)
652+
return;
606653

607-
if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, &cmd))
654+
/*
655+
* Use the new interface from DMCUB if available.
656+
* Avoids hanging the RDCPSPIPE if DMCUB wasn't already running.
657+
*/
658+
if (has_query_dp_alt(enc)) {
659+
if (!query_dp_alt_from_dmub(enc, &cmd))
608660
return;
609661

610-
if (cmd.query_dp_alt.data.is_usb && cmd.query_dp_alt.data.is_dp4 == 0)
662+
if (cmd.query_dp_alt.data.is_usb &&
663+
cmd.query_dp_alt.data.is_dp4 == 0)
611664
link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
665+
666+
return;
612667
}
668+
669+
/* Legacy path, avoid if possible. */
670+
if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) {
671+
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4,
672+
&is_in_usb_c_dp4_mode);
673+
} else {
674+
if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) ||
675+
(enc10->base.transmitter == TRANSMITTER_UNIPHY_B) ||
676+
(enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) {
677+
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4,
678+
&is_in_usb_c_dp4_mode);
679+
} else {
680+
REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4,
681+
&is_in_usb_c_dp4_mode);
682+
}
683+
}
684+
685+
if (!is_in_usb_c_dp4_mode)
686+
link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
613687
}

0 commit comments

Comments
 (0)