drm/i915/icl: toggle PHY clock gating around link training
The Gen11 TypeC PHY DDI Buffer chapter, PHY Clock Gating Programming section says that PHY clock gating should be disabled before starting voltage swing programming, then enabled after any link training is complete. v2: Simple rebase. Cc: Animesh Manna <animesh.manna@intel.com> Cc: Manasi Navare <manasi.d.navare@intel.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> (v1) Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180725002813.6938-6-paulo.r.zanoni@intel.com
This commit is contained in:
parent
340a44bef2
commit
bc334d914e
|
@ -2106,6 +2106,26 @@ enum i915_power_well_id {
|
|||
MG_DP_MODE_LN1_ACU_PORT1)
|
||||
#define MG_DP_MODE_CFG_DP_X2_MODE (1 << 7)
|
||||
#define MG_DP_MODE_CFG_DP_X1_MODE (1 << 6)
|
||||
#define MG_DP_MODE_CFG_TR2PWR_GATING (1 << 5)
|
||||
#define MG_DP_MODE_CFG_TRPWR_GATING (1 << 4)
|
||||
#define MG_DP_MODE_CFG_CLNPWR_GATING (1 << 3)
|
||||
#define MG_DP_MODE_CFG_DIGPWR_GATING (1 << 2)
|
||||
#define MG_DP_MODE_CFG_GAONPWR_GATING (1 << 1)
|
||||
|
||||
#define MG_MISC_SUS0_PORT1 0x168814
|
||||
#define MG_MISC_SUS0_PORT2 0x169814
|
||||
#define MG_MISC_SUS0_PORT3 0x16A814
|
||||
#define MG_MISC_SUS0_PORT4 0x16B814
|
||||
#define MG_MISC_SUS0(tc_port) \
|
||||
_MMIO(_PORT(tc_port, MG_MISC_SUS0_PORT1, MG_MISC_SUS0_PORT2))
|
||||
#define MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE_MASK (3 << 14)
|
||||
#define MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE(x) ((x) << 14)
|
||||
#define MG_MISC_SUS0_CFG_TR2PWR_GATING (1 << 12)
|
||||
#define MG_MISC_SUS0_CFG_CL2PWR_GATING (1 << 11)
|
||||
#define MG_MISC_SUS0_CFG_GAONPWR_GATING (1 << 10)
|
||||
#define MG_MISC_SUS0_CFG_TRPWR_GATING (1 << 7)
|
||||
#define MG_MISC_SUS0_CFG_CL1PWR_GATING (1 << 6)
|
||||
#define MG_MISC_SUS0_CFG_DGPWR_GATING (1 << 5)
|
||||
|
||||
/* The spec defines this only for BXT PHY0, but lets assume that this
|
||||
* would exist for PHY1 too if it had a second channel.
|
||||
|
|
|
@ -2810,6 +2810,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
|
|||
intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
|
||||
|
||||
icl_program_mg_dp_mode(intel_dp);
|
||||
icl_disable_phy_clock_gating(dig_port);
|
||||
|
||||
if (IS_ICELAKE(dev_priv))
|
||||
icl_ddi_vswing_sequence(encoder, crtc_state->port_clock,
|
||||
|
@ -2828,6 +2829,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
|
|||
if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
|
||||
intel_dp_stop_link_train(intel_dp);
|
||||
|
||||
icl_enable_phy_clock_gating(dig_port);
|
||||
|
||||
intel_ddi_enable_pipe_clock(crtc_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -295,6 +295,72 @@ void icl_program_mg_dp_mode(struct intel_dp *intel_dp)
|
|||
I915_WRITE(MG_DP_MODE(port, 1), ln1);
|
||||
}
|
||||
|
||||
void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
|
||||
enum port port = dig_port->base.port;
|
||||
enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
|
||||
i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
if (tc_port == PORT_TC_NONE)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mg_regs); i++) {
|
||||
val = I915_READ(mg_regs[i]);
|
||||
val |= MG_DP_MODE_CFG_TR2PWR_GATING |
|
||||
MG_DP_MODE_CFG_TRPWR_GATING |
|
||||
MG_DP_MODE_CFG_CLNPWR_GATING |
|
||||
MG_DP_MODE_CFG_DIGPWR_GATING |
|
||||
MG_DP_MODE_CFG_GAONPWR_GATING;
|
||||
I915_WRITE(mg_regs[i], val);
|
||||
}
|
||||
|
||||
val = I915_READ(MG_MISC_SUS0(tc_port));
|
||||
val |= MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE(3) |
|
||||
MG_MISC_SUS0_CFG_TR2PWR_GATING |
|
||||
MG_MISC_SUS0_CFG_CL2PWR_GATING |
|
||||
MG_MISC_SUS0_CFG_GAONPWR_GATING |
|
||||
MG_MISC_SUS0_CFG_TRPWR_GATING |
|
||||
MG_MISC_SUS0_CFG_CL1PWR_GATING |
|
||||
MG_MISC_SUS0_CFG_DGPWR_GATING;
|
||||
I915_WRITE(MG_MISC_SUS0(tc_port), val);
|
||||
}
|
||||
|
||||
void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
|
||||
enum port port = dig_port->base.port;
|
||||
enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
|
||||
i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
if (tc_port == PORT_TC_NONE)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mg_regs); i++) {
|
||||
val = I915_READ(mg_regs[i]);
|
||||
val &= ~(MG_DP_MODE_CFG_TR2PWR_GATING |
|
||||
MG_DP_MODE_CFG_TRPWR_GATING |
|
||||
MG_DP_MODE_CFG_CLNPWR_GATING |
|
||||
MG_DP_MODE_CFG_DIGPWR_GATING |
|
||||
MG_DP_MODE_CFG_GAONPWR_GATING);
|
||||
I915_WRITE(mg_regs[i], val);
|
||||
}
|
||||
|
||||
val = I915_READ(MG_MISC_SUS0(tc_port));
|
||||
val &= ~(MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE_MASK |
|
||||
MG_MISC_SUS0_CFG_TR2PWR_GATING |
|
||||
MG_MISC_SUS0_CFG_CL2PWR_GATING |
|
||||
MG_MISC_SUS0_CFG_GAONPWR_GATING |
|
||||
MG_MISC_SUS0_CFG_TRPWR_GATING |
|
||||
MG_MISC_SUS0_CFG_CL1PWR_GATING |
|
||||
MG_MISC_SUS0_CFG_DGPWR_GATING);
|
||||
I915_WRITE(MG_MISC_SUS0(tc_port), val);
|
||||
}
|
||||
|
||||
int
|
||||
intel_dp_max_data_rate(int max_link_clock, int max_lanes)
|
||||
{
|
||||
|
|
|
@ -1715,6 +1715,8 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
|||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void icl_program_mg_dp_mode(struct intel_dp *intel_dp);
|
||||
void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port);
|
||||
void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port);
|
||||
|
||||
void
|
||||
intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
|
||||
|
|
Loading…
Reference in New Issue