[PATCH 5/5] drm/i915/display: Programing sequence of allow/disallow DC3Co has been changed

Gwan-gyeong Mun gwan-gyeong.mun at intel.com
Mon Mar 15 15:44:40 UTC 2021


DC3co programming of PSR2 requires PSR2 to be disabled and re-enabled
following the PSR2 sequences.
Below is the changed sequence.

Sequence to Allow DC3co
 1. Disable DC states by setting "Dynamic DC State enable bit" to 00b
    from DC_STATE_EN register
 2. Disable PSR2
 3. Set Idle Frames to 0 from PSR2_CTL register.
 4. Enable PSR2
 5. Configure and enable the PSR2 transcoder's Early Exit line.
 6. Set Display Clock Off Enable bit to 1b from DC_STATE_EN register

Sequence to Disallow DC3co
 1. Clear Display DC*CO State Status by writing a 0 to it.
 2. Set Display Clock Off Enable to 0b
 3. Wait DC3co exit time for disable to complete.
 4. Disable PSR2
 5. Restore PSR2 deep sleep by programming correct allowed Idle Frames in
    PSR2_CTL
 6. If PSR2 is still needed, re-enable PSR2

Bspec: 49196

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun at intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_psr.c      | 53 +++++++++++--------
 2 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 5983130a3f86..19b244928707 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1468,6 +1468,7 @@ struct intel_psr {
 	bool sink_not_reliable;
 	bool irq_aux_error;
 	u16 su_x_granularity;
+	bool dc3co_allow_entry;
 	u32 dc3co_exitline;
 	u32 dc3co_exit_delay;
 	struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index e63d260b5925..18849d58efe0 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -458,6 +458,9 @@ static u8 psr_compute_idle_frames(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	int idle_frames;
 
+	if (intel_dp->psr.dc3co_allow_entry)
+		return 0;
+
 	/* Let's use 6 as the minimum to cover all known cases including the
 	 * off-by-one issue that HW has in some cases.
 	 */
@@ -591,33 +594,35 @@ static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate)
 			    drm_mode_vrefresh(&cstate->hw.adjusted_mode));
 }
 
-static void psr2_program_idle_frames(struct intel_dp *intel_dp,
-				     u32 idle_frames)
+static void tgl_psr2_enable_dc3co_locked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 val;
 
-	idle_frames <<=  EDP_PSR2_IDLE_FRAME_SHIFT;
-	val = intel_de_read(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder));
-	val &= ~EDP_PSR2_IDLE_FRAME_MASK;
-	val |= idle_frames;
-	intel_de_write(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
-}
+	intel_dp->psr.dc3co_allow_entry = true;
+	intel_display_power_set_target_dc_state(dev_priv, DC_STATE_DISABLE);
+	mutex_unlock(&intel_dp->psr.lock);
 
-static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	intel_psr_pause(intel_dp);
+	intel_psr_resume(intel_dp);
 
-	psr2_program_idle_frames(intel_dp, 0);
+	mutex_lock(&intel_dp->psr.lock);
+	intel_dp->psr.dc3co_allow_entry = false;
 	intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_DC3CO);
+	mod_delayed_work(system_wq, &intel_dp->psr.dc3co_work,
+			 intel_dp->psr.dc3co_exit_delay);
 }
 
-static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp)
+static void tgl_psr2_disable_dc3co_locked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
 	intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
-	psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp));
+	mutex_unlock(&intel_dp->psr.lock);
+
+	intel_psr_pause(intel_dp);
+	intel_psr_resume(intel_dp);
+
+	mutex_lock(&intel_dp->psr.lock);
 }
 
 static void tgl_dc3co_disable_work(struct work_struct *work)
@@ -630,19 +635,27 @@ static void tgl_dc3co_disable_work(struct work_struct *work)
 	if (delayed_work_pending(&intel_dp->psr.dc3co_work))
 		goto unlock;
 
-	tgl_psr2_disable_dc3co(intel_dp);
+	tgl_psr2_disable_dc3co_locked(intel_dp);
 unlock:
 	mutex_unlock(&intel_dp->psr.lock);
 }
 
 static void tgl_disallow_dc3co_on_psr2_exit(struct intel_dp *intel_dp)
 {
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
 	if (!intel_dp->psr.dc3co_exitline)
 		return;
 
 	cancel_delayed_work(&intel_dp->psr.dc3co_work);
-	/* Before PSR2 exit disallow dc3co*/
-	tgl_psr2_disable_dc3co(intel_dp);
+	/*
+	 * Before PSR2 exit disallow dc3co
+	 * When tgl_disallow_dc3co_on_psr2_exit() is called during
+	 * "Allow DC3co" processing, do not change dc_state.
+	 */
+	if (!intel_dp->psr.dc3co_allow_entry)
+		intel_display_power_set_target_dc_state(dev_priv,
+							DC_STATE_EN_UPTO_DC6);
 }
 
 static void
@@ -1851,9 +1864,7 @@ tgl_dc3co_flush(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
 	    INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
 		goto unlock;
 
-	tgl_psr2_enable_dc3co(intel_dp);
-	mod_delayed_work(system_wq, &intel_dp->psr.dc3co_work,
-			 intel_dp->psr.dc3co_exit_delay);
+	tgl_psr2_enable_dc3co_locked(intel_dp);
 
 unlock:
 	mutex_unlock(&intel_dp->psr.lock);
-- 
2.30.1



More information about the Intel-gfx-trybot mailing list