Re: [Intel-gfx] [PATCH 11/29] drm/i915/dp: Pass actual BW overhead to m_n calculation

2023-10-24 Thread Lisovskiy, Stanislav
On Tue, Oct 24, 2023 at 04:09:07AM +0300, Imre Deak wrote:
> A follow-up MST patch will need to specify the total BW allocation
> overhead, prepare for that here by passing the amount of overhead
> to intel_link_compute_m_n(), keeping the existing behavior.
> 
> Signed-off-by: Imre Deak 

Reviewed-by: Stanislav Lisovskiy 

> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 40 +---
>  drivers/gpu/drm/i915/display/intel_display.h |  4 +-
>  drivers/gpu/drm/i915/display/intel_dp.c  | 30 ---
>  drivers/gpu/drm/i915/display/intel_dp.h  |  2 +
>  drivers/gpu/drm/i915/display/intel_dp_mst.c  |  8 ++--
>  drivers/gpu/drm/i915/display/intel_fdi.c |  5 ++-
>  6 files changed, 71 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 28d85e1e858ea..de352d9c43439 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -2396,17 +2396,45 @@ static void compute_m_n(u32 *ret_m, u32 *ret_n,
>   intel_reduce_m_n_ratio(ret_m, ret_n);
>  }
>  
> +static void
> +add_bw_alloc_overhead(int link_clock, int bw_overhead,
> +   int pixel_data_rate, int link_data_rate,
> +   u32 *data_m, u32 *data_n)
> +{
> + bool is_uhbr = intel_dp_is_uhbr_rate(link_clock);
> + int ch_coding_efficiency =
> + drm_dp_bw_channel_coding_efficiency(is_uhbr);
> +
> + /*
> +  * TODO: adjust for actual UHBR channel coding efficiency and BW
> +  * overhead.
> +  */
> + if (is_uhbr) {
> + *data_m = pixel_data_rate;
> + *data_n = link_data_rate * 8 / 10;
> + return;
> + }
> +
> + *data_m = DIV_ROUND_UP_ULL(mul_u32_u32(pixel_data_rate, bw_overhead),
> +100);
> + *data_n = DIV_ROUND_DOWN_ULL(mul_u32_u32(link_data_rate, 
> ch_coding_efficiency),
> +  100);
> +}
> +
>  void
>  intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
>  int pixel_clock, int link_clock,
> -struct intel_link_m_n *m_n,
> -bool fec_enable)
> +int bw_overhead,
> +struct intel_link_m_n *m_n)
>  {
>   u32 data_clock = bits_per_pixel * pixel_clock;
> + u32 data_m;
> + u32 data_n;
>  
> - if (fec_enable)
> - data_clock = intel_dp_mode_to_fec_clock(data_clock);
> -
> + add_bw_alloc_overhead(link_clock, bw_overhead,
> +   data_clock,
> +   link_clock * 10 * nlanes,
> +   _m, _n);
>   /*
>* Windows/BIOS uses fixed M/N values always. Follow suit.
>*
> @@ -2416,7 +2444,7 @@ intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
>*/
>   m_n->tu = 64;
>   compute_m_n(_n->data_m, _n->data_n,
> - data_clock, link_clock * nlanes * 8,
> + data_m, data_n,
>   0x800);
>  
>   compute_m_n(_n->link_m, _n->link_n,
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
> b/drivers/gpu/drm/i915/display/intel_display.h
> index 0e5dffe8f0189..dea3202849e72 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -395,8 +395,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state 
> *state,
>  u8 active_pipes);
>  void intel_link_compute_m_n(u16 bpp, int nlanes,
>   int pixel_clock, int link_clock,
> - struct intel_link_m_n *m_n,
> - bool fec_enable);
> + int bw_overhead,
> + struct intel_link_m_n *m_n);
>  u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> u32 pixel_format, u64 modifier);
>  enum drm_mode_status
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 0c0f026fb3161..0235de5bb8cd1 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -121,10 +121,15 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
>  
>  static void intel_dp_unset_edid(struct intel_dp *intel_dp);
>  
> +bool intel_dp_is_uhbr_rate(int rate)
> +{
> + return rate >= 100;
> +}
> +
>  /* Is link rate UHBR and thus 128b/132b? */
>  bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state)
>  {
> - return crtc_state->port_clock >= 100;
> + return intel_dp_is_uhbr_rate(crtc_state->port_clock);
>  }
>  
>  static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
> @@ -684,6 +689,20 @@ u32 intel_dp_mode_to_fec_clock(u32 mode_clock)
>  100U);
>  }
>  
> +int intel_dp_bw_fec_overhead(bool fec_enabled)
> +{
> + /*
> +  * TODO: 

[Intel-gfx] [PATCH 11/29] drm/i915/dp: Pass actual BW overhead to m_n calculation

2023-10-23 Thread Imre Deak
A follow-up MST patch will need to specify the total BW allocation
overhead, prepare for that here by passing the amount of overhead
to intel_link_compute_m_n(), keeping the existing behavior.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_display.c | 40 +---
 drivers/gpu/drm/i915/display/intel_display.h |  4 +-
 drivers/gpu/drm/i915/display/intel_dp.c  | 30 ---
 drivers/gpu/drm/i915/display/intel_dp.h  |  2 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  8 ++--
 drivers/gpu/drm/i915/display/intel_fdi.c |  5 ++-
 6 files changed, 71 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 28d85e1e858ea..de352d9c43439 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2396,17 +2396,45 @@ static void compute_m_n(u32 *ret_m, u32 *ret_n,
intel_reduce_m_n_ratio(ret_m, ret_n);
 }
 
+static void
+add_bw_alloc_overhead(int link_clock, int bw_overhead,
+ int pixel_data_rate, int link_data_rate,
+ u32 *data_m, u32 *data_n)
+{
+   bool is_uhbr = intel_dp_is_uhbr_rate(link_clock);
+   int ch_coding_efficiency =
+   drm_dp_bw_channel_coding_efficiency(is_uhbr);
+
+   /*
+* TODO: adjust for actual UHBR channel coding efficiency and BW
+* overhead.
+*/
+   if (is_uhbr) {
+   *data_m = pixel_data_rate;
+   *data_n = link_data_rate * 8 / 10;
+   return;
+   }
+
+   *data_m = DIV_ROUND_UP_ULL(mul_u32_u32(pixel_data_rate, bw_overhead),
+  100);
+   *data_n = DIV_ROUND_DOWN_ULL(mul_u32_u32(link_data_rate, 
ch_coding_efficiency),
+100);
+}
+
 void
 intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
   int pixel_clock, int link_clock,
