Enables PSR2 for idle screen.

Cc: Rodrigo Vivi <[email protected]>
Signed-off-by: vathsala nagaraju <[email protected]>
---
 drivers/gpu/drm/i915/i915_reg.h  |  21 +++-
 drivers/gpu/drm/i915/intel_psr.c | 262 ++++++++++++++++++++++++++-------------
 include/drm/drm_dp_helper.h      |   1 +
 3 files changed, 195 insertions(+), 89 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index da82744..49682f5 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3301,9 +3301,12 @@ enum {
 #define   EDP_PSR_PERF_CNT_MASK                0xffffff
 
 #define EDP_PSR_DEBUG_CTL              _MMIO(dev_priv->psr_mmio_base + 0x60)
-#define   EDP_PSR_DEBUG_MASK_LPSP      (1<<27)
-#define   EDP_PSR_DEBUG_MASK_MEMUP     (1<<26)
-#define   EDP_PSR_DEBUG_MASK_HPD       (1<<25)
+#define   EDP_PSR_DEBUG_MASK_MAX_SLEEP         (1<<28)
+#define   EDP_PSR_DEBUG_MASK_LPSP              (1<<27)
+#define   EDP_PSR_DEBUG_MASK_MEMUP             (1<<26)
+#define   EDP_PSR_DEBUG_MASK_HPD               (1<<25)
+#define   EDP_PSR_DEBUG_MASK_DISP_REG_WRITE    (1<<16)
+#define   EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1<<15)
 
 #define EDP_PSR2_CTL                   _MMIO(0x6f900)
 #define   EDP_PSR2_ENABLE              (1<<31)
@@ -3318,6 +3321,11 @@ enum {
 #define   EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4
 #define   EDP_PSR2_FRAME_BEFORE_SU_MASK        (0xf<<4)
 #define   EDP_PSR2_IDLE_MASK           0xf
+#define   EDP_FRAMES_BEFORE_SU_ENTRY   (1<<4)
+
+#define EDP_PSR2_STATUS_CTL            _MMIO(0x6f940)
+#define EDP_PSR2_STATUS_STATE_MASK     (0xf<<28)
+#define EDP_PSR2_STATUS_STATE_IDLE     0
 
 /* VGA port control */
 #define ADPA                   _MMIO(0x61100)
@@ -6133,6 +6141,13 @@ enum {
 #define  BDW_DPRS_MASK_VBLANK_SRD      (1 << 0)
 #define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, 
_CHICKEN_PIPESL_1_B)
 
+#define CHICKEN_TRANS_A         0x420c0
+#define CHICKEN_TRANS_B         0x420c4
+#define CHICKEN_TRANS(trans) _MMIO_TRANS(trans, CHICKEN_TRANS_A, 
CHICKEN_TRANS_B)
+#define TRANS_EDP              3
+#define CHICKEN_TRANS_BIT12    (1<<12)
+#define CHICKEN_TRANS_BIT15    (1<<15)
+
 #define DISP_ARB_CTL   _MMIO(0x45000)
 #define  DISP_FBC_MEMORY_WAKE          (1<<31)
 #define  DISP_TILE_SURFACE_SWIZZLING   (1<<13)
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 76a630b..12429c2 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -197,6 +197,7 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
        enum port port = dig_port->port;
        u32 aux_ctl;
        int i;
+       uint8_t enable_psr2 = 0;
 
        BUILD_BUG_ON(sizeof(aux_msg) > 20);
 
@@ -207,13 +208,32 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
                drm_dp_dpcd_writeb(&intel_dp->aux,
                                DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF,
                                DP_AUX_FRAME_SYNC_ENABLE);
+       /* enable ALPM for PSR2 */
+       if (dev_priv->psr.psr2_support) {
+               uint8_t alpm_caps;
+
+               /* confirm panel supports ALPM */
+               drm_dp_dpcd_readb(&intel_dp->aux,
+                               DP_RECEIVER_ALPM_CAP,
+                               &alpm_caps);
+               if (alpm_caps & DP_ALPM_CAP)
+               drm_dp_dpcd_writeb(&intel_dp->aux,
+                               DP_RECEIVER_ALPM_CONFIG,
+                               DP_ALPM_ENABLE);
+
+               enable_psr2 = DP_PSR2_PROTOCOL;
+       }
+
 
        if (dev_priv->psr.link_standby)
-               drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
-                                  DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE);
+               drm_dp_dpcd_writeb(&intel_dp->aux,
+                               DP_PSR_EN_CFG,
+                               DP_PSR_ENABLE |
+                               DP_PSR_MAIN_LINK_ACTIVE |
+                               enable_psr2);
        else
                drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
