drm/dp_mst: Fix fractional DSC bpp handling
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 24 Oct 2023 01:08:57 +0000 (04:08 +0300)
committerImre Deak <imre.deak@intel.com>
Wed, 8 Nov 2023 15:22:05 +0000 (17:22 +0200)
The current code does '(bpp << 4) / 16' in the MST PBN
calculation, but that is just the same as 'bpp' so the
DSC codepath achieves absolutely nothing. Fix it up so that
the fractional part of the bpp value is actually used instead
of truncated away. 64*1006 has enough zero lsbs that we can
just shift that down in the dividend and thus still manage
to stick to a 32bit divisor.

And while touching this, let's just make the whole thing more
straightforward by making the passed in bpp value .4 binary
fixed point always, instead of having to pass in different
things based on whether DSC is enabled or not.

v2:
- Fix DSC kunit test cases.

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: David Francis <David.Francis@amd.com>
Cc: Mikita Lipski <mikita.lipski@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Fixes: dc48529fb14e ("drm/dp_mst: Add PBN calculation for DSC modes")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
[Imre: Fix kunit test cases]
Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-3-imre.deak@intel.com
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/display/drm_dp_mst_topology.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
include/drm/display/drm_dp_mst_helper.h

index c6fd34bab3585ad8c027f4b1bcc3af145bb379a9..df3c42bb92742487ca13109d76f3c9be646226ae 100644 (file)
@@ -6876,7 +6876,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
                                                                    max_bpc);
                bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
                clock = adjusted_mode->clock;
-               dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
+               dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp << 4);
        }
 
        dm_new_connector_state->vcpi_slots =
index 57230661132bd9bf7a9c41cd3ceaa589000d9754..2afd1bc74978da3cfcb824d4687e58741dd3fdd6 100644 (file)
@@ -1636,7 +1636,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
        } else {
                /* check if mode could be supported within full_pbn */
                bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3;
-               pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false);
+               pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp << 4);
 
                if (pbn > aconnector->mst_output_port->full_pbn)
                        return DC_FAIL_BANDWIDTH_VALIDATE;
index c490e8befc2facf104ec577f7b54ffef5287ffb4..bc2c9dfe229fc67947ac9bf071440f17b5d7a7c6 100644 (file)
@@ -4718,13 +4718,12 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
 
 /**
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
- * @clock: dot clock for the mode
- * @bpp: bpp for the mode.
- * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel
+ * @clock: dot clock
+ * @bpp: bpp as .4 binary fixed point
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
+int drm_dp_calc_pbn_mode(int clock, int bpp)
 {
        /*
         * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
@@ -4735,18 +4734,9 @@ int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
         * peak_kbps *= (1006/1000)
         * peak_kbps *= (64/54)
         * peak_kbps *= 8    convert to bytes
-        *
-        * If the bpp is in units of 1/16, further divide by 16. Put this
-        * factor in the numerator rather than the denominator to avoid
-        * integer overflow
         */
-
-       if (dsc)
-               return DIV_ROUND_UP_ULL(mul_u32_u32(clock * (bpp / 16), 64 * 1006),
-                                       8 * 54 * 1000 * 1000);
-
-       return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006),
-                               8 * 54 * 1000 * 1000);
+       return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006 >> 4),
+                               1000 * 8 * 54 * 1000);
 }
 EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 
index 4625900416e9e83d2d589a193ebd086dfa065bcc..6f9c9f3b5b12131b22ffda20d8c33e258169b5a9 100644 (file)
@@ -107,8 +107,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
                        continue;
 
                crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-                                                      dsc ? bpp << 4 : bpp,
-                                                      dsc);
+                                                      bpp << 4);
 
                slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
                                                      connector->port,
@@ -982,7 +981,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
                return ret;
 
        if (mode_rate > max_rate || mode->clock > max_dotclk ||
-           drm_dp_calc_pbn_mode(mode->clock, min_bpp, false) > port->full_pbn) {
+           drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) {
                *status = MODE_CLOCK_HIGH;
                return 0;
        }
index 52f1569ee37c1de3520c14b6cb5fd88d600f289d..3d390f5029f659f4016a751c24972aa4e6bbbffc 100644 (file)
@@ -982,8 +982,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
                const int clock = crtc_state->adjusted_mode.clock;
 
                asyh->or.bpc = connector->display_info.bpc;
-               asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3,
-                                                   false);
+               asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3 << 4);
        }
 
        mst_state = drm_atomic_get_mst_topology_state(state, &mstm->mgr);
index 545beea33e8c70d0c9544528ce176cb72ddb9454..e3c818dfc0e6d28e48a135a4011527dcb8af7e0f 100644 (file)
@@ -42,13 +42,13 @@ static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases
                .clock = 332880,
                .bpp = 24,
                .dsc = true,
-               .expected = 50
+               .expected = 1191
        },
        {
                .clock = 324540,
                .bpp = 24,
                .dsc = true,
-               .expected = 49
+               .expected = 1161
        },
 };
 
@@ -56,7 +56,7 @@ static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
 {
        const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
 
-       KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp, params->dsc),
+       KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp << 4),
                        params->expected);
 }
 
index 4429d3b1745b63b060ea691957f604558560c12d..655862b3d2a4988d33758e9e756b761cb8d27e4d 100644 (file)
@@ -842,7 +842,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector,
 int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
                             int link_rate, int link_lane_count);
 
-int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc);
+int drm_dp_calc_pbn_mode(int clock, int bpp);
 
 void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap);