#include "skl_watermark.h"
 #include "skl_watermark_regs.h"
 
+/*It is expected that DSB can do posted writes to every register in
+ * the pipe and planes within 100us. For flip queue use case, the
+ * recommended DSB execution time is 100us + one SAGV block time.
+ */
+#define DSB_EXE_TIME 100
+
 static void skl_sagv_disable(struct drm_i915_private *i915);
 
 /* Stores plane specific WM parameters */
        return 0;
 }
 
+/*
+ * If Fixed Refresh Rate:
+ * Program DEEP PKG_C_LATENCY Pkg C with highest valid latency from
+ * watermark level1 and up and above. If watermark level 1 is
+ * invalid program it with all 1's.
+ * Program PKG_C_LATENCY Added Wake Time = DSB execution time
+ * If Variable Refresh Rate:
+ * Program DEEP PKG_C_LATENCY Pkg C with all 1's.
+ * Program PKG_C_LATENCY Added Wake Time = 0
+ */
+static void
+skl_program_dpkgc_latency(struct drm_i915_private *i915, bool vrr_enabled)
+{
+       u32 max_latency = 0;
+       u32 clear = 0, val = 0;
+       u32 added_wake_time = 0;
+
+       if (DISPLAY_VER(i915) < 20)
+               return;
+
+       if (vrr_enabled) {
+               max_latency = LNL_PKG_C_LATENCY_MASK;
+               added_wake_time = 0;
+       } else {
+               max_latency = skl_watermark_max_latency(i915, 1);
+               if (max_latency == 0)
+                       max_latency = LNL_PKG_C_LATENCY_MASK;
+               added_wake_time = DSB_EXE_TIME +
+                       i915->display.sagv.block_time_us;
+       }
+
+       clear |= LNL_ADDED_WAKE_TIME_MASK | LNL_PKG_C_LATENCY_MASK;
+       val |= REG_FIELD_PREP(LNL_PKG_C_LATENCY_MASK, max_latency);
+       val |= REG_FIELD_PREP(LNL_ADDED_WAKE_TIME_MASK, added_wake_time);
+
+       intel_uncore_rmw(&i915->uncore, LNL_PKG_C_LATENCY, clear, val);
+}
+
 static int
 skl_compute_wm(struct intel_atomic_state *state)
 {
        struct intel_crtc *crtc;
        struct intel_crtc_state __maybe_unused *new_crtc_state;
        int ret, i;
+       bool vrr_enabled = false;
 
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
                ret = skl_build_pipe_wm(state, crtc);
                ret = skl_wm_add_affected_planes(state, crtc);
                if (ret)
                        return ret;
+
+               if (new_crtc_state->vrr.enable)
+                       vrr_enabled = true;
        }
 
+       skl_program_dpkgc_latency(to_i915(state->base.dev), vrr_enabled);
+
        skl_print_wm_changes(state);
 
        return 0;
                                    &intel_sagv_status_fops);
 }
 
-unsigned int skl_watermark_max_latency(struct drm_i915_private *i915)
+unsigned int skl_watermark_max_latency(struct drm_i915_private *i915, int initial_wm_level)
 {
        int level;
 
-       for (level = i915->display.wm.num_levels - 1; level >= 0; level--) {
+       for (level = i915->display.wm.num_levels - 1; level >= initial_wm_level; level--) {
                unsigned int latency = skl_wm_latency(i915, level, NULL);
 
                if (latency)