drm/amd/display: determine USB C DP2 mode only when USB DP Alt is enabled

[why]
When display is connected with a native DP port, DP2 mode register value
is a don't care. Driver mistakenly reduce max supported lane count to 2
lane based on the don't care value.

[how]
Add additional check only if USB C DP alt mode is enabled, we will
determine max lane count supported based on current mode.

Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Wenjing Liu 2020-04-05 16:41:13 -04:00 committed by Alex Deucher
parent 4404b47852
commit 8ccf0e2076
10 changed files with 101 additions and 64 deletions

View File

@ -682,7 +682,7 @@ static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
new_edid->raw_edid, new_edid->length) == 0);
}
static bool wait_for_alt_mode(struct dc_link *link)
static bool wait_for_entering_dp_alt_mode(struct dc_link *link)
{
/**
* something is terribly wrong if time out is > 200ms. (5Hz)
@ -836,7 +836,7 @@ static bool dc_link_detect_helper(struct dc_link *link,
/* wa HPD high coming too early*/
if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
/* if alt mode times out, return false */
if (!wait_for_alt_mode(link))
if (!wait_for_entering_dp_alt_mode(link))
return false;
}

View File

@ -1710,19 +1710,10 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
static struct dc_link_settings get_max_link_cap(struct dc_link *link)
{
/* Set Default link settings */
struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
struct dc_link_settings max_link_cap = {0};
/* Higher link settings based on feature supported */
if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH2;
if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH3;
if (link->link_enc->funcs->get_max_link_cap)
link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
/* get max link encoder capability */
link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
/* Lower link settings based on sink's link cap */
if (link->reported_link_cap.lane_count < max_link_cap.lane_count)

View File

@ -118,7 +118,8 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
.enable_hpd = dce110_link_encoder_enable_hpd,
.disable_hpd = dce110_link_encoder_disable_hpd,
.is_dig_enabled = dce110_is_dig_enabled,
.destroy = dce110_link_encoder_destroy
.destroy = dce110_link_encoder_destroy,
.get_max_link_cap = dce110_link_encoder_get_max_link_cap
};
static enum bp_result link_transmitter_control(
@ -1389,3 +1390,20 @@ void dce110_link_encoder_disable_hpd(struct link_encoder *enc)
set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN);
}
void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings)
{
/* Set Default link settings */
struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
/* Higher link settings based on feature supported */
if (enc->features.flags.bits.IS_HBR2_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH2;
if (enc->features.flags.bits.IS_HBR3_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH3;
*link_settings = max_link_cap;
}

View File

@ -271,4 +271,7 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc,
bool dce110_is_dig_enabled(struct link_encoder *enc);
void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
#endif /* __DC_LINK_ENCODER__DCE110_H__ */

View File

@ -90,7 +90,8 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = {
.is_dig_enabled = dcn10_is_dig_enabled,
.get_dig_frontend = dcn10_get_dig_frontend,
.get_dig_mode = dcn10_get_dig_mode,
.destroy = dcn10_link_encoder_destroy
.destroy = dcn10_link_encoder_destroy,
.get_max_link_cap = dcn10_link_encoder_get_max_link_cap,
};
static enum bp_result link_transmitter_control(
@ -1370,7 +1371,6 @@ void dcn10_link_encoder_disable_hpd(struct link_encoder *enc)
DC_HPD_EN, 0);
}
#define AUX_REG(reg)\
(enc10->aux_regs->reg)
@ -1425,3 +1425,19 @@ enum signal_type dcn10_get_dig_mode(
return SIGNAL_TYPE_NONE;
}
void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings)
{
/* Set Default link settings */
struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
/* Higher link settings based on feature supported */
if (enc->features.flags.bits.IS_HBR2_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH2;
if (enc->features.flags.bits.IS_HBR3_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH3;
*link_settings = max_link_cap;
}

View File

@ -575,4 +575,7 @@ void dcn10_aux_initialize(struct dcn10_link_encoder *enc10);
enum signal_type dcn10_get_dig_mode(
struct link_encoder *enc);
void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
#endif /* __DC_LINK_ENCODER__DCN10_H__ */

View File

@ -49,6 +49,12 @@
#define IND_REG(index) \
(enc10->link_regs->index)
#ifndef MAX
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#endif
#ifndef MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#endif
static struct mpll_cfg dcn2_mpll_cfg[] = {
// RBR
@ -260,6 +266,38 @@ void dcn20_link_encoder_enable_dp_output(
}
void dcn20_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;
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)) {
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode);
if (!is_in_usb_c_dp4_mode)
link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
}
}
bool dcn20_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 = 0;
bool is_usb_c_alt_mode = false;
if (enc->features.flags.bits.DP_IS_USB_C) {
/* if value == 1 alt mode is disabled, otherwise it is enabled */
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
is_usb_c_alt_mode = (dp_alt_mode_disable == 0);
}
return is_usb_c_alt_mode;
}
#define AUX_REG(reg)\
(enc10->aux_regs->reg)
@ -311,28 +349,6 @@ void enc2_hw_init(struct link_encoder *enc)
dcn10_aux_initialize(enc10);
}
void dcn20_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 value;
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &value);
if (!value && link_settings->lane_count > LANE_COUNT_TWO)
link_settings->lane_count = LANE_COUNT_TWO;
}
bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
uint32_t value;
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &value);
// if value == 1 alt mode is disabled, otherwise it is enabled
return !value;
}
static const struct link_encoder_funcs dcn20_link_enc_funcs = {
.read_state = link_enc2_read_state,
.validate_output_with_stream =

View File

@ -343,6 +343,10 @@ void dcn20_link_encoder_enable_dp_output(
const struct dc_link_settings *link_settings,
enum clock_source_id clock_source);
bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc);
void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
void dcn20_link_encoder_construct(
struct dcn20_link_encoder *enc20,
const struct encoder_init_data *init_data,

View File

@ -203,29 +203,6 @@ static bool update_cfg_data(
return true;
}
void dcn21_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 value;
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &value);
if (!value && link_settings->lane_count > LANE_COUNT_TWO)
link_settings->lane_count = LANE_COUNT_TWO;
}
bool dcn21_link_encoder_is_in_alt_mode(struct link_encoder *enc)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
uint32_t value;
REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &value);
// if value == 1 alt mode is disabled, otherwise it is enabled
return !value;
}
bool dcn21_link_encoder_acquire_phy(struct link_encoder *enc)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
@ -348,8 +325,8 @@ static const struct link_encoder_funcs dcn21_link_enc_funcs = {
.fec_set_ready = enc2_fec_set_ready,
.fec_is_active = enc2_fec_is_active,
.get_dig_frontend = dcn10_get_dig_frontend,
.is_in_alt_mode = dcn21_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn21_link_encoder_get_max_link_cap,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
};
void dcn21_link_encoder_construct(

View File

@ -84,6 +84,14 @@ static void virtual_link_encoder_destroy(struct link_encoder **enc)
*enc = NULL;
}
static void virtual_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings)
{
/* Set Default link settings */
struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
*link_settings = max_link_cap;
}
static const struct link_encoder_funcs virtual_lnk_enc_funcs = {
.validate_output_with_stream =
@ -94,6 +102,7 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = {
.enable_dp_output = virtual_link_encoder_enable_dp_output,
.enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output,
.disable_output = virtual_link_encoder_disable_output,
.get_max_link_cap = virtual_link_encoder_get_max_link_cap,
.dp_set_lane_settings = virtual_link_encoder_dp_set_lane_settings,
.dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern,
.update_mst_stream_allocation_table =