From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Reintroduce the special PSR AUX CH setup for hsw/bdw. Not all of it was even removed (BDW AUX data registers were left behind). Update the code to use REG_BIT() & co. while at it. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_dp_aux.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_aux.h | 4 ++ drivers/gpu/drm/i915/display/intel_psr.c | 61 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_psr_regs.h | 11 ++++ 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index abf77ba76972..847fd6bfa7e4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -14,7 +14,7 @@ #include "intel_pps.h" #include "intel_tc.h" -static u32 intel_dp_aux_pack(const u8 *src, int src_bytes) +u32 intel_dp_aux_pack(const u8 *src, int src_bytes) { int i; u32 v = 0; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.h b/drivers/gpu/drm/i915/display/intel_dp_aux.h index 138e340f94ee..3bc529a23dd6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.h +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h @@ -6,6 +6,8 @@ #ifndef __INTEL_DP_AUX_H__ #define __INTEL_DP_AUX_H__ +#include <linux/types.h> + enum aux_ch; struct intel_dp; struct intel_encoder; @@ -15,4 +17,6 @@ void intel_dp_aux_init(struct intel_dp *intel_dp); enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder); +u32 intel_dp_aux_pack(const u8 *src, int src_bytes); + #endif /* __INTEL_DP_AUX_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 7f748c7a71f3..2ff6f75c2bee 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -288,6 +288,24 @@ static i915_reg_t psr_iir_reg(struct drm_i915_private *dev_priv, return EDP_PSR_IIR; } +static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_AUX_CTL(cpu_transcoder); + else + return HSW_SRD_AUX_CTL; +} + +static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder, int i) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_AUX_DATA(cpu_transcoder, i); + else + return HSW_SRD_AUX_DATA(i); +} + static void psr_irq_control(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -512,6 +530,42 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) } } +static void hsw_psr_setup_aux(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + enum transcoder cpu_transcoder = intel_dp->psr.transcoder; + u32 aux_clock_divider, aux_ctl; + static const u8 aux_msg[] = { + [0] = (DP_AUX_NATIVE_WRITE << 4) | ((DP_SET_POWER >> 16) & 0xf), + [1] = (DP_SET_POWER >> 8) & 0xff, + [2] = DP_SET_POWER & 0xff, + [3] = 1 - 1, + [4] = DP_SET_POWER_D0, + }; + int i; + + BUILD_BUG_ON(sizeof(aux_msg) > 20); + for (i = 0; i < sizeof(aux_msg); i += 4) + intel_de_write(dev_priv, + psr_aux_data_reg(dev_priv, cpu_transcoder, i >> 2), + intel_dp_aux_pack(&aux_msg[i], sizeof(aux_msg) - i)); + + aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); + + /* Start with bits set for DDI_AUX_CTL register */ + aux_ctl = intel_dp->get_aux_send_ctl(intel_dp, sizeof(aux_msg), + aux_clock_divider); + + /* Select only valid bits for SRD_AUX_CTL */ + aux_ctl &= EDP_PSR_AUX_CTL_TIME_OUT_MASK | + EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK | + EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK | + EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK; + + intel_de_write(dev_priv, psr_aux_ctl_reg(dev_priv, cpu_transcoder), + aux_ctl); +} + static void intel_psr_enable_sink(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1318,6 +1372,13 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, enum transcoder cpu_transcoder = intel_dp->psr.transcoder; u32 mask; + /* + * Only HSW and BDW have PSR AUX registers that need to be setup. + * SKL+ use hardcoded values PSR AUX transactions + */ + if (DISPLAY_VER(dev_priv) < 9) + hsw_psr_setup_aux(intel_dp); + /* * Per Spec: Avoid continuous PSR exit by masking MEMUP and HPD also * mask LPSP to avoid dependency on other drivers that might block diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 998f638ee182..5e54817b6a0f 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -80,6 +80,17 @@ #define EDP_PSR_PRE_ENTRY(trans) (TGL_PSR_PRE_ENTRY << \ _EDP_PSR_TRANS_SHIFT(trans)) +#define HSW_SRD_AUX_CTL _MMIO(0x64810) +#define _SRD_AUX_CTL_A 0x60810 +#define _SRD_AUX_CTL_EDP 0x6f810 +#define EDP_PSR_AUX_CTL(tran) _MMIO_TRANS2(tran, _SRD_AUX_CTL_A) +#define EDP_PSR_AUX_CTL_TIME_OUT_MASK REG_GENMASK(27, 26) +#define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK REG_GENMASK(24, 20) +#define EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK REG_GENMASK(19, 16) +#define EDP_PSR_AUX_CTL_ERROR_INTERRUPT REG_BIT(11) +#define EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK REG_GENMASK(10, 0) + +#define HSW_SRD_AUX_DATA(i) _MMIO(0x64814 + (i) * 4) /* 5 registers */ #define _SRD_AUX_DATA_A 0x60814 #define _SRD_AUX_DATA_EDP 0x6f814 #define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) * 4) /* 5 registers */ -- 2.39.2