diff mbox series

[v2,04/23] drm/i915/dp: Add helpers for Compressed BPP and Slice Count for DSC

Message ID 1533071239-28815-5-git-send-email-manasi.d.navare@intel.com (mailing list archive)
State New, archived
Headers show
Series Display Stream Compression enabling on eDP/DP | expand

Commit Message

Navare, Manasi July 31, 2018, 9:07 p.m. UTC
This patch adds helpers for calculating the maximum compressed BPP
supported with small joiner.
This also adds a helper for calculating the slice count in case
of small joiner.
These are inside intel_dp since they take into account hardware
limitations.

v5:
* Get the max slice width from DPCD
* Check against Min_Slice_width of 2560 (Anusha)
v4:
* #defines for PPR in slice count helper (Gaurav)
v3:
* Simply logic for bpp (DK)
* Limit the valid slice count by max supported by Sink (Manasi)
v2:
* Change the small joiner RAM buffer constant as bspec changed (Manasi)
* rename it as SMALL_JOINER since we are not enabling big joiner yet (Anusha)

Cc: Gaurav K Singh <gaurav.k.singh@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 104 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   4 ++
 2 files changed, 108 insertions(+)

Comments

Srivatsa, Anusha Aug. 17, 2018, 7:21 p.m. UTC | #1
>-----Original Message-----
>From: Navare, Manasi D
>Sent: Tuesday, July 31, 2018 2:07 PM
>To: intel-gfx@lists.freedesktop.org
>Cc: Navare, Manasi D <manasi.d.navare@intel.com>; Singh, Gaurav K
><gaurav.k.singh@intel.com>; Jani Nikula <jani.nikula@linux.intel.com>; Ville
>Syrjala <ville.syrjala@linux.intel.com>; Srivatsa, Anusha
><anusha.srivatsa@intel.com>; Pandiyan, Dhinakaran
><dhinakaran.pandiyan@intel.com>
>Subject: [PATCH v2 04/23] drm/i915/dp: Add helpers for Compressed BPP and
>Slice Count for DSC
>
>This patch adds helpers for calculating the maximum compressed BPP supported
>with small joiner.
>This also adds a helper for calculating the slice count in case of small joiner.
>These are inside intel_dp since they take into account hardware limitations.
>
>v5:
>* Get the max slice width from DPCD
>* Check against Min_Slice_width of 2560 (Anusha)
>v4:
>* #defines for PPR in slice count helper (Gaurav)
>v3:
>* Simply logic for bpp (DK)
>* Limit the valid slice count by max supported by Sink (Manasi)
>v2:
>* Change the small joiner RAM buffer constant as bspec changed (Manasi)
>* rename it as SMALL_JOINER since we are not enabling big joiner yet (Anusha)
>
>Cc: Gaurav K Singh <gaurav.k.singh@intel.com>
>Cc: Jani Nikula <jani.nikula@linux.intel.com>
>Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
>Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
>Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Looks good.
Reviewed-by: Anusha Srivatsa <anusha.srivatsa@intel.com>

