diff mbox series

[08/29] drm/dp: Add helpers to calculate the link BW overhead

Message ID 20231024010925.3949910-9-imre.deak@intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Improve BW management on MST links | expand

Commit Message

Imre Deak Oct. 24, 2023, 1:09 a.m. UTC
Add helpers drivers can use to calculate the BW allocation overhead -
due to SSC, FEC, DSC and data alignment on symbol cycles - and the
channel coding efficiency - due to the 8b/10b, 128b/132b encoding. On
128b/132b links the FEC overhead is part of the coding efficiency, so
not accounted for in the BW allocation overhead.

The drivers can use these functions to calculate a ratio, controlling
the stream symbol insertion rate of the source device in each SST TU
or MST MTP frame. Drivers can calculate this

m/n = drm_dp_bw_overhead() / drm_dp_bw_channel_coding_efficiency()

ratio for a given stream and with that the

mtp_count = CEIL(64 * m / n)

allocated MTPs for the stream in a frame and

pbn = CEIL(64 * dm_mst_get_pbn_divider() * m / n)

allocated PBNs for the stream on the MST link path.

Take drm_dp_bw_overhead() into use in drm_dp_calc_pbn_mode(), for
drivers calculating the PBN value directly.

Cc: Lyude Paul <lyude@redhat.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_helper.c       | 113 ++++++++++++++++++
 drivers/gpu/drm/display/drm_dp_mst_topology.c |  23 +++-
 include/drm/display/drm_dp_helper.h           |  11 ++
 3 files changed, 141 insertions(+), 6 deletions(-)

Comments

kernel test robot Oct. 24, 2023, 2:47 a.m. UTC | #1
Hi Imre,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-tip/drm-tip]

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-dp_mst-Fix-fractional-DSC-bpp-handling/20231024-091920
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20231024010925.3949910-9-imre.deak%40intel.com
patch subject: [Intel-gfx] [PATCH 08/29] drm/dp: Add helpers to calculate the link BW overhead
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20231024/202310241055.Pz9vy06V-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231024/202310241055.Pz9vy06V-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202310241055.Pz9vy06V-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/display/drm_dp_helper.c:4002: warning: Function parameter or member 'is_uhbr' not described in 'drm_dp_bw_channel_coding_efficiency'
>> drivers/gpu/drm/display/drm_dp_helper.c:4002: warning: expecting prototype for Returns the efficiency in the 100%/coding(). Prototype was for drm_dp_bw_channel_coding_efficiency() instead


vim +4002 drivers/gpu/drm/display/drm_dp_helper.c

  3996	
  3997	/**
  3998	 * Returns the efficiency in the 100%/coding-overhead% ratio in
  3999	 * 1ppm units.
  4000	 */
  4001	int drm_dp_bw_channel_coding_efficiency(bool is_uhbr)
> 4002	{
  4003		if (is_uhbr)
  4004			return 967100;
  4005		else
  4006			/*
  4007			 * Note that on 8b/10b MST the efficiency is only
  4008			 * 78.75% due to the 1 out of 64 MTPH packet overhead,
  4009			 * not accounted for here.
  4010			 */
  4011			return 800000;
  4012	}
  4013	EXPORT_SYMBOL(drm_dp_bw_channel_coding_efficiency);
  4014
