diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 |
4 files changed, 91 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cf1d2bbb0613..5530c470f30d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -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. diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 399c438bd210..0adc043529f2 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -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); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 28de73be4507..cc33d7c6ba19 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -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) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4e5b00052b5b..99a5f5be5b82 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -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, |