>---
> drivers/gpu/drm/i915/intel_dp.c  | 104
>+++++++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_drv.h |   4 ++
> 2 files changed, 108 insertions(+)
>
>diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>index afa4e2d..ec2af43 100644
>--- a/drivers/gpu/drm/i915/intel_dp.c
>+++ b/drivers/gpu/drm/i915/intel_dp.c
>@@ -45,6 +45,17 @@
>
> #define DP_DPRX_ESI_LEN 14
>
>+/* DP DSC small joiner has 2 FIFOs each of 640 x 6 bytes */
>+#define DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER	61440
>+
>+/* DP DSC throughput values used for slice count calculations KPixels/s */
>+#define DP_DSC_PEAK_PIXEL_RATE			2720000
>+#define DP_DSC_MAX_ENC_THROUGHPUT_0		340000
>+#define DP_DSC_MAX_ENC_THROUGHPUT_1		400000
>+
>+/* DP DSC FEC Overhead factor = (100 - 2.4)/100 */
>+#define DP_DSC_FEC_OVERHEAD_FACTOR		976
>+
> /* Compliance test status bits  */
> #define INTEL_DP_RESOLUTION_SHIFT_MASK	0
> #define INTEL_DP_RESOLUTION_PREFERRED	(1 <<
>INTEL_DP_RESOLUTION_SHIFT_MASK)
>@@ -93,6 +104,14 @@ static const struct dp_link_dpll chv_dpll[] = {
> 		{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },  };
>
>+/* Constants for DP DSC configurations */ static const u8
>+valid_dsc_bpp[] = {6, 8, 10, 12, 15};
>+
>+/* With Single pipe configuration, HW is capable of supporting maximum
>+ * of 4 slices per line.
>+ */
>+static const u8 valid_dsc_slicecount[] = {1, 2, 4};
>+
> /**
>  * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or
>PCH)
>  * @intel_dp: DP struct
>@@ -4087,6 +4106,91 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp,
>u8 *sink_irq_vector)
> 		DP_DPRX_ESI_LEN;
> }
>
>+uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
>+				     int mode_clock, int mode_hdisplay) {
>+	u16 bits_per_pixel, max_bpp_small_joiner_ram;
>+	int i;
>+
>+	/*
>+	 * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
>+	 * (LinkSymbolClock)* 8 * ((100-FECOverhead)/100)*(TimeSlotsPerMTP)
>+	 * FECOverhead = 2.4%, for SST -> TimeSlotsPerMTP is 1,
>+	 * for MST -> TimeSlotsPerMTP has to be calculated
>+	 */
>+	bits_per_pixel = (link_clock * lane_count * 8 *
>+			  DP_DSC_FEC_OVERHEAD_FACTOR) /
>+		(mode_clock * 1000);
>+
>+	/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
>+	max_bpp_small_joiner_ram =
>DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER /
>+		mode_hdisplay;
>+
>+	/*
>+	 * Greatest allowed DSC BPP = MIN (output BPP from avaialble Link BW
>+	 * check, output bpp from small joiner RAM check)
>+	 */
>+	bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram);
>+
>+	/* Error out if the max bpp is less than smallest allowed valid bpp */
>+	if (bits_per_pixel < valid_dsc_bpp[0]) {
>+		DRM_DEBUG_KMS("Unsupported BPP %d\n", bits_per_pixel);
>+		return 0;
>+	}
>+
>+	/* Find the nearest match in the array of known BPPs from VESA */
>+	for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
>+		if (bits_per_pixel < valid_dsc_bpp[i + 1])
>+			break;
>+	}
>+	bits_per_pixel = valid_dsc_bpp[i];
>+
>+	/*
>+	 * Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
>+	 * fractional part is 0
>+	 */
>+	return bits_per_pixel << 4;
>+}
>+
>+uint8_t intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
>+				     int mode_clock,
>+				     int mode_hdisplay)
>+{
>+	u8 min_slice_count, i;
>+	int max_slice_width;
>+
>+	if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE)
>+		min_slice_count = DIV_ROUND_UP(mode_clock,
>+
>DP_DSC_MAX_ENC_THROUGHPUT_0);
>+	else
>+		min_slice_count = DIV_ROUND_UP(mode_clock,
>+
>DP_DSC_MAX_ENC_THROUGHPUT_1);
>+
>+	max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp-
>>dsc_dpcd);
>+	if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) {
>+		DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink
>device\n",
>+			      max_slice_width);
>+		return 0;
>+	}
>+	/* Also take into account max slice width */
>+	min_slice_count = min_t(uint8_t, min_slice_count,
>+				DIV_ROUND_UP(mode_hdisplay,
>+					     max_slice_width));
>+
>+	/* Find the closest match to the valid slice count values */
>+	for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
>+		if (valid_dsc_slicecount[i] >
>+		    drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
>+						    false))
>+			break;
>+		if (min_slice_count  <= valid_dsc_slicecount[i])
>+			return valid_dsc_slicecount[i];
>+	}
>+
>+	DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count);
>+	return 0;
>+}
>+
> static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)  {
> 	int status = 0;
>diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>index 29abe7a..68b2401 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -1735,6 +1735,10 @@ bool intel_dp_source_supports_hbr2(struct intel_dp
>*intel_dp);  bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);  bool
>intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t
>link_status[DP_LINK_STATUS_SIZE]);
>+uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
>+				     int mode_clock, int mode_hdisplay); uint8_t
>+intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
>+				     int mode_hdisplay);
>
> static inline unsigned int intel_dp_unused_lane_mask(int lane_count)  {
>--
>2.7.4
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index afa4e2d..ec2af43 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -45,6 +45,17 @@ 
 
 #define DP_DPRX_ESI_LEN 14
 
+/* DP DSC small joiner has 2 FIFOs each of 640 x 6 bytes */
+#define DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER	61440
+
+/* DP DSC throughput values used for slice count calculations KPixels/s */
+#define DP_DSC_PEAK_PIXEL_RATE			2720000
+#define DP_DSC_MAX_ENC_THROUGHPUT_0		340000
+#define DP_DSC_MAX_ENC_THROUGHPUT_1		400000
+
+/* DP DSC FEC Overhead factor = (100 - 2.4)/100 */
+#define DP_DSC_FEC_OVERHEAD_FACTOR		976
+
 /* Compliance test status bits  */
 #define INTEL_DP_RESOLUTION_SHIFT_MASK	0
 #define INTEL_DP_RESOLUTION_PREFERRED	(1 << INTEL_DP_RESOLUTION_SHIFT_MASK)
@@ -93,6 +104,14 @@  static const struct dp_link_dpll chv_dpll[] = {
 		{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
 };
 
+/* Constants for DP DSC configurations */
+static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
+
+/* With Single pipe configuration, HW is capable of supporting maximum
+ * of 4 slices per line.
+ */
+static const u8 valid_dsc_slicecount[] = {1, 2, 4};
+
 /**
  * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
  * @intel_dp: DP struct
@@ -4087,6 +4106,91 @@  intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 		DP_DPRX_ESI_LEN;
 }
 
+uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
+				     int mode_clock, int mode_hdisplay)
+{
+	u16 bits_per_pixel, max_bpp_small_joiner_ram;
+	int i;
+
+	/*
+	 * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
+	 * (LinkSymbolClock)* 8 * ((100-FECOverhead)/100)*(TimeSlotsPerMTP)
+	 * FECOverhead = 2.4%, for SST -> TimeSlotsPerMTP is 1,
+	 * for MST -> TimeSlotsPerMTP has to be calculated
+	 */
+	bits_per_pixel = (link_clock * lane_count * 8 *
+			  DP_DSC_FEC_OVERHEAD_FACTOR) /
+		(mode_clock * 1000);
+
+	/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
+	max_bpp_small_joiner_ram = DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER /
+		mode_hdisplay;
+
+	/*
+	 * Greatest allowed DSC BPP = MIN (output BPP from avaialble Link BW
+	 * check, output bpp from small joiner RAM check)
+	 */
+	bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram);
+
+	/* Error out if the max bpp is less than smallest allowed valid bpp */
+	if (bits_per_pixel < valid_dsc_bpp[0]) {
+		DRM_DEBUG_KMS("Unsupported BPP %d\n", bits_per_pixel);
+		return 0;
+	}
+
+	/* Find the nearest match in the array of known BPPs from VESA */
+	for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
+		if (bits_per_pixel < valid_dsc_bpp[i + 1])
+			break;
+	}
+	bits_per_pixel = valid_dsc_bpp[i];
+
+	/*
+	 * Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
+	 * fractional part is 0
+	 */
+	return bits_per_pixel << 4;
+}
+
+uint8_t intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
+				     int mode_clock,
+				     int mode_hdisplay)
+{
+	u8 min_slice_count, i;
+	int max_slice_width;
+
+	if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE)
+		min_slice_count = DIV_ROUND_UP(mode_clock,
+					       DP_DSC_MAX_ENC_THROUGHPUT_0);
+	else
+		min_slice_count = DIV_ROUND_UP(mode_clock,
+					       DP_DSC_MAX_ENC_THROUGHPUT_1);
+
+	max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd);
+	if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) {
+		DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink device\n",
+			      max_slice_width);
+		return 0;
+	}
+	/* Also take into account max slice width */
+	min_slice_count = min_t(uint8_t, min_slice_count,
+				DIV_ROUND_UP(mode_hdisplay,
+					     max_slice_width));
+
+	/* Find the closest match to the valid slice count values */
+	for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
+		if (valid_dsc_slicecount[i] >
+		    drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
+						    false))
+			break;
+		if (min_slice_count  <= valid_dsc_slicecount[i])
+			return valid_dsc_slicecount[i];
+	}
+
+	DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count);
+	return 0;
+}
+
 static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 {
 	int status = 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 29abe7a..68b2401 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1735,6 +1735,10 @@  bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
 bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);
 bool
 intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);
+uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
+				     int mode_clock, int mode_hdisplay);
+uint8_t intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
+				     int mode_hdisplay);
 
 static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
 {