-                                  DP_PSR_ENABLE);
+                                  DP_PSR_ENABLE | enable_psr2);
 
        aux_ctl_reg = psr_aux_ctl_reg(dev_priv, port);
 
@@ -276,59 +296,75 @@ static void hsw_psr_enable_source(struct intel_dp 
*intel_dp)
        uint32_t idle_frames = dev_priv->vbt.psr.idle_frames + 1;
        uint32_t val = EDP_PSR_ENABLE;
 
-       val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
-       val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
+       if (!dev_priv->psr.psr2_support) {
+               val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
+               val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
 
-       if (IS_HASWELL(dev))
-               val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
+               if (IS_HASWELL(dev))
+                       val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
-       if (dev_priv->psr.link_standby)
-               val |= EDP_PSR_LINK_STANDBY;
-
-       if (dev_priv->vbt.psr.tp1_wakeup_time > 5)
-               val |= EDP_PSR_TP1_TIME_2500us;
-       else if (dev_priv->vbt.psr.tp1_wakeup_time > 1)
-               val |= EDP_PSR_TP1_TIME_500us;
-       else if (dev_priv->vbt.psr.tp1_wakeup_time > 0)
-               val |= EDP_PSR_TP1_TIME_100us;
-       else
-               val |= EDP_PSR_TP1_TIME_0us;
-
-       if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
-               val |= EDP_PSR_TP2_TP3_TIME_2500us;
-       else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
-               val |= EDP_PSR_TP2_TP3_TIME_500us;
-       else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
-               val |= EDP_PSR_TP2_TP3_TIME_100us;
-       else
-               val |= EDP_PSR_TP2_TP3_TIME_0us;
+               if (dev_priv->psr.link_standby)
+                       val |= EDP_PSR_LINK_STANDBY;
 
-       if (intel_dp_source_supports_hbr2(intel_dp) &&
-           drm_dp_tps3_supported(intel_dp->dpcd))
-               val |= EDP_PSR_TP1_TP3_SEL;
-       else
-               val |= EDP_PSR_TP1_TP2_SEL;
+               if (dev_priv->vbt.psr.tp1_wakeup_time > 5)
+                       val |= EDP_PSR_TP1_TIME_2500us;
+               else if (dev_priv->vbt.psr.tp1_wakeup_time > 1)
+                       val |= EDP_PSR_TP1_TIME_500us;
+               else if (dev_priv->vbt.psr.tp1_wakeup_time > 0)
+                       val |= EDP_PSR_TP1_TIME_100us;
+               else
+                       val |= EDP_PSR_TP1_TIME_0us;
+
+               if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
+                       val |= EDP_PSR_TP2_TP3_TIME_2500us;
+               else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
+                       val |= EDP_PSR_TP2_TP3_TIME_500us;
+               else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
+                       val |= EDP_PSR_TP2_TP3_TIME_100us;
+               else
+                       val |= EDP_PSR_TP2_TP3_TIME_0us;
 
-       I915_WRITE(EDP_PSR_CTL, val);
+               if (intel_dp_source_supports_hbr2(intel_dp) &
+                       drm_dp_tps3_supported(intel_dp->dpcd))
+                       val |= EDP_PSR_TP1_TP3_SEL;
+               else
+                       val |= EDP_PSR_TP1_TP2_SEL;
 
-       if (!dev_priv->psr.psr2_support)
-               return;
+               I915_WRITE(EDP_PSR_CTL, val);
 
-       /* FIXME: selective update is probably totally broken because it doesn't
-        * mesh at all with our frontbuffer tracking. And the hw alone isn't
-        * good enough. */
-       val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE;
-
-       if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
-               val |= EDP_PSR2_TP2_TIME_2500;
-       else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
-               val |= EDP_PSR2_TP2_TIME_500;
-       else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
-               val |= EDP_PSR2_TP2_TIME_100;
-       else
-               val |= EDP_PSR2_TP2_TIME_50;
+       } else {
+               /* FIXME: selective update is probably totally broken because
+                * it doesn't mesh at all with our frontbuffer tracking. And
+                * the hw alone isn't good enough.
+                */
+               val = EDP_PSR2_ENABLE |
+                       EDP_SU_TRACK_ENABLE |
+                       EDP_FRAMES_BEFORE_SU_ENTRY;
+
+               if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
+                       val |= EDP_PSR2_TP2_TIME_2500;
+               else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
+                       val |= EDP_PSR2_TP2_TIME_500;
+               else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
+                       val |= EDP_PSR2_TP2_TIME_100;
+               else
+                       val |= EDP_PSR2_TP2_TIME_50;
 
-       I915_WRITE(EDP_PSR2_CTL, val);
+               if (idle_frames < 4)
+                       idle_frames = 4;
+
+               val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
+
+               if (dev_priv->psr.y_cord_support)
+                       I915_WRITE(CHICKEN_TRANS(TRANS_EDP),
+                               CHICKEN_TRANS_BIT12 |
+                               CHICKEN_TRANS_BIT15);
+               else
+                       I915_WRITE(CHICKEN_TRANS(TRANS_EDP),
+                               CHICKEN_TRANS_BIT12);
+
+               I915_WRITE(EDP_PSR2_CTL, val);
+       }
 }
 
 static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