kernel test robot Oct. 24, 2023, 12:34 p.m. UTC | #2
Hi Imre,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-tip/drm-tip]

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-dp_mst-Fix-fractional-DSC-bpp-handling/20231024-091920
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20231024010925.3949910-9-imre.deak%40intel.com
patch subject: [Intel-gfx] [PATCH 08/29] drm/dp: Add helpers to calculate the link BW overhead
config: x86_64-buildonly-randconfig-003-20231024 (https://download.01.org/0day-ci/archive/20231024/202310242019.Hp2KseM1-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231024/202310242019.Hp2KseM1-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202310242019.Hp2KseM1-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/gpu/drm/display/drm_dp_mst_topology.o: in function `drm_dp_calc_pbn_mode':
>> drm_dp_mst_topology.c:(.text+0x1403): undefined reference to `drm_dp_bw_overhead'
kernel test robot Oct. 25, 2023, 3:47 p.m. UTC | #3
Hi Imre,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-tip/drm-tip]

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-dp_mst-Fix-fractional-DSC-bpp-handling/20231024-091920
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20231024010925.3949910-9-imre.deak%40intel.com
patch subject: [Intel-gfx] [PATCH 08/29] drm/dp: Add helpers to calculate the link BW overhead
config: arm-s5pv210_defconfig (https://download.01.org/0day-ci/archive/20231025/202310252345.i0qKzGuh-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231025/202310252345.i0qKzGuh-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202310252345.i0qKzGuh-lkp@intel.com/

All errors (new ones prefixed by >>):

   arm-linux-gnueabi-ld: drivers/gpu/drm/display/drm_dp_mst_topology.o: in function `drm_dp_calc_pbn_mode':
>> drivers/gpu/drm/display/drm_dp_mst_topology.c:4745:(.text+0x12b0): undefined reference to `drm_dp_bw_overhead'


vim +4745 drivers/gpu/drm/display/drm_dp_mst_topology.c

  4718	
  4719	/**
  4720	 * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
  4721	 * @clock: dot clock
  4722	 * @bpp: bpp as .4 binary fixed point
  4723	 *
  4724	 * This uses the formula in the spec to calculate the PBN value for a mode.
  4725	 */
  4726	int drm_dp_calc_pbn_mode(int clock, int bpp)
  4727	{
  4728		/*
  4729		 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
  4730		 * common multiplier to render an integer PBN for all link rate/lane
  4731		 * counts combinations
  4732		 * calculate
  4733		 * peak_kbps = clock * bpp / 16
  4734		 * peak_kbps *= SSC overhead / 1000000
  4735		 * peak_kbps /= 8    convert to Kbytes
  4736		 * peak_kBps *= (64/54) / 1000    convert to PBN
  4737		 */
  4738		/*
  4739		 * TODO: Use the actual link and mode parameters to calculate
  4740		 * the overhead. For now it's assumed that these are
  4741		 * 4 link lanes, 4096 hactive pixels, which don't add any
  4742		 * significant data padding overhead and that there is no DSC
  4743		 * or FEC overhead.
  4744		 */
> 4745		int overhead = drm_dp_bw_overhead(4, 4096, 0, bpp,
  4746						  DRM_DP_BW_OVERHEAD_MST |
  4747						  DRM_DP_BW_OVERHEAD_SSC);
  4748	
  4749		return DIV64_U64_ROUND_UP(mul_u32_u32(clock * bpp, 64 * overhead >> 4),
  4750					  1000000ULL * 8 * 54 * 1000);
  4751	}
  4752	EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
  4753
diff mbox series

Patch

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index e5d7970a9ddd0..98c533b74ac89 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -3899,4 +3899,117 @@  int drm_panel_dp_aux_backlight(struct drm_panel *panel, struct drm_dp_aux *aux)
 }
 EXPORT_SYMBOL(drm_panel_dp_aux_backlight);
 
+/* See DP Standard v2.1 2.6.4.4.1.1, 2.8.4.4, 2.8.7 */
+static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16,
+				     int symbol_size, bool is_mst)
+{
+	int cycles = DIV_ROUND_UP(pixels * bpp_x16, 16 * symbol_size * lane_count);
+	int align = is_mst ? 4 / lane_count : 1;
+
+	return ALIGN(cycles, align);
+}
+
+static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int slice_count,
+					 int bpp_x16, int symbol_size, bool is_mst)
+{
+	int slice_pixels = DIV_ROUND_UP(pixels, slice_count);
+	int slice_data_cycles = drm_dp_link_symbol_cycles(lane_count, slice_pixels,
+							  bpp_x16, symbol_size, is_mst);
+	int slice_eoc_cycles = is_mst ? 4 / lane_count : 1;
+
+	return slice_count * (slice_data_cycles + slice_eoc_cycles);
+}
+
+/**
+ * drm_dp_bw_overhead - Calculate the BW overhead of a DP link stream
+ * @lane_count: DP link lane count
+ * @hactive: pixel count of the active period in one scanline of the stream
+ * @dsc_slice_count: DSC slice count if @flags/DRM_DP_LINK_BW_OVERHEAD_DSC is set
+ * @bpp_x16: bits per pixel in .4 binary fixed point
+ * @flags: DRM_DP_OVERHEAD_x flags
+ *
+ * Calculate the BW allocation overhead of a DP link stream, depending
+ * on the link's
+ * - @lane_count
+ * - SST/MST mode (@flags / %DRM_DP_OVERHEAD_MST)
+ * - symbol size (@flags / %DRM_DP_OVERHEAD_UHBR)
+ * - FEC mode (@flags / %DRM_DP_OVERHEAD_FEC)
+ * - SSC mode (@flags / %DRM_DP_OVERHEAD_SSC)
+ * as well as the stream's
+ * - @hactive timing
+ * - @bpp_x16 color depth
+ * - compression mode (@flags / %DRM_DP_OVERHEAD_DSC).
+ * Note that this overhead doesn't account for the 8b/10b, 128b/132b
+ * channel coding efficiency, for that see
+ * @drm_dp_link_bw_channel_coding_efficiency().
+ *
+ * Returns the overhead as 100% + overhead% in 1ppm units.
+ */
+int drm_dp_bw_overhead(int lane_count, int hactive,
+		       int dsc_slice_count,
+		       int bpp_x16, unsigned long flags)
+{
+	int symbol_size = flags & DRM_DP_BW_OVERHEAD_UHBR ? 32 : 8;
+	bool is_mst = flags & DRM_DP_BW_OVERHEAD_MST;
+	u32 overhead = 1000000;
+	int symbol_cycles;
+
+	/*
+	 * DP Standard v2.1 2.6.4.1
+	 * SSC downspread and ref clock variation margin:
+	 *   5300ppm + 300ppm ~ 0.6%
+	 */
+	if (flags & DRM_DP_BW_OVERHEAD_SSC)
+		overhead += 6000;
+
+	/*
+	 * DP Standard v2.1 2.6.4.1.1:
+	 * FEC symbol insertions for 8b/10b channel coding:
+	 *   2.4%
+	 */
+	if (flags & DRM_DP_BW_OVERHEAD_FEC)
+		overhead += 24000;
+
+	/*
+	 * DP Standard v2.1 2.7.9, 5.9.7
+	 * The FEC overhead for UHBR is accounted for in its 96.71% channel
+	 * coding efficiency.
+	 */
+	WARN_ON((flags & DRM_DP_BW_OVERHEAD_UHBR) &&
+		(flags & DRM_DP_BW_OVERHEAD_FEC));
+
+	if (flags & DRM_DP_BW_OVERHEAD_DSC)
+		symbol_cycles = drm_dp_link_dsc_symbol_cycles(lane_count, hactive,
+							      dsc_slice_count,
+							      bpp_x16, symbol_size,
+							      is_mst);
+	else
+		symbol_cycles = drm_dp_link_symbol_cycles(lane_count, hactive,
+							  bpp_x16, symbol_size,
+							  is_mst);
+
+	return DIV_ROUND_UP_ULL(mul_u32_u32(symbol_cycles * symbol_size * lane_count,
+					    overhead * 16),
+				hactive * bpp_x16);
+}
+EXPORT_SYMBOL(drm_dp_bw_overhead);
+
+/**
+ * Returns the efficiency in the 100%/coding-overhead% ratio in
+ * 1ppm units.
+ */
+int drm_dp_bw_channel_coding_efficiency(bool is_uhbr)
+{
+	if (is_uhbr)
+		return 967100;
+	else
+		/*
+		 * Note that on 8b/10b MST the efficiency is only
+		 * 78.75% due to the 1 out of 64 MTPH packet overhead,
+		 * not accounted for here.
+		 */
+		return 800000;
+}
+EXPORT_SYMBOL(drm_dp_bw_channel_coding_efficiency);
+
 #endif
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index cc0a8fe84d290..d7383f2fd6cfe 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4726,17 +4726,28 @@  EXPORT_SYMBOL(drm_dp_check_act_status);
 int drm_dp_calc_pbn_mode(int clock, int bpp)
 {
 	/*
-	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
 	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
 	 * common multiplier to render an integer PBN for all link rate/lane
 	 * counts combinations
 	 * calculate
-	 * peak_kbps *= (1006/1000)
-	 * peak_kbps *= (64/54)
-	 * peak_kbps *= 8    convert to bytes
+	 * peak_kbps = clock * bpp / 16
+	 * peak_kbps *= SSC overhead / 1000000
+	 * peak_kbps /= 8    convert to Kbytes
+	 * peak_kBps *= (64/54) / 1000    convert to PBN
 	 */
-	return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006 >> 4),
-				1000 * 8 * 54 * 1000);
+	/*
+	 * TODO: Use the actual link and mode parameters to calculate
+	 * the overhead. For now it's assumed that these are
+	 * 4 link lanes, 4096 hactive pixels, which don't add any
+	 * significant data padding overhead and that there is no DSC
+	 * or FEC overhead.
+	 */
+	int overhead = drm_dp_bw_overhead(4, 4096, 0, bpp,
+					  DRM_DP_BW_OVERHEAD_MST |
+					  DRM_DP_BW_OVERHEAD_SSC);
+
+	return DIV64_U64_ROUND_UP(mul_u32_u32(clock * bpp, 64 * overhead >> 4),
+				  1000000ULL * 8 * 54 * 1000);
 }
 EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index 351f38d5cc351..010cb5a3b39e0 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -788,4 +788,15 @@  bool drm_dp_downstream_rgb_to_ycbcr_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZ
 					       const u8 port_cap[4], u8 color_spc);
 int drm_dp_pcon_convert_rgb_to_ycbcr(struct drm_dp_aux *aux, u8 color_spc);
 
+#define DRM_DP_BW_OVERHEAD_MST	BIT(0)
+#define DRM_DP_BW_OVERHEAD_UHBR	BIT(1)
+#define DRM_DP_BW_OVERHEAD_SSC	BIT(2)
+#define DRM_DP_BW_OVERHEAD_FEC	BIT(3)
+#define DRM_DP_BW_OVERHEAD_DSC	BIT(4)
+
+int drm_dp_bw_overhead(int lane_count, int hactive,
+		       int dsc_slice_count,
+		       int bpp_x16, unsigned long flags);
+int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
+
 #endif /* _DRM_DP_HELPER_H_ */