Merge tag 'drm/panel/for-4.6-rc1' of http://anongit.freedesktop.org/git/tegra/linux...
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_psr.c
index 9ccff30..0b42ada 100644 (file)
@@ -225,7 +225,12 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
                   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
        }
 
-       drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, DP_PSR_ENABLE);
+       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);
+       else
+               drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
+                                  DP_PSR_ENABLE);
 }
 
 static void vlv_psr_enable_source(struct intel_dp *intel_dp)
@@ -280,6 +285,9 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
        if (IS_HASWELL(dev))
                val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
+       if (dev_priv->psr.link_standby)
+               val |= EDP_PSR_LINK_STANDBY;
+
        I915_WRITE(EDP_PSR_CTL, val |
                   max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
                   idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
@@ -304,8 +312,15 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
 
        dev_priv->psr.source_ok = false;
 
-       if (IS_HASWELL(dev) && dig_port->port != PORT_A) {
-               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
+       /*
+        * HSW spec explicitly says PSR is tied to port A.
+        * BDW+ platforms with DDI implementation of PSR have different
+        * PSR registers per transcoder and we only implement transcoder EDP
+        * ones. Since by Display design transcoder EDP is tied to port A
+        * we can safely escape based on the port A.
+        */
+       if (HAS_DDI(dev) && dig_port->port != PORT_A) {
+               DRM_DEBUG_KMS("PSR condition failed: Port not supported\n");
                return false;
        }
 
@@ -314,6 +329,12 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
                return false;
        }
 
+       if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+           !dev_priv->psr.link_standby) {
+               DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n");
+               return false;
+       }
+
        if (IS_HASWELL(dev) &&
            I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) &
                      S3D_ENABLE) {
@@ -327,12 +348,6 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
                return false;
        }
 
-       if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
-           ((dev_priv->vbt.psr.full_link) || (dig_port->port != PORT_A))) {
-               DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n");
-               return false;
-       }
-
        dev_priv->psr.source_ok = true;
        return true;
 }
@@ -763,6 +778,36 @@ void intel_psr_init(struct drm_device *dev)
        dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ?
                HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE;
 
+       /* Per platform default */
+       if (i915.enable_psr == -1) {
+               if (IS_HASWELL(dev) || IS_BROADWELL(dev) ||
+                   IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+                       i915.enable_psr = 1;
+               else
+                       i915.enable_psr = 0;
+       }
+
+       /* Set link_standby x link_off defaults */
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               /* HSW and BDW require workarounds that we don't implement. */
+               dev_priv->psr.link_standby = false;
+       else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+               /* On VLV and CHV only standby mode is supported. */
+               dev_priv->psr.link_standby = true;
+       else
+               /* For new platforms let's respect VBT back again */
+               dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
+
+       /* Override link_standby x link_off defaults */
+       if (i915.enable_psr == 2 && !dev_priv->psr.link_standby) {
+               DRM_DEBUG_KMS("PSR: Forcing link standby\n");
+               dev_priv->psr.link_standby = true;
+       }
+       if (i915.enable_psr == 3 && dev_priv->psr.link_standby) {
+               DRM_DEBUG_KMS("PSR: Forcing main link off\n");
+               dev_priv->psr.link_standby = false;
+       }
+
        INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
        mutex_init(&dev_priv->psr.lock);
 }