drm/i915/dc3co: Add description of how it works
authorJosé Roberto de Souza <jose.souza@intel.com>
Wed, 5 Feb 2020 21:49:45 +0000 (13:49 -0800)
committerJosé Roberto de Souza <jose.souza@intel.com>
Mon, 10 Feb 2020 17:15:54 +0000 (09:15 -0800)
Add a basic description about how DC3CO works to help people not
familiar with it.

While at it, I also improved the delayed work handle and function
names and removed a debug message that is ambiguous and not much
useful, no changes in behavior here.

Cc: Anshuman Gupta <anshuman.gupta@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200205214945.131012-1-jose.souza@intel.com
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/i915_drv.h

index e86e9dc1fe06f61c8a83db5c200c562dbe5534d1..b4942b6445aee2d66e4b32a0ba2ba03ae173ab1c 100644 (file)
  * get called by the frontbuffer tracking code. Note that because of locking
  * issues the self-refresh re-enable code is done from a work queue, which
  * must be correctly synchronized/cancelled when shutting down the pipe."
+ *
+ * DC3CO (DC3 clock off)
+ *
+ * On top of PSR2, GEN12 adds a intermediate power savings state that turns
+ * clock off automatically during PSR2 idle state.
+ * The smaller overhead of DC3co entry/exit vs. the overhead of PSR2 deep sleep
+ * entry/exit allows the HW to enter a low-power state even when page flipping
+ * periodically (for instance a 30fps video playback scenario).
+ *
+ * Every time a flips occurs PSR2 will get out of deep sleep state(if it was),
+ * so DC3CO is enabled and tgl_dc3co_disable_work is schedule to run after 6
+ * frames, if no other flip occurs and the function above is executed, DC3CO is
+ * disabled and PSR2 is configured to enter deep sleep, resetting again in case
+ * of another flip.
+ * Front buffer modifications do not trigger DC3CO activation on purpose as it
+ * would bring a lot of complexity and most of the moderns systems will only
+ * use page flips.
  */
 
 static bool psr_global_enabled(struct drm_i915_private *i915)
@@ -583,17 +600,16 @@ static void tgl_psr2_disable_dc3co(struct drm_i915_private *dev_priv)
        psr2_program_idle_frames(dev_priv, psr_compute_idle_frames(intel_dp));
 }
 
-static void tgl_dc5_idle_thread(struct work_struct *work)
+static void tgl_dc3co_disable_work(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv =
-               container_of(work, typeof(*dev_priv), psr.idle_work.work);
+               container_of(work, typeof(*dev_priv), psr.dc3co_work.work);
 
        mutex_lock(&dev_priv->psr.lock);
        /* If delayed work is pending, it is not idle */
-       if (delayed_work_pending(&dev_priv->psr.idle_work))
+       if (delayed_work_pending(&dev_priv->psr.dc3co_work))
                goto unlock;
 
-       drm_dbg_kms(&dev_priv->drm, "DC5/6 idle thread\n");
        tgl_psr2_disable_dc3co(dev_priv);
 unlock:
        mutex_unlock(&dev_priv->psr.lock);
@@ -604,7 +620,7 @@ static void tgl_disallow_dc3co_on_psr2_exit(struct drm_i915_private *dev_priv)
        if (!dev_priv->psr.dc3co_enabled)
                return;
 
-       cancel_delayed_work(&dev_priv->psr.idle_work);
+       cancel_delayed_work(&dev_priv->psr.dc3co_work);
        /* Before PSR2 exit disallow dc3co*/
        tgl_psr2_disable_dc3co(dev_priv);
 }
@@ -1040,7 +1056,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 
        mutex_unlock(&dev_priv->psr.lock);
        cancel_work_sync(&dev_priv->psr.work);
-       cancel_delayed_work_sync(&dev_priv->psr.idle_work);
+       cancel_delayed_work_sync(&dev_priv->psr.dc3co_work);
 }
 
 static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
@@ -1350,7 +1366,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
  * When we will be completely rely on PSR2 S/W tracking in future,
  * intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
  * event also therefore tgl_dc3co_flush() require to be changed
- * accrodingly in future.
+ * accordingly in future.
  */
 static void
 tgl_dc3co_flush(struct drm_i915_private *dev_priv,
@@ -1373,7 +1389,7 @@ tgl_dc3co_flush(struct drm_i915_private *dev_priv,
                goto unlock;
 
        tgl_psr2_enable_dc3co(dev_priv);
-       mod_delayed_work(system_wq, &dev_priv->psr.idle_work,
+       mod_delayed_work(system_wq, &dev_priv->psr.dc3co_work,
                         dev_priv->psr.dc3co_exit_delay);
 
 unlock:
@@ -1458,7 +1474,7 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
                dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
 
        INIT_WORK(&dev_priv->psr.work, intel_psr_work);
-       INIT_DELAYED_WORK(&dev_priv->psr.idle_work, tgl_dc5_idle_thread);
+       INIT_DELAYED_WORK(&dev_priv->psr.dc3co_work, tgl_dc3co_disable_work);
        mutex_init(&dev_priv->psr.lock);
 }
 
index 3452926d7b770e3cab0d6016fa8ba13b51db009b..da509d9b8895ed75795b79070e144618992ceafe 100644 (file)
@@ -504,7 +504,7 @@ struct i915_psr {
        u16 su_x_granularity;
        bool dc3co_enabled;
        u32 dc3co_exit_delay;
-       struct delayed_work idle_work;
+       struct delayed_work dc3co_work;
        bool initially_probed;
 };