Commit 8ccf0e20 authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher

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: default avatarWenjing Liu <wenjing.liu@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4404b478
...@@ -682,7 +682,7 @@ static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid) ...@@ -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); 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) * something is terribly wrong if time out is > 200ms. (5Hz)
...@@ -836,7 +836,7 @@ static bool dc_link_detect_helper(struct dc_link *link, ...@@ -836,7 +836,7 @@ static bool dc_link_detect_helper(struct dc_link *link,
/* wa HPD high coming too early*/ /* wa HPD high coming too early*/
if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) { if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
/* if alt mode times out, return false */ /* if alt mode times out, return false */
if (!wait_for_alt_mode(link)) if (!wait_for_entering_dp_alt_mode(link))
return false; return false;
} }
......
...@@ -1710,19 +1710,10 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) ...@@ -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) static struct dc_link_settings get_max_link_cap(struct dc_link *link)
{ {
/* Set Default link settings */ struct dc_link_settings max_link_cap = {0};
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 (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) /* get max link encoder capability */
link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap); link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
/* Lower link settings based on sink's link cap */ /* Lower link settings based on sink's link cap */
if (link->reported_link_cap.lane_count < max_link_cap.lane_count) if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
......
...@@ -118,7 +118,8 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { ...@@ -118,7 +118,8 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
.enable_hpd = dce110_link_encoder_enable_hpd, .enable_hpd = dce110_link_encoder_enable_hpd,
.disable_hpd = dce110_link_encoder_disable_hpd, .disable_hpd = dce110_link_encoder_disable_hpd,
.is_dig_enabled = dce110_is_dig_enabled, .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( static enum bp_result link_transmitter_control(
...@@ -1389,3 +1390,20 @@ void dce110_link_encoder_disable_hpd(struct link_encoder *enc) ...@@ -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); 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;
}
...@@ -271,4 +271,7 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc, ...@@ -271,4 +271,7 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc,
bool dce110_is_dig_enabled(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__ */ #endif /* __DC_LINK_ENCODER__DCE110_H__ */
...@@ -90,7 +90,8 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { ...@@ -90,7 +90,8 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = {
.is_dig_enabled = dcn10_is_dig_enabled, .is_dig_enabled = dcn10_is_dig_enabled,
.get_dig_frontend = dcn10_get_dig_frontend, .get_dig_frontend = dcn10_get_dig_frontend,
.get_dig_mode = dcn10_get_dig_mode, .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( static enum bp_result link_transmitter_control(
...@@ -1370,7 +1371,6 @@ void dcn10_link_encoder_disable_hpd(struct link_encoder *enc) ...@@ -1370,7 +1371,6 @@ void dcn10_link_encoder_disable_hpd(struct link_encoder *enc)
DC_HPD_EN, 0); DC_HPD_EN, 0);
} }
#define AUX_REG(reg)\ #define AUX_REG(reg)\
(enc10->aux_regs->reg) (enc10->aux_regs->reg)
...@@ -1425,3 +1425,19 @@ enum signal_type dcn10_get_dig_mode( ...@@ -1425,3 +1425,19 @@ enum signal_type dcn10_get_dig_mode(
return SIGNAL_TYPE_NONE; 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;
}
...@@ -575,4 +575,7 @@ void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); ...@@ -575,4 +575,7 @@ void dcn10_aux_initialize(struct dcn10_link_encoder *enc10);
enum signal_type dcn10_get_dig_mode( enum signal_type dcn10_get_dig_mode(
struct link_encoder *enc); 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__ */ #endif /* __DC_LINK_ENCODER__DCN10_H__ */
...@@ -49,6 +49,12 @@ ...@@ -49,6 +49,12 @@
#define IND_REG(index) \ #define IND_REG(index) \
(enc10->link_regs->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[] = { static struct mpll_cfg dcn2_mpll_cfg[] = {
// RBR // RBR
...@@ -260,6 +266,38 @@ void dcn20_link_encoder_enable_dp_output( ...@@ -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)\ #define AUX_REG(reg)\
(enc10->aux_regs->reg) (enc10->aux_regs->reg)
...@@ -311,28 +349,6 @@ void enc2_hw_init(struct link_encoder *enc) ...@@ -311,28 +349,6 @@ void enc2_hw_init(struct link_encoder *enc)
dcn10_aux_initialize(enc10); 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 = { static const struct link_encoder_funcs dcn20_link_enc_funcs = {
.read_state = link_enc2_read_state, .read_state = link_enc2_read_state,
.validate_output_with_stream = .validate_output_with_stream =
......
...@@ -343,6 +343,10 @@ void dcn20_link_encoder_enable_dp_output( ...@@ -343,6 +343,10 @@ void dcn20_link_encoder_enable_dp_output(
const struct dc_link_settings *link_settings, const struct dc_link_settings *link_settings,
enum clock_source_id clock_source); 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( void dcn20_link_encoder_construct(
struct dcn20_link_encoder *enc20, struct dcn20_link_encoder *enc20,
const struct encoder_init_data *init_data, const struct encoder_init_data *init_data,
......
...@@ -203,29 +203,6 @@ static bool update_cfg_data( ...@@ -203,29 +203,6 @@ static bool update_cfg_data(
return true; 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) bool dcn21_link_encoder_acquire_phy(struct link_encoder *enc)
{ {
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(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 = { ...@@ -348,8 +325,8 @@ static const struct link_encoder_funcs dcn21_link_enc_funcs = {
.fec_set_ready = enc2_fec_set_ready, .fec_set_ready = enc2_fec_set_ready,
.fec_is_active = enc2_fec_is_active, .fec_is_active = enc2_fec_is_active,
.get_dig_frontend = dcn10_get_dig_frontend, .get_dig_frontend = dcn10_get_dig_frontend,
.is_in_alt_mode = dcn21_link_encoder_is_in_alt_mode, .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn21_link_encoder_get_max_link_cap, .get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
}; };
void dcn21_link_encoder_construct( void dcn21_link_encoder_construct(
......
...@@ -84,6 +84,14 @@ static void virtual_link_encoder_destroy(struct link_encoder **enc) ...@@ -84,6 +84,14 @@ static void virtual_link_encoder_destroy(struct link_encoder **enc)
*enc = NULL; *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 = { static const struct link_encoder_funcs virtual_lnk_enc_funcs = {
.validate_output_with_stream = .validate_output_with_stream =
...@@ -94,6 +102,7 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { ...@@ -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_output = virtual_link_encoder_enable_dp_output,
.enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output, .enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output,
.disable_output = virtual_link_encoder_disable_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_lane_settings = virtual_link_encoder_dp_set_lane_settings,
.dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern,
.update_mst_stream_allocation_table = .update_mst_stream_allocation_table =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment