Re: [Intel-gfx] [PATCH 11/29] drm/i915/dp: Pass actual BW overhead to m_n calculation
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
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