-  struct intel_link_m_n *m_n,
-  bool fec_enable)
+  int bw_overhead,
+  struct intel_link_m_n *m_n)
 {
u32 data_clock = bits_per_pixel * pixel_clock;
+   u32 data_m;
+   u32 data_n;
 
-   if (fec_enable)
-   data_clock = intel_dp_mode_to_fec_clock(data_clock);
-
+   add_bw_alloc_overhead(link_clock, bw_overhead,
+ data_clock,
+ link_clock * 10 * nlanes,
+ _m, _n);
/*
 * Windows/BIOS uses fixed M/N values always. Follow suit.
 *
@@ -2416,7 +2444,7 @@ intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
 */
m_n->tu = 64;
compute_m_n(_n->data_m, _n->data_n,
-   data_clock, link_clock * nlanes * 8,
+   data_m, data_n,
0x800);
 
compute_m_n(_n->link_m, _n->link_n,
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index 0e5dffe8f0189..dea3202849e72 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -395,8 +395,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state *state,
   u8 active_pipes);
 void intel_link_compute_m_n(u16 bpp, int nlanes,
int pixel_clock, int link_clock,
-   struct intel_link_m_n *m_n,
-   bool fec_enable);
+   int bw_overhead,
+   struct intel_link_m_n *m_n);
 u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
  u32 pixel_format, u64 modifier);
 enum drm_mode_status
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 0c0f026fb3161..0235de5bb8cd1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -121,10 +121,15 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
 
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+bool intel_dp_is_uhbr_rate(int rate)
+{
+   return rate >= 100;
+}
+
 /* Is link rate UHBR and thus 128b/132b? */
 bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state)
 {
-   return crtc_state->port_clock >= 100;
+   return intel_dp_is_uhbr_rate(crtc_state->port_clock);
 }
 
 static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
@@ -684,6 +689,20 @@ u32 intel_dp_mode_to_fec_clock(u32 mode_clock)
   100U);
 }
 
+int intel_dp_bw_fec_overhead(bool fec_enabled)
+{
+   /*
+* TODO: Calculate the actual overhead for a given mode.
+* The hard-coded 1/0.972261=2.853% overhead factor
+* corresponds (for instance) to the 8b/10b DP FEC 2.4% +
+* 0.453% DSC overhead. This is enough for a 3840 width