mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 05:24:12 +08:00
drm/i915: Switch to LTTPR transparent mode link training
By default LTTPRs should be in transparent link training mode, nevertheless in this patch we switch to this default mode explicitly. The DP Standard recommends this, supposedly because an LTTPR may be left in the non-transparent mode (by BIOS, previous kernel, or after reset due to a firmware bug). I haven't seen this happening, but let's follow the DP Standard. v2: - Add a code comment about the explicit disabling of non-transparent mode. v3: - Move check to prevent initing LTTPRs on eDP to init_dp_lttpr_init(). Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201007170917.1764556-6-imre.deak@intel.com
This commit is contained in:
parent
9782f52ab5
commit
7b2a4ab8b0
@ -1302,6 +1302,7 @@ struct intel_dp {
|
|||||||
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
|
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
|
||||||
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
|
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
|
||||||
u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
|
u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
|
||||||
|
u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
|
||||||
u8 fec_capable;
|
u8 fec_capable;
|
||||||
/* source rates */
|
/* source rates */
|
||||||
int num_source_rates;
|
int num_source_rates;
|
||||||
|
@ -4790,6 +4790,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
intel_dp_lttpr_init(intel_dp);
|
||||||
|
|
||||||
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
|
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -34,6 +34,55 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
|
|||||||
link_status[3], link_status[4], link_status[5]);
|
link_status[3], link_status[4], link_status[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
|
||||||
|
{
|
||||||
|
if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
|
||||||
|
intel_dp->lttpr_common_caps) < 0) {
|
||||||
|
memset(intel_dp->lttpr_common_caps, 0,
|
||||||
|
sizeof(intel_dp->lttpr_common_caps));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
|
||||||
|
"LTTPR common capabilities: %*ph\n",
|
||||||
|
(int)sizeof(intel_dp->lttpr_common_caps),
|
||||||
|
intel_dp->lttpr_common_caps);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
|
||||||
|
{
|
||||||
|
u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT :
|
||||||
|
DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
|
||||||
|
|
||||||
|
return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
|
||||||
|
* @intel_dp: Intel DP struct
|
||||||
|
*
|
||||||
|
* Read the LTTPR common capabilities and switch to transparent link training
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
int intel_dp_lttpr_init(struct intel_dp *intel_dp)
|
||||||
|
{
|
||||||
|
if (intel_dp_is_edp(intel_dp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
intel_dp_read_lttpr_common_caps(intel_dp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See DP Standard v2.0 3.6.6.1. about the explicit disabling of
|
||||||
|
* non-transparent mode.
|
||||||
|
*/
|
||||||
|
intel_dp_set_lttpr_transparent_mode(intel_dp, true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static u8 dp_voltage_max(u8 preemph)
|
static u8 dp_voltage_max(u8 preemph)
|
||||||
{
|
{
|
||||||
switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
|
switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
|
||||||
@ -492,6 +541,12 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp,
|
|||||||
void intel_dp_start_link_train(struct intel_dp *intel_dp,
|
void intel_dp_start_link_train(struct intel_dp *intel_dp,
|
||||||
const struct intel_crtc_state *crtc_state)
|
const struct intel_crtc_state *crtc_state)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* TODO: Reiniting LTTPRs here won't be needed once proper connector
|
||||||
|
* HW state readout is added.
|
||||||
|
*/
|
||||||
|
intel_dp_lttpr_init(intel_dp);
|
||||||
|
|
||||||
if (!intel_dp_link_train(intel_dp, crtc_state))
|
if (!intel_dp_link_train(intel_dp, crtc_state))
|
||||||
intel_dp_schedule_fallback_link_training(intel_dp, crtc_state);
|
intel_dp_schedule_fallback_link_training(intel_dp, crtc_state);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
struct intel_crtc_state;
|
struct intel_crtc_state;
|
||||||
struct intel_dp;
|
struct intel_dp;
|
||||||
|
|
||||||
|
int intel_dp_lttpr_init(struct intel_dp *intel_dp);
|
||||||
|
|
||||||
void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
|
void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
|
||||||
const struct intel_crtc_state *crtc_state,
|
const struct intel_crtc_state *crtc_state,
|
||||||
const u8 link_status[DP_LINK_STATUS_SIZE]);
|
const u8 link_status[DP_LINK_STATUS_SIZE]);
|
||||||
|
Loading…
Reference in New Issue
Block a user