@@ -408,7 +444,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
-       WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
+       if (dev_priv->psr.psr2_support)
+               WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE);
+       else
+               WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
        WARN_ON(dev_priv->psr.active);
        lockdep_assert_held(&dev_priv->psr.lock);
 
@@ -460,8 +499,6 @@ void intel_psr_enable(struct intel_dp *intel_dp)
        dev_priv->psr.busy_frontbuffer_bits = 0;
 
        if (HAS_DDI(dev)) {
-               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 ||
@@ -469,17 +506,27 @@ void intel_psr_enable(struct intel_dp *intel_dp)
                                dev_priv->psr.psr2_support = false;
                        else
                                skl_psr_setup_su_vsc(intel_dp);
+                               I915_WRITE(EDP_PSR_DEBUG_CTL,
+                                       EDP_PSR_DEBUG_MASK_MEMUP |
+                                       EDP_PSR_DEBUG_MASK_HPD |
+                                       EDP_PSR_DEBUG_MASK_LPSP |
+                                       EDP_PSR_DEBUG_MASK_MAX_SLEEP |
+                                       EDP_PSR_DEBUG_MASK_DISP_REG_WRITE);
+               } else {
+
+                       hsw_psr_setup_vsc(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 runtime_pm besides
+                        * preventing  other hw tracking issues now we can rely
+                        * on frontbuffer tracking.
+                        */
+                       I915_WRITE(EDP_PSR_DEBUG_CTL,
+                               EDP_PSR_DEBUG_MASK_MEMUP |
+                               EDP_PSR_DEBUG_MASK_HPD |
+                               EDP_PSR_DEBUG_MASK_LPSP);
                }
-
-               /*
-                * Per Spec: Avoid continuous PSR exit by masking MEMUP and HPD.
-                * Also mask LPSP to avoid dependency on other drivers that
-                * might block runtime_pm besides preventing other hw tracking
-                * issues now we can rely on frontbuffer tracking.
-                */
-               I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
-                          EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
-
                /* Enable PSR on the panel */
                hsw_psr_enable_sink(intel_dp);
 
@@ -555,20 +602,41 @@ static void hsw_psr_disable(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = to_i915(dev);
 
        if (dev_priv->psr.active) {
-               I915_WRITE(EDP_PSR_CTL,
-                          I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE);
-
-               /* Wait till PSR is idle */
-               if (intel_wait_for_register(dev_priv,
-                                           EDP_PSR_STATUS_CTL,
-                                           EDP_PSR_STATUS_STATE_MASK,
-                                           0,
-                                           2000))
-                       DRM_ERROR("Timed out waiting for PSR Idle State\n");
-
+               if (dev_priv->psr.psr2_support) {
+                       /* disable AUX frame sync */
+                       if (dev_priv->psr.aux_frame_sync)
+                               drm_dp_dpcd_writeb(&intel_dp->aux,
+                                       DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF,
+                                               0);
+                       I915_WRITE(EDP_PSR2_CTL,
+                               I915_READ(EDP_PSR2_CTL) &
+                               ~(EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE));
+                       /* Wait till PSR2 is idle */
+                       if (intel_wait_for_register(dev_priv,
+                                               EDP_PSR2_STATUS_CTL,
+                                               EDP_PSR2_STATUS_STATE_MASK,
+                                               0,
+                                               2000))
+                               DRM_ERROR("Timed out waiting for PSR2 Idle 
State\n");
+               } else {
+                       I915_WRITE(EDP_PSR_CTL,
+                                       I915_READ(EDP_PSR_CTL) &
+                                       ~EDP_PSR_ENABLE);
+
+                       /* Wait till PSR is idle */
+                       if (intel_wait_for_register(dev_priv,
+                                               EDP_PSR_STATUS_CTL,
+                                               EDP_PSR_STATUS_STATE_MASK,
+                                               0,
+                                               2000))
+                               DRM_ERROR("Timed out waiting for PSR Idle 
State\n");
+               }
                dev_priv->psr.active = false;
        } else {
-               WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
+               if (dev_priv->psr.psr2_support)
+                       WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE);
+               else
+                       WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
        }
 }
 
@@ -619,13 +687,25 @@ static void intel_psr_work(struct work_struct *work)
         * and be ready for re-enable.
         */
        if (HAS_DDI(dev_priv)) {
-               if (intel_wait_for_register(dev_priv,
-                                           EDP_PSR_STATUS_CTL,
-                                           EDP_PSR_STATUS_STATE_MASK,
-                                           0,
-                                           50)) {
-                       DRM_ERROR("Timed out waiting for PSR Idle for 
re-enable\n");
-                       return;
+               if (dev_priv->psr.psr2_support) {
+                       if (intel_wait_for_register(dev_priv,
+                                               EDP_PSR2_STATUS_CTL,
+                                               EDP_PSR2_STATUS_STATE_MASK,
+                                               0,
+                                               50)) {
+                               DRM_ERROR("Timed out waiting for PSR2 Idle for 
re-enable\n");
+                               return;
+                       }
+
+               } else {
+                       if (intel_wait_for_register(dev_priv,
+                                               EDP_PSR_STATUS_CTL,
+                                               EDP_PSR_STATUS_STATE_MASK,
+                                               0,
+                                               50)) {
+                               DRM_ERROR("Timed out waiting for PSR Idle for 
re-enable\n");
+                               return;
+                       }
                }
        } else {
                if (intel_wait_for_register(dev_priv,
@@ -667,11 +747,21 @@ static void intel_psr_exit(struct drm_i915_private 
*dev_priv)
                return;
 
        if (HAS_DDI(dev_priv)) {
-               val = I915_READ(EDP_PSR_CTL);
-
-               WARN_ON(!(val & EDP_PSR_ENABLE));
-
-               I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE);
+               if (dev_priv->psr.psr2_support) {
+                       /*disable aux-frame sync */
+                       if (dev_priv->psr.aux_frame_sync)
+                               drm_dp_dpcd_writeb(&intel_dp->aux,
+                                       DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF,
+                                       0);
+
+                       val = I915_READ(EDP_PSR2_CTL);
+                       WARN_ON(!(val & EDP_PSR2_ENABLE));
+                       I915_WRITE(EDP_PSR2_CTL, val & ~EDP_PSR2_ENABLE);
+               } else {
+                       val = I915_READ(EDP_PSR_CTL);
+                       WARN_ON(!(val & EDP_PSR_ENABLE));
+                       I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE);
+               }
        } else {
                val = I915_READ(VLV_PSRCTL(pipe));
 
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 3d875c0..6303a3a 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -343,6 +343,7 @@
 # define DP_PSR_FRAME_CAPTURE              (1 << 3)
 # define DP_PSR_SELECTIVE_UPDATE           (1 << 4)
 # define DP_PSR_IRQ_HPD_WITH_CRC_ERRORS     (1 << 5)
+# define DP_PSR2_PROTOCOL              (1 << 6)
 
 #define DP_ADAPTER_CTRL                            0x1a0
 # define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE   (1 << 0)
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to