drm/amd/display: Query DMCUB for dp alt status
[Why] To avoid hanging RDPCSPIPE when INTERCEPTB isn't set. DMCUB owns control of that bit so DMCUB should manage returning the information driver needs for link encoder control. [How] Add a new DMCUB command to return dp alt disable and dp4 information. Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com> Acked-by: Pavle Kotarac <Pavle.Kotarac@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
32b119c896
commit
41f91315b5
|
@ -67,6 +67,39 @@
|
|||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
static uint8_t phy_id_from_transmitter(enum transmitter t)
|
||||
{
|
||||
uint8_t phy_id;
|
||||
|
||||
switch (t) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
phy_id = 0;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
phy_id = 1;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
phy_id = 2;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
phy_id = 3;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
phy_id = 4;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_F:
|
||||
phy_id = 5;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_G:
|
||||
phy_id = 6;
|
||||
break;
|
||||
default:
|
||||
phy_id = 0;
|
||||
break;
|
||||
}
|
||||
return phy_id;
|
||||
}
|
||||
|
||||
void dcn31_link_encoder_set_dio_phy_mux(
|
||||
struct link_encoder *enc,
|
||||
enum encoder_type_select sel,
|
||||
|
@ -536,57 +569,45 @@ void dcn31_link_encoder_disable_output(
|
|||
bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
uint32_t dp_alt_mode_disable;
|
||||
struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
|
||||
union dmub_rb_cmd cmd;
|
||||
bool is_usb_c_alt_mode = false;
|
||||
|
||||
if (enc->features.flags.bits.DP_IS_USB_C) {
|
||||
if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) {
|
||||
// [Note] no need to check hw_internal_rev once phy mux selection is ready
|
||||
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
|
||||
} else {
|
||||
/*
|
||||
* B0 phys use a new set of registers to check whether alt mode is disabled.
|
||||
* if value == 1 alt mode is disabled, otherwise it is enabled.
|
||||
*/
|
||||
if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A)
|
||||
|| (enc10->base.transmitter == TRANSMITTER_UNIPHY_B)
|
||||
|| (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) {
|
||||
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
|
||||
} else {
|
||||
// [Note] need to change TRANSMITTER_UNIPHY_C/D to F/G once phy mux selection is ready
|
||||
REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
|
||||
}
|
||||
}
|
||||
if (enc->features.flags.bits.DP_IS_USB_C && dc_dmub_srv) {
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.query_dp_alt.header.type = DMUB_CMD__VBIOS;
|
||||
cmd.query_dp_alt.header.sub_type = DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT;
|
||||
cmd.query_dp_alt.header.payload_bytes = sizeof(cmd.panel_cntl.data);
|
||||
cmd.query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
|
||||
|
||||
is_usb_c_alt_mode = (dp_alt_mode_disable == 0);
|
||||
if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, &cmd))
|
||||
return false;
|
||||
|
||||
is_usb_c_alt_mode = (cmd.query_dp_alt.data.is_dp_alt_disable == 0);
|
||||
}
|
||||
|
||||
return is_usb_c_alt_mode;
|
||||
}
|
||||
|
||||
void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc,
|
||||
struct dc_link_settings *link_settings)
|
||||
void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
uint32_t is_in_usb_c_dp4_mode = 0;
|
||||
struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
|
||||
union dmub_rb_cmd cmd;
|
||||
|
||||
dcn10_link_encoder_get_max_link_cap(enc, link_settings);
|
||||
|
||||
/* in usb c dp2 mode, max lane count is 2 */
|
||||
if (enc->funcs->is_in_alt_mode && enc->funcs->is_in_alt_mode(enc)) {
|
||||
if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) {
|
||||
// [Note] no need to check hw_internal_rev once phy mux selection is ready
|
||||
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode);
|
||||
} else {
|
||||
if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A)
|
||||
|| (enc10->base.transmitter == TRANSMITTER_UNIPHY_B)
|
||||
|| (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) {
|
||||
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode);
|
||||
} else {
|
||||
REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode);
|
||||
}
|
||||
}
|
||||
if (!is_in_usb_c_dp4_mode)
|
||||
if (enc->features.flags.bits.DP_IS_USB_C && dc_dmub_srv) {
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.query_dp_alt.header.type = DMUB_CMD__VBIOS;
|
||||
cmd.query_dp_alt.header.sub_type = DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT;
|
||||
cmd.query_dp_alt.header.payload_bytes = sizeof(cmd.panel_cntl.data);
|
||||
cmd.query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
|
||||
|
||||
if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, &cmd))
|
||||
return;
|
||||
|
||||
if (cmd.query_dp_alt.data.is_usb && cmd.query_dp_alt.data.is_dp4 == 0)
|
||||
link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,14 @@ enum dmub_cmd_vbios_type {
|
|||
* Enables or disables power gating.
|
||||
*/
|
||||
DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING = 3,
|
||||
/**
|
||||
* Controls embedded panels.
|
||||
*/
|
||||
DMUB_CMD__VBIOS_LVTMA_CONTROL = 15,
|
||||
/**
|
||||
* Query DP alt status on a transmitter.
|
||||
*/
|
||||
DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT = 26,
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
@ -2393,6 +2400,24 @@ struct dmub_rb_cmd_lvtma_control {
|
|||
struct dmub_cmd_lvtma_control_data data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed in/out in a DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT command.
|
||||
*/
|
||||
struct dmub_rb_cmd_transmitter_query_dp_alt_data {
|
||||
uint8_t phy_id; /**< 0=UNIPHYA, 1=UNIPHYB, 2=UNIPHYC, 3=UNIPHYD, 4=UNIPHYE, 5=UNIPHYF */
|
||||
uint8_t is_usb; /**< is phy is usb */
|
||||
uint8_t is_dp_alt_disable; /**< is dp alt disable */
|
||||
uint8_t is_dp4; /**< is dp in 4 lane */
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT command.
|
||||
*/
|
||||
struct dmub_rb_cmd_transmitter_query_dp_alt {
|
||||
struct dmub_cmd_header header; /**< header */
|
||||
struct dmub_rb_cmd_transmitter_query_dp_alt_data data; /**< payload */
|
||||
};
|
||||
|
||||
/**
|
||||
* Maximum number of bytes a chunk sent to DMUB for parsing
|
||||
*/
|
||||
|
@ -2600,6 +2625,10 @@ union dmub_rb_cmd {
|
|||
* Definition of a DMUB_CMD__VBIOS_LVTMA_CONTROL command.
|
||||
*/
|
||||
struct dmub_rb_cmd_lvtma_control lvtma_control;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT command.
|
||||
*/
|
||||
struct dmub_rb_cmd_transmitter_query_dp_alt query_dp_alt;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__DPIA_DIG1_CONTROL command.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue