Commit 474d1ec4 authored by Sonika Jindal's avatar Sonika Jindal Committed by Daniel Vetter

drm/i915/skl: Enabling PSR2 SU with frame sync

We make use of HW tracking for Selective update region and enable frame sync on
sink. We use hardware's hardcoded data values for frame sync and GTC.

v2: Add 3200x2000 resolution restriction with PSR2, move psr2_support to i915_psr
struct, add aux_frame_sync to independently control aux frame sync, rename the
TP2 TIME macro for 2500us (Rodrigo, Siva)
v3: Moving the resolution restriction to intel_psr_enable so that we check it
only once(Durga)

Cc: Durgadoss R <durgadoss.r@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarSonika Jindal <sonika.jindal@intel.com>
Reviewed-by: default avatarDurgadoss R <durgadoss.r@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 2d1070b2
...@@ -881,6 +881,8 @@ struct i915_psr { ...@@ -881,6 +881,8 @@ struct i915_psr {
struct delayed_work work; struct delayed_work work;
unsigned busy_frontbuffer_bits; unsigned busy_frontbuffer_bits;
bool link_standby; bool link_standby;
bool psr2_support;
bool aux_frame_sync;
}; };
enum intel_pch { enum intel_pch {
......
...@@ -2748,6 +2748,20 @@ enum skl_disp_power_wells { ...@@ -2748,6 +2748,20 @@ enum skl_disp_power_wells {
#define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26)
#define EDP_PSR_DEBUG_MASK_HPD (1<<25) #define EDP_PSR_DEBUG_MASK_HPD (1<<25)
#define EDP_PSR2_CTL 0x6f900
#define EDP_PSR2_ENABLE (1<<31)
#define EDP_SU_TRACK_ENABLE (1<<30)
#define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20)
#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f<<20)
#define EDP_PSR2_TP2_TIME_500 (0<<8)
#define EDP_PSR2_TP2_TIME_100 (1<<8)
#define EDP_PSR2_TP2_TIME_2500 (2<<8)
#define EDP_PSR2_TP2_TIME_50 (3<<8)
#define EDP_PSR2_TP2_TIME_MASK (3<<8)
#define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4
#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4)
#define EDP_PSR2_IDLE_MASK 0xf
/* VGA port control */ /* VGA port control */
#define ADPA 0x61100 #define ADPA 0x61100
#define PCH_ADPA 0xe1100 #define PCH_ADPA 0xe1100
......
...@@ -3785,6 +3785,21 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) ...@@ -3785,6 +3785,21 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
dev_priv->psr.sink_support = true; dev_priv->psr.sink_support = true;
DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
} }
if (INTEL_INFO(dev)->gen >= 9 &&
(intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
uint8_t frame_sync_cap;
dev_priv->psr.sink_support = true;
intel_dp_dpcd_read_wake(&intel_dp->aux,
DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
&frame_sync_cap, 1);
dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
/* PSR2 needs frame sync as well */
dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
DRM_DEBUG_KMS("PSR2 %s on sink",
dev_priv->psr.psr2_support ? "supported" : "not supported");
}
} }
/* Training Pattern 3 support, both source and sink */ /* Training Pattern 3 support, both source and sink */
......
...@@ -117,6 +117,19 @@ static void vlv_psr_setup_vsc(struct intel_dp *intel_dp) ...@@ -117,6 +117,19 @@ static void vlv_psr_setup_vsc(struct intel_dp *intel_dp)
I915_WRITE(VLV_VSCSDP(pipe), val); I915_WRITE(VLV_VSCSDP(pipe), val);
} }
static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp)
{
struct edp_vsc_psr psr_vsc;
/* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */
memset(&psr_vsc, 0, sizeof(psr_vsc));
psr_vsc.sdp_header.HB0 = 0;
psr_vsc.sdp_header.HB1 = 0x7;
psr_vsc.sdp_header.HB2 = 0x3;
psr_vsc.sdp_header.HB3 = 0xb;
intel_psr_write_vsc(intel_dp, &psr_vsc);
}
static void hsw_psr_setup_vsc(struct intel_dp *intel_dp) static void hsw_psr_setup_vsc(struct intel_dp *intel_dp)
{ {
struct edp_vsc_psr psr_vsc; struct edp_vsc_psr psr_vsc;
...@@ -165,6 +178,12 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) ...@@ -165,6 +178,12 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE); DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
/* Enable AUX frame sync at sink */
if (dev_priv->psr.aux_frame_sync)
drm_dp_dpcd_writeb(&intel_dp->aux,
DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF,
DP_AUX_FRAME_SYNC_ENABLE);
aux_data_reg = (INTEL_INFO(dev)->gen >= 9) ? aux_data_reg = (INTEL_INFO(dev)->gen >= 9) ?
DPA_AUX_CH_DATA1 : EDP_PSR_AUX_DATA1(dev); DPA_AUX_CH_DATA1 : EDP_PSR_AUX_DATA1(dev);
aux_ctl_reg = (INTEL_INFO(dev)->gen >= 9) ? aux_ctl_reg = (INTEL_INFO(dev)->gen >= 9) ?
...@@ -183,8 +202,10 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) ...@@ -183,8 +202,10 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
val |= DP_AUX_CH_CTL_TIME_OUT_1600us; val |= DP_AUX_CH_CTL_TIME_OUT_1600us;
val &= ~DP_AUX_CH_CTL_MESSAGE_SIZE_MASK; val &= ~DP_AUX_CH_CTL_MESSAGE_SIZE_MASK;
val |= (sizeof(aux_msg) << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); val |= (sizeof(aux_msg) << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
/* Use hardcoded data values for PSR */ /* Use hardcoded data values for PSR, frame sync and GTC */
val &= ~DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL; val &= ~DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL;
val &= ~DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL;
val &= ~DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL;
I915_WRITE(aux_ctl_reg, val); I915_WRITE(aux_ctl_reg, val);
} else { } else {
I915_WRITE(aux_ctl_reg, I915_WRITE(aux_ctl_reg,
...@@ -232,6 +253,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) ...@@ -232,6 +253,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = dig_port->base.base.dev; struct drm_device *dev = dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t max_sleep_time = 0x1f; uint32_t max_sleep_time = 0x1f;
/* Lately it was identified that depending on panel idle frame count /* Lately it was identified that depending on panel idle frame count
* calculated at HW can be off by 1. So let's use what came * calculated at HW can be off by 1. So let's use what came
...@@ -255,6 +277,10 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) ...@@ -255,6 +277,10 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
EDP_PSR_ENABLE); EDP_PSR_ENABLE);
if (dev_priv->psr.psr2_support)
I915_WRITE(EDP_PSR2_CTL, EDP_PSR2_ENABLE |
EDP_SU_TRACK_ENABLE | EDP_PSR2_TP2_TIME_100);
} }
static bool intel_psr_match_conditions(struct intel_dp *intel_dp) static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
...@@ -332,6 +358,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) ...@@ -332,6 +358,7 @@ void intel_psr_enable(struct intel_dp *intel_dp)
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
if (!HAS_PSR(dev)) { if (!HAS_PSR(dev)) {
DRM_DEBUG_KMS("PSR not supported on this platform\n"); DRM_DEBUG_KMS("PSR not supported on this platform\n");
...@@ -364,6 +391,15 @@ void intel_psr_enable(struct intel_dp *intel_dp) ...@@ -364,6 +391,15 @@ void intel_psr_enable(struct intel_dp *intel_dp)
if (HAS_DDI(dev)) { if (HAS_DDI(dev)) {
hsw_psr_setup_vsc(intel_dp); hsw_psr_setup_vsc(intel_dp);
if (dev_priv->psr.psr2_support) {
/* PSR2 is restricted to work with panel resolutions upto 3200x2000 */
if (crtc->config->pipe_src_w > 3200 ||
crtc->config->pipe_src_h > 2000)
dev_priv->psr.psr2_support = false;
else
skl_psr_setup_su_vsc(intel_dp);
}
/* Avoid continuous PSR exit by masking memup and hpd */ /* Avoid continuous PSR exit by masking memup and hpd */
I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
......
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