]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/cdclk: Add prefill helpers for CDCLK
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 14 Oct 2025 19:18:02 +0000 (22:18 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 16 Oct 2025 15:19:55 +0000 (18:19 +0300)
Add helpers to compute the CDCLKl adjustment factor for prefill
calculations. The adjustment factor is always <= 1.0. That is,
a faster CDCLK speeds up the pipe prefill.

intel_cdclk_prefill_adjustment_worst() gives out a worst case estimate,
meant to be used during guardband sizing. We can actually do better
than 1.0 here because the absolute minimum CDCLK is limited by the
dotclock. This will still allow planes, pfit, etc. to be changed any
which way without having to resize the guardband yet again.

intel_cdclk_prefill_adjustment() is supposed to give a more accurate
value based on the current min cdclk for the pipe, but currently that
is not yet available when this gets called. So for now use the same
worst case estimate here.

The returned numbers are in .16 binary fixed point.

TODO: the intel_cdclk_prefill_adjustment_worst() approach here
      can result in guardband changes for DRRS. But I'm thinking
      that is fine since M/N changes will always happen on the
      legacy timing generator so guardband doesn't actually matter.
      May need to think about this a bit more though...

v2: Use the worst case estimate always for now

Reviewed-by: Uma Shankar <uma.shankar@intel.com> #v1
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20251014191808.12326-4-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/display/intel_cdclk.h

index f2e092f89ddd72ea134b34fc9445e3d504395fac..10abc2521fabeafe6ab14fdd3674af7cae6c8510 100644 (file)
@@ -2806,16 +2806,20 @@ static int intel_cdclk_guardband(struct intel_display *display)
                return 90;
 }
 
-static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
+static int _intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state, int pixel_rate)
 {
        struct intel_display *display = to_intel_display(crtc_state);
        int ppc = intel_cdclk_ppc(display, crtc_state->double_wide);
        int guardband = intel_cdclk_guardband(display);
-       int pixel_rate = crtc_state->pixel_rate;
 
        return DIV_ROUND_UP(pixel_rate * 100, guardband * ppc);
 }
 
+static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
+{
+       return _intel_pixel_rate_to_cdclk(crtc_state, crtc_state->pixel_rate);
+}
+
 static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -4056,3 +4060,63 @@ void intel_cdclk_read_hw(struct intel_display *display)
        cdclk_state->actual = display->cdclk.hw;
        cdclk_state->logical = display->cdclk.hw;
 }
+
+static int calc_cdclk(const struct intel_crtc_state *crtc_state, int min_cdclk)
+{
+       struct intel_display *display = to_intel_display(crtc_state);
+
+       if (DISPLAY_VER(display) >= 10 || display->platform.broxton) {
+               return bxt_calc_cdclk(display, min_cdclk);
+       } else if (DISPLAY_VER(display) == 9) {
+               int vco;
+
+               vco = display->cdclk.skl_preferred_vco_freq;
+               if (vco == 0)
+                       vco = 8100000;
+
+               return skl_calc_cdclk(min_cdclk, vco);
+       } else if (display->platform.broadwell) {
+               return bdw_calc_cdclk(min_cdclk);
+       } else if (display->platform.cherryview || display->platform.valleyview) {
+               return vlv_calc_cdclk(display, min_cdclk);
+       } else {
+               return display->cdclk.max_cdclk_freq;
+       }
+}
+
+static unsigned int _intel_cdclk_prefill_adj(const struct intel_crtc_state *crtc_state,
+                                            int clock, int min_cdclk)
+{
+       struct intel_display *display = to_intel_display(crtc_state);
+       int ppc = intel_cdclk_ppc(display, crtc_state->double_wide);
+       int cdclk = calc_cdclk(crtc_state, min_cdclk);
+
+       return min(0x10000, DIV_ROUND_UP_ULL((u64)clock << 16, ppc * cdclk));
+}
+
+unsigned int intel_cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state)
+{
+       /* FIXME use the actual min_cdclk for the pipe here */
+       return intel_cdclk_prefill_adjustment_worst(crtc_state);
+}
+
+unsigned int intel_cdclk_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state)
+{
+       int clock = crtc_state->hw.pipe_mode.crtc_clock;
+       int min_cdclk;
+
+       /*
+        * FIXME could perhaps consider a few more of the factors
+        * that go the per-crtc min_cdclk. Namely anything that
+        * only changes during full modesets.
+        *
+        * FIXME this assumes 1:1 scaling, but the other _worst() stuff
+        * assumes max downscaling, so the final result will be
+        * unrealistically bad. Figure out where the actual maximum value
+        * lies and use that to compute a more realistic worst case
+        * estimate...
+        */
+       min_cdclk = _intel_pixel_rate_to_cdclk(crtc_state, clock);
+
+       return _intel_cdclk_prefill_adj(crtc_state, clock, min_cdclk);
+}
index 72963f6f399a6922f041c640ebbb01bf24dc97af..8774a320670bd04636eb74e4302284ff40d80f99 100644 (file)
@@ -70,4 +70,7 @@ bool intel_cdclk_pmdemand_needs_update(struct intel_atomic_state *state);
 void intel_cdclk_force_min_cdclk(struct intel_cdclk_state *cdclk_state, int force_min_cdclk);
 void intel_cdclk_read_hw(struct intel_display *display);
 
+unsigned int intel_cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state);
+unsigned int intel_cdclk_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state);
+
 #endif /* __INTEL_CDCLK_H__ */