From: Ville Syrjälä <[email protected]>

Fix up the total mess when calculating the DCLK
frequency. Some codepaths are trying to do both DIV_ROUND_UP()
and an open coded "round to nearest" at the same time. The
MTL+ codepath was the only one that was correct (using
DIV_ROUND_CLOSEST()).

Let's unify all of them, and borrow the actual '100/6'
approach from adl_calc_psf_bw() so that we get even less
rounding errors.

Signed-off-by: Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_bw.c | 26 +++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bw.c 
b/drivers/gpu/drm/i915/display/intel_bw.c
index d10eebec196e..442e6b657ca5 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -67,25 +67,31 @@ struct intel_qgv_info {
        u8 deinterleave;
 };
 
+static int dclk_freq_mhz(int ratio)
+{
+       /* multiple of 16.666 MHz (100/6) */
+       return DIV_ROUND_CLOSEST(ratio * 100, 6);
+}
+
 static int dg1_mchbar_read_qgv_point_info(struct intel_display *display,
                                          struct intel_qgv_point *sp,
                                          int point)
 {
-       u32 dclk_ratio, dclk_reference;
+       u32 dclk_ratio;
        u32 val;
 
        val = intel_mchbar_read(display, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
        dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val);
        if (val & DG1_QCLK_REFERENCE)
-               dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
+               dclk_ratio *= 6; /* 6 * 16.666 MHz = 100 MHz */
        else
-               dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
-       sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 
1000);
+               dclk_ratio *= 8; /* 8 * 16.666 MHz = 133 MHz */
 
        val = intel_mchbar_read(display, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
        if (val & DG1_GEAR_TYPE)
-               sp->dclk *= 2;
+               dclk_ratio *= 2;
 
+       sp->dclk = dclk_freq_mhz(dclk_ratio);
        if (sp->dclk == 0)
                return -EINVAL;
 
@@ -107,7 +113,6 @@ static int icl_pcode_read_qgv_point_info(struct 
intel_display *display,
                                         int point)
 {
        u32 val = 0, val2 = 0;
-       u16 dclk;
        int ret;
 
        ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
@@ -116,9 +121,7 @@ static int icl_pcode_read_qgv_point_info(struct 
intel_display *display,
        if (ret)
                return ret;
 
-       dclk = val & 0xffff;
-       sp->dclk = DIV_ROUND_UP((16667 * dclk) + (DISPLAY_VER(display) >= 12 ? 
500 : 0),
-                               1000);
+       sp->dclk = dclk_freq_mhz(val & 0xffff);
        sp->t_rp = (val & 0xff0000) >> 16;
        sp->t_rcd = (val & 0xff000000) >> 24;
 
@@ -208,12 +211,11 @@ static int mtl_read_qgv_point_info(struct intel_display 
*display,
                                   struct intel_qgv_point *sp, int point)
 {
        u32 val, val2;
-       u16 dclk;
 
        val = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_LOW(point));
        val2 = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
-       dclk = REG_FIELD_GET(MTL_DCLK_MASK, val);
-       sp->dclk = DIV_ROUND_CLOSEST(16667 * dclk, 1000);
+
+       sp->dclk = dclk_freq_mhz(REG_FIELD_GET(MTL_DCLK_MASK, val));
        sp->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val);
        sp->t_rcd = REG_FIELD_GET(MTL_TRCD_MASK, val);
 
-- 
2.52.0

Reply via email to