Commit bc334d91 authored by Paulo Zanoni's avatar Paulo Zanoni

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: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180725002813.6938-6-paulo.r.zanoni@intel.com
parent 340a44be
......@@ -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,
......
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