Re: [PATCH 4/9] drm/i915: Introduce fb->min_alignment

2024-05-28 Thread Imre Deak
On Tue, May 28, 2024 at 10:38:06PM +0300, Ville Syrjälä wrote:
> On Tue, May 28, 2024 at 02:27:52PM +0300, Imre Deak wrote:
> > On Mon, May 13, 2024 at 08:59:37PM +0300, Ville Syrjala wrote:
> > > From: Ville Syrjälä 
> > > 
> > > Different planes could have different alignment requirements
> > > even for the same format/modifier. Collect the alignment
> > > requirements across all planes capable of scanning out the
> > > fb such that the alignment used when pinning the normal ggtt
> > > view is satisfactory to all those planes.
> > > 
> > > When pinning per-plane views we only have to satisfy the
> > > alignment requirements of the specific plane.
> > > 
> > > Signed-off-by: Ville Syrjälä 
> > > ---
> > >  .../drm/i915/display/intel_display_types.h|  2 ++
> > >  drivers/gpu/drm/i915/display/intel_fb.c   | 23 
> > >  drivers/gpu/drm/i915/display/intel_fb_pin.c   | 27 +--
> > >  drivers/gpu/drm/i915/display/intel_fbdev.c| 18 +
> > >  4 files changed, 51 insertions(+), 19 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
> > > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > > index 40d6e5f4c350..58bb65832adf 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > > @@ -145,6 +145,8 @@ struct intel_framebuffer {
> > >   };
> > >  
> > >   struct i915_address_space *dpt_vm;
> > > +
> > > + unsigned int min_alignment;
> > >  };
> > >  
> > >  enum intel_hotplug_state {
> > > diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> > > b/drivers/gpu/drm/i915/display/intel_fb.c
> > > index 3f3a9cd534f4..c5bae05cbbc3 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_fb.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_fb.c
> > > @@ -10,6 +10,7 @@
> > >  #include 
> > >  
> > >  #include "i915_drv.h"
> > > +#include "intel_atomic_plane.h"
> > >  #include "intel_display.h"
> > >  #include "intel_display_types.h"
> > >  #include "intel_dpt.h"
> > > @@ -1616,6 +1617,26 @@ bool intel_fb_supports_90_270_rotation(const 
> > > struct intel_framebuffer *fb)
> > >  fb->base.modifier == I915_FORMAT_MOD_Yf_TILED;
> > >  }
> > >  
> > > +static unsigned int intel_fb_min_alignment(const struct drm_framebuffer 
> > > *fb)
> > > +{
> > > + struct drm_i915_private *i915 = to_i915(fb->dev);
> > > + struct intel_plane *plane;
> > > + unsigned int min_alignment = 0;
> > > +
> > > + for_each_intel_plane(>drm, plane) {
> > > + if (!drm_plane_has_format(>base, fb->format->format, 
> > > fb->modifier))
> > > + continue;
> > > +
> > > + if (intel_plane_needs_physical(plane))
> > > + continue;
> > > +
> > > + min_alignment = max(min_alignment,
> > > + plane->min_alignment(plane, fb, 0));
> > > + }
> > > +
> > > + return min_alignment;
> > > +}
> > > +
> > >  int intel_fill_fb_info(struct drm_i915_private *i915, struct 
> > > intel_framebuffer *fb)
> > >  {
> > >   struct drm_i915_gem_object *obj = intel_fb_obj(>base);
> > > @@ -1698,6 +1719,8 @@ int intel_fill_fb_info(struct drm_i915_private 
> > > *i915, struct intel_framebuffer *
> > >   return -EINVAL;
> > >   }
> > >  
> > > + fb->min_alignment = intel_fb_min_alignment(>base);
> > > +
> > >   return 0;
> > >  }
> > >  
> > > diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c 
> > > b/drivers/gpu/drm/i915/display/intel_fb_pin.c
> > > index 9b0f1ea41b70..1ae02de906f5 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c
> > > @@ -230,13 +230,36 @@ void intel_fb_unpin_vma(struct i915_vma *vma, 
> > > unsigned long flags)
> > >   i915_vma_put(vma);
> > >  }
> > >  
> > > +static bool gtt_view_is_per_plane(const struct intel_plane_state 
> > > *plane_state)
> > > +{
> > > + const struct intel_framebuffer *fb = 
> > > to_intel_framebuffer(pla

Re: [PATCH 9/9] drm/i915: Nuke the TGL+ chroma plane tile row alignment stuff

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:42PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> I don't think the display hardware really has such chroma
> plane tile row alignment requirements as outlined in
> commit d156135e6a54 ("drm/i915/tgl: Make sure a semiplanar
> UV plane is tile row size aligned")
> 
> Bspec had the same exact thing to say about earlier hardware
> as well, but we never cared and things work just fine.
> 
> The one thing mentioned in that commit that is definitely
> true however is the fence alignment issue. But we don't
> deal with that on earlier hardware either. We do have code
> to deal with that issue for the first color plane, but not
> the chroma planes. So I think if we did want to check this
> more extensively we should do it in the same places where
> we already check the first color plane (namely
> convert_plane_offset_to_xy() and intel_fb_bo_framebuffer_init()).

Imo a correct alignment should be required to help users figure out why
a given config doesn't work (even if an incorrect alignment doesn't
cause other HW issues). But agreed that it should be the same then for
all platforms, so ok to remove it in its current form.

> 
> Signed-off-by: Ville Syrjälä 
> ---
>  drivers/gpu/drm/i915/display/intel_fb.c| 12 +---
>  drivers/gpu/drm/i915/display/intel_fb.h|  1 -
>  drivers/gpu/drm/i915/display/skl_universal_plane.c | 11 ---
>  3 files changed, 1 insertion(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> b/drivers/gpu/drm/i915/display/intel_fb.c
> index c80f866f3fb6..fc18da3106fd 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb.c
> +++ b/drivers/gpu/drm/i915/display/intel_fb.c
> @@ -584,12 +584,6 @@ static bool is_gen12_ccs_cc_plane(const struct 
> drm_framebuffer *fb, int color_pl
>   return intel_fb_rc_ccs_cc_plane(fb) == color_plane;
>  }
>  
> -bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int 
> color_plane)
> -{
> - return intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
> - color_plane == 1;
> -}
> -
>  bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane)
>  {
>   return fb->modifier == DRM_FORMAT_MOD_LINEAR ||
> @@ -1019,11 +1013,7 @@ static int intel_fb_offset_to_xy(int *x, int *y,
>   struct drm_i915_private *i915 = to_i915(fb->dev);
>   unsigned int height, alignment, unused;
>  
> - if (DISPLAY_VER(i915) >= 12 &&
> - !intel_fb_needs_pot_stride_remap(to_intel_framebuffer(fb)) &&
> - is_semiplanar_uv_plane(fb, color_plane))
> - alignment = intel_tile_row_size(fb, color_plane);
> - else if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
> + if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
>   alignment = intel_tile_size(i915);
>   else
>   alignment = 0;
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.h 
> b/drivers/gpu/drm/i915/display/intel_fb.h
> index 1b1fef2dc39a..6dee0c8b7f22 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb.h
> +++ b/drivers/gpu/drm/i915/display/intel_fb.h
> @@ -34,7 +34,6 @@ bool intel_fb_is_ccs_modifier(u64 modifier);
>  bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier);
>  bool intel_fb_is_mc_ccs_modifier(u64 modifier);
>  
> -bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int 
> color_plane);
>  bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int 
> color_plane);
>  int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb);
>  
> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
> b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> index ca7fc9fae990..476f5b7d9497 100644
> --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> @@ -514,17 +514,6 @@ static u32 tgl_plane_min_alignment(struct intel_plane 
> *plane,
>   if (intel_fb_is_ccs_aux_plane(fb, color_plane))
>   return mult * 4 * 1024;
>  
> - if (is_semiplanar_uv_plane(fb, color_plane)) {
> - /*
> -  * TODO: cross-check wrt. the bspec stride in bytes * 64 bytes
> -  * alignment for linear UV planes on all platforms.
> -      */
> - if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
> - return 256 * 1024;
> -
> - return intel_tile_row_size(fb, color_plane);
> - }

The above will also use the correct 2MB for DPT, which the previous
patch should've kept already. Other than that looks ok:

Reviewed-by: Imre Deak 

> -
>   switch (fb->modifier) {
>   case DRM_FORMAT_MOD_LINEAR:
>   case I915_FORMAT_MOD_X_TILED:
> -- 
> 2.43.2
> 


Re: [PATCH 8/9] drm/i915: Update plane alignment requirements for TGL+

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:41PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Currently we still use the SKL+ PLANE_SURF alignment even
> for TGL+ even though the hardware no longer needs it.
> Introduce a separate tgl_plane_min_alignment() and update
> it to more accurately reflect the hardware requirements.
> 
> Signed-off-by: Ville Syrjälä 
> ---
>  .../drm/i915/display/skl_universal_plane.c| 103 ++
>  1 file changed, 55 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
> b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> index 1ecd7c691317..ca7fc9fae990 100644
> --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> @@ -502,75 +502,79 @@ skl_plane_max_stride(struct intel_plane *plane,
>   max_pixels, max_bytes);
>  }
>  
> -static unsigned int skl_plane_min_alignment(struct intel_plane *plane,
> - const struct drm_framebuffer *fb,
> - int color_plane)
> +static u32 tgl_plane_min_alignment(struct intel_plane *plane,
> +const struct drm_framebuffer *fb,
> +int color_plane)
>  {
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -
> - if (intel_fb_uses_dpt(fb)) {
> - /* AUX_DIST needs only 4K alignment */
> - if (intel_fb_is_ccs_aux_plane(fb, color_plane))
> - return 512 * 4096;
> -
> - /*
> -  * FIXME ADL sees GGTT/DMAR faults with async
> -  * flips unless we align to 16k at least.
> -  * Figure out what's going on here...
> -  */
> - if (IS_ALDERLAKE_P(dev_priv) &&
> - !intel_fb_is_ccs_modifier(fb->modifier) &&
> - HAS_ASYNC_FLIPS(dev_priv))
> - return 512 * 16 * 1024;
> -
> - return 512 * 4096;
> - }
> + struct drm_i915_private *i915 = to_i915(plane->base.dev);
> + /* PLANE_SURF GGTT -> DPT alignment */
> + int mult = intel_fb_uses_dpt(fb) ? 512 : 1;
>  
>   /* AUX_DIST needs only 4K alignment */
>   if (intel_fb_is_ccs_aux_plane(fb, color_plane))
> - return 4096;
> + return mult * 4 * 1024;
>  
>   if (is_semiplanar_uv_plane(fb, color_plane)) {
>   /*
>* TODO: cross-check wrt. the bspec stride in bytes * 64 bytes
>* alignment for linear UV planes on all platforms.
>*/
> - if (DISPLAY_VER(dev_priv) >= 12) {
> - if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
> - return 256 * 1024;
> -
> - return intel_tile_row_size(fb, color_plane);
> - }
> -
> - return 4096;
> - }
> -
> - drm_WARN_ON(_priv->drm, color_plane != 0);
> -
> - switch (fb->modifier) {
> - case DRM_FORMAT_MOD_LINEAR:
> - return 256 * 1024;
> - case I915_FORMAT_MOD_X_TILED:
> - if (HAS_ASYNC_FLIPS(dev_priv))
> + if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
>   return 256 * 1024;
> - return 0;
> +
> + return intel_tile_row_size(fb, color_plane);
> + }
> +
> + switch (fb->modifier) {
> + case DRM_FORMAT_MOD_LINEAR:
> + case I915_FORMAT_MOD_X_TILED:
> + case I915_FORMAT_MOD_Y_TILED:
> + case I915_FORMAT_MOD_4_TILED:
> + /*
> +  * FIXME ADL sees GGTT/DMAR faults with async
> +  * flips unless we align to 16k at least.
> +  * Figure out what's going on here...
> +  */
> + if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915))

On ADL HAS_ASYNC_FLIPS() is always true, otherwise looks ok:

Reviewed-by: Imre Deak 

> + return mult * 16 * 1024;
> + return mult * 4 * 1024;
>   case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
>   case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
>   case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
> + case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
> + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
> + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
>   case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
>   case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
>   case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
> - return 16 * 1024;
> + /* 4x1 main surface tiles (16K) match 64B of AUX */
> +   

Re: [PATCH 7/9] drm/i915: Move intel_surf_alignment() into skl_univerals_plane.c

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:40PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Now that all pre-skl platforms have their own .min_alignment()
> functions the remainder of intel_surf_alignment() can be hoisted
> into skl_univerals_plane.c (and renamed appropriately).
> 
> Signed-off-by: Ville Syrjälä 

Reviewed-by: Imre Deak 

> ---
>  drivers/gpu/drm/i915/display/intel_fb.c   | 77 +--
>  drivers/gpu/drm/i915/display/intel_fb.h   |  4 +-
>  .../drm/i915/display/skl_universal_plane.c| 77 ++-
>  3 files changed, 78 insertions(+), 80 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> b/drivers/gpu/drm/i915/display/intel_fb.c
> index eea93d84a16e..c80f866f3fb6 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb.c
> +++ b/drivers/gpu/drm/i915/display/intel_fb.c
> @@ -584,7 +584,7 @@ static bool is_gen12_ccs_cc_plane(const struct 
> drm_framebuffer *fb, int color_pl
>   return intel_fb_rc_ccs_cc_plane(fb) == color_plane;
>  }
>  
> -static bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int 
> color_plane)
> +bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int 
> color_plane)
>  {
>   return intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
>   color_plane == 1;
> @@ -776,81 +776,6 @@ bool intel_fb_uses_dpt(const struct drm_framebuffer *fb)
>   intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier);
>  }
>  
> -unsigned int intel_surf_alignment(struct intel_plane *plane,
> -   const struct drm_framebuffer *fb,
> -   int color_plane)
> -{
> - struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -
> - if (intel_fb_uses_dpt(fb)) {
> - /* AUX_DIST needs only 4K alignment */
> - if (intel_fb_is_ccs_aux_plane(fb, color_plane))
> - return 512 * 4096;
> -
> - /*
> -  * FIXME ADL sees GGTT/DMAR faults with async
> -  * flips unless we align to 16k at least.
> -  * Figure out what's going on here...
> -  */
> - if (IS_ALDERLAKE_P(dev_priv) &&
> - !intel_fb_is_ccs_modifier(fb->modifier) &&
> - HAS_ASYNC_FLIPS(dev_priv))
> - return 512 * 16 * 1024;
> -
> - return 512 * 4096;
> - }
> -
> - /* AUX_DIST needs only 4K alignment */
> - if (intel_fb_is_ccs_aux_plane(fb, color_plane))
> - return 4096;
> -
> - if (is_semiplanar_uv_plane(fb, color_plane)) {
> - /*
> -  * TODO: cross-check wrt. the bspec stride in bytes * 64 bytes
> -  * alignment for linear UV planes on all platforms.
> -  */
> - if (DISPLAY_VER(dev_priv) >= 12) {
> - if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
> - return 256 * 1024;
> -
> - return intel_tile_row_size(fb, color_plane);
> - }
> -
> - return 4096;
> - }
> -
> - drm_WARN_ON(_priv->drm, color_plane != 0);
> -
> - switch (fb->modifier) {
> - case DRM_FORMAT_MOD_LINEAR:
> - return 256 * 1024;
> - case I915_FORMAT_MOD_X_TILED:
> - if (HAS_ASYNC_FLIPS(dev_priv))
> - return 256 * 1024;
> - return 0;
> - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> - case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
> - case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
> - case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
> - case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
> - return 16 * 1024;
> - case I915_FORMAT_MOD_Y_TILED_CCS:
> - case I915_FORMAT_MOD_Yf_TILED_CCS:
> - case I915_FORMAT_MOD_Y_TILED:
> - case I915_FORMAT_MOD_4_TILED:
> - case I915_FORMAT_MOD_Yf_TILED:
> - return 1 * 1024 * 1024;
> - case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
> - case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
> - case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
> - return 16 * 1024;
> - default:
> - MISSING_CASE(fb->modifier);
> - return 0;
> - }
> -}
> -
>  void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
>   const struct drm_framebuffer *fb,
>   int color_plane)
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.h 
> b/drivers/gpu/drm/i915/display/intel_fb.h
> i

Re: [PATCH 6/9] drm/i915: Split pre-skl platforms out from intel_surf_alignment()

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:39PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Extract the necessary chunks from intel_surf_alignment()
> into per-platform variants for all pre-skl primary/sprite
> planes.
> 
> Signed-off-by: Ville Syrjälä 
> ---
>  drivers/gpu/drm/i915/display/i9xx_plane.c   | 69 -
>  drivers/gpu/drm/i915/display/intel_fb.c | 17 +
>  drivers/gpu/drm/i915/display/intel_sprite.c | 28 -
>  3 files changed, 96 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c 
> b/drivers/gpu/drm/i915/display/i9xx_plane.c
> index 85dbf5b950e2..0d64176c1e6f 100644
> --- a/drivers/gpu/drm/i915/display/i9xx_plane.c
> +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
> @@ -762,6 +762,66 @@ i8xx_plane_max_stride(struct intel_plane *plane,
>   return 8 * 1024;
>  }
>  
> +static unsigned int vlv_primary_min_alignment(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane)
> +{
> + struct drm_i915_private *i915 = to_i915(plane->base.dev);
> +
> + switch (fb->modifier) {
> + case I915_FORMAT_MOD_X_TILED:
> + if (HAS_ASYNC_FLIPS(i915))

Nit: the function is used on VLV and CHV and both support async flips.

> + return 256 * 1024;
> + return 4 * 1024;

This changes the current 0 alignment to 4k, but these seem to be
equivalent.

Regardless of the above nit:
Reviewed-by: Imre Deak 


> + case DRM_FORMAT_MOD_LINEAR:
> + return 128 * 1024;
> + default:
> + MISSING_CASE(fb->modifier);
> + return 0;
> + }
> +}
> +
> +static unsigned int g4x_primary_min_alignment(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane)
> +{
> + struct drm_i915_private *i915 = to_i915(plane->base.dev);
> +
> + switch (fb->modifier) {
> + case I915_FORMAT_MOD_X_TILED:
> + if (HAS_ASYNC_FLIPS(i915))
> + return 256 * 1024;
> + return 4 * 1024;
> + case DRM_FORMAT_MOD_LINEAR:
> + return 4 * 1024;
> + default:
> + MISSING_CASE(fb->modifier);
> + return 0;
> + }
> +}
> +
> +static unsigned int i965_plane_min_alignment(struct intel_plane *plane,
> +  const struct drm_framebuffer *fb,
> +  int color_plane)
> +{
> + switch (fb->modifier) {
> + case I915_FORMAT_MOD_X_TILED:
> + return 4 * 1024;
> + case DRM_FORMAT_MOD_LINEAR:
> + return 128 * 1024;
> + default:
> + MISSING_CASE(fb->modifier);
> + return 0;
> + }
> +}
> +
> +static unsigned int i9xx_plane_min_alignment(struct intel_plane *plane,
> +  const struct drm_framebuffer *fb,
> +  int color_plane)
> +{
> + return 0;
> +}
> +
>  static const struct drm_plane_funcs i965_plane_funcs = {
>   .update_plane = drm_atomic_helper_update_plane,
>   .disable_plane = drm_atomic_helper_disable_plane,
> @@ -867,7 +927,14 @@ intel_primary_plane_create(struct drm_i915_private 
> *dev_priv, enum pipe pipe)
>   plane->max_stride = ilk_primary_max_stride;
>   }
>  
> - plane->min_alignment = intel_surf_alignment;
> + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> + plane->min_alignment = vlv_primary_min_alignment;
> + else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
> + plane->min_alignment = g4x_primary_min_alignment;
> + else if (DISPLAY_VER(dev_priv) == 4)
> + plane->min_alignment = i965_plane_min_alignment;
> + else
> + plane->min_alignment = i9xx_plane_min_alignment;
>  
>   if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
>   plane->update_arm = i830_plane_update_arm;
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> b/drivers/gpu/drm/i915/display/intel_fb.c
> index c84ecae3a57c..eea93d84a16e 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb.c
> +++ b/drivers/gpu/drm/i915/display/intel_fb.c
> @@ -776,19 +776,6 @@ bool intel_fb_uses_dpt(const struct drm_framebuffer *fb)
>   intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier);
>  }
>  
> -static unsigned int intel_linear_alignment(const struct dr

Re: [PATCH 5/9] drm/i915: Split cursor alignment to per-platform vfuncs

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:38PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Split intel_cursor_alignment() into per-platform variants.
> 
> Signed-off-by: Ville Syrjälä 

Reviewed-by: Imre Deak 

> ---
>  drivers/gpu/drm/i915/display/intel_cursor.c | 40 +++--
>  drivers/gpu/drm/i915/display/intel_fb.c | 16 -
>  drivers/gpu/drm/i915/display/intel_fb.h |  3 --
>  3 files changed, 38 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c 
> b/drivers/gpu/drm/i915/display/intel_cursor.c
> index 026975f569a7..737d53c50901 100644
> --- a/drivers/gpu/drm/i915/display/intel_cursor.c
> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
> @@ -193,6 +193,13 @@ i845_cursor_max_stride(struct intel_plane *plane,
>   return 2048;
>  }
>  
> +static unsigned int i845_cursor_min_alignment(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane)
> +{
> + return 32;
> +}
> +
>  static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
>  {
>   u32 cntl = 0;
> @@ -343,6 +350,28 @@ i9xx_cursor_max_stride(struct intel_plane *plane,
>   return plane->base.dev->mode_config.cursor_width * 4;
>  }
>  
> +static unsigned int i830_cursor_min_alignment(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane)
> +{
> + /* "AlmadorM Errata – Requires 32-bpp cursor data to be 16KB aligned." 
> */
> + return 16 * 1024; /* physical */
> +}
> +
> +static unsigned int i85x_cursor_min_alignment(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane)
> +{
> + return 256; /* physical */
> +}
> +
> +static unsigned int i9xx_cursor_min_alignment(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane)
> +{
> + return 4 * 1024; /* physical for i915/i945 */
> +}
> +
>  static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
>  {
>   struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> @@ -884,20 +913,27 @@ intel_cursor_plane_create(struct drm_i915_private 
> *dev_priv,
>  
>   if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
>   cursor->max_stride = i845_cursor_max_stride;
> + cursor->min_alignment = i845_cursor_min_alignment;
>   cursor->update_arm = i845_cursor_update_arm;
>   cursor->disable_arm = i845_cursor_disable_arm;
>   cursor->get_hw_state = i845_cursor_get_hw_state;
>   cursor->check_plane = i845_check_cursor;
>   } else {
>   cursor->max_stride = i9xx_cursor_max_stride;
> +
> + if (IS_I830(dev_priv))
> + cursor->min_alignment = i830_cursor_min_alignment;
> + else if (IS_I85X(dev_priv))
> + cursor->min_alignment = i85x_cursor_min_alignment;
> + else
> + cursor->min_alignment = i9xx_cursor_min_alignment;
> +
>   cursor->update_arm = i9xx_cursor_update_arm;
>   cursor->disable_arm = i9xx_cursor_disable_arm;
>   cursor->get_hw_state = i9xx_cursor_get_hw_state;
>   cursor->check_plane = i9xx_check_cursor;
>   }
>  
> - cursor->min_alignment = intel_cursor_alignment;
> -
>   cursor->cursor.base = ~0;
>   cursor->cursor.cntl = ~0;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> b/drivers/gpu/drm/i915/display/intel_fb.c
> index c5bae05cbbc3..c84ecae3a57c 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb.c
> +++ b/drivers/gpu/drm/i915/display/intel_fb.c
> @@ -776,22 +776,6 @@ bool intel_fb_uses_dpt(const struct drm_framebuffer *fb)
>   intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier);
>  }
>  
> -unsigned int intel_cursor_alignment(struct intel_plane *plane,
> - const struct drm_framebuffer *fb,
> - int color_plane)
> -{
> - struct drm_i915_private *i915 = to_i915(plane->base.dev);
> -
> - if (IS_I830(i915))
> - return 16 * 1024;
> - else if (IS_I85X(i915))
> - return 256;
> - else if (IS_I845G(i915) || IS_I865G(i915))
> - retu

Re: [PATCH 4/9] drm/i915: Introduce fb->min_alignment

2024-05-28 Thread Imre Deak
On Tue, May 28, 2024 at 02:27:58PM +0300, Imre Deak wrote:
> [...]
> > +}
> > +
> >  static unsigned int
> >  intel_plane_fb_min_alignment(const struct intel_plane_state *plane_state)
> >  {
> > struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> > -   const struct drm_framebuffer *fb = plane_state->hw.fb;
> > +   const struct intel_framebuffer *fb = 
> > to_intel_framebuffer(plane_state->hw.fb);
> >  
> > -   return plane->min_alignment(plane, fb, 0);
> > +   /*
> > +* Only use plane specific alignment for binding
> > +* a per-plane gtt view (remapped or rotated),
> > +* otherwise make sure the alignment is suitable
> > +* for all planes.
> > +*/
> > +   if (!gtt_view_is_per_plane(plane_state))
> > +   return fb->min_alignment;
> > +
> > +   if (intel_plane_needs_physical(plane))
> > +   return 0;
> 
> I guess the above is ok, though looks like an unrelated change: the
> cursor plane min_alignment() for relevant platforms is <= 4k, which will
> be rounded up to 4k anyway when binding the vma.

Hm, actually this would change the current 16k vma alignment for cursors on 
i830?

> 
> > +
> > +   return plane->min_alignment(plane, >base, 0);
> 
> The commit could've had more details about the rational for the above.
> As I understand it avoids having to rebind the vma for different plane
> types, though this is already handled to some degree by
> i915_vma::display_alignment.
> 
> >  }
> >  
> >  static unsigned int
> > diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c 
> > b/drivers/gpu/drm/i915/display/intel_fbdev.c
> > index ff685aebbd1a..124aac172acb 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fbdev.c
> > +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
> > @@ -46,7 +46,6 @@
> >  #include "gem/i915_gem_mman.h"
> >  
> >  #include "i915_drv.h"
> > -#include "intel_crtc.h"
> >  #include "intel_display_types.h"
> >  #include "intel_fb.h"
> >  #include "intel_fb_pin.h"
> > @@ -172,21 +171,6 @@ static const struct fb_ops intelfb_ops = {
> >  
> >  __diag_pop();
> >  
> > -static unsigned int intel_fbdev_min_alignment(const struct drm_framebuffer 
> > *fb)
> > -{
> > -   struct drm_i915_private *i915 = to_i915(fb->dev);
> > -   struct intel_plane *plane;
> > -   struct intel_crtc *crtc;
> > -
> > -   crtc = intel_first_crtc(i915);
> > -   if (!crtc)
> > -   return 0;
> > -
> > -   plane = to_intel_plane(crtc->base.primary);
> > -
> > -   return plane->min_alignment(plane, fb, 0);
> > -}
> > -
> >  static int intelfb_create(struct drm_fb_helper *helper,
> >   struct drm_fb_helper_surface_size *sizes)
> >  {
> > @@ -244,7 +228,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
> >  * BIOS is suitable for own access.
> >  */
> > vma = intel_fb_pin_to_ggtt(>base, ,
> > -  intel_fbdev_min_alignment(>base), 0,
> > +  fb->min_alignment, 0,
> >false, );
> > if (IS_ERR(vma)) {
> > ret = PTR_ERR(vma);
> > -- 
> > 2.43.2
> > 


Re: [PATCH 4/9] drm/i915: Introduce fb->min_alignment

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:37PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Different planes could have different alignment requirements
> even for the same format/modifier. Collect the alignment
> requirements across all planes capable of scanning out the
> fb such that the alignment used when pinning the normal ggtt
> view is satisfactory to all those planes.
> 
> When pinning per-plane views we only have to satisfy the
> alignment requirements of the specific plane.
> 
> Signed-off-by: Ville Syrjälä 
> ---
>  .../drm/i915/display/intel_display_types.h|  2 ++
>  drivers/gpu/drm/i915/display/intel_fb.c   | 23 
>  drivers/gpu/drm/i915/display/intel_fb_pin.c   | 27 +--
>  drivers/gpu/drm/i915/display/intel_fbdev.c| 18 +
>  4 files changed, 51 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 40d6e5f4c350..58bb65832adf 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -145,6 +145,8 @@ struct intel_framebuffer {
>   };
>  
>   struct i915_address_space *dpt_vm;
> +
> + unsigned int min_alignment;
>  };
>  
>  enum intel_hotplug_state {
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> b/drivers/gpu/drm/i915/display/intel_fb.c
> index 3f3a9cd534f4..c5bae05cbbc3 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb.c
> +++ b/drivers/gpu/drm/i915/display/intel_fb.c
> @@ -10,6 +10,7 @@
>  #include 
>  
>  #include "i915_drv.h"
> +#include "intel_atomic_plane.h"
>  #include "intel_display.h"
>  #include "intel_display_types.h"
>  #include "intel_dpt.h"
> @@ -1616,6 +1617,26 @@ bool intel_fb_supports_90_270_rotation(const struct 
> intel_framebuffer *fb)
>  fb->base.modifier == I915_FORMAT_MOD_Yf_TILED;
>  }
>  
> +static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb)
> +{
> + struct drm_i915_private *i915 = to_i915(fb->dev);
> + struct intel_plane *plane;
> + unsigned int min_alignment = 0;
> +
> + for_each_intel_plane(>drm, plane) {
> + if (!drm_plane_has_format(>base, fb->format->format, 
> fb->modifier))
> + continue;
> +
> + if (intel_plane_needs_physical(plane))
> + continue;
> +
> + min_alignment = max(min_alignment,
> + plane->min_alignment(plane, fb, 0));
> + }
> +
> + return min_alignment;
> +}
> +
>  int intel_fill_fb_info(struct drm_i915_private *i915, struct 
> intel_framebuffer *fb)
>  {
>   struct drm_i915_gem_object *obj = intel_fb_obj(>base);
> @@ -1698,6 +1719,8 @@ int intel_fill_fb_info(struct drm_i915_private *i915, 
> struct intel_framebuffer *
>   return -EINVAL;
>   }
>  
> + fb->min_alignment = intel_fb_min_alignment(>base);
> +
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c 
> b/drivers/gpu/drm/i915/display/intel_fb_pin.c
> index 9b0f1ea41b70..1ae02de906f5 100644
> --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c
> +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c
> @@ -230,13 +230,36 @@ void intel_fb_unpin_vma(struct i915_vma *vma, unsigned 
> long flags)
>   i915_vma_put(vma);
>  }
>  
> +static bool gtt_view_is_per_plane(const struct intel_plane_state 
> *plane_state)
> +{
> + const struct intel_framebuffer *fb = 
> to_intel_framebuffer(plane_state->hw.fb);
> +
> + if (plane_state->view.gtt.type == I915_GTT_VIEW_REMAPPED &&
> + intel_fb_needs_pot_stride_remap(fb))
> + return false;

The above view is created only once for the FB, I suppose this is how
you differentiate it from views created each time due to a stride
limit (based on intel_plane_needs_remap()).

> +
> + return plane_state->view.gtt.type != I915_GTT_VIEW_NORMAL;

So the rotated and remapped views created for a stride limit are
per-plane based on the above. There is also a rotated view created only
once for the FB, is it intentional to regard this kind of view as
per-plane as well?

> +}
> +
>  static unsigned int
>  intel_plane_fb_min_alignment(const struct intel_plane_state *plane_state)
>  {
>   struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> - const struct drm_framebuffer *fb = plane_state->hw.fb;
> + const struct intel_framebuffer *fb = 
> to_intel_framebuffer(plane_state->hw.fb);
>  
> - return plane->min_alignment(plane, fb, 0);
> + /*
> +  * Only use plane specific alignment for binding
> +  * a per-plane gtt view (remapped or rotated),
> +  * otherwise make sure the alignment is suitable
> +  * for all planes.
> +  */
> + if (!gtt_view_is_per_plane(plane_state))
> + return fb->min_alignment;
> +
> + if (intel_plane_needs_physical(plane))
> + return 0;

I guess the above is ok, 

Re: [PATCH 3/9] drm/i915: Introduce plane->min_alignment() vfunc

2024-05-28 Thread Imre Deak
On Mon, May 13, 2024 at 08:59:36PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä 
> 
> Different hardware generations have different scanout alignment
> requirements. Introduce a new vfunc that will allow us to
> make that distinction without horrible if-ladders.
> 
> For now we directly plug in the existing intel_surf_alignment()
> and intel_cursor_alignment() functions.
> 
> For fbdev we (temporarily) introduce intel_fbdev_min_alignment()
> that simply queries the alignment from the primary plane of
> the first crtc.
> 
> TODO: someone will need to fix xe's alignment handling
> 
> Signed-off-by: Ville Syrjälä 

Reviewed-by: Imre Deak 

> ---
>  drivers/gpu/drm/i915/display/i9xx_plane.c |  8 ++--
>  drivers/gpu/drm/i915/display/intel_cursor.c   |  2 +
>  .../drm/i915/display/intel_display_types.h|  3 ++
>  drivers/gpu/drm/i915/display/intel_fb.c   | 22 +-
>  drivers/gpu/drm/i915/display/intel_fb.h   |  7 +++-
>  drivers/gpu/drm/i915/display/intel_fb_pin.c   | 40 ++-
>  drivers/gpu/drm/i915/display/intel_fb_pin.h   |  3 +-
>  drivers/gpu/drm/i915/display/intel_fbdev.c| 21 +-
>  drivers/gpu/drm/i915/display/intel_sprite.c   |  2 +
>  .../drm/i915/display/skl_universal_plane.c| 11 +++--
>  drivers/gpu/drm/xe/display/xe_fb_pin.c|  3 +-
>  drivers/gpu/drm/xe/display/xe_plane_initial.c |  4 +-
>  12 files changed, 89 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c 
> b/drivers/gpu/drm/i915/display/i9xx_plane.c
> index ea4d8ba55ad8..85dbf5b950e2 100644
> --- a/drivers/gpu/drm/i915/display/i9xx_plane.c
> +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
> @@ -224,8 +224,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state 
> *crtc_state,
>  
>  int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
>  {
> - struct drm_i915_private *dev_priv =
> - to_i915(plane_state->uapi.plane->dev);
> + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>   const struct drm_framebuffer *fb = plane_state->hw.fb;
>   int src_x, src_y, src_w;
>   u32 offset;
> @@ -266,7 +266,7 @@ int i9xx_check_plane_surface(struct intel_plane_state 
> *plane_state)
>* despite them not using the linear offset anymore.
>*/
>   if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == 
> I915_FORMAT_MOD_X_TILED) {
> - unsigned int alignment = intel_surf_alignment(fb, 0);
> + unsigned int alignment = plane->min_alignment(plane, fb, 0);
>   int cpp = fb->format->cpp[0];
>  
>   while ((src_x + src_w) * cpp > 
> plane_state->view.color_plane[0].mapping_stride) {
> @@ -867,6 +867,8 @@ intel_primary_plane_create(struct drm_i915_private 
> *dev_priv, enum pipe pipe)
>   plane->max_stride = ilk_primary_max_stride;
>   }
>  
> + plane->min_alignment = intel_surf_alignment;
> +
>   if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
>   plane->update_arm = i830_plane_update_arm;
>   } else {
> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c 
> b/drivers/gpu/drm/i915/display/intel_cursor.c
> index 2118b87ccb10..026975f569a7 100644
> --- a/drivers/gpu/drm/i915/display/intel_cursor.c
> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
> @@ -896,6 +896,8 @@ intel_cursor_plane_create(struct drm_i915_private 
> *dev_priv,
>   cursor->check_plane = i9xx_check_cursor;
>   }
>  
> + cursor->min_alignment = intel_cursor_alignment;
> +
>   cursor->cursor.base = ~0;
>   cursor->cursor.cntl = ~0;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index fec3de25ea54..40d6e5f4c350 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1550,6 +1550,9 @@ struct intel_plane {
>   int (*max_height)(const struct drm_framebuffer *fb,
> int color_plane,
> unsigned int rotation);
> + unsigned int (*min_alignment)(struct intel_plane *plane,
> +   const struct drm_framebuffer *fb,
> +   int color_plane);
>   unsigned int (*max_stride)(struct intel_plane *plane,
>  u32 pixel_format, u64 modifier,
>  unsigned int rotation);
> diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
> b/drivers/gpu/drm/

Re: ✗ Fi.CI.IGT: failure for drm/i915/dp: Few MTL/DSC and a UHBR monitor fix (rev4)

2024-04-19 Thread Imre Deak
On Thu, Apr 18, 2024 at 12:22:53PM +, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915/dp: Few MTL/DSC and a UHBR monitor fix (rev4)
> URL   : https://patchwork.freedesktop.org/series/131386/
> State : failure

I pushed the patchset to drm-intel-next, amending the code comment in
patch 4 as requested, thanks for the reviews, acks.

The test failure is unrelated see below.

> == Summary ==
> 
> CI Bug Log - changes from CI_DRM_14596_full -> Patchwork_131386v4_full
> 
> 
> Summary
> ---
> 
>   **FAILURE**
> 
>   Serious unknown changes coming with Patchwork_131386v4_full absolutely need 
> to be
>   verified manually.
>   
>   If you think the reported changes have nothing to do with the changes
>   introduced in Patchwork_131386v4_full, please notify your bug team 
> (i915-ci-in...@lists.freedesktop.org) to allow them
>   to document this new failure mode, which will reduce false positives in CI.
> 
> Participating hosts (9 -> 10)
> --
> 
>   Additional (1): shard-snb-0 
> 
> Possible new issues
> ---
> 
>   Here are the unknown changes that may have been introduced in 
> Patchwork_131386v4_full:
> 
> ### IGT changes ###
> 
>  Possible regressions 
> 
>   * igt@perf@polling@0-rcs0:
> - shard-rkl:  [PASS][1] -> [FAIL][2]
>[1]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14596/shard-rkl-3/igt@perf@poll...@0-rcs0.html
>[2]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-rkl-5/igt@perf@poll...@0-rcs0.html

Only an HDMI display is connected to the above RKL, so can't see how the
DP/MST/DSC changes could have an effect. There is already an open ticket
for the issue, probably RKL needs to be added to the platform list:

https://gitlab.freedesktop.org/drm/intel/-/issues/10538

(perf:1120) DEBUG: engine 0:0 - TestOa metric set UUID = 
74dbc739-d871-41b5-be7b-fb547ac5bec9
(perf:1120) DEBUG: tick length = 1000ns, oa period = 21.845ms, test 
duration = 100ns, min iter. = 359, max iter. = 459
(perf:1120) DEBUG: 461 non-blocking reads during test with 45 Hz OA sampling 
(expect no more than 459)
(perf:1120) DEBUG: 1 extra iterations seen, not related to periodic sampling 
(e.g. context switches)
(perf:1120) DEBUG: time in userspace = 0ns (+-1000ns) (start utime = 0, end 
= 0)
(perf:1120) DEBUG: time in kernelspace = 1000ns (+-1000ns) (start stime 
= 5, end = 6)
(perf:1120) CRITICAL: Test assertion failure function test_polling, file 
../../../usr/src/igt-gpu-tools/tests/intel/perf.c:2730:
(perf:1120) CRITICAL: Failed assertion: n <= (max_iterations + 
n_extra_iterations)

> Known issues
> 
> 
>   Here are the changes found in Patchwork_131386v4_full that come from known 
> issues:
> 
> ### IGT changes ###
> 
>  Issues hit 
> 
>   * igt@api_intel_bb@blit-reloc-keep-cache:
> - shard-dg2:  NOTRUN -> [SKIP][3] ([i915#8411])
>[3]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-dg2-2/igt@api_intel...@blit-reloc-keep-cache.html
> 
>   * igt@drm_fdinfo@busy@vcs1:
> - shard-dg1:  NOTRUN -> [SKIP][4] ([i915#8414]) +9 other tests 
> skip
>[4]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-dg1-16/igt@drm_fdinfo@b...@vcs1.html
> 
>   * igt@drm_fdinfo@most-busy-idle-check-all@vecs1:
> - shard-dg2:  NOTRUN -> [SKIP][5] ([i915#8414]) +7 other tests 
> skip
>[5]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-dg2-2/igt@drm_fdinfo@most-busy-idle-check-...@vecs1.html
> 
>   * igt@gem_bad_reloc@negative-reloc-lut:
> - shard-rkl:  NOTRUN -> [SKIP][6] ([i915#3281]) +7 other tests 
> skip
>[6]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-rkl-3/igt@gem_bad_re...@negative-reloc-lut.html
> 
>   * igt@gem_basic@multigpu-create-close:
> - shard-mtlp: NOTRUN -> [SKIP][7] ([i915#7697])
>[7]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-mtlp-3/igt@gem_ba...@multigpu-create-close.html
> 
>   * igt@gem_caching@reads:
> - shard-mtlp: NOTRUN -> [SKIP][8] ([i915#4873])
>[8]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-mtlp-4/igt@gem_cach...@reads.html
> 
>   * igt@gem_ccs@ctrl-surf-copy:
> - shard-mtlp: NOTRUN -> [SKIP][9] ([i915#3555] / [i915#9323])
>[9]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-mtlp-4/igt@gem_...@ctrl-surf-copy.html
> 
>   * igt@gem_ccs@suspend-resume:
> - shard-rkl:  NOTRUN -> [SKIP][10] ([i915#9323])
>[10]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-rkl-3/igt@gem_...@suspend-resume.html
> - shard-dg1:  NOTRUN -> [SKIP][11] ([i915#9323])
>[11]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_131386v4/shard-dg1-16/igt@gem_...@suspend-resume.html
> 
>   * 

Re: [PATCH] drm/dp: Fix documentation of DP tunnel functions

2024-04-19 Thread Imre Deak
On Fri, Apr 19, 2024 at 03:40:39PM +0300, Jani Nikula wrote:
> On Wed, 28 Feb 2024, Imre Deak  wrote:
> > Fix the documentation issues below, also reported by 'make htmldocs':
> >
> > drivers/gpu/drm/display/drm_dp_tunnel.c:447: warning: Function parameter or 
> > struct member 'tunnel' not described in 'drm_dp_tunnel_put'
> > drivers/gpu/drm/display/drm_dp_tunnel.c:447: warning: Function parameter or 
> > struct member 'tracker' not described in 'drm_dp_tunnel_put'
> > drivers/gpu/drm/display/drm_dp_tunnel.c:1185: warning: expecting prototype 
> > for drm_dp_tunnel_atomic_get_allocated_bw(). Prototype was for 
> > drm_dp_tunnel_get_allocated_bw() instead
> > drivers/gpu/drm/display/drm_dp_tunnel.c:1903: warning: Function parameter 
> > or struct member 'max_group_count' not described in 
> > 'drm_dp_tunnel_mgr_create'
> >
> > Fixes: 295654f7e554 ("drm/dp: Add support for DP tunneling")
> > Reported-by: kernel test robot 
> > Signed-off-by: Imre Deak 
> 
> This came up today [1]. Even if the regressing commit was merged via
> drm-intel, you still need the acks for queueing non-i915 changes via
> drm-intel, and the acks absolutely must be recorded in the commit
> messages when pushing the patches.

There wasn't a reason to merge this via drm-intel instead of
drm-misc-next, not sure why I did that; otherwise I always ask and
record the acks.

> dim should complain about applying non-i915 patches without acks.

I don't remember seeing it this time, but yes it should complain and
require an override; maybe I managed to overlook somehow that as well.

> BR,
> Jani.
> 
> 
> [1] https://lore.kernel.org/r/zh_q72gykmmbg...@intel.com
> 
> 
> 
> > ---
> >  drivers/gpu/drm/display/drm_dp_tunnel.c | 7 ---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c 
> > b/drivers/gpu/drm/display/drm_dp_tunnel.c
> > index 120e0de674c19..017f1d4c63415 100644
> > --- a/drivers/gpu/drm/display/drm_dp_tunnel.c
> > +++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
> > @@ -436,8 +436,8 @@ EXPORT_SYMBOL(drm_dp_tunnel_get);
> >  
> >  /**
> >   * drm_dp_tunnel_put - Put a reference for a DP tunnel
> > - * @tunnel - Tunnel object
> > - * @tracker - Debug tracker for the reference
> > + * @tunnel: Tunnel object
> > + * @tracker: Debug tracker for the reference
> >   *
> >   * Put a reference for @tunnel along with its debug *@tracker, which
> >   * was obtained with drm_dp_tunnel_get().
> > @@ -1170,7 +1170,7 @@ int drm_dp_tunnel_alloc_bw(struct drm_dp_tunnel 
> > *tunnel, int bw)
> >  EXPORT_SYMBOL(drm_dp_tunnel_alloc_bw);
> >  
> >  /**
> > - * drm_dp_tunnel_atomic_get_allocated_bw - Get the BW allocated for a DP 
> > tunnel
> > + * drm_dp_tunnel_get_allocated_bw - Get the BW allocated for a DP tunnel
> >   * @tunnel: Tunnel object
> >   *
> >   * Get the current BW allocated for @tunnel. After the tunnel is created /
> > @@ -1892,6 +1892,7 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)
> >  /**
> >   * drm_dp_tunnel_mgr_create - Create a DP tunnel manager
> >   * @dev: DRM device object
> > + * @max_group_count: Maximum number of tunnel groups
> >   *
> >   * Creates a DP tunnel manager for @dev.
> >   *
> 
> -- 
> Jani Nikula, Intel


[PATCH v3 11/11] drm/i915/dp_mst: Enable HBLANK expansion quirk for UHBR rates

2024-04-17 Thread Imre Deak
Enabling the 5k@60Hz uncompressed mode on the MediaTek/Dell U3224KBA
monitor results in a blank screen, at least on MTL platforms on UHBR
link rates with some (<30) uncompressed bpp values. Enabling compression
fixes the problem, so do that for now. Windows enables DSC always if the
sink supports it and forcing it to enable the mode without compression
leads to the same problem above (which suggests a panel issue with
uncompressed mode).

The same 5k mode on non-UHBR link rates is not affected and lower
resolution modes are not affected either. The problem is similar to the
one fixed by the HBLANK expansion quirk on Synaptics hubs, with the
difference that the problematic mode has a longer HBLANK duration. Also
the monitor doesn't report supporting HBLANK expansion; either its
internal MST hub does the expansion internally - similarly to the
Synaptics hub - or the issue has another root cause, but still related
to the mode's short HBLANK duration. Enable the quirk for the monitor
adjusting the detection for the above differences.

v2: Rebase on drm_dp_128132b_supported() change.

Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ankit Nautiyal 
Tested-by: Khaled Almahallawy 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_helper.c |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 22 +
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index 023907da98581..79a615667aab1 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2281,6 +2281,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
/* Synaptics DP1.4 MST hubs require DSC for some modes on which it 
applies HBLANK expansion. */
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
+   /* MediaTek panels (at least in U3224KBA) require DSC for modes with a 
short HBLANK on UHBR links. */
+   { OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, 
BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
/* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low 
DP_MAX_LINK_RATE */
{ OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, 
BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
 };
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index fb5e167c3c659..1cd375963f243 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -421,15 +421,22 @@ static int mode_hblank_period_ns(const struct 
drm_display_mode *mode)
 
 static bool
 hblank_expansion_quirk_needs_dsc(const struct intel_connector *connector,
-const struct intel_crtc_state *crtc_state)
+const struct intel_crtc_state *crtc_state,
+const struct link_config_limits *limits)
 {
const struct drm_display_mode *adjusted_mode =
_state->hw.adjusted_mode;
+   bool is_uhbr_sink = connector->mst_port &&
+   
drm_dp_128b132b_supported(connector->mst_port->dpcd);
+   int hblank_limit = is_uhbr_sink ? 500 : 300;
 
if (!connector->dp.dsc_hblank_expansion_quirk)
return false;
 
-   if (mode_hblank_period_ns(adjusted_mode) > 300)
+   if (is_uhbr_sink && !drm_dp_is_uhbr_rate(limits->max_rate))
+   return false;
+
+   if (mode_hblank_period_ns(adjusted_mode) > hblank_limit)
return false;
 
return true;
@@ -445,7 +452,7 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct 
intel_connector *conne
const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
int min_bpp_x16 = limits->link.min_bpp_x16;
 
-   if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state))
+   if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state, limits))
return true;
 
if (!dsc) {
@@ -1604,7 +1611,14 @@ static bool detect_dsc_hblank_expansion_quirk(const 
struct intel_connector *conn
  DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC))
return false;
 
-   if (!(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE))
+   /*
+* UHBR (MST sink) devices requiring this quirk don't advertise the
+* HBLANK expansion support. Presuming that they perform HBLANK
+* expansion internally, or are affected by this issue on modes with a
+* short HBLANK for other reasons.
+*/
+   if (!drm_dp_128b132b_supported(dpcd) &&
+   !(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE))
return false;
 
drm_dbg_kms(>drm,
-- 
2.43.3



[PATCH v3 07/11] drm/dp: Add drm_dp_128b132b_supported()

2024-04-17 Thread Imre Deak
Factor out a function to check for 128b/132b channel coding support used
by a follow-up patch in the patchset.

v2: s/drm_dp_uhbr_channel_coding_supported()/drm_dp128b132b_supported()
(Jani)

Cc: dri-devel@lists.freedesktop.org
Cc: Jani Nikula 
Reviewed-by: Ankit Nautiyal 
Reviewed-by: Manasi Navare 
Acked-by: Maarten Lankhorst 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
 include/drm/display/drm_dp_helper.h | 6 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 23808e9d41d5d..e05e25cd4a940 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -225,7 +225,7 @@ static void intel_dp_set_dpcd_sink_rates(struct intel_dp 
*intel_dp)
 * Sink rates for 128b/132b. If set, sink should support all 8b/10b
 * rates and 10 Gbps.
 */
-   if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B) 
{
+   if (drm_dp_128b132b_supported(intel_dp->dpcd)) {
u8 uhbr_rates = 0;
 
BUILD_BUG_ON(ARRAY_SIZE(intel_dp->sink_rates) < 
ARRAY_SIZE(dp_rates) + 3);
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index baf9949ff96fc..8bed890eec2c6 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -251,6 +251,12 @@ drm_dp_channel_coding_supported(const u8 
dpcd[DP_RECEIVER_CAP_SIZE])
return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_8B10B;
 }
 
+static inline bool
+drm_dp_128b132b_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B;
+}
+
 static inline bool
 drm_dp_alternate_scrambler_reset_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
-- 
2.43.3



Re: [PATCH v2 07/11] drm/dp: Add drm_dp_uhbr_channel_coding_supported()

2024-04-17 Thread Imre Deak
On Wed, Apr 17, 2024 at 12:21:58PM +0300, Jani Nikula wrote:
> On Wed, 17 Apr 2024, Imre Deak  wrote:
> > Factor out a function to check for UHBR channel coding support used by a
> > follow-up patch in the patchset.
> >
> > Cc: dri-devel@lists.freedesktop.org
> > Reviewed-by: Ankit Nautiyal 
> > Reviewed-by: Manasi Navare 
> > Acked-by: Maarten Lankhorst 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
> >  include/drm/display/drm_dp_helper.h | 6 ++
> >  2 files changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 23808e9d41d5d..41127069b55e4 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -225,7 +225,7 @@ static void intel_dp_set_dpcd_sink_rates(struct 
> > intel_dp *intel_dp)
> >  * Sink rates for 128b/132b. If set, sink should support all 8b/10b
> >  * rates and 10 Gbps.
> >  */
> > -   if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B) 
> > {
> > +   if (drm_dp_uhbr_channel_coding_supported(intel_dp->dpcd)) {
> > u8 uhbr_rates = 0;
> >  
> > BUILD_BUG_ON(ARRAY_SIZE(intel_dp->sink_rates) < 
> > ARRAY_SIZE(dp_rates) + 3);
> > diff --git a/include/drm/display/drm_dp_helper.h 
> > b/include/drm/display/drm_dp_helper.h
> > index baf9949ff96fc..8a64fe8d97af2 100644
> > --- a/include/drm/display/drm_dp_helper.h
> > +++ b/include/drm/display/drm_dp_helper.h
> > @@ -251,6 +251,12 @@ drm_dp_channel_coding_supported(const u8 
> > dpcd[DP_RECEIVER_CAP_SIZE])
> > return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_8B10B;
> >  }
> >  
> > +static inline bool
> > +drm_dp_uhbr_channel_coding_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> > +{
> > +   return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B;
> > +}
> 
> Nitpick, "uhbr channel coding" is not pedantically correct, and it does
> rub me the wrong way.
> 
> Yes, using 128b/132b channel coding implies UHBR, and UHBR requires
> 128b/132b channel coding, but they are not the same thing. We do
> conflate the two quite a bit in the code, checking for UHBR when we
> really mean 128b/132b, but embedding this confusion in the function name
> directly is a bit much.
> 
> I've named the link training functions drm_dp_128b132b_* in the same
> file, and I think this one should be named similarly. Maybe just
> drm_dp_128b132b_supported(), and rename
> drm_dp_channel_coding_supported() to drm_dp_8b10b_supported() to unify?

Ok, makes sense, will rename it to drm_dp_128b132b_supported() and
can do the same - as a follow-up - for 8b10b.

> BR,
> Jani.
> 
> 
> 
> > +
> >  static inline bool
> >  drm_dp_alternate_scrambler_reset_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> >  {
> 
> -- 
> Jani Nikula, Intel


Re: [PATCH v2 11/11] drm/i915/dp_mst: Enable HBLANK expansion quirk for UHBR rates

2024-04-17 Thread Imre Deak
On Wed, Apr 17, 2024 at 12:39:40PM +0300, Jani Nikula wrote:
> On Wed, 17 Apr 2024, Imre Deak  wrote:
> > Enabling the 5k@60Hz uncompressed mode on the MediaTek/Dell U3224KBA
> > monitor results in a blank screen, at least on MTL platforms on UHBR
> > link rates with some (<30) uncompressed bpp values. Enabling compression
> > fixes the problem, so do that for now. Windows enables DSC always if the
> > sink supports it and forcing it to enable the mode without compression
> > leads to the same problem above (which suggests a panel issue with
> > uncompressed mode).
> >
> > The same 5k mode on non-UHBR link rates is not affected and lower
> > resolution modes are not affected either. The problem is similar to the
> > one fixed by the HBLANK expansion quirk on Synaptics hubs, with the
> > difference that the problematic mode has a longer HBLANK duration. Also
> > the monitor doesn't report supporting HBLANK expansion; either its
> > internal MST hub does the expansion internally - similarly to the
> > Synaptics hub - or the issue has another root cause, but still related
> > to the mode's short HBLANK duration. Enable the quirk for the monitor
> > adjusting the detection for the above differences.
> >
> > Cc: dri-devel@lists.freedesktop.org
> > Reviewed-by: Ankit Nautiyal 
> > Tested-by: Khaled Almahallawy 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/display/drm_dp_helper.c |  2 ++
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 22 +
> >  2 files changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> > b/drivers/gpu/drm/display/drm_dp_helper.c
> > index 023907da98581..79a615667aab1 100644
> > --- a/drivers/gpu/drm/display/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> > @@ -2281,6 +2281,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
> > { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
> > BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
> > /* Synaptics DP1.4 MST hubs require DSC for some modes on which it 
> > applies HBLANK expansion. */
> > { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
> > BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
> > +   /* MediaTek panels (at least in U3224KBA) require DSC for modes with a 
> > short HBLANK on UHBR links. */
> > +   { OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, 
> > BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
> > /* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low 
> > DP_MAX_LINK_RATE */
> > { OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, 
> > BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
> >  };
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
> > b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index fb5e167c3c659..71b01f7631919 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -421,15 +421,22 @@ static int mode_hblank_period_ns(const struct 
> > drm_display_mode *mode)
> >  
> >  static bool
> >  hblank_expansion_quirk_needs_dsc(const struct intel_connector *connector,
> > -const struct intel_crtc_state *crtc_state)
> > +const struct intel_crtc_state *crtc_state,
> > +const struct link_config_limits *limits)
> >  {
> > const struct drm_display_mode *adjusted_mode =
> > _state->hw.adjusted_mode;
> > +   bool is_uhbr_sink = connector->mst_port &&
> > +   
> > drm_dp_uhbr_channel_coding_supported(connector->mst_port->dpcd);
> 
> Why do you combine connector->mst_port to "is uhbr sink"? I think it's
> confusing.

It is a way to get the DPCD of the root port, to determine if it
supports UHBR.

> > +   int hblank_limit = is_uhbr_sink ? 500 : 300;
> >  
> > if (!connector->dp.dsc_hblank_expansion_quirk)
> > return false;
> >  
> > -   if (mode_hblank_period_ns(adjusted_mode) > 300)
> > +   if (is_uhbr_sink && !drm_dp_is_uhbr_rate(limits->max_rate))
> 
> I'm not saying that's not correct, but I find that condition a bit
> surprising. "This does not apply to sinks capable of 128b/132b, but not
> running at UHBR."
> 
> IOW, this applies to sinks not capable of 128b/132b, and sinks capable
> of 128b/132b and running at UHBR.

Yes, on the particular monitor I tested and enabled the quirk for - DELL
U3224KBA - all the mode

[PATCH v2 09/11] drm/dp_mst: Add drm_dp_mst_aux_for_parent()

2024-04-16 Thread Imre Deak
Add a function to get the AUX device of the parent of an MST port, used
by a follow-up i915 patch in the patchset.

v2: Move drm_dp_mst_aux_for_parent() forward declaration to this patch
(Ankit)

Cc: Lyude Paul 
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ankit Nautiyal 
Acked-by: Maarten Lankhorst 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 16 
 include/drm/display/drm_dp_mst_helper.h   |  1 +
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 46b99d5fe0086..3577786b5db2c 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -6010,6 +6010,22 @@ static bool drm_dp_mst_is_virtual_dpcd(struct 
drm_dp_mst_port *port)
return false;
 }
 
+/**
+ * drm_dp_mst_aux_for_parent() - Get the AUX device for an MST port's parent
+ * @port: MST port whose parent's AUX device is returned
+ *
+ * Return the AUX device for @port's parent or NULL if port's parent is the
+ * root port.
+ */
+struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port)
+{
+   if (!port->parent || !port->parent->port_parent)
+   return NULL;
+
+   return >parent->port_parent->aux;
+}
+EXPORT_SYMBOL(drm_dp_mst_aux_for_parent);
+
 /**
  * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC
  * @port: The port to check. A leaf of the MST tree with an attached display.
diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index f00e32b0315d7..3546b58a121bc 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -954,6 +954,7 @@ bool drm_dp_mst_port_is_logical(struct drm_dp_mst_port 
*port)
return port->port_num >= DP_MST_LOGICAL_PORT_0;
 }
 
+struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port);
 struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);
 
 static inline struct drm_dp_mst_topology_state *
-- 
2.43.3



[PATCH v2 11/11] drm/i915/dp_mst: Enable HBLANK expansion quirk for UHBR rates

2024-04-16 Thread Imre Deak
Enabling the 5k@60Hz uncompressed mode on the MediaTek/Dell U3224KBA
monitor results in a blank screen, at least on MTL platforms on UHBR
link rates with some (<30) uncompressed bpp values. Enabling compression
fixes the problem, so do that for now. Windows enables DSC always if the
sink supports it and forcing it to enable the mode without compression
leads to the same problem above (which suggests a panel issue with
uncompressed mode).

The same 5k mode on non-UHBR link rates is not affected and lower
resolution modes are not affected either. The problem is similar to the
one fixed by the HBLANK expansion quirk on Synaptics hubs, with the
difference that the problematic mode has a longer HBLANK duration. Also
the monitor doesn't report supporting HBLANK expansion; either its
internal MST hub does the expansion internally - similarly to the
Synaptics hub - or the issue has another root cause, but still related
to the mode's short HBLANK duration. Enable the quirk for the monitor
adjusting the detection for the above differences.

Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ankit Nautiyal 
Tested-by: Khaled Almahallawy 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_helper.c |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 22 +
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index 023907da98581..79a615667aab1 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2281,6 +2281,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
/* Synaptics DP1.4 MST hubs require DSC for some modes on which it 
applies HBLANK expansion. */
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
+   /* MediaTek panels (at least in U3224KBA) require DSC for modes with a 
short HBLANK on UHBR links. */
+   { OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, 
BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
/* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low 
DP_MAX_LINK_RATE */
{ OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, 
BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
 };
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index fb5e167c3c659..71b01f7631919 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -421,15 +421,22 @@ static int mode_hblank_period_ns(const struct 
drm_display_mode *mode)
 
 static bool
 hblank_expansion_quirk_needs_dsc(const struct intel_connector *connector,
-const struct intel_crtc_state *crtc_state)
+const struct intel_crtc_state *crtc_state,
+const struct link_config_limits *limits)
 {
const struct drm_display_mode *adjusted_mode =
_state->hw.adjusted_mode;
+   bool is_uhbr_sink = connector->mst_port &&
+   
drm_dp_uhbr_channel_coding_supported(connector->mst_port->dpcd);
+   int hblank_limit = is_uhbr_sink ? 500 : 300;
 
if (!connector->dp.dsc_hblank_expansion_quirk)
return false;
 
-   if (mode_hblank_period_ns(adjusted_mode) > 300)
+   if (is_uhbr_sink && !drm_dp_is_uhbr_rate(limits->max_rate))
+   return false;
+
+   if (mode_hblank_period_ns(adjusted_mode) > hblank_limit)
return false;
 
return true;
@@ -445,7 +452,7 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct 
intel_connector *conne
const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
int min_bpp_x16 = limits->link.min_bpp_x16;
 
-   if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state))
+   if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state, limits))
return true;
 
if (!dsc) {
@@ -1604,7 +1611,14 @@ static bool detect_dsc_hblank_expansion_quirk(const 
struct intel_connector *conn
  DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC))
return false;
 
-   if (!(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE))
+   /*
+* UHBR (MST sink) devices requiring this quirk doesn't advertise the
+* HBLANK expansion support. Presuming that they perform HBLANK
+* expansion internally, or are affected by this issue on modes with a
+* short HBLANK for other reasons.
+*/
+   if (!drm_dp_uhbr_channel_coding_supported(dpcd) &&
+   !(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE))
return false;
 
drm_dbg_kms(>drm,
-- 
2.43.3



[PATCH v2 08/11] drm/dp_mst: Factor out drm_dp_mst_port_is_logical()

2024-04-16 Thread Imre Deak
Factor out a function to check if an MST port is logical, used by a
follow-up i915 patch in the patchset.

v2: Move drm_dp_mst_aux_for_parent() forward declaration to the next
patch. (Ankit)

Cc: Lyude Paul 
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ankit Nautiyal 
Acked-by: Maarten Lankhorst 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 6 +++---
 include/drm/display/drm_dp_mst_helper.h   | 6 ++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index c193be3577f7a..46b99d5fe0086 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -2274,7 +2274,7 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch 
*mstb,
 
if (port->pdt != DP_PEER_DEVICE_NONE &&
drm_dp_mst_is_end_device(port->pdt, port->mcs) &&
-   port->port_num >= DP_MST_LOGICAL_PORT_0)
+   drm_dp_mst_port_is_logical(port))
port->cached_edid = drm_edid_read_ddc(port->connector,
  >aux.ddc);
 
@@ -4219,7 +4219,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector,
case DP_PEER_DEVICE_SST_SINK:
ret = connector_status_connected;
/* for logical ports - cache the EDID */
-   if (port->port_num >= DP_MST_LOGICAL_PORT_0 && 
!port->cached_edid)
+   if (drm_dp_mst_port_is_logical(port) && !port->cached_edid)
port->cached_edid = drm_edid_read_ddc(connector, 
>aux.ddc);
break;
case DP_PEER_DEVICE_DP_LEGACY_CONV:
@@ -5983,7 +5983,7 @@ static bool drm_dp_mst_is_virtual_dpcd(struct 
drm_dp_mst_port *port)
return false;
 
/* Virtual DP Sink (Internal Display Panel) */
-   if (port->port_num >= 8)
+   if (drm_dp_mst_port_is_logical(port))
return true;
 
/* DP-to-HDMI Protocol Converter */
diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index cbcb49cb6a460..f00e32b0315d7 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -948,6 +948,12 @@ int __must_check drm_dp_mst_root_conn_atomic_check(struct 
drm_connector_state *n
 void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
 void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
 
+static inline
+bool drm_dp_mst_port_is_logical(struct drm_dp_mst_port *port)
+{
+   return port->port_num >= DP_MST_LOGICAL_PORT_0;
+}
+
 struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);
 
 static inline struct drm_dp_mst_topology_state *
-- 
2.43.3



[PATCH v2 07/11] drm/dp: Add drm_dp_uhbr_channel_coding_supported()

2024-04-16 Thread Imre Deak
Factor out a function to check for UHBR channel coding support used by a
follow-up patch in the patchset.

Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ankit Nautiyal 
Reviewed-by: Manasi Navare 
Acked-by: Maarten Lankhorst 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
 include/drm/display/drm_dp_helper.h | 6 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 23808e9d41d5d..41127069b55e4 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -225,7 +225,7 @@ static void intel_dp_set_dpcd_sink_rates(struct intel_dp 
*intel_dp)
 * Sink rates for 128b/132b. If set, sink should support all 8b/10b
 * rates and 10 Gbps.
 */
-   if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B) 
{
+   if (drm_dp_uhbr_channel_coding_supported(intel_dp->dpcd)) {
u8 uhbr_rates = 0;
 
BUILD_BUG_ON(ARRAY_SIZE(intel_dp->sink_rates) < 
ARRAY_SIZE(dp_rates) + 3);
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index baf9949ff96fc..8a64fe8d97af2 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -251,6 +251,12 @@ drm_dp_channel_coding_supported(const u8 
dpcd[DP_RECEIVER_CAP_SIZE])
return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_8B10B;
 }
 
+static inline bool
+drm_dp_uhbr_channel_coding_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B;
+}
+
 static inline bool
 drm_dp_alternate_scrambler_reset_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
-- 
2.43.3



[PATCH v2 01/11] drm/i915/dp: Fix DSC line buffer depth programming

2024-04-16 Thread Imre Deak
Fix the calculation of the DSC line buffer depth. This is limited both
by the source's and sink's maximum line buffer depth, but the former one
was not taken into account. On all Intel platform's the source's maximum
buffer depth is 13, so the overall limit is simply the minimum of the
source/sink's limit, regardless of the DSC version.

This leaves the DSI DSC line buffer depth calculation as-is, trusting
VBT.

On DSC version 1.2 for sinks reporting a maximum line buffer depth of 16
the line buffer depth was incorrectly programmed as 0, leading to a
corruption in color gradients / lines on the decompressed screen image.

Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ankit Nautiyal 
Reviewed-by: Manasi Navare 
Acked-by: Maarten Lankhorst 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 16 ++--
 include/drm/display/drm_dsc.h   |  3 ---
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 163da48bc4065..23808e9d41d5d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -89,6 +89,9 @@
 #define DP_DSC_MAX_ENC_THROUGHPUT_034
 #define DP_DSC_MAX_ENC_THROUGHPUT_140
 
+/* Max DSC line buffer depth supported by HW. */
+#define INTEL_DP_DSC_MAX_LINE_BUF_DEPTH13
+
 /* DP DSC FEC Overhead factor in ppm = 1/(0.972261) = 1.028530 */
 #define DP_DSC_FEC_OVERHEAD_FACTOR 1028530
 
@@ -1705,7 +1708,6 @@ static int intel_dp_dsc_compute_params(const struct 
intel_connector *connector,
 {
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct drm_dsc_config *vdsc_cfg = _state->dsc.config;
-   u8 line_buf_depth;
int ret;
 
/*
@@ -1734,20 +1736,14 @@ static int intel_dp_dsc_compute_params(const struct 
intel_connector *connector,
connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - 
DP_DSC_SUPPORT] &
DP_DSC_RGB;
 
-   line_buf_depth = drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd);
-   if (!line_buf_depth) {
+   vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH,
+  
drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd));
+   if (!vdsc_cfg->line_buf_depth) {
drm_dbg_kms(>drm,
"DSC Sink Line Buffer Depth invalid\n");
return -EINVAL;
}
 
-   if (vdsc_cfg->dsc_version_minor == 2)
-   vdsc_cfg->line_buf_depth = (line_buf_depth == 
DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ?
-   DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth;
-   else
-   vdsc_cfg->line_buf_depth = (line_buf_depth > 
DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ?
-   DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
-
vdsc_cfg->block_pred_enable =
connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - 
DP_DSC_SUPPORT] &
DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
diff --git a/include/drm/display/drm_dsc.h b/include/drm/display/drm_dsc.h
index bc90273d06a62..bbbe7438473d3 100644
--- a/include/drm/display/drm_dsc.h
+++ b/include/drm/display/drm_dsc.h
@@ -40,9 +40,6 @@
 #define DSC_PPS_RC_RANGE_MINQP_SHIFT   11
 #define DSC_PPS_RC_RANGE_MAXQP_SHIFT   6
 #define DSC_PPS_NATIVE_420_SHIFT   1
-#define DSC_1_2_MAX_LINEBUF_DEPTH_BITS 16
-#define DSC_1_2_MAX_LINEBUF_DEPTH_VAL  0
-#define DSC_1_1_MAX_LINEBUF_DEPTH_BITS 13
 
 /**
  * struct drm_dsc_rc_range_parameters - DSC Rate Control range parameters
-- 
2.43.3



Re: [PATCH 01/11] drm/i915/dp: Fix DSC line buffer depth programming

2024-03-28 Thread Imre Deak
On Wed, Mar 20, 2024 at 10:11:41PM +0200, Imre Deak wrote:
> Fix the calculation of the DSC line buffer depth. This is limited both
> by the source's and sink's maximum line buffer depth, but the former one
> was not taken into account. On all Intel platform's the source's maximum
> buffer depth is 13, so the overall limit is simply the minimum of the
> source/sink's limit, regardless of the DSC version.
> 
> This leaves the DSI DSC line buffer depth calculation as-is, trusting
> VBT.
> 
> On DSC version 1.2 for sinks reporting a maximum line buffer depth of 16
> the line buffer depth was incorrectly programmed as 0, leading to a
> corruption in color gradients / lines on the decompressed screen image.
> 
> Cc: dri-devel@lists.freedesktop.org
> Signed-off-by: Imre Deak 

Hi Maarten, Thomas, Maxime,

are you ok to merge the DRM DP-DSC/MST changes in patches 1, 7-9, 11 via
drm-intel-next?

--Imre

> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 16 ++--
>  include/drm/display/drm_dsc.h   |  3 ---
>  2 files changed, 6 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index af7ca00e9bc0a..dbe65651bf277 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -89,6 +89,9 @@
>  #define DP_DSC_MAX_ENC_THROUGHPUT_0  34
>  #define DP_DSC_MAX_ENC_THROUGHPUT_1  40
>  
> +/* Max DSC line buffer depth supported by HW. */
> +#define INTEL_DP_DSC_MAX_LINE_BUF_DEPTH  13
> +
>  /* DP DSC FEC Overhead factor in ppm = 1/(0.972261) = 1.028530 */
>  #define DP_DSC_FEC_OVERHEAD_FACTOR   1028530
>  
> @@ -1703,7 +1706,6 @@ static int intel_dp_dsc_compute_params(const struct 
> intel_connector *connector,
>  {
>   struct drm_i915_private *i915 = to_i915(connector->base.dev);
>   struct drm_dsc_config *vdsc_cfg = _state->dsc.config;
> - u8 line_buf_depth;
>   int ret;
>  
>   /*
> @@ -1732,20 +1734,14 @@ static int intel_dp_dsc_compute_params(const struct 
> intel_connector *connector,
>   connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - 
> DP_DSC_SUPPORT] &
>   DP_DSC_RGB;
>  
> - line_buf_depth = drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd);
> - if (!line_buf_depth) {
> + vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH,
> +
> drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd));
> + if (!vdsc_cfg->line_buf_depth) {
>   drm_dbg_kms(>drm,
>   "DSC Sink Line Buffer Depth invalid\n");
>   return -EINVAL;
>   }
>  
> - if (vdsc_cfg->dsc_version_minor == 2)
> - vdsc_cfg->line_buf_depth = (line_buf_depth == 
> DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ?
> - DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth;
> - else
> - vdsc_cfg->line_buf_depth = (line_buf_depth > 
> DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ?
> - DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
> -
>   vdsc_cfg->block_pred_enable =
>   connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - 
> DP_DSC_SUPPORT] &
>   DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
> diff --git a/include/drm/display/drm_dsc.h b/include/drm/display/drm_dsc.h
> index bc90273d06a62..bbbe7438473d3 100644
> --- a/include/drm/display/drm_dsc.h
> +++ b/include/drm/display/drm_dsc.h
> @@ -40,9 +40,6 @@
>  #define DSC_PPS_RC_RANGE_MINQP_SHIFT 11
>  #define DSC_PPS_RC_RANGE_MAXQP_SHIFT 6
>  #define DSC_PPS_NATIVE_420_SHIFT 1
> -#define DSC_1_2_MAX_LINEBUF_DEPTH_BITS   16
> -#define DSC_1_2_MAX_LINEBUF_DEPTH_VAL0
> -#define DSC_1_1_MAX_LINEBUF_DEPTH_BITS   13
>  
>  /**
>   * struct drm_dsc_rc_range_parameters - DSC Rate Control range parameters
> -- 
> 2.43.3
> 


Re: [PATCH 01/11] drm/i915/dp: Fix DSC line buffer depth programming

2024-03-27 Thread Imre Deak
On Tue, Mar 26, 2024 at 12:50:17PM -0700, Manasi Navare wrote:
Hi,

> Hi Imre,
> 
> Thanks for the DSC fixes.
>
> Would the line buf depth calculation that was getting set to 0 impact
> DSC on all platforms or was this issue only specific to MTL and was
> getting set correctly with older platforms?

Only those configs are affected where both the source and the sink supports
DSC1.2, so ADL is not affected.

> We didnt notice any DSC issues/corruptions with ADL based systems.

Yes, that makes sense.

> The actual change makes sense, just want to confirm if this applies to
> all platforms or any particular?

The change will make a difference only on MTL+.

> With that clarification:
> 
> Reviewed-by: Manasi Navare 

Thanks.

> Regards
> Manasi
> 
> On Tue, Mar 26, 2024 at 3:01 AM Nautiyal, Ankit K
>  wrote:
> >
> >
> > On 3/21/2024 1:41 AM, Imre Deak wrote:
> > > Fix the calculation of the DSC line buffer depth. This is limited both
> > > by the source's and sink's maximum line buffer depth, but the former one
> > > was not taken into account. On all Intel platform's the source's maximum
> > > buffer depth is 13, so the overall limit is simply the minimum of the
> > > source/sink's limit, regardless of the DSC version.
> > >
> > > This leaves the DSI DSC line buffer depth calculation as-is, trusting
> > > VBT.
> > >
> > > On DSC version 1.2 for sinks reporting a maximum line buffer depth of 16
> > > the line buffer depth was incorrectly programmed as 0, leading to a
> > > corruption in color gradients / lines on the decompressed screen image.
> > >
> > > Cc: dri-devel@lists.freedesktop.org
> > > Signed-off-by: Imre Deak 
> >
> > LGTM.
> >
> > Reviewed-by: Ankit Nautiyal 
> >
> > > ---
> > >   drivers/gpu/drm/i915/display/intel_dp.c | 16 ++--
> > >   include/drm/display/drm_dsc.h   |  3 ---
> > >   2 files changed, 6 insertions(+), 13 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> > > b/drivers/gpu/drm/i915/display/intel_dp.c
> > > index af7ca00e9bc0a..dbe65651bf277 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > @@ -89,6 +89,9 @@
> > >   #define DP_DSC_MAX_ENC_THROUGHPUT_0 34
> > >   #define DP_DSC_MAX_ENC_THROUGHPUT_1 40
> > >
> > > +/* Max DSC line buffer depth supported by HW. */
> > > +#define INTEL_DP_DSC_MAX_LINE_BUF_DEPTH  13
> > > +
> > >   /* DP DSC FEC Overhead factor in ppm = 1/(0.972261) = 1.028530 */
> > >   #define DP_DSC_FEC_OVERHEAD_FACTOR  1028530
> > >
> > > @@ -1703,7 +1706,6 @@ static int intel_dp_dsc_compute_params(const struct 
> > > intel_connector *connector,
> > >   {
> > >   struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > >   struct drm_dsc_config *vdsc_cfg = _state->dsc.config;
> > > - u8 line_buf_depth;
> > >   int ret;
> > >
> > >   /*
> > > @@ -1732,20 +1734,14 @@ static int intel_dp_dsc_compute_params(const 
> > > struct intel_connector *connector,
> > >   connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP 
> > > - DP_DSC_SUPPORT] &
> > >   DP_DSC_RGB;
> > >
> > > - line_buf_depth = 
> > > drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd);
> > > - if (!line_buf_depth) {
> > > + vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH,
> > > +
> > > drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd));
> > > + if (!vdsc_cfg->line_buf_depth) {
> > >   drm_dbg_kms(>drm,
> > >   "DSC Sink Line Buffer Depth invalid\n");
> > >   return -EINVAL;
> > >   }
> > >
> > > - if (vdsc_cfg->dsc_version_minor == 2)
> > > - vdsc_cfg->line_buf_depth = (line_buf_depth == 
> > > DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ?
> > > - DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth;
> > > - else
> > > - vdsc_cfg->line_buf_depth = (line_buf_depth > 
> > > DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ?
> > > - DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
> > > -
> > >   vdsc_cfg->block_pred_e

Re: [PATCH 09/11] drm/dp_mst: Add drm_dp_mst_aux_for_parent()

2024-03-27 Thread Imre Deak
On Wed, Mar 27, 2024 at 02:30:53PM +0530, Nautiyal, Ankit K wrote:
> 
> On 3/21/2024 1:41 AM, Imre Deak wrote:
> > Add a function to get the AUX device of the parent of an MST port, used
> > by a follow-up i915 patch in the patchset.
> > 
> > Cc: Lyude Paul 
> > Cc: dri-devel@lists.freedesktop.org
> > Signed-off-by: Imre Deak 
> > ---
> >   drivers/gpu/drm/display/drm_dp_mst_topology.c | 16 
> >   1 file changed, 16 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
> > b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > index 6bd471a2266ce..d70f7de644371 100644
> > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > @@ -6004,6 +6004,22 @@ static bool drm_dp_mst_is_virtual_dpcd(struct 
> > drm_dp_mst_port *port)
> > return false;
> >   }
> > +/**
> > + * drm_dp_mst_aux_for_parent() - Get the AUX device for an MST port's 
> > parent
> > + * @port: MST port whose parent's AUX device is returned
> > + *
> > + * Return the AUX device for @port's parent or NULL if port's parent is the
> > + * root port.
> > + */
> > +struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port)
> > +{
> > +   if (!port->parent || !port->parent->port_parent)
> > +   return NULL;
> > +
> > +   return >parent->port_parent->aux;
> > +}
> > +EXPORT_SYMBOL(drm_dp_mst_aux_for_parent);
> 
> As mentioned in previous patch, the declaration of this in the header,
> got included in previous patch.

Yes thanks, the header change should've been in this patch, will move it here
(while applying the patches if nothing else comes up).

> Regards,
> 
> Ankit
> 
> > +
> >   /**
> >* drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC
> >* @port: The port to check. A leaf of the MST tree with an attached 
> > display.


[PATCH 11/11] drm/i915/dp_mst: Enable HBLANK expansion quirk for UHBR rates

2024-03-20 Thread Imre Deak
Enabling the 5k@60Hz uncompressed mode on the MediaTek/Dell U3224KBA
monitor results in a blank screen, at least on MTL platforms on UHBR
link rates with some (<30) uncompressed bpp values. Enabling compression
fixes the problem, so do that for now. Windows enables DSC always if the
sink supports it and forcing it to enable the mode without compression
leads to the same problem above (which suggests a panel issue with
uncompressed mode).

The same 5k mode on non-UHBR link rates is not affected and lower
resolution modes are not affected either. The problem is similar to the
one fixed by the HBLANK expansion quirk on Synaptics hubs, with the
difference that the problematic mode has a longer HBLANK duration. Also
the monitor doesn't report supporting HBLANK expansion; either its
internal MST hub does the expansion internally - similarly to the
Synaptics hub - or the issue has another root cause, but still related
to the mode's short HBLANK duration. Enable the quirk for the monitor
adjusting the detection for the above differences.

Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_helper.c |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 22 +
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index f5d4be8978660..3e8e1bb59dea3 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2281,6 +2281,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
/* Synaptics DP1.4 MST hubs require DSC for some modes on which it 
applies HBLANK expansion. */
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, 
BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
+   /* MediaTek panels (at least in U3224KBA) require DSC for modes with a 
short HBLANK on UHBR links. */
+   { OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, 
BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
/* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low 
DP_MAX_LINK_RATE */
{ OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, 
BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
 };
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 76a8fb21b8e52..b5224fe6cc16b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -407,15 +407,22 @@ static int mode_hblank_period_ns(const struct 
drm_display_mode *mode)
 
 static bool
 hblank_expansion_quirk_needs_dsc(const struct intel_connector *connector,
-const struct intel_crtc_state *crtc_state)
+const struct intel_crtc_state *crtc_state,
+const struct link_config_limits *limits)
 {
const struct drm_display_mode *adjusted_mode =
_state->hw.adjusted_mode;
+   bool is_uhbr_sink = connector->mst_port &&
+   
drm_dp_uhbr_channel_coding_supported(connector->mst_port->dpcd);
+   int hblank_limit = is_uhbr_sink ? 500 : 300;
 
if (!connector->dp.dsc_hblank_expansion_quirk)
return false;
 
-   if (mode_hblank_period_ns(adjusted_mode) > 300)
+   if (is_uhbr_sink && !drm_dp_is_uhbr_rate(limits->max_rate))
+   return false;
+
+   if (mode_hblank_period_ns(adjusted_mode) > hblank_limit)
return false;
 
return true;
@@ -431,7 +438,7 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct 
intel_connector *conne
const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
int min_bpp_x16 = limits->link.min_bpp_x16;
 
-   if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state))
+   if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state, limits))
return true;
 
if (!dsc) {
@@ -1539,7 +1546,14 @@ static bool detect_dsc_hblank_expansion_quirk(const 
struct intel_connector *conn
  DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC))
return false;
 
-   if (!(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE))
+   /*
+* UHBR (MST sink) devices requiring this quirk doesn't advertise the
+* HBLANK expansion support. Presuming that they perform HBLANK
+* expansion internally, or are affected by this issue on modes with a
+* short HBLANK for other reasons.
+*/
+   if (!drm_dp_uhbr_channel_coding_supported(dpcd) &&
+   !(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE))
return false;
 
drm_dbg_kms(>drm,
-- 
2.43.3



[PATCH 09/11] drm/dp_mst: Add drm_dp_mst_aux_for_parent()

2024-03-20 Thread Imre Deak
Add a function to get the AUX device of the parent of an MST port, used
by a follow-up i915 patch in the patchset.

Cc: Lyude Paul 
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 6bd471a2266ce..d70f7de644371 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -6004,6 +6004,22 @@ static bool drm_dp_mst_is_virtual_dpcd(struct 
drm_dp_mst_port *port)
return false;
 }
 
+/**
+ * drm_dp_mst_aux_for_parent() - Get the AUX device for an MST port's parent
+ * @port: MST port whose parent's AUX device is returned
+ *
+ * Return the AUX device for @port's parent or NULL if port's parent is the
+ * root port.
+ */
+struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port)
+{
+   if (!port->parent || !port->parent->port_parent)
+   return NULL;
+
+   return >parent->port_parent->aux;
+}
+EXPORT_SYMBOL(drm_dp_mst_aux_for_parent);
+
 /**
  * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC
  * @port: The port to check. A leaf of the MST tree with an attached display.
-- 
2.43.3



[PATCH 08/11] drm/dp_mst: Factor out drm_dp_mst_port_is_logical()

2024-03-20 Thread Imre Deak
Factor out a function to check if an MST port is logical, used by a
follow-up i915 patch in the patchset.

Cc: Lyude Paul 
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 6 +++---
 include/drm/display/drm_dp_mst_helper.h   | 7 +++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 03d5282094262..6bd471a2266ce 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -2274,7 +2274,7 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch 
*mstb,
 
if (port->pdt != DP_PEER_DEVICE_NONE &&
drm_dp_mst_is_end_device(port->pdt, port->mcs) &&
-   port->port_num >= DP_MST_LOGICAL_PORT_0)
+   drm_dp_mst_port_is_logical(port))
port->cached_edid = drm_edid_read_ddc(port->connector,
  >aux.ddc);
 
@@ -4213,7 +4213,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector,
case DP_PEER_DEVICE_SST_SINK:
ret = connector_status_connected;
/* for logical ports - cache the EDID */
-   if (port->port_num >= DP_MST_LOGICAL_PORT_0 && 
!port->cached_edid)
+   if (drm_dp_mst_port_is_logical(port) && !port->cached_edid)
port->cached_edid = drm_edid_read_ddc(connector, 
>aux.ddc);
break;
case DP_PEER_DEVICE_DP_LEGACY_CONV:
@@ -5977,7 +5977,7 @@ static bool drm_dp_mst_is_virtual_dpcd(struct 
drm_dp_mst_port *port)
return false;
 
/* Virtual DP Sink (Internal Display Panel) */
-   if (port->port_num >= 8)
+   if (drm_dp_mst_port_is_logical(port))
return true;
 
/* DP-to-HDMI Protocol Converter */
diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index 3ae88a383a41f..c12f18b744d01 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -927,6 +927,13 @@ int __must_check drm_dp_mst_root_conn_atomic_check(struct 
drm_connector_state *n
 void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
 void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
 
+static inline
+bool drm_dp_mst_port_is_logical(struct drm_dp_mst_port *port)
+{
+   return port->port_num >= DP_MST_LOGICAL_PORT_0;
+}
+
+struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port);
 struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);
 
 static inline struct drm_dp_mst_topology_state *
-- 
2.43.3



[PATCH 07/11] drm/dp: Add drm_dp_uhbr_channel_coding_supported()

2024-03-20 Thread Imre Deak
Factor out a function to check for UHBR channel coding support used by a
follow-up patch in the patchset.

Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
 include/drm/display/drm_dp_helper.h | 6 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index dbe65651bf277..1d13a1ba2b97d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -217,7 +217,7 @@ static void intel_dp_set_dpcd_sink_rates(struct intel_dp 
*intel_dp)
 * Sink rates for 128b/132b. If set, sink should support all 8b/10b
 * rates and 10 Gbps.
 */
-   if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B) 
{
+   if (drm_dp_uhbr_channel_coding_supported(intel_dp->dpcd)) {
u8 uhbr_rates = 0;
 
BUILD_BUG_ON(ARRAY_SIZE(intel_dp->sink_rates) < 
ARRAY_SIZE(dp_rates) + 3);
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index a62fcd051d4d4..150c37a99a16f 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -221,6 +221,12 @@ drm_dp_channel_coding_supported(const u8 
dpcd[DP_RECEIVER_CAP_SIZE])
return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_8B10B;
 }
 
+static inline bool
+drm_dp_uhbr_channel_coding_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B;
+}
+
 static inline bool
 drm_dp_alternate_scrambler_reset_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
-- 
2.43.3



[PATCH 01/11] drm/i915/dp: Fix DSC line buffer depth programming

2024-03-20 Thread Imre Deak
Fix the calculation of the DSC line buffer depth. This is limited both
by the source's and sink's maximum line buffer depth, but the former one
was not taken into account. On all Intel platform's the source's maximum
buffer depth is 13, so the overall limit is simply the minimum of the
source/sink's limit, regardless of the DSC version.

This leaves the DSI DSC line buffer depth calculation as-is, trusting
VBT.

On DSC version 1.2 for sinks reporting a maximum line buffer depth of 16
the line buffer depth was incorrectly programmed as 0, leading to a
corruption in color gradients / lines on the decompressed screen image.

Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 16 ++--
 include/drm/display/drm_dsc.h   |  3 ---
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index af7ca00e9bc0a..dbe65651bf277 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -89,6 +89,9 @@
 #define DP_DSC_MAX_ENC_THROUGHPUT_034
 #define DP_DSC_MAX_ENC_THROUGHPUT_140
 
+/* Max DSC line buffer depth supported by HW. */
+#define INTEL_DP_DSC_MAX_LINE_BUF_DEPTH13
+
 /* DP DSC FEC Overhead factor in ppm = 1/(0.972261) = 1.028530 */
 #define DP_DSC_FEC_OVERHEAD_FACTOR 1028530
 
@@ -1703,7 +1706,6 @@ static int intel_dp_dsc_compute_params(const struct 
intel_connector *connector,
 {
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct drm_dsc_config *vdsc_cfg = _state->dsc.config;
-   u8 line_buf_depth;
int ret;
 
/*
@@ -1732,20 +1734,14 @@ static int intel_dp_dsc_compute_params(const struct 
intel_connector *connector,
connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - 
DP_DSC_SUPPORT] &
DP_DSC_RGB;
 
-   line_buf_depth = drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd);
-   if (!line_buf_depth) {
+   vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH,
+  
drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd));
+   if (!vdsc_cfg->line_buf_depth) {
drm_dbg_kms(>drm,
"DSC Sink Line Buffer Depth invalid\n");
return -EINVAL;
}
 
-   if (vdsc_cfg->dsc_version_minor == 2)
-   vdsc_cfg->line_buf_depth = (line_buf_depth == 
DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ?
-   DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth;
-   else
-   vdsc_cfg->line_buf_depth = (line_buf_depth > 
DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ?
-   DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
-
vdsc_cfg->block_pred_enable =
connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - 
DP_DSC_SUPPORT] &
DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
diff --git a/include/drm/display/drm_dsc.h b/include/drm/display/drm_dsc.h
index bc90273d06a62..bbbe7438473d3 100644
--- a/include/drm/display/drm_dsc.h
+++ b/include/drm/display/drm_dsc.h
@@ -40,9 +40,6 @@
 #define DSC_PPS_RC_RANGE_MINQP_SHIFT   11
 #define DSC_PPS_RC_RANGE_MAXQP_SHIFT   6
 #define DSC_PPS_NATIVE_420_SHIFT   1
-#define DSC_1_2_MAX_LINEBUF_DEPTH_BITS 16
-#define DSC_1_2_MAX_LINEBUF_DEPTH_VAL  0
-#define DSC_1_1_MAX_LINEBUF_DEPTH_BITS 13
 
 /**
  * struct drm_dsc_rc_range_parameters - DSC Rate Control range parameters
-- 
2.43.3



Re: [PATCH v4] Fix divide-by-zero regression on DP MST unplug with nouveau

2024-03-18 Thread Imre Deak
_1 
> mei_hdcp thunderbolt bluetooth intel_cstate wmi_bmof intel_wmi_thunderbolt 
> cfg80211 snd_pcm mc snd_seq_device i2c_i801 r8169 ecdh_generic snd_timer 
> i2c_smbus ecc snd mei_me intel_lpss_pci mei ahci intel_lpss soundcore realtek 
> libahci idma64 intel_pch_thermal i2c_hid_acpi i2c_hid acpi_pad sch_fq_codel 
> msr parport_pc ppdev lp parport efi_pstore ip_tables x_tables autofs4 
> dm_crypt raid10 raid456 libcrc32c async_raid6_recov async_memcpy async_pq 
> async_xor xor async_tx raid6_pq raid1 raid0 joydev input_leds hid_generic 
> usbhid hid nouveau i915 drm_ttm_helper gpu_sched drm_gpuvm drm_exec 
> i2c_algo_bit drm_buddy ttm drm_display_helper drm_kms_helper cec rc_core drm 
> nvme nvme_core mxm_wmi xhci_pci xhci_pci_renesas video wmi pinctrl_cannonlake 
> mac_hid
>  ---[ end trace  ]---
> 
> Fix this by avoiding the divide if bpp is 0.
> 
> Fixes: c1d6a22b7219 ("drm/dp: Add helpers to calculate the link BW overhead")
> Cc: sta...@vger.kernel.org
> Acked-by: Imre Deak 
> Signed-off-by: Chris Bainbridge 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index b1ca3a1100da..26c188ce5f1c 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -3982,6 +3982,13 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
>   u32 overhead = 100;
>   int symbol_cycles;
>  
> + if (lane_count == 0 || hactive == 0 || bpp_x16 == 0) {
> + DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, 
> hactive %d, bpp_x16 %d.%04d\n",
> +   lane_count, hactive,
> +   bpp_x16 >> 4, (bpp_x16 & 0xf) * 625);
> + return 0;
> + }
> +
>   /*
>* DP Standard v2.1 2.6.4.1
>* SSC downspread and ref clock variation margin:
> -- 
> 2.39.2
> 


Re: [PATCH] drm/bridge: Select DRM_KMS_HELPER for DRM_PANEL_BRIDGE

2024-03-18 Thread Imre Deak
On Mon, Mar 18, 2024 at 12:59:29PM +0200, Jani Nikula wrote:
> On Mon, 18 Mar 2024, Jani Nikula  wrote:
> > On Mon, 18 Mar 2024, Neil Armstrong  wrote:
> >> Hi,
> >>
> >> On Thu, 11 Jan 2024 13:38:04 +0100, Luca Weiss wrote:
> >>> Since the kconfig symbol of DRM_PANEL_BRIDGE is only adding
> >>> bridge/panel.o to drm_kms_helper object, we need to select
> >>> DRM_KMS_HELPER to make sure the file is actually getting built.
> >>> 
> >>> Otherwise with certain defconfigs e.g. devm_drm_of_get_bridge will not
> >>> be properly available:
> >>> 
> >>> [...]
> >>
> >> Thanks, Applied to https://gitlab.freedesktop.org/drm/misc/kernel.git 
> >> (drm-misc-fixes)
> >>
> >> [1/1] drm/bridge: Select DRM_KMS_HELPER for DRM_PANEL_BRIDGE
> >>   
> >> https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/e3f18b0dd1db242791afbc3bd173026163ce0ccc
> >
> > With my kernel config, e3f18b0dd1db ("drm/bridge: Select DRM_KMS_HELPER
> > for DRM_PANEL_BRIDGE") leads to:
> >
> > WARNING: unmet direct dependencies detected for DRM_KMS_HELPER
> >   Depends on [m]: HAS_IOMEM [=y] && DRM [=m]
> >   Selected by [y]:
> >   - DRM_PANEL_BRIDGE [=y] && HAS_IOMEM [=y] && DRM_BRIDGE [=y]
> >   Selected by [m]:
> >   - DRM [=m] && HAS_IOMEM [=y] && (AGP [=y] || AGP [=y]=n) && 
> > !EMULATED_CMPXCHG && HAS_DMA [=y] && DRM_FBDEV_EMULATION [=y]
> >   - DRM_MIPI_DBI [=m] && HAS_IOMEM [=y] && DRM [=m]
> >   - DRM_KUNIT_TEST [=m] && HAS_IOMEM [=y] && DRM [=m] && KUNIT [=y] && MMU 
> > [=y]
> >   - DRM_RADEON [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y] 
> > && (AGP [=y] || !AGP [=y])
> >   - DRM_AMDGPU [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y] 
> > && !UML
> >   - DRM_NOUVEAU [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y]
> >   - DRM_I915 [=m] && HAS_IOMEM [=y] && DRM [=m] && X86 [=y] && PCI [=y] && 
> > !PREEMPT_RT [=n]
> >   - DRM_XE [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y] && (m 
> > && MODULES [=y] || y && KUNIT [=y]=y) && 64BIT [=y]
> >   - DRM_VKMS [=m] && HAS_IOMEM [=y] && DRM [=m] && MMU [=y]
> >   - DRM_VMWGFX [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y] 
> > && (X86 [=y] || ARM64)
> >   - DRM_GMA500 [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && X86 [=y] 
> > && MMU [=y]
> >   - DRM_UDL [=m] && HAS_IOMEM [=y] && DRM [=m] && USB [=m] && 
> > USB_ARCH_HAS_HCD [=y] && MMU [=y]
> >   - DRM_AST [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y]
> >   - DRM_MGAG200 [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y]
> >   - DRM_QXL [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y]
> >   - DRM_VIRTIO_GPU [=m] && HAS_IOMEM [=y] && DRM [=m] && VIRTIO_MENU [=y] 
> > && MMU [=y]
> >   - DRM_BOCHS [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU [=y]
> >   - DRM_CIRRUS_QEMU [=m] && HAS_IOMEM [=y] && DRM [=m] && PCI [=y] && MMU 
> > [=y]
> >   - DRM_GM12U320 [=m] && HAS_IOMEM [=y] && DRM [=m] && USB [=m] && MMU [=y]
> >   - DRM_PANEL_MIPI_DBI [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - DRM_SIMPLEDRM [=m] && HAS_IOMEM [=y] && DRM [=m] && MMU [=y]
> >   - TINYDRM_HX8357D [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_ILI9163 [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_ILI9225 [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_ILI9341 [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_ILI9486 [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_MI0283QT [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_REPAPER [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_ST7586 [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - TINYDRM_ST7735R [=m] && HAS_IOMEM [=y] && DRM [=m] && SPI [=y]
> >   - DRM_XEN_FRONTEND [=m] && HAS_IOMEM [=y] && XEN [=y] && DRM [=m]
> >   - DRM_VBOXVIDEO [=m] && HAS_IOMEM [=y] && DRM [=m] && X86 [=y] && PCI [=y]
> >   - DRM_GUD [=m] && HAS_IOMEM [=y] && DRM [=m] && USB [=m] && MMU [=y]
> >   - DRM_SSD130X [=m] && HAS_IOMEM [=y] && DRM [=m] && MMU [=y]
> >   - DRM_ANALOGIX_ANX78XX [=m] && HAS_IOMEM [=y] && DRM [=m] && DRM_BRIDGE 
> > [=y]
> 
> Please read Documentation/kbuild/kconfig-language.rst.
> 
> Basically boolean DRM_PANEL_BRIDGE selecting tristate DRM_KMS_HELPER
> forces it to y while it should remain m.
> 
> Please revert.

I can also see the above issue with the latest drm-tip, in particular a
CONFIG_DRM=m build will fail with the above kconfig warns and then
multiple linker errors:

ld: drivers/gpu/drm/drm_atomic_helper.o: in function 
`drm_atomic_helper_check_wb_connector_state':
/home/imre/intel-gfx/drm-misc-fixes/drivers/gpu/drm/drm_atomic_helper.c:832: 
undefined reference to `__drm_dev_dbg'
ld: drivers/gpu/drm/drm_atomic_helper.o: in function 
`drm_atomic_helper_async_check':
/home/imre/intel-gfx/drm-misc-fixes/drivers/gpu/drm/drm_atomic_helper.c:1932: 
undefined reference to `__drm_dev_dbg'
ld: 
/home/imre/intel-gfx/drm-misc-fixes/drivers/gpu/drm/drm_atomic_helper.c:1924: 
undefined reference to 

Re: [PATCH v3] Fix divide-by-zero regression on DP MST unplug with nouveau

2024-03-14 Thread Imre Deak
i_me intel_lpss_pci mei ahci intel_lpss soundcore realtek 
> libahci idma64 intel_pch_thermal i2c_hid_acpi i2c_hid acpi_pad sch_fq_codel 
> msr parport_pc ppdev lp parport efi_pstore ip_tables x_tables autofs4 
> dm_crypt raid10 raid456 libcrc32c async_raid6_recov async_memcpy async_pq 
> async_xor xor async_tx raid6_pq raid1 raid0 joydev input_leds hid_generic 
> usbhid hid nouveau i915 drm_ttm_helper gpu_sched drm_gpuvm drm_exec 
> i2c_algo_bit drm_buddy ttm drm_display_helper drm_kms_helper cec rc_core drm 
> nvme nvme_core mxm_wmi xhci_pci xhci_pci_renesas video wmi pinctrl_cannonlake 
> mac_hid
>  ---[ end trace  ]---
> 
> Fix this by avoiding the divide if bpp is 0.
> 
> Fixes: c1d6a22b7219 ("drm/dp: Add helpers to calculate the link BW overhead")
> Cc: sta...@vger.kernel.org
> Acked-by: Imre Deak 
> Signed-off-by: Chris Bainbridge 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index b1ca3a1100da..d51c1bcee258 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -3982,6 +3982,12 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
>   u32 overhead = 100;
>   int symbol_cycles;
>  
> + if (lane_count == 0 || hactive == 0 || bpp_x16 == 0) {
> + DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, 
> hactive %d, bpp_x16 %.04d\n",

bpp_x16 is a .4 fixed point param and the proper formatting for it is:

"bpp_x16 %d.%04d", bpp_x16 >> 4, (bpp_x16 & 0xf) * 625

> +   lane_count, hactive, bpp_x16);
> + return 0;
> + }
> +
>   /*
>* DP Standard v2.1 2.6.4.1
>* SSC downspread and ref clock variation margin:
> -- 
> 2.39.2
> 


Re: [PATCH v2] Fix divide-by-zero regression on DP MST unplug with nouveau

2024-03-12 Thread Imre Deak
i_me intel_lpss_pci mei ahci intel_lpss soundcore realtek 
> libahci idma64 intel_pch_thermal i2c_hid_acpi i2c_hid acpi_pad sch_fq_codel 
> msr parport_pc ppdev lp parport efi_pstore ip_tables x_tables autofs4 
> dm_crypt raid10 raid456 libcrc32c async_raid6_recov async_memcpy async_pq 
> async_xor xor async_tx raid6_pq raid1 raid0 joydev input_leds hid_generic 
> usbhid hid nouveau i915 drm_ttm_helper gpu_sched drm_gpuvm drm_exec 
> i2c_algo_bit drm_buddy ttm drm_display_helper drm_kms_helper cec rc_core drm 
> nvme nvme_core mxm_wmi xhci_pci xhci_pci_renesas video wmi pinctrl_cannonlake 
> mac_hid
>  ---[ end trace  ]---
> 
> Fix this by avoiding the divide if bpp is 0.
> 
> Fixes: c1d6a22b7219 ("drm/dp: Add helpers to calculate the link BW overhead")
> Signed-off-by: Chris Bainbridge 
> Acked-by: Imre Deak 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index b1ca3a1100da..9f0e7142f174 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -3982,6 +3982,13 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
>   u32 overhead = 100;
>   int symbol_cycles;
>  
> + if (bpp_x16 == 0) {
> + DRM_DEBUG("drm_dp_bw_overhead called with bpp 0\n");
> + }
> + if (lane_count == 0 || hactive == 0 || bpp_x16 == 0) {

Could you add lane_count and hactive to the debug print as well?
Something like "Invalid BW overhead params: lane_count %d, hactive %d, bpp_x16 
%d.04d". 

> + return 0;
> + }
> +
>   /*
>* DP Standard v2.1 2.6.4.1
>* SSC downspread and ref clock variation margin:
> -- 
> 2.39.2
> 


Re: [PATCH] Fix divide-by-zero on DP unplug with nouveau

2024-03-11 Thread Imre Deak
On Mon, Mar 11, 2024 at 06:09:29PM +0200, Imre Deak wrote:
> On Sat, Feb 10, 2024 at 09:24:59PM +, Chris Bainbridge wrote:
> 
> Sorry for the delay.
> 
> > The following trace occurs when using nouveau and unplugging a DP MST
> > adaptor:
> > 
> >  divide error:  [#1] PREEMPT SMP PTI
> >  CPU: 7 PID: 2962 Comm: Xorg Not tainted 6.8.0-rc3+ #744
> >  Hardware name: Razer Blade/DANA_MB, BIOS 01.01 08/31/2018
> >  RIP: 0010:drm_dp_bw_overhead+0xb4/0x110 [drm_display_helper]
> >  Code: c6 b8 01 00 00 00 75 61 01 c6 41 0f af f3 41 0f af f1 c1 e1 04 48 63 
> > c7 31 d2 89 ff 48 8b 5d f8 c9 48 0f af f1 48 8d 44 06 ff <48> f7 f7 31 d2 
> > 31 c9 31 f6 31 ff 45 31 c0 45 31 c9 45 31 d2 45 31
> >  RSP: 0018:b2c5c211fa30 EFLAGS: 00010206
> >  RAX:  RBX:  RCX: 00f59b00
> >  RDX:  RSI:  RDI: 
> >  RBP: b2c5c211fa48 R08: 0001 R09: 0020
> >  R10: 0004 R11:  R12: 00023b4a
> >  R13: 91d37d165800 R14: 91d36fac6d80 R15: 91d34a764010
> >  FS:  7f4a1ca3fa80() GS:91d6edbc() 
> > knlGS:
> >  CS:  0010 DS:  ES:  CR0: 80050033
> >  CR2: 559491d49000 CR3: 00011d180002 CR4: 003706f0
> >  Call Trace:
> >   
> >   ? show_regs+0x6d/0x80
> >   ? die+0x37/0xa0
> >   ? do_trap+0xd4/0xf0
> >   ? do_error_trap+0x71/0xb0
> >   ? drm_dp_bw_overhead+0xb4/0x110 [drm_display_helper]
> >   ? exc_divide_error+0x3a/0x70
> >   ? drm_dp_bw_overhead+0xb4/0x110 [drm_display_helper]
> >   ? asm_exc_divide_error+0x1b/0x20
> >   ? drm_dp_bw_overhead+0xb4/0x110 [drm_display_helper]
> >   ? drm_dp_calc_pbn_mode+0x2e/0x70 [drm_display_helper]
> >   nv50_msto_atomic_check+0xda/0x120 [nouveau]
> >   drm_atomic_helper_check_modeset+0xa87/0xdf0 [drm_kms_helper]
> >   drm_atomic_helper_check+0x19/0xa0 [drm_kms_helper]
> >   nv50_disp_atomic_check+0x13f/0x2f0 [nouveau]
> >   drm_atomic_check_only+0x668/0xb20 [drm]
> >   ? drm_connector_list_iter_next+0x86/0xc0 [drm]
> >   drm_atomic_commit+0x58/0xd0 [drm]
> >   ? __pfx___drm_printfn_info+0x10/0x10 [drm]
> >   drm_atomic_connector_commit_dpms+0xd7/0x100 [drm]
> >   drm_mode_obj_set_property_ioctl+0x1c5/0x450 [drm]
> >   ? __pfx_drm_connector_property_set_ioctl+0x10/0x10 [drm]
> >   drm_connector_property_set_ioctl+0x3b/0x60 [drm]
> >   drm_ioctl_kernel+0xb9/0x120 [drm]
> >   drm_ioctl+0x2d0/0x550 [drm]
> >   ? __pfx_drm_connector_property_set_ioctl+0x10/0x10 [drm]
> >   nouveau_drm_ioctl+0x61/0xc0 [nouveau]
> >   __x64_sys_ioctl+0xa0/0xf0
> >   do_syscall_64+0x76/0x140
> >   ? do_syscall_64+0x85/0x140
> >   ? do_syscall_64+0x85/0x140
> >   entry_SYSCALL_64_after_hwframe+0x6e/0x76
> >  RIP: 0033:0x7f4a1cd1a94f
> >  Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 
> > 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <41> 89 c0 3d 00 
> > f0 ff ff 77 1f 48 8b 44 24 18 64 48 2b 04 25 28 00
> >  RSP: 002b:7ffd2f1df520 EFLAGS: 0246 ORIG_RAX: 0010
> >  RAX: ffda RBX: 7ffd2f1df5b0 RCX: 7f4a1cd1a94f
> >  RDX: 7ffd2f1df5b0 RSI: c01064ab RDI: 000f
> >  RBP: c01064ab R08: 56347932deb8 R09: 56347a7d99c0
> >  R10:  R11: 0246 R12: 56347938a220
> >  R13: 000f R14: 563479d9f3f0 R15: 
> >   
> >  Modules linked in: rfcomm xt_conntrack nft_chain_nat xt_MASQUERADE nf_nat 
> > nf_conntrack_netlink nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xfrm_user 
> > xfrm_algo xt_addrtype nft_compat nf_tables nfnetlink br_netfilter bridge 
> > stp llc ccm cmac algif_hash overlay algif_skcipher af_alg bnep binfmt_misc 
> > snd_sof_pci_intel_cnl snd_sof_intel_hda_common snd_soc_hdac_hda snd_sof_pci 
> > snd_sof_xtensa_dsp snd_sof_intel_hda snd_sof snd_sof_utils 
> > snd_soc_acpi_intel_match snd_soc_acpi snd_soc_core snd_compress 
> > snd_sof_intel_hda_mlink snd_hda_ext_core iwlmvm intel_rapl_msr 
> > intel_rapl_common intel_tcc_cooling x86_pkg_temp_thermal intel_powerclamp 
> > mac80211 coretemp kvm_intel snd_hda_codec_hdmi kvm snd_hda_codec_realtek 
> > snd_hda_codec_generic uvcvideo libarc4 snd_hda_intel snd_intel_dspcfg 
> > snd_hda_codec iwlwifi videobuf2_vmalloc videobuf2_memops uvc irqbypass 
> > btusb videobuf2_v4l2 snd_seq_midi crct10dif_pclmul hid_multitouch 
> > crc32_pclmul snd_seq_midi_event btrtl snd_hwdep videodev polyval_clmulni 
&g

Re: [PATCH] Fix divide-by-zero on DP unplug with nouveau

2024-03-11 Thread Imre Deak
id_acpi i2c_hid acpi_pad sch_fq_codel 
> msr parport_pc ppdev lp parport efi_pstore ip_tables x_tables autofs4 
> dm_crypt raid10 raid456 libcrc32c async_raid6_recov async_memcpy async_pq 
> async_xor xor async_tx raid6_pq raid1 raid0 joydev input_leds hid_generic 
> usbhid hid nouveau i915 drm_ttm_helper gpu_sched drm_gpuvm drm_exec 
> i2c_algo_bit drm_buddy ttm drm_display_helper drm_kms_helper cec rc_core drm 
> nvme nvme_core mxm_wmi xhci_pci xhci_pci_renesas video wmi pinctrl_cannonlake 
> mac_hid
>  ---[ end trace  ]---
> 
> Fix this by avoiding the divide if bpp is 0.
> 
> Fixes: c1d6a22b7219 ("drm/dp: Add helpers to calculate the link BW overhead")
> Signed-off-by: Chris Bainbridge 
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index b1ca3a1100da..bb8794c8f99c 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -4024,6 +4024,9 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
> bpp_x16, symbol_size,
> is_mst);
>  
> + /* Avoid potential divide by zero in DIV_ROUND_UP_ULL */

The above comment is redundant.

> + if (bpp_x16 == 0)
> + return 0;

Could you please move the check to the beginnig of the function and add
a debug message in case bpp_x16 is 0?

It looks odd that a driver calls this function with a 0 bpp_x16, and
ideally it should be fixed in the driver. However as it's a regression
and we don't have a better idea now:

Acked-by: Imre Deak 

>   return DIV_ROUND_UP_ULL(mul_u32_u32(symbol_cycles * symbol_size * 
> lane_count,
>   overhead * 16),
>   hactive * bpp_x16);
> -- 
> 2.39.2
> 


Re: [PATCH] drm: Fix output poll work for drm_kms_helper_poll=n

2024-03-04 Thread Imre Deak
On Sat, Mar 02, 2024 at 12:55:48PM +0300, Dmitry Baryshkov wrote:
> On Fri, 1 Mar 2024 at 18:22, Imre Deak  wrote:
> >
> > If drm_kms_helper_poll=n the output poll work will only get scheduled
> > from drm_helper_probe_single_connector_modes() to handle a delayed
> > hotplug event. Since polling is disabled the work in this case should
> > just call drm_kms_helper_hotplug_event() w/o detecting the state of
> > connectors and rescheduling the work.
> >
> > After commit d33a54e3991d after a delayed hotplug event above the
> > connectors did get re-detected in the poll work and the work got
> > re-scheduled periodically (since poll_running is also false if
> > drm_kms_helper_poll=n), in effect ignoring the drm_kms_helper_poll=n
> > kernel param.
> >
> > Fix the above by calling only drm_kms_helper_hotplug_event() for a
> > delayed hotplug event if drm_kms_helper_hotplug_event=n, as was done
> > before d33a54e3991d.
> >
> > Cc: Dmitry Baryshkov 
> > Reported-by: Ville Syrjälä 
> > Fixes: d33a54e3991d ("drm/probe_helper: sort out poll_running vs 
> > poll_enabled")
> 
> Reviewed-by: Dmitry Baryshkov 

Patch is pushed to drm-misc-fixes, thanks for the report and review.

> 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/drm_probe_helper.c | 8 +---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> -- 
> With best wishes
> Dmitry


[PATCH] drm: Fix output poll work for drm_kms_helper_poll=n

2024-03-01 Thread Imre Deak
If drm_kms_helper_poll=n the output poll work will only get scheduled
from drm_helper_probe_single_connector_modes() to handle a delayed
hotplug event. Since polling is disabled the work in this case should
just call drm_kms_helper_hotplug_event() w/o detecting the state of
connectors and rescheduling the work.

After commit d33a54e3991d after a delayed hotplug event above the
connectors did get re-detected in the poll work and the work got
re-scheduled periodically (since poll_running is also false if
drm_kms_helper_poll=n), in effect ignoring the drm_kms_helper_poll=n
kernel param.

Fix the above by calling only drm_kms_helper_hotplug_event() for a
delayed hotplug event if drm_kms_helper_hotplug_event=n, as was done
before d33a54e3991d.

Cc: Dmitry Baryshkov 
Reported-by: Ville Syrjälä 
Fixes: d33a54e3991d ("drm/probe_helper: sort out poll_running vs poll_enabled")
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/drm_probe_helper.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index 19ecb749704be..4d60cc810b577 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -767,9 +767,11 @@ static void output_poll_execute(struct work_struct *work)
changed = dev->mode_config.delayed_event;
dev->mode_config.delayed_event = false;
 
-   if (!drm_kms_helper_poll && dev->mode_config.poll_running) {
-   drm_kms_helper_disable_hpd(dev);
-   dev->mode_config.poll_running = false;
+   if (!drm_kms_helper_poll) {
+   if (dev->mode_config.poll_running) {
+   drm_kms_helper_disable_hpd(dev);
+   dev->mode_config.poll_running = false;
+   }
goto out;
}
 
-- 
2.43.3



[PATCH] drm/dp: Fix documentation of DP tunnel functions

2024-02-28 Thread Imre Deak
Fix the documentation issues below, also reported by 'make htmldocs':

drivers/gpu/drm/display/drm_dp_tunnel.c:447: warning: Function parameter or 
struct member 'tunnel' not described in 'drm_dp_tunnel_put'
drivers/gpu/drm/display/drm_dp_tunnel.c:447: warning: Function parameter or 
struct member 'tracker' not described in 'drm_dp_tunnel_put'
drivers/gpu/drm/display/drm_dp_tunnel.c:1185: warning: expecting prototype for 
drm_dp_tunnel_atomic_get_allocated_bw(). Prototype was for 
drm_dp_tunnel_get_allocated_bw() instead
drivers/gpu/drm/display/drm_dp_tunnel.c:1903: warning: Function parameter or 
struct member 'max_group_count' not described in 'drm_dp_tunnel_mgr_create'

Fixes: 295654f7e554 ("drm/dp: Add support for DP tunneling")
Reported-by: kernel test robot 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_tunnel.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c 
b/drivers/gpu/drm/display/drm_dp_tunnel.c
index 120e0de674c19..017f1d4c63415 100644
--- a/drivers/gpu/drm/display/drm_dp_tunnel.c
+++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
@@ -436,8 +436,8 @@ EXPORT_SYMBOL(drm_dp_tunnel_get);
 
 /**
  * drm_dp_tunnel_put - Put a reference for a DP tunnel
- * @tunnel - Tunnel object
- * @tracker - Debug tracker for the reference
+ * @tunnel: Tunnel object
+ * @tracker: Debug tracker for the reference
  *
  * Put a reference for @tunnel along with its debug *@tracker, which
  * was obtained with drm_dp_tunnel_get().
@@ -1170,7 +1170,7 @@ int drm_dp_tunnel_alloc_bw(struct drm_dp_tunnel *tunnel, 
int bw)
 EXPORT_SYMBOL(drm_dp_tunnel_alloc_bw);
 
 /**
- * drm_dp_tunnel_atomic_get_allocated_bw - Get the BW allocated for a DP tunnel
+ * drm_dp_tunnel_get_allocated_bw - Get the BW allocated for a DP tunnel
  * @tunnel: Tunnel object
  *
  * Get the current BW allocated for @tunnel. After the tunnel is created /
@@ -1892,6 +1892,7 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)
 /**
  * drm_dp_tunnel_mgr_create - Create a DP tunnel manager
  * @dev: DRM device object
+ * @max_group_count: Maximum number of tunnel groups
  *
  * Creates a DP tunnel manager for @dev.
  *
-- 
2.43.3



Re: ✗ Fi.CI.IGT: failure for drm/i915: Add Display Port tunnel BW allocation support (rev6)

2024-02-27 Thread Imre Deak
On Tue, Feb 27, 2024 at 02:21:29PM +, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915: Add Display Port tunnel BW allocation support (rev6)
> URL   : https://patchwork.freedesktop.org/series/129082/
> State : failure

Thanks for the reviews,acks, patchset is pushed to drm-intel-next. The
failure is unrelated see below.

> 
> == Summary ==
> 
> CI Bug Log - changes from CI_DRM_14345_full -> Patchwork_129082v6_full
> 
> 
> Summary
> ---
> 
>   **FAILURE**
> 
>   Serious unknown changes coming with Patchwork_129082v6_full absolutely need 
> to be
>   verified manually.
>   
>   If you think the reported changes have nothing to do with the changes
>   introduced in Patchwork_129082v6_full, please notify your bug team 
> (i915-ci-in...@lists.freedesktop.org) to allow them
>   to document this new failure mode, which will reduce false positives in CI.
> 
>   
> 
> Participating hosts (8 -> 8)
> --
> 
>   No changes in participating hosts
> 
> Possible new issues
> ---
> 
>   Here are the unknown changes that may have been introduced in 
> Patchwork_129082v6_full:
> 
> ### IGT changes ###
> 
>  Possible regressions 
> 
>   * igt@kms_fbcon_fbt@fbc-suspend:
> - shard-snb:  [PASS][1] -> [DMESG-WARN][2]
>[1]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-snb7/igt@kms_fbcon_...@fbc-suspend.html
>[2]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_129082v6/shard-snb7/igt@kms_fbcon_...@fbc-suspend.html

No TBT/DP tunnels on the above machine, an unrelated system/suspend
resume problem in the EPB driver:

<7>[  554.320951] Calling intel_epb_restore+0x0/0xb0
<4>[  554.320956] unchecked MSR access error: RDMSR from 0x1b0 at rIP: 
0x8104d4d3 (intel_epb_restore+0x13/0xb0)

The same was already reported at:
https://gitlab.freedesktop.org/drm/intel/-/issues/10007

>  Warnings 
> 
>   * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-move:
> - shard-snb:  [SKIP][3] ([fdo#109271]) -> [FAIL][4]
>[3]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-snb5/igt@kms_frontbuffer_track...@psr-2p-scndscrn-cur-indfb-move.html
>[4]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_129082v6/shard-snb4/igt@kms_frontbuffer_track...@psr-2p-scndscrn-cur-indfb-move.html
> 
>   
> Known issues
> 
> 
>   Here are the changes found in Patchwork_129082v6_full that come from known 
> issues:
> 
> ### CI changes ###
> 
>  Possible fixes 
> 
>   * boot:
> - shard-glk:  ([PASS][5], [PASS][6], [PASS][7], [PASS][8], 
> [PASS][9], [PASS][10], [PASS][11], [PASS][12], [PASS][13], [FAIL][14], 
> [PASS][15], [PASS][16], [PASS][17], [PASS][18], [PASS][19], [PASS][20], 
> [PASS][21], [PASS][22], [PASS][23], [PASS][24], [PASS][25], [PASS][26], 
> [PASS][27], [PASS][28], [FAIL][29]) ([i915#8293]) -> ([PASS][30], [PASS][31], 
> [PASS][32], [PASS][33], [PASS][34], [PASS][35], [PASS][36], [PASS][37], 
> [PASS][38], [PASS][39], [PASS][40], [PASS][41], [PASS][42], [PASS][43], 
> [PASS][44], [PASS][45], [PASS][46], [PASS][47], [PASS][48], [PASS][49], 
> [PASS][50], [PASS][51], [PASS][52], [PASS][53])
>[5]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk9/boot.html
>[6]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk9/boot.html
>[7]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk9/boot.html
>[8]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk8/boot.html
>[9]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk8/boot.html
>[10]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk8/boot.html
>[11]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk7/boot.html
>[12]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk7/boot.html
>[13]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk7/boot.html
>[14]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk5/boot.html
>[15]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk5/boot.html
>[16]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk5/boot.html
>[17]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk4/boot.html
>[18]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk4/boot.html
>[19]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk4/boot.html
>[20]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk3/boot.html
>[21]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk3/boot.html
>[22]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk3/boot.html
>[23]: 
> https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_14345/shard-glk3/boot.html
>[24]: 
> 

Re: [PATCH v2 12/21] drm/i915/dp: Add support for DP tunnel BW allocation

2024-02-26 Thread Imre Deak
On Fri, Feb 23, 2024 at 11:37:41PM +0200, Ville Syrjälä wrote:
> On Tue, Feb 20, 2024 at 11:18:32PM +0200, Imre Deak wrote:
> > +static void queue_retry_work(struct intel_atomic_state *state,
> > +struct drm_dp_tunnel *tunnel,
> > +const struct intel_crtc_state *crtc_state)
> > +{
> > +   struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +   struct intel_encoder *encoder;
> > +
> > +   encoder = intel_get_crtc_new_encoder(state, crtc_state);
> 
> I was pondering what happens if we have no encoder here?

That is when the crtc is disabled.

> But I guess crtc_state->tunnel_ref.tunnel should be NULL in
> that case and so we should not end up here.

Yes, in case crtc is disabled tunnel should be NULL, so
queue_retry_work() is not called.

> > +
> > +   if (!intel_digital_port_connected(encoder))
> > +   return;
> > +
> > +   drm_dbg_kms(>drm,
> > +   "[DPTUN %s][ENCODER:%d:%s] BW allocation failed on a 
> > connected sink\n",
> > +   drm_dp_tunnel_name(tunnel),
> > +   encoder->base.base.id,
> > +   encoder->base.name);
> > +
> > +   intel_dp_queue_modeset_retry_for_link(state, encoder, crtc_state);
> > +}
> > +
> 
> -- 
> Ville Syrjälä
> Intel


Re: [PATCH v2 02/21] drm/dp: Add support for DP tunneling

2024-02-26 Thread Imre Deak
On Fri, Feb 23, 2024 at 11:32:21PM +0200, Ville Syrjälä wrote:
> On Tue, Feb 20, 2024 at 11:18:22PM +0200, Imre Deak wrote:
> > +static inline void drm_dp_tunnel_ref_put(struct drm_dp_tunnel_ref 
> > *tunnel_ref)
> > +{
> > +   drm_dp_tunnel_put(tunnel_ref->tunnel, _ref->tracker);
> 
> Should we set tunnel_ref->tunnel=NULL here?

Yes, thanks for spotting this. It also fixes 
intel_crtc_prepare_cleared_state()->
intel_dp_tunnel_atomic_clear_stream_bw()

if crtc_state::dp_tunnel_ref state doesn't get recomputed, for instance
when disabling the crtc.

> 
> -- 
> Ville Syrjälä
> Intel


Re: [PATCH v2 11/21] drm/i915/dp: Add way to get active pipes with syncing commits

2024-02-23 Thread Imre Deak
On Fri, Feb 23, 2024 at 11:11:45PM +0200, Ville Syrjälä wrote:
> On Tue, Feb 20, 2024 at 11:18:31PM +0200, Imre Deak wrote:
> > Add a way to get the active pipes through a given DP port by syncing
> > against a related pending non-blocking commit. Atm
> > intel_dp_get_active_pipes() will only try to sync a given pipe and if
> > that would block ignore the pipe. A follow-up change enabling the DP
> > tunnel BW allocation mode will need to ensure that all active pipes are
> > returned.
> > 
> > This change will use intel_crtc_state::uapi.commit instead of the
> > corresponding commit in the connector state. This shouldn't make a
> > difference, since the two commit objects match for an active pipe.
> 
> There is a slight difference here in that a non-modeset/fastset commit
> will not have the connector inluded in the state and thus
> connector->state.commit will be updated.
> 
> I think the original idea of the code was to just skip anything that
> looks like it's already undergoing a full modeset. With this we might
> skip the retrain if there happens to be any kind of commit happening
> on the crtc. Althoguh it seems that the original code is already
> broken in the same way when there's a fastset happening in parallel.

Ok, didn't think of it. Are you ok to sync instead of try-sync the pipes
in case of link re-training?

> > A follow-up patchset will remove syncing during TC port reset, which
> > should reset a port/pipe even if syncing against a commit would block.
> > Syncing OTOH is not needed there, since the commit used for the reset
> > implies a sync already. For now add a TODO comment for this.
> > 
> > v2:
> > - Add a separate function to try-sync the pipes. (Ville)
> > 
> > Cc: Ville Syrjälä 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/i915/display/intel_crtc.c | 27 +++
> >  drivers/gpu/drm/i915/display/intel_crtc.h |  1 +
> >  drivers/gpu/drm/i915/display/intel_dp.c   |  6 ++---
> >  drivers/gpu/drm/i915/display/intel_tc.c   |  7 ++
> >  4 files changed, 37 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c 
> > b/drivers/gpu/drm/i915/display/intel_crtc.c
> > index 25593f6aae7de..17ed2e62cc66a 100644
> > --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> > @@ -654,3 +654,30 @@ void intel_pipe_update_end(struct intel_atomic_state 
> > *state,
> >  out:
> > intel_psr_unlock(new_crtc_state);
> >  }
> > +
> > +/**
> > + * intel_crtc_try_sync_pipes - Try syncing pending commits on a set of 
> > pipes
> > + * @i915: i915 device object
> > + * @pipe_mask: Mask of pipes to sync
> > + *
> > + * Try to sync a pending non-blocking commit for the provided pipes in
> > + * @pipe_mask. The commit won't be synced if this would block.
> > + *
> > + * Return a mask of the pipes that got synced or didn't need syncing.
> > + */
> > +u32 intel_crtc_try_sync_pipes(struct drm_i915_private *i915, u32 pipe_mask)
> > +{
> > +   struct intel_crtc *crtc;
> > +   u32 synced = 0;
> > +
> > +   for_each_intel_crtc_in_pipe_mask(>drm, crtc, pipe_mask) {
> > +   const struct intel_crtc_state *crtc_state =
> > +   to_intel_crtc_state(crtc->base.state);
> > +
> > +   if (!crtc_state->uapi.commit ||
> > +   try_wait_for_completion(_state->uapi.commit->hw_done))
> > +   synced |= BIT(crtc->pipe);
> > +   }
> > +
> > +   return synced;
> > +}
> > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h 
> > b/drivers/gpu/drm/i915/display/intel_crtc.h
> > index 22d7993d1f0ba..71a5b93166da7 100644
> > --- a/drivers/gpu/drm/i915/display/intel_crtc.h
> > +++ b/drivers/gpu/drm/i915/display/intel_crtc.h
> > @@ -47,5 +47,6 @@ struct intel_crtc *intel_crtc_for_pipe(struct 
> > drm_i915_private *i915,
> >  void intel_wait_for_vblank_if_active(struct drm_i915_private *i915,
> >  enum pipe pipe);
> >  void intel_crtc_wait_for_next_vblank(struct intel_crtc *crtc);
> > +u32 intel_crtc_try_sync_pipes(struct drm_i915_private *i915, u32 
> > pipe_mask);
> >  
> >  #endif
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index d9e75922ff8f5..d0452d3e534a7 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -5048,10 +5048,6 @@ int intel_dp_get_acti

Re: [PATCH v2 02/21] drm/dp: Add support for DP tunneling

2024-02-23 Thread Imre Deak
On Fri, Feb 23, 2024 at 08:25:38AM +0200, Shankar, Uma wrote:
> [...]
> > diff --git a/drivers/gpu/drm/display/Kconfig 
> > b/drivers/gpu/drm/display/Kconfig
> > index 09712b88a5b83..c0f56888c3280 100644
> > --- a/drivers/gpu/drm/display/Kconfig
> > +++ b/drivers/gpu/drm/display/Kconfig
> [...]
> > +struct drm_dp_tunnel {
> > + struct drm_dp_tunnel_group *group;
> > +
> > + struct list_head node;
> > +
> > + struct kref kref;
> > + struct ref_tracker *tracker;
> > + struct drm_dp_aux *aux;
> > + char name[8];
> > +
> > + int bw_granularity;
> > + int estimated_bw;
> > + int allocated_bw;
> > +
> > + int max_dprx_rate;
> > + u8 max_dprx_lane_count;
> > +
> > + u8 adapter_id;
> > +
> > + bool bw_alloc_supported:1;
> > + bool bw_alloc_enabled:1;
> > + bool has_io_error:1;
> > + bool destroyed:1;
> > +};
> > +
> > +struct drm_dp_tunnel_group_state;
> > +
> > +struct drm_dp_tunnel_state {
> > + struct drm_dp_tunnel_group_state *group_state;
> > +
> > + struct drm_dp_tunnel_ref tunnel_ref;
> > +
> > + struct list_head node;
> > +
> > + u32 stream_mask;
> > + int *stream_bw;
> > +};
> > +
> > +struct drm_dp_tunnel_group_state {
> > + struct drm_private_state base;
> > +
> > + struct list_head tunnel_states;
> > +};
> > +
> > +struct drm_dp_tunnel_group {
> > + struct drm_private_obj base;
> > + struct drm_dp_tunnel_mgr *mgr;
> > +
> > + struct list_head tunnels;
> > +
> > + /* available BW including the allocated_bw of all tunnels in the 
> > group */
> > + int available_bw;
> > + u8 drv_group_id;
> > +
> > + char name[8];
> > +
> 
> We can drop these line gaps.

Those are used in general to keep related fields together, but the above
three fields could be better grouped, can do that.

> > + bool active:1;
> > +};
> > +
> > +struct drm_dp_tunnel_mgr {
> > + struct drm_device *dev;
> > +
> > + int group_count;
> > + struct drm_dp_tunnel_group *groups;
> > + wait_queue_head_t bw_req_queue;
> > +
> > +#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
> > + struct ref_tracker_dir ref_tracker;
> > +#endif
> > +};
> > +
> > + [...]
> > +/* Return granularity in kB/s units */
> > +static int tunnel_reg_bw_granularity(const struct drm_dp_tunnel_regs *regs)
> > +{
> > + int gr = tunnel_reg(regs, DP_BW_GRANULARITY) &
> > DP_BW_GRANULARITY_MASK;
> > +
> > + WARN_ON(gr > 2);
> > +
> 
> I think it should fail as well along with WARN, > 2 is not supported.
> However, this situation is highly unlikely though.

Yes, validating this in tunnel_regs_are_valid() is missing, will add
that.

> > + return (25 << gr) / 8;
> [...]
> > +
> > +static int check_and_clear_status_change(struct drm_dp_tunnel *tunnel)
> > +{
> > + u8 mask = DP_BW_ALLOCATION_CAPABILITY_CHANGED | 
> > DP_ESTIMATED_BW_CHANGED;
> > + u8 val;
> > +
> > + if (drm_dp_dpcd_readb(tunnel->aux, DP_TUNNELING_STATUS, ) < 0)
> > + goto out_err;
> > +
> > + val &= mask;
> > +
> > + if (val) {
> > + if (drm_dp_dpcd_writeb(tunnel->aux, DP_TUNNELING_STATUS, val) 
> > < 0)
> > + goto out_err;
> > +
> > + return 1;
> 
> Seems this return value is not considered by the caller.

It indicates a status change and handled accordingly by the caller.
Probably it's better to document this, can add that.

> Hi Imre,
> Overall changes look good to me.
> It would be ideal if we can break this patch down, no major concern though.
> Leaving to your judgment.

The current way adds the DRM/i915 specific support separately, each
adding one .c file, the rest of the patchset taking these into use, each
patch doing this for a given scope of functionality. Didn't have a
better idea, maybe the DPCD registers could be added separately, but not
sure if that would make reviewing easier.

> With some above minor nits addressed, this is
> Reviewed-by: Uma Shankar 
> 
> Note: Have checked the register definitions/addresses, offsets. Have 
> Logically checked the code
> in general, as well. It would be good if tunnel manager and tunnel groups 
> related logic can be double
> confirmed by someone. Having said that, no issue I could spot there.

Thanks.

> Regards,
> Uma Shankar
> 
> > + }
> > +
> > + if (!drm_dp_tunnel_bw_alloc_is_enabled(tunnel))
> > + return 0;
> > +
> > + /*
> > +  * Check for estimated BW changes explicitly to account for lost
> > +  * BW change notifications.
> > +  */
> > + if (drm_dp_dpcd_readb(tunnel->aux, DP_ESTIMATED_BW, ) < 0)
> > + goto out_err;
> > +
> > + if (val * tunnel->bw_granularity != tunnel->estimated_bw)
> > + return 1;
> > +
> > + return 0;
> > +
> > +out_err:
> > + drm_dp_tunnel_set_io_error(tunnel);
> > +
> > + return -EIO;
> > +}
> > +
> > +/**
> > + * drm_dp_tunnel_update_state - Update DP tunnel SW state with the HW state
> > + * @tunnel: Tunnel object
> > 

[PATCH v2 20/21] drm/i915/dp: Read DPRX for all long HPD pulses

2024-02-20 Thread Imre Deak
The TBT DP tunnel BW request logic in the Thunderbolt Connection Manager
depends on the GFX driver reading out the sink's DPRX capabilities in
response to a long HPD pulse. Since in i915 this read-out can be blocked
by another connector's/encoder's hotplug event handling (which is
serialized by drm_mode_config::connection_mutex), do a dummy DPRX read-out
in the encoder's HPD pulse handler (which is not blocked by other
encoders).

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 35ef17439038a..f7f8bd5742ad4 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6162,6 +6162,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, 
bool long_hpd)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_dp *intel_dp = _port->dp;
+   u8 dpcd[DP_RECEIVER_CAP_SIZE];
 
if (dig_port->base.type == INTEL_OUTPUT_EDP &&
(long_hpd || !intel_pps_have_panel_power_or_vdd(intel_dp))) {
@@ -6184,6 +6185,17 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, 
bool long_hpd)
dig_port->base.base.name,
long_hpd ? "long" : "short");
 
+   /*
+* TBT DP tunnels require the GFX driver to read out the DPRX caps in
+* response to long HPD pulses. The DP hotplug handler does that,
+* however the hotplug handler may be blocked by another
+* connector's/encoder's hotplug handler. Since the TBT CM may not
+* complete the DP tunnel BW request for the latter connector/encoder
+* waiting for this encoder's DPRX read, perform a dummy read here.
+*/
+   if (long_hpd)
+   intel_dp_read_dprx_caps(intel_dp, dpcd);
+
if (long_hpd) {
intel_dp->reset_link_params = true;
return IRQ_NONE;
-- 
2.39.2



[PATCH v2 19/21] drm/i915/dp: Suspend/resume DP tunnels

2024-02-20 Thread Imre Deak
Suspend and resume DP tunnels during system suspend/resume, disabling
the BW allocation mode during suspend, re-enabling it after resume. This
reflects the link's BW management component (Thunderbolt CM) disabling
BWA during suspend. Before any BW requests the driver must read the
sink's DPRX capabilities (since the BW manager requires this
information, so snoops for it on AUX), so ensure this read takes place.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index a3dfcbb710027..35ef17439038a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -36,6 +36,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3313,18 +3314,21 @@ void intel_dp_sync_state(struct intel_encoder *encoder,
 const struct intel_crtc_state *crtc_state)
 {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-   if (!crtc_state)
-   return;
+   bool dpcd_updated = false;
 
/*
 * Don't clobber DPCD if it's been already read out during output
 * setup (eDP) or detect.
 */
-   if (intel_dp->dpcd[DP_DPCD_REV] == 0)
+   if (crtc_state && intel_dp->dpcd[DP_DPCD_REV] == 0) {
intel_dp_get_dpcd(intel_dp);
+   dpcd_updated = true;
+   }
 
-   intel_dp_reset_max_link_params(intel_dp);
+   intel_dp_tunnel_resume(intel_dp, crtc_state, dpcd_updated);
+
+   if (crtc_state)
+   intel_dp_reset_max_link_params(intel_dp);
 }
 
 bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
@@ -5947,6 +5951,8 @@ void intel_dp_encoder_suspend(struct intel_encoder 
*intel_encoder)
struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
 
intel_pps_vdd_off_sync(intel_dp);
+
+   intel_dp_tunnel_suspend(intel_dp);
 }
 
 void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
-- 
2.39.2



[PATCH v2 21/21] drm/i915/dp: Enable DP tunnel BW allocation mode

2024-02-20 Thread Imre Deak
Detect DP tunnels and enable the BW allocation mode on them. Send a
hotplug notification to userspace in response to a BW change.

Signed-off-by: Imre Deak 
---
 .../drm/i915/display/intel_display_driver.c   | 20 +++
 drivers/gpu/drm/i915/display/intel_dp.c   | 14 +++--
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c 
b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 4f7ba7eb03d27..87dd07e0d138d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -35,6 +35,7 @@
 #include "intel_dkl_phy.h"
 #include "intel_dmc.h"
 #include "intel_dp.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpll.h"
 #include "intel_dpll_mgr.h"
 #include "intel_fb.h"
@@ -434,10 +435,8 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
 
for_each_pipe(i915, pipe) {
ret = intel_crtc_init(i915, pipe);
-   if (ret) {
-   intel_mode_config_cleanup(i915);
-   return ret;
-   }
+   if (ret)
+   goto err_mode_config;
}
 
intel_plane_possible_crtcs_init(i915);
@@ -457,6 +456,10 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
intel_vga_disable(i915);
intel_setup_outputs(i915);
 
+   ret = intel_dp_tunnel_mgr_init(i915);
+   if (ret)
+   goto err_hdcp;
+
intel_display_driver_disable_user_access(i915);
 
drm_modeset_lock_all(dev);
@@ -475,6 +478,13 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
ilk_wm_sanitize(i915);
 
return 0;
+
+err_hdcp:
+   intel_hdcp_component_fini(i915);
+err_mode_config:
+   intel_mode_config_cleanup(i915);
+
+   return ret;
 }
 
 /* part #3: call after gem init */
@@ -599,6 +609,8 @@ void intel_display_driver_remove_noirq(struct 
drm_i915_private *i915)
 
intel_mode_config_cleanup(i915);
 
+   intel_dp_tunnel_mgr_cleanup(i915);
+
intel_overlay_cleanup(i915);
 
intel_gmbus_teardown(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f7f8bd5742ad4..789b5fa074fd0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5726,6 +5726,7 @@ intel_dp_detect(struct drm_connector *connector,
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = _port->base;
enum drm_connector_status status;
+   int ret;
 
drm_dbg_kms(_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
@@ -5761,9 +5762,18 @@ intel_dp_detect(struct drm_connector *connector,
intel_dp->is_mst);
}
 
+   intel_dp_tunnel_disconnect(intel_dp);
+
goto out;
}
 
+   ret = intel_dp_tunnel_detect(intel_dp, ctx);
+   if (ret == -EDEADLK)
+   return ret;
+
+   if (ret == 1)
+   intel_connector->base.epoch_counter++;
+
intel_dp_detect_dsc_caps(intel_dp, intel_connector);
 
intel_dp_configure_mst(intel_dp);
@@ -5794,8 +5804,6 @@ intel_dp_detect(struct drm_connector *connector,
 * with an IRQ_HPD, so force a link status check.
 */
if (!intel_dp_is_edp(intel_dp)) {
-   int ret;
-
ret = intel_dp_retrain_link(encoder, ctx);
if (ret)
return ret;
@@ -5935,6 +5943,8 @@ void intel_dp_encoder_flush_work(struct drm_encoder 
*encoder)
 
intel_dp_mst_encoder_cleanup(dig_port);
 
+   intel_dp_tunnel_destroy(intel_dp);
+
intel_pps_vdd_off_sync(intel_dp);
 
/*
-- 
2.39.2



[PATCH v2 18/21] drm/i915/dp: Call intel_dp_sync_state() always for DDI DP encoders

2024-02-20 Thread Imre Deak
A follow-up change will need to resume DP tunnels during system resume,
so call intel_dp_sync_state() always for DDI encoders, so this function
can resume the tunnels for all DP connectors.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index ed7301808604d..c587a8efeafcf 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4151,7 +4151,7 @@ static void intel_ddi_sync_state(struct intel_encoder 
*encoder,
intel_tc_port_sanitize_mode(enc_to_dig_port(encoder),
crtc_state);
 
-   if (crtc_state && intel_crtc_has_dp_encoder(crtc_state))
+   if (intel_encoder_is_dp(encoder))
intel_dp_sync_state(encoder, crtc_state);
 }
 
-- 
2.39.2



[PATCH v2 15/21] drm/i915/dp: Compute DP tunnel BW during encoder state computation

2024-02-20 Thread Imre Deak
Compute the BW required through a DP tunnel on links with such tunnels
detected and add the corresponding atomic state during a modeset.

v2:
- Fix error check of intel_dp_tunnel_compute_stream_bw(). (Ville)
- Move intel_dp_tunnel_atomic_cleanup_inherited_state() to this patch.
  (Ville)
- Move intel_dp_tunnel_atomic_clear_stream_bw() to this patch.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar  (v1)
---
 drivers/gpu/drm/i915/display/intel_atomic.c  |  2 ++
 drivers/gpu/drm/i915/display/intel_display.c |  2 ++
 drivers/gpu/drm/i915/display/intel_dp.c  | 16 
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 13 -
 4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 798cb90361a83..2bb270f82932e 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -352,6 +352,8 @@ void intel_atomic_state_clear(struct drm_atomic_state *s)
/* state->internal not reset on purpose */
 
state->dpll_set = state->modeset = false;
+
+   intel_dp_tunnel_atomic_cleanup_inherited_state(state);
 }
 
 struct intel_crtc_state *
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 16973ebb7865d..20647c97e86fa 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4541,6 +4541,8 @@ intel_crtc_prepare_cleared_state(struct 
intel_atomic_state *state,
/* free the old crtc_state->hw members */
intel_crtc_free_hw_state(crtc_state);
 
+   intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state);
+
/* FIXME: before the switch to atomic started, a new pipe_config was
 * kzalloc'd. Code that depends on any field being zero should be
 * fixed, so that the crtc_state can be safely duplicated. For now,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f4f748d95ad17..5ad7808788745 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2875,6 +2875,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_atomic_state *state = 
to_intel_atomic_state(conn_state->state);
struct drm_display_mode *adjusted_mode = _config->hw.adjusted_mode;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
const struct drm_display_mode *fixed_mode;
@@ -2975,7 +2976,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, 
conn_state);
 
-   return 0;
+   return intel_dp_tunnel_atomic_compute_stream_bw(state, intel_dp, 
connector,
+   pipe_config);
 }
 
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
@@ -6063,6 +6065,15 @@ static int intel_dp_connector_atomic_check(struct 
drm_connector *conn,
return ret;
}
 
+   if (!intel_connector_needs_modeset(state, conn))
+   return 0;
+
+   ret = intel_dp_tunnel_atomic_check_state(state,
+intel_dp,
+intel_conn);
+   if (ret)
+   return ret;
+
/*
 * We don't enable port sync on BDW due to missing w/as and
 * due to not having adjusted the modeset sequence appropriately.
@@ -6070,9 +6081,6 @@ static int intel_dp_connector_atomic_check(struct 
drm_connector *conn,
if (DISPLAY_VER(dev_priv) < 9)
return 0;
 
-   if (!intel_connector_needs_modeset(state, conn))
-   return 0;
-
if (conn->has_tile) {
ret = intel_modeset_tile_group(state, conn->tile_group->id);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 4b6c8ff974297..db1254b036f18 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -42,6 +42,7 @@
 #include "intel_dp.h"
 #include "intel_dp_hdcp.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_hdcp.h"
 #include "intel_hotplug.h"
@@ -523,6 +524,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder 
*encoder,
   struct drm_connector_state *conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_atomic_state *state = 
to_

[PATCH v2 17/21] drm/i915/dp: Handle DP tunnel IRQs

2024-02-20 Thread Imre Deak
Handle DP tunnel IRQs a sink (or rather a BW management component like
the Thunderbolt Connection Manager) raises to signal the completion of a
BW request by the driver, or to signal any state change related to the
link BW.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 37 +++--
 include/drm/display/drm_dp.h|  1 +
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 5ad7808788745..a3dfcbb710027 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4904,13 +4904,15 @@ static bool intel_dp_mst_link_status(struct intel_dp 
*intel_dp)
  * - %true if pending interrupts were serviced (or no interrupts were
  *   pending) w/o detecting an error condition.
  * - %false if an error condition - like AUX failure or a loss of link - is
- *   detected, which needs servicing from the hotplug work.
+ *   detected, or another condition - like a DP tunnel BW state change - needs
+ *   servicing from the hotplug work.
  */
 static bool
 intel_dp_check_mst_status(struct intel_dp *intel_dp)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
bool link_ok = true;
+   bool reprobe_needed = false;
 
drm_WARN_ON_ONCE(>drm, intel_dp->active_mst_links < 0);
 
@@ -4937,6 +4939,13 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 
intel_dp_mst_hpd_irq(intel_dp, esi, ack);
 
+   if (esi[3] & DP_TUNNELING_IRQ) {
+   if 
(drm_dp_tunnel_handle_irq(i915->display.dp_tunnel_mgr,
+_dp->aux))
+   reprobe_needed = true;
+   ack[3] |= DP_TUNNELING_IRQ;
+   }
+
if (!memchr_inv(ack, 0, sizeof(ack)))
break;
 
@@ -4947,7 +4956,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
drm_dp_mst_hpd_irq_send_new_request(_dp->mst_mgr);
}
 
-   return link_ok;
+   return link_ok && !reprobe_needed;
 }
 
 static void
@@ -5304,23 +5313,32 @@ static void intel_dp_check_device_service_irq(struct 
intel_dp *intel_dp)
drm_dbg_kms(>drm, "Sink specific irq unhandled\n");
 }
 
-static void intel_dp_check_link_service_irq(struct intel_dp *intel_dp)
+static bool intel_dp_check_link_service_irq(struct intel_dp *intel_dp)
 {
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   bool reprobe_needed = false;
u8 val;
 
if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
-   return;
+   return false;
 
if (drm_dp_dpcd_readb(_dp->aux,
  DP_LINK_SERVICE_IRQ_VECTOR_ESI0, ) != 1 || 
!val)
-   return;
+   return false;
+
+   if ((val & DP_TUNNELING_IRQ) &&
+   drm_dp_tunnel_handle_irq(i915->display.dp_tunnel_mgr,
+_dp->aux))
+   reprobe_needed = true;
 
if (drm_dp_dpcd_writeb(_dp->aux,
   DP_LINK_SERVICE_IRQ_VECTOR_ESI0, val) != 1)
-   return;
+   return reprobe_needed;
 
if (val & HDMI_LINK_STATUS_CHANGED)
intel_dp_handle_hdmi_link_status_change(intel_dp);
+
+   return reprobe_needed;
 }
 
 /*
@@ -5341,6 +5359,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 old_sink_count = intel_dp->sink_count;
+   bool reprobe_needed = false;
bool ret;
 
/*
@@ -5363,7 +5382,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
}
 
intel_dp_check_device_service_irq(intel_dp);
-   intel_dp_check_link_service_irq(intel_dp);
+   reprobe_needed = intel_dp_check_link_service_irq(intel_dp);
 
/* Handle CEC interrupts, if any */
drm_dp_cec_irq(_dp->aux);
@@ -5390,10 +5409,10 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 * FIXME get rid of the ad-hoc phy test modeset code
 * and properly incorporate it into the normal modeset.
 */
-   return false;
+   reprobe_needed = true;
}
 
-   return true;
+   return !reprobe_needed;
 }
 
 /* XXX this is probably wrong for multiple downstream ports */
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 8bfd5d007be8d..4891bd916d26a 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -1081,6 +1081,7 @@
 # define STREAM_STATUS_CHANGED   (1 << 2)
 # define HDMI_LINK_STATUS_CHANGED(1 << 3)
 # define CONNECTED_OFF_ENTRY_REQUESTED   (1 << 4)
+# define DP_TUNNELING_IRQ(1 <&l

[PATCH v2 16/21] drm/i915/dp: Allocate/free DP tunnel BW in the encoder enable/disable hooks

2024-02-20 Thread Imre Deak
Allocate and free the DP tunnel BW required by a stream while
enabling/disabling the stream during a modeset.

v2:
- Move the allocation up from encoder hooks to
  intel_atomic_commit_tail().

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar  (v1)
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 1 +
 drivers/gpu/drm/i915/display/intel_display.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index bea4415902044..ed7301808604d 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -54,6 +54,7 @@
 #include "intel_dp_aux.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_dsi.h"
 #include "intel_fdi.h"
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 20647c97e86fa..445efe0087cde 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7123,6 +7123,8 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 
intel_commit_modeset_disables(state);
 
+   intel_dp_tunnel_atomic_alloc_bw(state);
+
/* FIXME: Eventually get rid of our crtc->config pointer */
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
crtc->config = new_crtc_state;
-- 
2.39.2



[PATCH v2 14/21] drm/i915/dp: Account for tunnel BW limit in intel_dp_max_link_data_rate()

2024-02-20 Thread Imre Deak
Take any link BW limitation into account in
intel_dp_max_link_data_rate(). Such a limitation can be due to multiple
displays on (Thunderbolt) links with DP tunnels sharing the link BW.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 32 +
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index d0452d3e534a7..f4f748d95ad17 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -63,6 +63,7 @@
 #include "intel_dp_hdcp.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_dpll.h"
 #include "intel_fifo_underrun.h"
@@ -152,6 +153,22 @@ int intel_dp_link_symbol_clock(int rate)
return DIV_ROUND_CLOSEST(rate * 10, intel_dp_link_symbol_size(rate));
 }
 
+static int max_dprx_rate(struct intel_dp *intel_dp)
+{
+   if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
+   return drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel);
+
+   return drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+}
+
+static int max_dprx_lane_count(struct intel_dp *intel_dp)
+{
+   if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
+   return drm_dp_tunnel_max_dprx_lane_count(intel_dp->tunnel);
+
+   return drm_dp_max_lane_count(intel_dp->dpcd);
+}
+
 static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
 {
intel_dp->sink_rates[0] = 162000;
@@ -180,7 +197,7 @@ static void intel_dp_set_dpcd_sink_rates(struct intel_dp 
*intel_dp)
/*
 * Sink rates for 8b/10b.
 */
-   max_rate = 
drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+   max_rate = max_dprx_rate(intel_dp);
max_lttpr_rate = 
drm_dp_lttpr_max_link_rate(intel_dp->lttpr_common_caps);
if (max_lttpr_rate)
max_rate = min(max_rate, max_lttpr_rate);
@@ -259,7 +276,7 @@ static void intel_dp_set_max_sink_lane_count(struct 
intel_dp *intel_dp)
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = _dig_port->base;
 
-   intel_dp->max_sink_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+   intel_dp->max_sink_lane_count = max_dprx_lane_count(intel_dp);
 
switch (intel_dp->max_sink_lane_count) {
case 1:
@@ -389,14 +406,21 @@ int intel_dp_effective_data_rate(int pixel_clock, int 
bpp_x16,
  * @max_dprx_rate: Maximum data rate of the DPRX
  * @max_dprx_lanes: Maximum lane count of the DPRX
  *
- * Calculate the maximum data rate for the provided link parameters.
+ * Calculate the maximum data rate for the provided link parameters taking into
+ * account any BW limitations by a DP tunnel attached to @intel_dp.
  *
  * Returns the maximum data rate in kBps units.
  */
 int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
int max_dprx_rate, int max_dprx_lanes)
 {
-   return drm_dp_max_dprx_data_rate(max_dprx_rate, max_dprx_lanes);
+   int max_rate = drm_dp_max_dprx_data_rate(max_dprx_rate, max_dprx_lanes);
+
+   if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
+   max_rate = min(max_rate,
+  drm_dp_tunnel_available_bw(intel_dp->tunnel));
+
+   return max_rate;
 }
 
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
-- 
2.39.2



[PATCH v2 12/21] drm/i915/dp: Add support for DP tunnel BW allocation

2024-02-20 Thread Imre Deak
Add support to enable the DP tunnel BW allocation mode. Follow-up
patches will call the required helpers added here to prepare for a
modeset on a link with DP tunnels, the last change in the patchset
actually enabling BWA.

With BWA enabled, the driver will expose the full mode list a display
supports, regardless of any BW limitation on a shared (Thunderbolt)
link. Such BW limits will be checked against only during a modeset, when
the driver has the full knowledge of each display's BW requirement.

If the link BW changes in a way that a connector's modelist may also
change, userspace will get a hotplug notification for all the connectors
sharing the same link (so it can adjust the mode used for a display).

The BW limitation can change at any point, asynchronously to modesets
on a given connector, so a modeset can fail even though the atomic check
for it passed. In such scenarios userspace will get a bad link
notification and in response is supposed to retry the modeset.

v2:
- Fix old vs. new connector state in intel_dp_tunnel_atomic_check_state().
  (Ville)
- Fix propagating the error from
  intel_dp_tunnel_atomic_compute_stream_bw(). (Ville)
- Move tunnel==NULL checks from driver to DRM core helpers. (Ville)
- Simplify return flow from intel_dp_tunnel_detect(). (Ville)
- s/dp_tunnel_state/inherited_dp_tunnels (Ville)
- Simplify struct intel_dp_tunnel_inherited_state. (Ville)
- Unconstify object pointers (vs. states) where possible. (Ville)
- Init crtc_state while declaring it in check_group_state(). (Ville)
- Join obj->base.id, obj->name arg lines in debug prints to reduce LOC.
  (Ville)
- Add/rework intel_dp_tunnel_atomic_alloc_bw() to prepare for moving the
  BW allocation from encoder hooks up to intel_atomic_commit_tail()
  later in the patchset.
- Disable BW alloc mode during system suspend.
- Allocate the required BW for all tunnels during system resume.
- Add intel_dp_tunnel_atomic_clear_stream_bw() instead of the open-coded
  sequence in a follow-up patch.
- Add function documentation to all exported functions.
- Add CONFIG_USB4 dependency to CONFIG_DRM_I915_DP_TUNNEL.

Cc: Ville Syrjälä 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/Kconfig  |  14 +
 drivers/gpu/drm/i915/Kconfig.debug|   1 +
 drivers/gpu/drm/i915/Makefile |   3 +
 drivers/gpu/drm/i915/display/intel_atomic.c   |   2 +
 drivers/gpu/drm/i915/display/intel_crtc.c |  25 +
 drivers/gpu/drm/i915/display/intel_crtc.h |   1 +
 .../gpu/drm/i915/display/intel_display_core.h |   1 +
 .../drm/i915/display/intel_display_types.h|   9 +
 .../gpu/drm/i915/display/intel_dp_tunnel.c| 815 ++
 .../gpu/drm/i915/display/intel_dp_tunnel.h| 133 +++
 10 files changed, 1004 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.h

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 3089029abba48..5932024f8f954 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -155,6 +155,20 @@ config DRM_I915_PXP
  protected session and manage the status of the alive software session,
  as well as its life cycle.
 
+config DRM_I915_DP_TUNNEL
+   bool "Enable DP tunnel support"
+   depends on DRM_I915
+   depends on USB4
+   select DRM_DISPLAY_DP_TUNNEL
+   default y
+   help
+ Choose this option to detect DP tunnels and enable the Bandwidth
+ Allocation mode for such tunnels. This allows using the maximum
+ resolution allowed by the link BW on all displays sharing the
+ link BW, for instance on a Thunderbolt link.
+
+ If in doubt, say "Y".
+
 menu "drm/i915 Debugging"
 depends on DRM_I915
 depends on EXPERT
diff --git a/drivers/gpu/drm/i915/Kconfig.debug 
b/drivers/gpu/drm/i915/Kconfig.debug
index 5b7162076850c..bc18e2d9ea05d 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -28,6 +28,7 @@ config DRM_I915_DEBUG
select STACKDEPOT
select STACKTRACE
select DRM_DP_AUX_CHARDEV
+   select DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE if DRM_I915_DP_TUNNEL
select X86_MSR # used by igt/pm_rpm
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
select DRM_DEBUG_MM if DRM=y
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index c13f14edb5088..3ef6ed41e62b4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -369,6 +369,9 @@ i915-y += \
display/vlv_dsi.o \
display/vlv_dsi_pll.o
 
+i915-$(CONFIG_DRM_I915_DP_TUNNEL) += \
+   display/intel_dp_tunnel.o
+
 i915-y += \
i915_perf.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index ec0d5168b5035..96ab37e158995 100644
--- a/drivers/gpu/drm/i915/display/intel

[PATCH v2 10/21] drm/i915/dp: Add intel_dp_max_link_data_rate()

2024-02-20 Thread Imre Deak
Add intel_dp_max_link_data_rate() to get the link BW vs. the sink DPRX
BW used by a follow-up patch enabling the DP tunnel BW allocation mode.
The link BW can be below the DPRX BW due to a BW limitation on a link
shared by multiple sinks.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 32 +
 drivers/gpu/drm/i915/display/intel_dp.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c |  3 +-
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 520c04245c2df..d9e75922ff8f5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -383,6 +383,22 @@ int intel_dp_effective_data_rate(int pixel_clock, int 
bpp_x16,
100 * 16 * 8);
 }
 
+/**
+ * intel_dp_max_link_data_rate: Calculate the maximum rate for the given link 
params
+ * @intel_dp: Intel DP object
+ * @max_dprx_rate: Maximum data rate of the DPRX
+ * @max_dprx_lanes: Maximum lane count of the DPRX
+ *
+ * Calculate the maximum data rate for the provided link parameters.
+ *
+ * Returns the maximum data rate in kBps units.
+ */
+int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
+   int max_dprx_rate, int max_dprx_lanes)
+{
+   return drm_dp_max_dprx_data_rate(max_dprx_rate, max_dprx_lanes);
+}
+
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
 {
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -612,7 +628,7 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct 
intel_dp *intel_dp,
int mode_rate, max_rate;
 
mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
-   max_rate = drm_dp_max_dprx_data_rate(link_rate, lane_count);
+   max_rate = intel_dp_max_link_data_rate(intel_dp, link_rate, lane_count);
if (mode_rate > max_rate)
return false;
 
@@ -1216,7 +1232,8 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
 
-   max_rate = drm_dp_max_dprx_data_rate(max_link_clock, max_lanes);
+   max_rate = intel_dp_max_link_data_rate(intel_dp, max_link_clock, 
max_lanes);
+
mode_rate = intel_dp_link_required(target_clock,
   
intel_dp_mode_min_output_bpp(connector, mode));
 
@@ -1566,8 +1583,10 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
for (lane_count = limits->min_lane_count;
 lane_count <= limits->max_lane_count;
 lane_count <<= 1) {
-   link_avail = 
drm_dp_max_dprx_data_rate(link_rate,
-  
lane_count);
+   link_avail = 
intel_dp_max_link_data_rate(intel_dp,
+
link_rate,
+
lane_count);
+
 
if (mode_rate <= link_avail) {
pipe_config->lane_count = lane_count;
@@ -2427,8 +2446,9 @@ intel_dp_compute_link_config(struct intel_encoder 
*encoder,
pipe_config->pipe_bpp,
BPP_X16_ARGS(pipe_config->dsc.compressed_bpp_x16),
intel_dp_config_required_rate(pipe_config),
-   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
- pipe_config->lane_count));
+   intel_dp_max_link_data_rate(intel_dp,
+   pipe_config->port_clock,
+   pipe_config->lane_count));
 
return 0;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 10e859b62bbe9..564a587e2d018 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -115,6 +115,8 @@ bool intel_dp_get_colorimetry_status(struct intel_dp 
*intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
 int bw_overhead);
+int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
+   int max_dprx_rate, int max_dprx_lanes);
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp);
 bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index b4d4bb90126e9..4b6c8ff974

[PATCH v2 11/21] drm/i915/dp: Add way to get active pipes with syncing commits

2024-02-20 Thread Imre Deak
Add a way to get the active pipes through a given DP port by syncing
against a related pending non-blocking commit. Atm
intel_dp_get_active_pipes() will only try to sync a given pipe and if
that would block ignore the pipe. A follow-up change enabling the DP
tunnel BW allocation mode will need to ensure that all active pipes are
returned.

This change will use intel_crtc_state::uapi.commit instead of the
corresponding commit in the connector state. This shouldn't make a
difference, since the two commit objects match for an active pipe.

A follow-up patchset will remove syncing during TC port reset, which
should reset a port/pipe even if syncing against a commit would block.
Syncing OTOH is not needed there, since the commit used for the reset
implies a sync already. For now add a TODO comment for this.

v2:
- Add a separate function to try-sync the pipes. (Ville)

Cc: Ville Syrjälä 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_crtc.c | 27 +++
 drivers/gpu/drm/i915/display/intel_crtc.h |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c   |  6 ++---
 drivers/gpu/drm/i915/display/intel_tc.c   |  7 ++
 4 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c 
b/drivers/gpu/drm/i915/display/intel_crtc.c
index 25593f6aae7de..17ed2e62cc66a 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -654,3 +654,30 @@ void intel_pipe_update_end(struct intel_atomic_state 
*state,
 out:
intel_psr_unlock(new_crtc_state);
 }
+
+/**
+ * intel_crtc_try_sync_pipes - Try syncing pending commits on a set of pipes
+ * @i915: i915 device object
+ * @pipe_mask: Mask of pipes to sync
+ *
+ * Try to sync a pending non-blocking commit for the provided pipes in
+ * @pipe_mask. The commit won't be synced if this would block.
+ *
+ * Return a mask of the pipes that got synced or didn't need syncing.
+ */
+u32 intel_crtc_try_sync_pipes(struct drm_i915_private *i915, u32 pipe_mask)
+{
+   struct intel_crtc *crtc;
+   u32 synced = 0;
+
+   for_each_intel_crtc_in_pipe_mask(>drm, crtc, pipe_mask) {
+   const struct intel_crtc_state *crtc_state =
+   to_intel_crtc_state(crtc->base.state);
+
+   if (!crtc_state->uapi.commit ||
+   try_wait_for_completion(_state->uapi.commit->hw_done))
+   synced |= BIT(crtc->pipe);
+   }
+
+   return synced;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h 
b/drivers/gpu/drm/i915/display/intel_crtc.h
index 22d7993d1f0ba..71a5b93166da7 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -47,5 +47,6 @@ struct intel_crtc *intel_crtc_for_pipe(struct 
drm_i915_private *i915,
 void intel_wait_for_vblank_if_active(struct drm_i915_private *i915,
 enum pipe pipe);
 void intel_crtc_wait_for_next_vblank(struct intel_crtc *crtc);
+u32 intel_crtc_try_sync_pipes(struct drm_i915_private *i915, u32 pipe_mask);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index d9e75922ff8f5..d0452d3e534a7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5048,10 +5048,6 @@ int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
if (!crtc_state->hw.active)
continue;
 
-   if (conn_state->commit &&
-   !try_wait_for_completion(_state->commit->hw_done))
-   continue;
-
*pipe_mask |= BIT(crtc->pipe);
}
drm_connector_list_iter_end(_iter);
@@ -5091,6 +5087,8 @@ int intel_dp_retrain_link(struct intel_encoder *encoder,
if (ret)
return ret;
 
+   pipe_mask &= intel_crtc_try_sync_pipes(dev_priv, pipe_mask);
+
if (pipe_mask == 0)
return 0;
 
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 6b374d481cd9e..14d17903a81f5 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -7,6 +7,7 @@
 #include "i915_reg.h"
 #include "intel_atomic.h"
 #include "intel_cx0_phy_regs.h"
+#include "intel_crtc.h"
 #include "intel_ddi.h"
 #include "intel_de.h"
 #include "intel_display.h"
@@ -1663,6 +1664,12 @@ static int reset_link_commit(struct intel_tc_port *tc,
if (ret)
return ret;
 
+   /*
+* TODO: remove the following, since an output must be reset
+* even if we had to wait for a non-blocking commit on a pipe.
+*/
+   pipe_mask &= intel_crtc_try_sync_pipes(i915, pipe_mask);
+
if (!pipe_mask)
return 0;
 
-- 
2.39.2



[PATCH v2 13/21] drm/i915/dp: Add DP tunnel atomic state and check BW limit

2024-02-20 Thread Imre Deak
Add the atomic state during a modeset required to enable the DP tunnel
BW allocation mode on links where such a tunnel was detected. This state
applies to an already enabled output, the state added for a newly
enabled output will be computed and added/cleared to/from the atomic
state in a follow-up patch.

v2:
- s/old_crtc_state/crtc_state in intel_crtc_duplicate_state().
- Move intel_dp_tunnel_atomic_cleanup_inherited_state() to a follow-up
  patch adding the corresponding state. (Ville)
- Move intel_dp_tunnel_atomic_clear_stream_bw() to a follow-up
  patch adding the corresponding state.

Cc: Ville Syrjälä 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_atomic.c  |  6 ++
 drivers/gpu/drm/i915/display/intel_display.c | 12 
 drivers/gpu/drm/i915/display/intel_link_bw.c |  5 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 96ab37e158995..798cb90361a83 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -260,6 +260,10 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
if (crtc_state->post_csc_lut)
drm_property_blob_get(crtc_state->post_csc_lut);
 
+   if (crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_get(crtc_state->dp_tunnel_ref.tunnel,
+ _state->dp_tunnel_ref);
+
crtc_state->update_pipe = false;
crtc_state->update_m_n = false;
crtc_state->update_lrr = false;
@@ -311,6 +315,8 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
 
__drm_atomic_helper_crtc_destroy_state(_state->uapi);
intel_crtc_free_hw_state(crtc_state);
+   if (crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_put(_state->dp_tunnel_ref);
kfree(crtc_state);
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index e1a4200f67a7e..16973ebb7865d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -33,6 +33,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -73,6 +74,7 @@
 #include "intel_dp.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpll.h"
 #include "intel_dpll_mgr.h"
 #include "intel_dpt.h"
@@ -4490,6 +4492,8 @@ copy_bigjoiner_crtc_state_modeset(struct 
intel_atomic_state *state,
saved_state->crc_enabled = slave_crtc_state->crc_enabled;
 
intel_crtc_free_hw_state(slave_crtc_state);
+   if (slave_crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_put(_crtc_state->dp_tunnel_ref);
memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state));
kfree(saved_state);
 
@@ -4505,6 +4509,10 @@ copy_bigjoiner_crtc_state_modeset(struct 
intel_atomic_state *state,
  _crtc_state->hw.adjusted_mode);
slave_crtc_state->hw.scaling_filter = 
master_crtc_state->hw.scaling_filter;
 
+   if (master_crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_get(master_crtc_state->dp_tunnel_ref.tunnel,
+   _crtc_state->dp_tunnel_ref);
+
copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc);
 
slave_crtc_state->uapi.mode_changed = 
master_crtc_state->uapi.mode_changed;
@@ -5365,6 +5373,10 @@ static int intel_modeset_pipe(struct intel_atomic_state 
*state,
if (ret)
return ret;
 
+   ret = intel_dp_tunnel_atomic_add_state_for_crtc(state, crtc);
+   if (ret)
+   return ret;
+
ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c 
b/drivers/gpu/drm/i915/display/intel_link_bw.c
index 27ea858897c9f..dfd7d5e23f3fa 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -9,6 +9,7 @@
 #include "intel_crtc.h"
 #include "intel_display_types.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_fdi.h"
 #include "intel_link_bw.h"
 
@@ -163,6 +164,10 @@ static int check_all_link_config(struct intel_atomic_state 
*state,
if (ret)
return ret;
 
+   ret = intel_dp_tunnel_atomic_check_link(state, limits);
+   if (ret)
+   return ret;
+
ret = intel_fdi_atomic_check_link(state, limits);
if (ret)
return ret;
-- 
2.39.2



[PATCH v2 08/21] drm/i915/dp: Factor out intel_dp_update_sink_caps()

2024-02-20 Thread Imre Deak
Factor out a function updating the sink's link rate and lane count
capabilities, used by a follow-up patch enabling the DP tunnel BW
allocation mode.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 11 ---
 drivers/gpu/drm/i915/display/intel_dp.h |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 20e04cbdffcae..520c04245c2df 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3944,6 +3944,13 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp)
  _dp->desc);
 }
 
+void intel_dp_update_sink_caps(struct intel_dp *intel_dp)
+{
+   intel_dp_set_sink_rates(intel_dp);
+   intel_dp_set_max_sink_lane_count(intel_dp);
+   intel_dp_set_common_rates(intel_dp);
+}
+
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
@@ -3960,9 +3967,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
drm_dp_read_desc(_dp->aux, _dp->desc,
 drm_dp_is_branch(intel_dp->dpcd));
 
-   intel_dp_set_sink_rates(intel_dp);
-   intel_dp_set_max_sink_lane_count(intel_dp);
-   intel_dp_set_common_rates(intel_dp);
+   intel_dp_update_sink_caps(intel_dp);
}
 
if (intel_dp_has_sink_count(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index ee0600b4425e1..10e859b62bbe9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -104,6 +104,7 @@ int intel_dp_config_required_rate(const struct 
intel_crtc_state *crtc_state);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 int intel_dp_max_common_rate(struct intel_dp *intel_dp);
 int intel_dp_max_common_lane_count(struct intel_dp *intel_dp);
+void intel_dp_update_sink_caps(struct intel_dp *intel_dp);
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
   u8 *link_bw, u8 *rate_select);
-- 
2.39.2



[PATCH v2 09/21] drm/i915/dp: Factor out intel_dp_read_dprx_caps()

2024-02-20 Thread Imre Deak
Factor out a function to read the sink's DPRX capabilities used by a
follow-up patch enabling the DP tunnel BW allocation mode.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 .../drm/i915/display/intel_dp_link_training.c | 30 +++
 .../drm/i915/display/intel_dp_link_training.h |  1 +
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 7b140cbf8dd31..fb84ca98bb7ab 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -162,6 +162,28 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, 
const u8 dpcd[DP_RECEI
return lttpr_count;
 }
 
+int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 
dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+   if (intel_dp_is_edp(intel_dp))
+   return 0;
+
+   /*
+* Detecting LTTPRs must be avoided on platforms with an AUX timeout
+* period < 3.2ms. (see DP Standard v2.0, 2.11.2, 3.6.6.1).
+*/
+   if (DISPLAY_VER(i915) >= 10 && !IS_GEMINILAKE(i915))
+   if (drm_dp_dpcd_probe(_dp->aux,
+ 
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV))
+   return -EIO;
+
+   if (drm_dp_read_dpcd_caps(_dp->aux, dpcd))
+   return -EIO;
+
+   return 0;
+}
+
 /**
  * intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the 
LTTPR link training mode
  * @intel_dp: Intel DP struct
@@ -192,12 +214,10 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp 
*intel_dp)
if (!intel_dp_is_edp(intel_dp) &&
(DISPLAY_VER(i915) >= 10 && !IS_GEMINILAKE(i915))) {
u8 dpcd[DP_RECEIVER_CAP_SIZE];
+   int err = intel_dp_read_dprx_caps(intel_dp, dpcd);
 
-   if (drm_dp_dpcd_probe(_dp->aux, 
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV))
-   return -EIO;
-
-   if (drm_dp_read_dpcd_caps(_dp->aux, dpcd))
-   return -EIO;
+   if (err != 0)
+   return err;
 
lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
index 2c8f2775891b0..19836a8a4f904 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
@@ -11,6 +11,7 @@
 struct intel_crtc_state;
 struct intel_dp;
 
+int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 
dpcd[DP_RECEIVER_CAP_SIZE]);
 int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp);
 
 void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
-- 
2.39.2



[PATCH v2 07/21] drm/i915/dp: Export intel_dp_max_common_rate/lane_count()

2024-02-20 Thread Imre Deak
Export intel_dp_max_common_rate() and intel_dp_max_lane_count() used by
a follow-up patch enabling the DP tunnel BW allocation mode.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 ++--
 drivers/gpu/drm/i915/display/intel_dp.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index c7e3e4efc324e..20e04cbdffcae 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -309,7 +309,7 @@ static int intel_dp_common_rate(struct intel_dp *intel_dp, 
int index)
 }
 
 /* Theoretical max between source and sink */
-static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
+int intel_dp_max_common_rate(struct intel_dp *intel_dp)
 {
return intel_dp_common_rate(intel_dp, intel_dp->num_common_rates - 1);
 }
@@ -326,7 +326,7 @@ static int intel_dp_max_source_lane_count(struct 
intel_digital_port *dig_port)
 }
 
 /* Theoretical max between source and sink */
-static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
+int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
 {
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
int source_max = intel_dp_max_source_lane_count(dig_port);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 4667870fed31a..ee0600b4425e1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -102,6 +102,8 @@ int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 int intel_dp_max_lane_count(struct intel_dp *intel_dp);
 int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
+int intel_dp_max_common_rate(struct intel_dp *intel_dp);
+int intel_dp_max_common_lane_count(struct intel_dp *intel_dp);
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
   u8 *link_bw, u8 *rate_select);
-- 
2.39.2



[PATCH v2 04/21] drm/i915/dp: Add support to notify MST connectors to retry modesets

2024-02-20 Thread Imre Deak
On shared (Thunderbolt) links with DP tunnels, the modeset may need to
be retried on all connectors on the link due to a link BW limitation
arising only after the atomic check phase. To support this add a helper
function queuing a work to retry the modeset on a given port's connector
and at the same time any MST connector with streams through the same
port. A follow-up change enabling the DP tunnel Bandwidth Allocation
Mode will take this into use.

v2:
- Send the uevent only to enabled MST connectors. (Jouni)

Cc: Jouni Högander 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_display.c  |  5 ++-
 drivers/gpu/drm/i915/display/intel_dp.c   | 45 ++-
 drivers/gpu/drm/i915/display/intel_dp.h   |  6 +++
 .../drm/i915/display/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  2 +
 5 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 485c38d71f106..2ee26d19c200b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8085,8 +8085,9 @@ void intel_hpd_poll_fini(struct drm_i915_private *i915)
/* Kill all the work that may have been queued by hpd. */
drm_connector_list_iter_begin(>drm, _iter);
for_each_intel_connector_iter(connector, _iter) {
-   if (connector->modeset_retry_work.func)
-   cancel_work_sync(>modeset_retry_work);
+   if (connector->modeset_retry_work.func &&
+   cancel_work_sync(>modeset_retry_work))
+   drm_connector_put(>base);
if (connector->hdcp.shim) {
cancel_delayed_work_sync(>hdcp.check_work);
cancel_work_sync(>hdcp.prop_work);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 217196196e50a..88606e336a920 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2842,6 +2842,40 @@ intel_dp_audio_compute_config(struct intel_encoder 
*encoder,
intel_dp_is_uhbr(pipe_config);
 }
 
+void intel_dp_queue_modeset_retry_work(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+
+   drm_connector_get(>base);
+   if (!queue_work(i915->unordered_wq, >modeset_retry_work))
+   drm_connector_put(>base);
+}
+
+void
+intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+   struct intel_connector *connector;
+   struct intel_digital_connector_state *conn_state;
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+   int i;
+
+   if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
+   intel_dp_queue_modeset_retry_work(intel_dp->attached_connector);
+
+   return;
+   }
+
+   for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
+   if (!conn_state->base.crtc)
+   continue;
+
+   if (connector->mst_port == intel_dp)
+   intel_dp_queue_modeset_retry_work(connector);
+   }
+}
+
 int
 intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
@@ -6441,6 +6475,14 @@ static void intel_dp_modeset_retry_work_fn(struct 
work_struct *work)
mutex_unlock(>dev->mode_config.mutex);
/* Send Hotplug uevent so userspace can reprobe */
drm_kms_helper_connector_hotplug_event(connector);
+
+   drm_connector_put(connector);
+}
+
+void intel_dp_init_modeset_retry_work(struct intel_connector *connector)
+{
+   INIT_WORK(>modeset_retry_work,
+ intel_dp_modeset_retry_work_fn);
 }
 
 bool
@@ -6457,8 +6499,7 @@ intel_dp_init_connector(struct intel_digital_port 
*dig_port,
int type;
 
/* Initialize the work for modeset in case of link train failure */
-   INIT_WORK(_connector->modeset_retry_work,
- intel_dp_modeset_retry_work_fn);
+   intel_dp_init_modeset_retry_work(intel_connector);
 
if (drm_WARN(dev, dig_port->max_lanes < 1,
 "Not enough lanes (%d) for DP on [ENCODER:%d:%s]\n",
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 530cc97bc42f4..e2875e03afba0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -43,6 +43,12 @@ void intel_dp_adjust_compliance_config(struct intel_dp 
*intel_dp,
 bool intel_dp_limited_color_range(const struct intel_crt

[PATCH v2 06/21] drm/i915/dp: Factor out intel_dp_config_required_rate()

2024-02-20 Thread Imre Deak
Factor out intel_dp_config_required_rate() used by a follow-up patch
enabling the DP tunnel BW allocation mode.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 43 +++--
 drivers/gpu/drm/i915/display/intel_dp.h |  1 +
 2 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 0a2ee43392142..c7e3e4efc324e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2343,6 +2343,17 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
   limits);
 }
 
+int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
+{
+   const struct drm_display_mode *adjusted_mode =
+   _state->hw.adjusted_mode;
+   int bpp = crtc_state->dsc.compression_enable ?
+   to_bpp_int_roundup(crtc_state->dsc.compressed_bpp_x16) :
+   crtc_state->pipe_bpp;
+
+   return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
+}
+
 static int
 intel_dp_compute_link_config(struct intel_encoder *encoder,
 struct intel_crtc_state *pipe_config,
@@ -2410,31 +2421,15 @@ intel_dp_compute_link_config(struct intel_encoder 
*encoder,
return ret;
}
 
-   if (pipe_config->dsc.compression_enable) {
-   drm_dbg_kms(>drm,
-   "DP lane count %d clock %d Input bpp %d Compressed 
bpp " BPP_X16_FMT "\n",
-   pipe_config->lane_count, pipe_config->port_clock,
-   pipe_config->pipe_bpp,
-   BPP_X16_ARGS(pipe_config->dsc.compressed_bpp_x16));
+   drm_dbg_kms(>drm,
+   "DP lane count %d clock %d bpp input %d compressed " 
BPP_X16_FMT " link rate required %d available %d\n",
+   pipe_config->lane_count, pipe_config->port_clock,
+   pipe_config->pipe_bpp,
+   BPP_X16_ARGS(pipe_config->dsc.compressed_bpp_x16),
+   intel_dp_config_required_rate(pipe_config),
+   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
+ pipe_config->lane_count));
 
-   drm_dbg_kms(>drm,
-   "DP link rate required %i available %i\n",
-   intel_dp_link_required(adjusted_mode->crtc_clock,
-  
to_bpp_int_roundup(pipe_config->dsc.compressed_bpp_x16)),
-   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
- pipe_config->lane_count));
-   } else {
-   drm_dbg_kms(>drm, "DP lane count %d clock %d bpp %d\n",
-   pipe_config->lane_count, pipe_config->port_clock,
-   pipe_config->pipe_bpp);
-
-   drm_dbg_kms(>drm,
-   "DP link rate required %i available %i\n",
-   intel_dp_link_required(adjusted_mode->crtc_clock,
-  pipe_config->pipe_bpp),
-   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
- pipe_config->lane_count));
-   }
return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 20252984b3b04..4667870fed31a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -100,6 +100,7 @@ void intel_dp_mst_suspend(struct drm_i915_private 
*dev_priv);
 void intel_dp_mst_resume(struct drm_i915_private *dev_priv);
 int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 int intel_dp_max_lane_count(struct intel_dp *intel_dp);
+int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
-- 
2.39.2



[PATCH v2 05/21] drm/i915/dp: Use drm_dp_max_dprx_data_rate()

2024-02-20 Thread Imre Deak
Instead of intel_dp_max_data_rate() use the equivalent
drm_dp_max_dprx_data_rate() which was copied from the former one in a
previous patch.

Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/i915/display/intel_display.c |  2 +-
 drivers/gpu/drm/i915/display/intel_dp.c  | 62 +++-
 drivers/gpu/drm/i915/display/intel_dp.h  |  1 -
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  2 +-
 4 files changed, 10 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 2ee26d19c200b..e1a4200f67a7e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2478,7 +2478,7 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
u32 link_symbol_clock = intel_dp_link_symbol_clock(link_clock);
u32 data_m = intel_dp_effective_data_rate(pixel_clock, 
bits_per_pixel_x16,
  bw_overhead);
-   u32 data_n = intel_dp_max_data_rate(link_clock, nlanes);
+   u32 data_n = drm_dp_max_dprx_data_rate(link_clock, nlanes);
 
/*
 * Windows/BIOS uses fixed M/N values always. Follow suit.
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 88606e336a920..0a2ee43392142 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -383,52 +383,6 @@ int intel_dp_effective_data_rate(int pixel_clock, int 
bpp_x16,
100 * 16 * 8);
 }
 
-/*
- * Given a link rate and lanes, get the data bandwidth.
- *
- * Data bandwidth is the actual payload rate, which depends on the data
- * bandwidth efficiency and the link rate.
- *
- * For 8b/10b channel encoding, SST and non-FEC, the data bandwidth efficiency
- * is 80%. For example, for a 1.62 Gbps link, 1.62*10^9 bps * 0.80 * (1/8) =
- * 162000 kBps. With 8-bit symbols, we have 162000 kHz symbol clock. Just by
- * coincidence, the port clock in kHz matches the data bandwidth in kBps, and
- * they equal the link bit rate in Gbps multiplied by 10. (Note that this 
no
- * longer holds for data bandwidth as soon as FEC or MST is taken into 
account!)
- *
- * For 128b/132b channel encoding, the data bandwidth efficiency is 96.71%. For
- * example, for a 10 Gbps link, 10*10^9 bps * 0.9671 * (1/8) = 1208875
- * kBps. With 32-bit symbols, we have 312500 kHz symbol clock. The value 
100
- * does not match the symbol clock, the port clock (not even if you think in
- * terms of a byte clock), nor the data bandwidth. It only matches the link bit
- * rate in units of 1 bps.
- */
-int
-intel_dp_max_data_rate(int max_link_rate, int max_lanes)
-{
-   int ch_coding_efficiency =
-   
drm_dp_bw_channel_coding_efficiency(drm_dp_is_uhbr_rate(max_link_rate));
-   int max_link_rate_kbps = max_link_rate * 10;
-
-   /*
-* UHBR rates always use 128b/132b channel encoding, and have
-* 97.71% data bandwidth efficiency. Consider max_link_rate the
-* link bit rate in units of 1 bps.
-*/
-   /*
-* Lower than UHBR rates always use 8b/10b channel encoding, and have
-* 80% data bandwidth efficiency for SST non-FEC. However, this turns
-* out to be a nop by coincidence:
-*
-*  int max_link_rate_kbps = max_link_rate * 10;
-*  max_link_rate_kbps = DIV_ROUND_DOWN_ULL(max_link_rate_kbps * 8, 
10);
-*  max_link_rate = max_link_rate_kbps / 8;
-*/
-   return DIV_ROUND_DOWN_ULL(mul_u32_u32(max_link_rate_kbps * max_lanes,
- ch_coding_efficiency),
- 100 * 8);
-}
-
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
 {
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -658,7 +612,7 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct 
intel_dp *intel_dp,
int mode_rate, max_rate;
 
mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
-   max_rate = intel_dp_max_data_rate(link_rate, lane_count);
+   max_rate = drm_dp_max_dprx_data_rate(link_rate, lane_count);
if (mode_rate > max_rate)
return false;
 
@@ -1262,7 +1216,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
 
-   max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+   max_rate = drm_dp_max_dprx_data_rate(max_link_clock, max_lanes);
mode_rate = intel_dp_link_required(target_clock,
   
intel_dp_mode_min_output_bpp(connector, mode));
 
@@ -1612,8 +1566,8 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
for (lane_count = limits->min_l

[PATCH v2 03/21] drm/i915: Fix display bpp limit computation during system resume

2024-02-20 Thread Imre Deak
The system resume display mode restoration should happen with an output
configuration matching that of the suspend time saved mode. Since the
restored mode configuration is subject to the bpp fallback logic,
starting out with an unlimited bpp and reducing the bpp as required by
any (MST) link BW limit, the resulting bpp will match the one during
suspend only if the BW limit checks during suspend and resume are
applied in an identical way. The latter is not guaranteed at the moment,
since the pre-suspend MST topology may not be in place during resume
(for instance if the MST sink was disconnected while being suspended),
which makes the MST link BW check accept the unlimited bpp mode
configuration unconditionally without ensuring that the required BW fits
into the available MST link BW.

To fix the above, initialize the bpp fallback logic with the max link
bpp / force-FEC limits left behind by the suspend time mode save.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_display.c |  3 +--
 drivers/gpu/drm/i915/display/intel_link_bw.c | 22 
 drivers/gpu/drm/i915/display/intel_link_bw.h |  2 +-
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 00ac65a140298..485c38d71f106 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6252,12 +6252,11 @@ static int intel_atomic_check_config(struct 
intel_atomic_state *state,
 
 static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
 {
-   struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_link_bw_limits new_limits;
struct intel_link_bw_limits old_limits;
int ret;
 
-   intel_link_bw_init_limits(i915, _limits);
+   intel_link_bw_init_limits(state, _limits);
old_limits = new_limits;
 
while (true) {
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c 
b/drivers/gpu/drm/i915/display/intel_link_bw.c
index 9c6d35a405a18..27ea858897c9f 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -6,6 +6,7 @@
 #include "i915_drv.h"
 
 #include "intel_atomic.h"
+#include "intel_crtc.h"
 #include "intel_display_types.h"
 #include "intel_dp_mst.h"
 #include "intel_fdi.h"
@@ -13,19 +14,32 @@
 
 /**
  * intel_link_bw_init_limits - initialize BW limits
- * @i915: device instance
+ * @state: Atomic state
  * @limits: link BW limits
  *
  * Initialize @limits.
  */
-void intel_link_bw_init_limits(struct drm_i915_private *i915, struct 
intel_link_bw_limits *limits)
+void intel_link_bw_init_limits(struct intel_atomic_state *state,
+  struct intel_link_bw_limits *limits)
 {
+   struct drm_i915_private *i915 = to_i915(state->base.dev);
enum pipe pipe;
 
limits->force_fec_pipes = 0;
limits->bpp_limit_reached_pipes = 0;
-   for_each_pipe(i915, pipe)
-   limits->max_bpp_x16[pipe] = INT_MAX;
+   for_each_pipe(i915, pipe) {
+   const struct intel_crtc_state *crtc_state =
+   intel_atomic_get_new_crtc_state(state,
+   
intel_crtc_for_pipe(i915, pipe));
+
+   if (state->base.duplicated && crtc_state) {
+   limits->max_bpp_x16[pipe] = 
crtc_state->max_link_bpp_x16;
+   if (crtc_state->fec_enable)
+   limits->force_fec_pipes |= BIT(pipe);
+   } else {
+   limits->max_bpp_x16[pipe] = INT_MAX;
+   }
+   }
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h 
b/drivers/gpu/drm/i915/display/intel_link_bw.h
index 2cf57307cc249..6b0ccfff59dab 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -22,7 +22,7 @@ struct intel_link_bw_limits {
int max_bpp_x16[I915_MAX_PIPES];
 };
 
-void intel_link_bw_init_limits(struct drm_i915_private *i915,
+void intel_link_bw_init_limits(struct intel_atomic_state *state,
   struct intel_link_bw_limits *limits);
 int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
 struct intel_link_bw_limits *limits,
-- 
2.39.2



[PATCH v2 02/21] drm/dp: Add support for DP tunneling

2024-02-20 Thread Imre Deak
Add support for Display Port tunneling. For now this includes the
support for Bandwidth Allocation Mode (BWA), leaving adding Panel Replay
support for later.

BWA allows using displays that share the same (Thunderbolt) link with
their maximum resolution. Atm, this may not be possible due to the
coarse granularity of partitioning the link BW among the displays on the
link: the BW allocation policy is in a SW/FW/HW component on the link
(on Thunderbolt it's the SW or FW Connection Manager), independent of
the driver. This policy will set the DPRX maximum rate and lane count
DPCD registers the GFX driver will see (0x0, 0x1, 0x02200,
0x02201) based on the available link BW.

The granularity of the current BW allocation policy is coarse, based on
the required link rate in the 1.62Gbs..8.1Gbps range and it may prevent
using higher resolutions all together: the display connected first will
get a share of the link BW which corresponds to its full DPRX capability
(regardless of the actual mode it uses). A subsequent display connected
will only get the remaining BW, which could be well below its full
capability.

BWA solves the above coarse granularity (reducing it to a 250Mbs..1Gps
range) and first-come/first-served issues by letting the driver request
the BW for each display on a link which reflects the actual modes the
displays use.

This patch adds the DRM core helper functions, while a follow-up change
in the patchset takes them into use in the i915 driver.

v2:
- Fix prepare_to_wait vs. wake-up cond check order in
  allocate_tunnel_bw(). (Ville)
- Move tunnel==NULL checks from callers in drivers to here. (Ville)
- Avoid var inits in declaration blocks that can fail or have
  side-effects. (Ville)
- Use u8 for driver and group IDs. (Ville)
- Simplify API removing drm_dp_tunnel_get/put_untracked(). (Ville)
- Reuse str_yes_no() instead of a local yes_no_chr(). (Ville)
- s/drm_dp_tunnel_atomic_clear_state()/free_tunnel_state() and unexport
  the function. (Ville)
- s/clear_tunnel_group_state()/free_group_state() and move kfree() to
  this function. (Ville)
- Add separate group_free_bw() helper and describe what the tunnel
  estimated BW includes. (Ville)
- Improve help text for CONFIG_DRM_DISPLAY_DP_TUNNEL. (Ville)
- Add code comment explaining the purpose of DPCD reg read helpers.
  (Ville)
- Add code comment describing the tunnel group name prefix format.
  (Ville)
- Report the allocated BW as undetermined until the first allocation
  request.
- Skip allocation requests matching the previous request.
- Clear any stale BW request status flags before a new request.
- Add missing error return check of drm_dp_tunnel_atomic_get_group_state()
  in drm_dp_tunnel_atomic_set_stream_bw().
- Add drm_dp_tunnel_get_allocated_bw().
- s/drm_dp_tunnel_atomic_get_tunnel_bw/drm_dp_tunnel_atomic_get_required_bw
- Fix return value description in function doc of drm_dp_tunnel_detect().
- Add function documentation to all exported functions.

Cc: Ville Syrjälä 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/Kconfig |   21 +
 drivers/gpu/drm/display/Makefile|2 +
 drivers/gpu/drm/display/drm_dp_tunnel.c | 1929 +++
 include/drm/display/drm_dp.h|   60 +
 include/drm/display/drm_dp_tunnel.h |  248 +++
 5 files changed, 2260 insertions(+)
 create mode 100644 drivers/gpu/drm/display/drm_dp_tunnel.c
 create mode 100644 include/drm/display/drm_dp_tunnel.h

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 09712b88a5b83..c0f56888c3280 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -17,6 +17,27 @@ config DRM_DISPLAY_DP_HELPER
help
  DRM display helpers for DisplayPort.
 
+config DRM_DISPLAY_DP_TUNNEL
+   bool
+   select DRM_DISPLAY_DP_HELPER
+   help
+ Enable support for DisplayPort tunnels. This allows drivers to use
+ DP tunnel features like the Bandwidth Allocation mode to maximize the
+ BW utilization for display streams on Thunderbolt links.
+
+config DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+   bool "Enable debugging the DP tunnel state"
+   depends on REF_TRACKER
+   depends on DRM_DISPLAY_DP_TUNNEL
+   depends on DEBUG_KERNEL
+   depends on EXPERT
+   help
+ Enables debugging the DP tunnel manager's state, including the
+ consistency of all managed tunnels' reference counting and the state 
of
+ streams contained in tunnels.
+
+ If in doubt, say "N".
+
 config DRM_DISPLAY_HDCP_HELPER
bool
depends on DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 17ac4a1006a80..7ca61333c6696 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -8,6 +8,8 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \
drm_dp_helper.o \
drm_dp_mst_topology.o \

[PATCH v2 00/21] drm/i915: Add Display Port tunnel BW allocation support

2024-02-20 Thread Imre Deak
This is v2 of [1], with the following changes:

- Several functional/typo/formatting fixes, detailed in the patches.
- Move the BW allocation from encoder hooks to
  intel_atomic_commit_tail() fixing the allocation for MST streams
  enabled/disabled w/o a full modeset (i.e. w/o re-enabling the master
  stream).
- Fix an MST mode restore issue during system resume, which also lead
  to a tunnel BW allocation failure. (Patch 3)
- Ensure a DPCD DPRX cap read as required by the TBT CM any time a long
  HPD pulse is detected. (Patch 20)
- Explicitly disable the BW allocation mode during system suspend.

The patchset is also available at:
https://github.com/ideak/linux/commits/dp_tun_bw_alloc

Cc: Mika Westerberg 
Cc: Ville Syrjälä 
Cc: Uma Shankar 
Cc: Jouni Högander 
Cc: Saranya Gopal 
Cc: Rajaram Regupathy 
Cc: Gil Fine 
Cc: Naama Shachar 
Cc: Pengfei Xu 

[1] https://lore.kernel.org/all/20240123102850.390126-1-imre.d...@intel.com

Imre Deak (21):
  drm/dp: Add drm_dp_max_dprx_data_rate()
  drm/dp: Add support for DP tunneling
  drm/i915: Fix display bpp limit computation during system resume
  drm/i915/dp: Add support to notify MST connectors to retry modesets
  drm/i915/dp: Use drm_dp_max_dprx_data_rate()
  drm/i915/dp: Factor out intel_dp_config_required_rate()
  drm/i915/dp: Export intel_dp_max_common_rate/lane_count()
  drm/i915/dp: Factor out intel_dp_update_sink_caps()
  drm/i915/dp: Factor out intel_dp_read_dprx_caps()
  drm/i915/dp: Add intel_dp_max_link_data_rate()
  drm/i915/dp: Add way to get active pipes with syncing commits
  drm/i915/dp: Add support for DP tunnel BW allocation
  drm/i915/dp: Add DP tunnel atomic state and check BW limit
  drm/i915/dp: Account for tunnel BW limit in
intel_dp_max_link_data_rate()
  drm/i915/dp: Compute DP tunnel BW during encoder state computation
  drm/i915/dp: Allocate/free DP tunnel BW in the encoder enable/disable
hooks
  drm/i915/dp: Handle DP tunnel IRQs
  drm/i915/dp: Call intel_dp_sync_state() always for DDI DP encoders
  drm/i915/dp: Suspend/resume DP tunnels
  drm/i915/dp: Read DPRX for all long HPD pulses
  drm/i915/dp: Enable DP tunnel BW allocation mode

 drivers/gpu/drm/display/Kconfig   |   21 +
 drivers/gpu/drm/display/Makefile  |2 +
 drivers/gpu/drm/display/drm_dp_helper.c   |   30 +
 drivers/gpu/drm/display/drm_dp_tunnel.c   | 1929 +
 drivers/gpu/drm/i915/Kconfig  |   14 +
 drivers/gpu/drm/i915/Kconfig.debug|1 +
 drivers/gpu/drm/i915/Makefile |3 +
 drivers/gpu/drm/i915/display/intel_atomic.c   |   10 +
 drivers/gpu/drm/i915/display/intel_crtc.c |   52 +
 drivers/gpu/drm/i915/display/intel_crtc.h |2 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |3 +-
 drivers/gpu/drm/i915/display/intel_display.c  |   26 +-
 .../gpu/drm/i915/display/intel_display_core.h |1 +
 .../drm/i915/display/intel_display_driver.c   |   20 +-
 .../drm/i915/display/intel_display_types.h|9 +
 drivers/gpu/drm/i915/display/intel_dp.c   |  292 ++-
 drivers/gpu/drm/i915/display/intel_dp.h   |   13 +-
 .../drm/i915/display/intel_dp_link_training.c |   33 +-
 .../drm/i915/display/intel_dp_link_training.h |1 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   18 +-
 .../gpu/drm/i915/display/intel_dp_tunnel.c|  815 +++
 .../gpu/drm/i915/display/intel_dp_tunnel.h|  133 ++
 drivers/gpu/drm/i915/display/intel_link_bw.c  |   27 +-
 drivers/gpu/drm/i915/display/intel_link_bw.h  |2 +-
 drivers/gpu/drm/i915/display/intel_tc.c   |7 +
 include/drm/display/drm_dp.h  |   61 +
 include/drm/display/drm_dp_helper.h   |2 +
 include/drm/display/drm_dp_tunnel.h   |  248 +++
 28 files changed, 3650 insertions(+), 125 deletions(-)
 create mode 100644 drivers/gpu/drm/display/drm_dp_tunnel.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.h
 create mode 100644 include/drm/display/drm_dp_tunnel.h

-- 
2.39.2



[PATCH v2 01/21] drm/dp: Add drm_dp_max_dprx_data_rate()

2024-02-20 Thread Imre Deak
Copy intel_dp_max_data_rate() to DRM core. It will be needed by a
follow-up DP tunnel patch, checking the maximum rate the DPRX (sink)
supports. Accordingly use the drm_dp_max_dprx_data_rate() name for
clarity. This patchset will also switch calling the new DRM function
in i915 instead of intel_dp_max_data_rate().

While at it simplify the function documentation/comments, removing
parts described already by drm_dp_bw_channel_coding_efficiency().

v2: (Ville)
- Remove max_link_rate_kbps.
- Simplify the function documentation.

Cc: Ville Syrjälä 
Signed-off-by: Imre Deak 
Reviewed-by: Uma Shankar 
---
 drivers/gpu/drm/display/drm_dp_helper.c | 30 +
 include/drm/display/drm_dp_helper.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index 8d6ce46471ae6..d046dfa79504f 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -4055,3 +4055,33 @@ int drm_dp_bw_channel_coding_efficiency(bool is_uhbr)
return 80;
 }
 EXPORT_SYMBOL(drm_dp_bw_channel_coding_efficiency);
+
+/**
+ * drm_dp_max_dprx_data_rate - Get the max data bandwidth of a DPRX sink
+ * @max_link_rate: max DPRX link rate in 10kbps units
+ * @max_lanes: max DPRX lane count
+ *
+ * Given a link rate and lanes, get the data bandwidth.
+ *
+ * Data bandwidth is the actual payload rate, which depends on the data
+ * bandwidth efficiency and the link rate.
+ *
+ * Note that protocol layers above the DPRX link level considered here can
+ * further limit the maximum data rate. Such layers are the MST topology (with
+ * limits on the link between the source and first branch device as well as on
+ * the whole MST path until the DPRX link) and (Thunderbolt) DP tunnels -
+ * which in turn can encapsulate an MST link with its own limit - with each
+ * SST or MST encapsulated tunnel sharing the BW of a tunnel group.
+ *
+ * Returns the maximum data rate in kBps units.
+ */
+int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes)
+{
+   int ch_coding_efficiency =
+   
drm_dp_bw_channel_coding_efficiency(drm_dp_is_uhbr_rate(max_link_rate));
+
+   return DIV_ROUND_DOWN_ULL(mul_u32_u32(max_link_rate * 10 * max_lanes,
+ ch_coding_efficiency),
+ 100 * 8);
+}
+EXPORT_SYMBOL(drm_dp_max_dprx_data_rate);
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index d02014a87f127..65dae9a9f2fb6 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -812,4 +812,6 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
   int bpp_x16, unsigned long flags);
 int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
 
+int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes);
+
 #endif /* _DRM_DP_HELPER_H_ */
-- 
2.39.2



Re: [PATCH 02/19] drm/dp: Add support for DP tunneling

2024-02-07 Thread Imre Deak
On Wed, Feb 07, 2024 at 10:48:43PM +0200, Imre Deak wrote:
> On Wed, Feb 07, 2024 at 10:02:18PM +0200, Ville Syrjälä wrote:
> > On Tue, Jan 23, 2024 at 12:28:33PM +0200, Imre Deak wrote:
> > > + [...]
> > > +static int group_allocated_bw(struct drm_dp_tunnel_group *group)
> > > +{
> > > + struct drm_dp_tunnel *tunnel;
> > > + int group_allocated_bw = 0;
> > > +
> > > + for_each_tunnel_in_group(group, tunnel) {
> > > + if (check_tunnel(tunnel) == 0 &&
> > > + tunnel->bw_alloc_enabled)
> > > + group_allocated_bw += tunnel->allocated_bw;
> > > + }
> > > +
> > > + return group_allocated_bw;
> > > +}
> > > +
> > > +static int calc_group_available_bw(const struct drm_dp_tunnel *tunnel)
> > > +{
> > > + return group_allocated_bw(tunnel->group) -
> > > +tunnel->allocated_bw +
> > > +tunnel->estimated_bw;
> > 
> > Hmm. So the estimated_bw=actually_free_bw + tunnel->allocated_bw?
> 
> Yes.
> 
> > Ie. how much bw might be available for this tunnel right now?
> 
> Correct.
> 
> > And here we're trying to deduce the total bandwidth available by
> > adding in the allocated_bw of all the other tunnels in the group?
> 
> Yes.
> 
> > Rather weird that we can't just get that number directly...
> 
> It is. Imo this could be simply communicated via a DPCD register
> dedicated for this. Perhaps adding this should be requested from TBT
> architects.

One reason for this design can be that a host/driver may not see all the
tunnels in the group. In that case the tunnel's current usable BW will
be only its estimated_bw (that is it can't use the BW already allocated
by other tunnels in the group, until those are released by the other
host/driver).

> I assume this could also use a code comment.
> 
> > > +}
> > > +
> > > +static int update_group_available_bw(struct drm_dp_tunnel *tunnel,
> > > +  const struct drm_dp_tunnel_regs *regs)
> > > +{
> > > + struct drm_dp_tunnel *tunnel_iter;
> > > + int group_available_bw;
> > > + bool changed;
> > > +
> > > + tunnel->estimated_bw = tunnel_reg(regs, DP_ESTIMATED_BW) * 
> > > tunnel->bw_granularity;
> > > +
> > > + if (calc_group_available_bw(tunnel) == tunnel->group->available_bw)
> > > + return 0;
> > > +
> > > + for_each_tunnel_in_group(tunnel->group, tunnel_iter) {
> > > + int err;
> > > +
> > > + if (tunnel_iter == tunnel)
> > > + continue;
> > > +
> > > + if (check_tunnel(tunnel_iter) != 0 ||
> > > + !tunnel_iter->bw_alloc_enabled)
> > > + continue;
> > > +
> > > + err = drm_dp_dpcd_probe(tunnel_iter->aux, DP_DPCD_REV);
> > > + if (err) {
> > > + tun_dbg(tunnel_iter,
> > > + "Probe failed, assume disconnected (err %pe)\n",
> > > + ERR_PTR(err));
> > > + drm_dp_tunnel_set_io_error(tunnel_iter);
> > > + }
> > > + }
> > > +
> > > + group_available_bw = calc_group_available_bw(tunnel);
> > > +
> > > + tun_dbg(tunnel, "Updated group available BW: %d->%d\n",
> > > + DPTUN_BW_ARG(tunnel->group->available_bw),
> > > + DPTUN_BW_ARG(group_available_bw));
> > > +
> > > + changed = tunnel->group->available_bw != group_available_bw;
> > > +
> > > + tunnel->group->available_bw = group_available_bw;
> > > +
> > > + return changed ? 1 : 0;
> > > +}
> > > +
> > > +static int set_bw_alloc_mode(struct drm_dp_tunnel *tunnel, bool enable)
> > > +{
> > > + u8 mask = DP_DISPLAY_DRIVER_BW_ALLOCATION_MODE_ENABLE | 
> > > DP_UNMASK_BW_ALLOCATION_IRQ;
> > > + u8 val;
> > > +
> > > + if (drm_dp_dpcd_readb(tunnel->aux, DP_DPTX_BW_ALLOCATION_MODE_CONTROL, 
> > > ) < 0)
> > > + goto out_err;
> > > +
> > > + if (enable)
> > > + val |= mask;
> > > + else
> > > + val &= ~mask;
> > > +
> > > + if (drm_dp_dpcd_writeb(tunnel->aux, DP_DPTX_BW_ALLOCATION_MODE_CONTROL, 
> > > val) < 0)
> > > + goto out_err;
> > > +
> > > + tunnel->bw_a

Re: [PATCH 02/19] drm/dp: Add support for DP tunneling

2024-02-07 Thread Imre Deak
On Wed, Feb 07, 2024 at 10:48:53PM +0200, Imre Deak wrote:
> On Wed, Feb 07, 2024 at 10:02:18PM +0200, Ville Syrjälä wrote:
> > > [...]
> > > +static int
> > > +drm_dp_tunnel_atomic_check_group_bw(struct drm_dp_tunnel_group_state 
> > > *new_group_state,
> > > + u32 *failed_stream_mask)
> > > +{
> > > + struct drm_dp_tunnel_group *group = to_group(new_group_state->base.obj);
> > > + struct drm_dp_tunnel_state *new_tunnel_state;
> > > + u32 group_stream_mask = 0;
> > > + int group_bw = 0;
> > > +
> > > + for_each_tunnel_state(new_group_state, new_tunnel_state) {
> > > + struct drm_dp_tunnel *tunnel = 
> > > new_tunnel_state->tunnel_ref.tunnel;
> > > + int max_dprx_bw = get_max_dprx_bw(tunnel);
> > > + int tunnel_bw = 
> > > drm_dp_tunnel_atomic_get_tunnel_bw(new_tunnel_state);
> > > +
> > > + tun_dbg(tunnel,
> > > + "%sRequired %d/%d Mb/s total for tunnel.\n",
> > > + tunnel_bw > max_dprx_bw ? "Not enough BW: " : "",
> > > + DPTUN_BW_ARG(tunnel_bw),
> > > + DPTUN_BW_ARG(max_dprx_bw));
> > > +
> > > + if (tunnel_bw > max_dprx_bw) {
> > 
> > I'm a bit confused why we're checking this here. Aren't we already
> > checking this somewhere else?
> 
> Ah, yes this should be checked already by the encoder compute config +
> the MST link BW check. It can be removed, thanks.

Though neither of that is guaranteed for drivers in general, so
shouldn't it be here still?

> > > + *failed_stream_mask = new_tunnel_state->stream_mask;
> > > + return -ENOSPC;
> > > + }
> > > +
> > > + group_bw += min(roundup(tunnel_bw, tunnel->bw_granularity),
> > > + max_dprx_bw);
> > > + group_stream_mask |= new_tunnel_state->stream_mask;
> > > + }
> > > +
> > > + tun_grp_dbg(group,
> > > + "%sRequired %d/%d Mb/s total for tunnel group.\n",
> > > + group_bw > group->available_bw ? "Not enough BW: " : "",
> > > + DPTUN_BW_ARG(group_bw),
> > > + DPTUN_BW_ARG(group->available_bw));
> > > +
> > > + if (group_bw > group->available_bw) {
> > > + *failed_stream_mask = group_stream_mask;
> > > + return -ENOSPC;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +


Re: [PATCH 02/19] drm/dp: Add support for DP tunneling

2024-02-07 Thread Imre Deak
On Wed, Feb 07, 2024 at 10:02:18PM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:33PM +0200, Imre Deak wrote:
> > +static char yes_no_chr(int val)
> > +{
> > +   return val ? 'Y' : 'N';
> > +}
> 
> We have str_yes_no() already.

Ok, will use this.

> v> +
> > +#define SKIP_DPRX_CAPS_CHECK   BIT(0)
> > +#define ALLOW_ALLOCATED_BW_CHANGE  BIT(1)
> > +
> > +static bool tunnel_regs_are_valid(struct drm_dp_tunnel_mgr *mgr,
> > + const struct drm_dp_tunnel_regs *regs,
> > + unsigned int flags)
> > +{
> > +   int drv_group_id = tunnel_reg_drv_group_id(regs);
> > +   bool check_dprx = !(flags & SKIP_DPRX_CAPS_CHECK);
> > +   bool ret = true;
> > +
> > +   if (!tunnel_reg_bw_alloc_supported(regs)) {
> > +   if (tunnel_group_id(drv_group_id)) {
> > +   drm_dbg_kms(mgr->dev,
> > +   "DPTUN: A non-zero group ID is only allowed 
> > with BWA support\n");
> > +   ret = false;
> > +   }
> > +
> > +   if (tunnel_reg(regs, DP_ALLOCATED_BW)) {
> > +   drm_dbg_kms(mgr->dev,
> > +   "DPTUN: BW is allocated without BWA 
> > support\n");
> > +   ret = false;
> > +   }
> > +
> > +   return ret;
> > +   }
> > +
> > +   if (!tunnel_group_id(drv_group_id)) {
> > +   drm_dbg_kms(mgr->dev,
> > +   "DPTUN: BWA support requires a non-zero group 
> > ID\n");
> > +   ret = false;
> > +   }
> > +
> > +   if (check_dprx && hweight8(tunnel_reg_max_dprx_lane_count(regs)) != 1) {
> > +   drm_dbg_kms(mgr->dev,
> > +   "DPTUN: Invalid DPRX lane count: %d\n",
> > +   tunnel_reg_max_dprx_lane_count(regs));
> > +
> > +   ret = false;
> > +   }
> > +
> > +   if (check_dprx && !tunnel_reg_max_dprx_rate(regs)) {
> > +   drm_dbg_kms(mgr->dev,
> > +   "DPTUN: DPRX rate is 0\n");
> > +
> > +   ret = false;
> > +   }
> > +
> > +   if (tunnel_reg(regs, DP_ALLOCATED_BW) > tunnel_reg(regs, 
> > DP_ESTIMATED_BW)) {
> > +   drm_dbg_kms(mgr->dev,
> > +   "DPTUN: Allocated BW %d > estimated BW %d Mb/s\n",
> > +   DPTUN_BW_ARG(tunnel_reg(regs, DP_ALLOCATED_BW) *
> > +tunnel_reg_bw_granularity(regs)),
> > +   DPTUN_BW_ARG(tunnel_reg(regs, DP_ESTIMATED_BW) *
> > +tunnel_reg_bw_granularity(regs)));
> > +
> > +   ret = false;
> > +   }
> > +
> > +   return ret;
> > +}
> > +
> > +static bool tunnel_info_changes_are_valid(struct drm_dp_tunnel *tunnel,
> > + const struct drm_dp_tunnel_regs *regs,
> > + unsigned int flags)
> > +{
> > +   int new_drv_group_id = tunnel_reg_drv_group_id(regs);
> > +   bool ret = true;
> > +
> > +   if (tunnel->bw_alloc_supported != tunnel_reg_bw_alloc_supported(regs)) {
> > +   tun_dbg(tunnel,
> > +   "BW alloc support has changed %c -> %c\n",
> > +   yes_no_chr(tunnel->bw_alloc_supported),
> > +   yes_no_chr(tunnel_reg_bw_alloc_supported(regs)));
> > +
> > +   ret = false;
> > +   }
> > +
> > +   if (tunnel->group->drv_group_id != new_drv_group_id) {
> > +   tun_dbg(tunnel,
> > +   "Driver/group ID has changed %d:%d:* -> %d:%d:*\n",
> > +   tunnel_group_drv_id(tunnel->group->drv_group_id),
> > +   tunnel_group_id(tunnel->group->drv_group_id),
> > +   tunnel_group_drv_id(new_drv_group_id),
> > +   tunnel_group_id(new_drv_group_id));
> > +
> > +   ret = false;
> > +   }
> > +
> > +   if (!tunnel->bw_alloc_supported)
> > +   return ret;
> > +
> > +   if (tunnel->bw_granularity != tunnel_reg_bw_granularity(regs)) {
> > +   tun_dbg(tunnel,
> > +   "BW granularity has changed: %d -> %d Mb/s\n",
> > +   DPTUN_BW_ARG(tunnel->bw_granularity),
> > +  

Re: [PATCH 14/19] drm/i915/dp: Compute DP tunel BW during encoder state computation

2024-02-07 Thread Imre Deak
On Wed, Feb 07, 2024 at 01:25:19AM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:45PM +0200, Imre Deak wrote:
> > Compute the BW required through a DP tunnel on links with such tunnels
> > detected and add the corresponding atomic state during a modeset.
> > 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/i915/display/intel_dp.c | 16 +---
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +
> >  2 files changed, 26 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 78dfe8be6031d..6968fdb7ffcdf 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -2880,6 +2880,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> > struct drm_connector_state *conn_state)
> >  {
> > struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> > +   struct intel_atomic_state *state = 
> > to_intel_atomic_state(conn_state->state);
> > struct drm_display_mode *adjusted_mode = _config->hw.adjusted_mode;
> > struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > const struct drm_display_mode *fixed_mode;
> > @@ -2980,6 +2981,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> > intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
> > intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, 
> > conn_state);
> >  
> > +   intel_dp_tunnel_atomic_compute_stream_bw(state, intel_dp, connector,
> > +pipe_config);
> 
> Error handling seems awol?

Yes, along with checking the return from
drm_dp_tunnel_atomic_set_stream_bw(), thanks for spotting this.

> 
> > +
> > return 0;
> >  }
> >  
> > @@ -6087,6 +6091,15 @@ static int intel_dp_connector_atomic_check(struct 
> > drm_connector *conn,
> > return ret;
> > }
> >  
> > +   if (!intel_connector_needs_modeset(state, conn))
> > +   return 0;
> > +
> > +   ret = intel_dp_tunnel_atomic_check_state(state,
> > +intel_dp,
> > +intel_conn);
> > +   if (ret)
> > +   return ret;
> > +
> > /*
> >  * We don't enable port sync on BDW due to missing w/as and
> >  * due to not having adjusted the modeset sequence appropriately.
> > @@ -6094,9 +6107,6 @@ static int intel_dp_connector_atomic_check(struct 
> > drm_connector *conn,
> > if (DISPLAY_VER(dev_priv) < 9)
> > return 0;
> >  
> > -   if (!intel_connector_needs_modeset(state, conn))
> > -   return 0;
> > -
> > if (conn->has_tile) {
> > ret = intel_modeset_tile_group(state, conn->tile_group->id);
> > if (ret)
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
> > b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index 520393dc8b453..cbfab3173b9ef 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -42,6 +42,7 @@
> >  #include "intel_dp.h"
> >  #include "intel_dp_hdcp.h"
> >  #include "intel_dp_mst.h"
> > +#include "intel_dp_tunnel.h"
> >  #include "intel_dpio_phy.h"
> >  #include "intel_hdcp.h"
> >  #include "intel_hotplug.h"
> > @@ -523,6 +524,7 @@ static int intel_dp_mst_compute_config(struct 
> > intel_encoder *encoder,
> >struct drm_connector_state *conn_state)
> >  {
> > struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> > +   struct intel_atomic_state *state = 
> > to_intel_atomic_state(conn_state->state);
> > struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
> > struct intel_dp *intel_dp = _mst->primary->dp;
> > const struct intel_connector *connector =
> > @@ -619,6 +621,9 @@ static int intel_dp_mst_compute_config(struct 
> > intel_encoder *encoder,
> >  
> > intel_psr_compute_config(intel_dp, pipe_config, conn_state);
> >  
> > +   intel_dp_tunnel_atomic_compute_stream_bw(state, intel_dp, connector,
> > +pipe_config);
> > +
> > return 0;
> >  }
> >  
> > @@ -876,6 +881,14 @@ intel_dp_mst_atomic_check(struct drm_con

Re: [PATCH 11/19] drm/i915/dp: Add support for DP tunnel BW allocation

2024-02-07 Thread Imre Deak
On Wed, Feb 07, 2024 at 01:08:43AM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:42PM +0200, Imre Deak wrote:
> > Add support to enable the DP tunnel BW allocation mode. Follow-up
> > patches will call the required helpers added here to prepare for a
> > modeset on a link with DP tunnels, the last change in the patchset
> > actually enabling BWA.
> > 
> > With BWA enabled, the driver will expose the full mode list a display
> > supports, regardless of any BW limitation on a shared (Thunderbolt)
> > link. Such BW limits will be checked against only during a modeset, when
> > the driver has the full knowledge of each display's BW requirement.
> > 
> > If the link BW changes in a way that a connector's modelist may also
> > change, userspace will get a hotplug notification for all the connectors
> > sharing the same link (so it can adjust the mode used for a display).
> > 
> > The BW limitation can change at any point, asynchronously to modesets
> > on a given connector, so a modeset can fail even though the atomic check
> > for it passed. In such scenarios userspace will get a bad link
> > notification and in response is supposed to retry the modeset.
> > 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/i915/Kconfig  |  13 +
> >  drivers/gpu/drm/i915/Kconfig.debug|   1 +
> >  drivers/gpu/drm/i915/Makefile |   3 +
> >  drivers/gpu/drm/i915/display/intel_atomic.c   |   2 +
> >  .../gpu/drm/i915/display/intel_display_core.h |   1 +
> >  .../drm/i915/display/intel_display_types.h|   9 +
> >  .../gpu/drm/i915/display/intel_dp_tunnel.c| 642 ++
> >  .../gpu/drm/i915/display/intel_dp_tunnel.h| 131 
> >  8 files changed, 802 insertions(+)
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.c
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.h
> > 
> > diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
> > index b5d6e3352071f..4636913c17868 100644
> > --- a/drivers/gpu/drm/i915/Kconfig
> > +++ b/drivers/gpu/drm/i915/Kconfig
> > @@ -155,6 +155,19 @@ config DRM_I915_PXP
> >   protected session and manage the status of the alive software session,
> >   as well as its life cycle.
> >  
> > +config DRM_I915_DP_TUNNEL
> > +   bool "Enable DP tunnel support"
> > +   depends on DRM_I915
> > +   select DRM_DISPLAY_DP_TUNNEL
> > +   default y
> > +   help
> > + Choose this option to detect DP tunnels and enable the Bandwidth
> > + Allocation mode for such tunnels. This allows using the maximum
> > + resolution allowed by the link BW on all displays sharing the
> > + link BW, for instance on a Thunderbolt link.
> > +
> > + If in doubt, say "Y".
> > +
> >  menu "drm/i915 Debugging"
> >  depends on DRM_I915
> >  depends on EXPERT
> > diff --git a/drivers/gpu/drm/i915/Kconfig.debug 
> > b/drivers/gpu/drm/i915/Kconfig.debug
> > index 5b7162076850c..bc18e2d9ea05d 100644
> > --- a/drivers/gpu/drm/i915/Kconfig.debug
> > +++ b/drivers/gpu/drm/i915/Kconfig.debug
> > @@ -28,6 +28,7 @@ config DRM_I915_DEBUG
> > select STACKDEPOT
> > select STACKTRACE
> > select DRM_DP_AUX_CHARDEV
> > +   select DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE if DRM_I915_DP_TUNNEL
> > select X86_MSR # used by igt/pm_rpm
> > select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
> > select DRM_DEBUG_MM if DRM=y
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index c13f14edb5088..3ef6ed41e62b4 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -369,6 +369,9 @@ i915-y += \
> > display/vlv_dsi.o \
> > display/vlv_dsi_pll.o
> >  
> > +i915-$(CONFIG_DRM_I915_DP_TUNNEL) += \
> > +   display/intel_dp_tunnel.o
> > +
> >  i915-y += \
> > i915_perf.o
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
> > b/drivers/gpu/drm/i915/display/intel_atomic.c
> > index ec0d5168b5035..96ab37e158995 100644
> > --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> > +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> > @@ -29,6 +29,7 @@
> >   * See intel_atomic_plane.c for the plane-specific atomic functionality.
> >   */
> >  
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -38,6 +39,7 @@
> >  #include "intel_atomic.h"
> 

Re: [PATCH 11/19] drm/i915/dp: Add support for DP tunnel BW allocation

2024-02-06 Thread Imre Deak
On Tue, Feb 06, 2024 at 12:47:22AM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:42PM +0200, Imre Deak wrote:
> > +static int check_inherited_tunnel_state(struct intel_atomic_state *state,
> > +   struct intel_dp *intel_dp,
> > +   const struct 
> > intel_digital_connector_state *old_conn_state)
> > +{
> > +   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > +   struct intel_encoder *encoder = _to_dig_port(intel_dp)->base;
> > +   const struct intel_connector *connector =
> > +   to_intel_connector(old_conn_state->base.connector);
> > +   struct intel_crtc *old_crtc;
> > +   const struct intel_crtc_state *old_crtc_state;
> > +
> > +   /*
> > +* If a BWA tunnel gets detected only after the corresponding
> > +* connector got enabled already without a BWA tunnel, or a different
> > +* BWA tunnel (which was removed meanwhile) the old CRTC state won't
> > +* contain the state of the current tunnel. This tunnel still has a
> > +* reserved BW, which needs to be released, add the state for such
> > +* inherited tunnels separately only to this atomic state.
> > +*/
> > +   if (!intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
> > +   return 0;
> > +
> > +   if (!old_conn_state->base.crtc)
> > +   return 0;
> > +
> > +   old_crtc = to_intel_crtc(old_conn_state->base.crtc);
> > +   old_crtc_state = intel_atomic_get_old_crtc_state(state, old_crtc);
> > +
> > +   if (!old_crtc_state->hw.active ||
> > +   old_crtc_state->dp_tunnel_ref.tunnel == intel_dp->tunnel)
> > +   return 0;
> > +
> > +   drm_dbg_kms(>drm,
> > +   "[DPTUN %s][CONNECTOR:%d:%s][ENCODER:%d:%s][CRTC:%d:%s] 
> > Adding state for inherited tunnel %p\n",
> > +   drm_dp_tunnel_name(intel_dp->tunnel),
> > +   connector->base.base.id,
> > +   connector->base.name,
> > +   encoder->base.base.id,
> > +   encoder->base.name,
> > +   old_crtc->base.base.id,
> > +   old_crtc->base.name,
> > +   intel_dp->tunnel);
> > +
> > +   return add_inherited_tunnel_state(state, intel_dp->tunnel, old_crtc);
> 
> I still strongly dislike this "tunnels are magically created by detect
> behind our back" approach. IMO in an ideal world we'd only ever create the
> tunnels during modeset/sanitize. What was the reason that didn't work again?
> I think you explained it to me in person at least once already, but can't
> remember anymore...

The tunnel information, describing which group the tunnel belongs to and
so how much BW it can use is needed already during detect time: to
filter the connectors' mode list during connector probing and to
pass/fail an atomic check of connectors that go through a tunnel/group
based on the modes the connectors use, the BW these require vs. the
available BW of the tunnel group.

The atomic state for the tunnel - with the required BW through it - is
only created/added during a modeset.

> -- 
> Ville Syrjälä
> Intel


Re: [PATCH 12/19] drm/i915/dp: Add DP tunnel atomic state and check BW limit

2024-02-05 Thread Imre Deak
On Mon, Feb 05, 2024 at 06:11:00PM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:43PM +0200, Imre Deak wrote:
> > Add the atomic state during a modeset required to enable the DP tunnel
> > BW allocation mode on links where such a tunnel was detected.
> > 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/i915/display/intel_atomic.c  |  8 
> >  drivers/gpu/drm/i915/display/intel_display.c | 19 +++
> >  drivers/gpu/drm/i915/display/intel_link_bw.c |  5 +
> >  3 files changed, 32 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
> > b/drivers/gpu/drm/i915/display/intel_atomic.c
> > index 96ab37e158995..4236740ede9ed 100644
> > --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> > +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> > @@ -260,6 +260,10 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
> > if (crtc_state->post_csc_lut)
> > drm_property_blob_get(crtc_state->post_csc_lut);
> >  
> > +   if (crtc_state->dp_tunnel_ref.tunnel)
> > +   drm_dp_tunnel_ref_get(old_crtc_state->dp_tunnel_ref.tunnel,
> 
> I'd probably s/old_crtc_state/crtc_state/ here. Same pointer, but
> looks out of place given everyone else just operates on 'crtc_state' 
> here.

Ok, will change that.

> > +   _state->dp_tunnel_ref);
> 
> Shame we have to have this ref wrapper. But I guess no clean
> way to have a magic tracked pointer type that works like a
> normal pointer in C...

I suppose returning a pointer to a kmalloced drm_dp_tunnel_ref from
drm_tunnel_get() and freeing this in drm_tunnel_put() would be one way,
but that imo defeats the purpose of the tracker information being valid
even after put() (so that ref_tracker can print information about where
a particular reference was already dropped).

> 
> > +
> > crtc_state->update_pipe = false;
> > crtc_state->update_m_n = false;
> > crtc_state->update_lrr = false;
> > @@ -311,6 +315,8 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
> >  
> > __drm_atomic_helper_crtc_destroy_state(_state->uapi);
> > intel_crtc_free_hw_state(crtc_state);
> > +   if (crtc_state->dp_tunnel_ref.tunnel)
> > +   drm_dp_tunnel_ref_put(_state->dp_tunnel_ref);
> > kfree(crtc_state);
> >  }
> >  
> > @@ -346,6 +352,8 @@ void intel_atomic_state_clear(struct drm_atomic_state 
> > *s)
> > /* state->internal not reset on purpose */
> >  
> > state->dpll_set = state->modeset = false;
> > +
> > +   intel_dp_tunnel_atomic_cleanup_inherited_state(state);
> 
> This seems to be in the wrong patch?

Yes, I guess a more logical place is in

[PATCH 14/19] drm/i915/dp: Compute DP tunel BW during encoder state computation

where the state is added, will move it there.

> 
> >  }
> >  
> >  struct intel_crtc_state *
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> > b/drivers/gpu/drm/i915/display/intel_display.c
> > index b9f985a5e705b..46b27a32c8640 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -33,6 +33,7 @@
> >  #include 
> >  
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -73,6 +74,7 @@
> >  #include "intel_dp.h"
> >  #include "intel_dp_link_training.h"
> >  #include "intel_dp_mst.h"
> > +#include "intel_dp_tunnel.h"
> >  #include "intel_dpll.h"
> >  #include "intel_dpll_mgr.h"
> >  #include "intel_dpt.h"
> > @@ -4490,6 +4492,8 @@ copy_bigjoiner_crtc_state_modeset(struct 
> > intel_atomic_state *state,
> > saved_state->crc_enabled = slave_crtc_state->crc_enabled;
> >  
> > intel_crtc_free_hw_state(slave_crtc_state);
> > +   if (slave_crtc_state->dp_tunnel_ref.tunnel)
> > +   drm_dp_tunnel_ref_put(_crtc_state->dp_tunnel_ref);
> > memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state));
> > kfree(saved_state);
> >  
> > @@ -4505,6 +4509,10 @@ copy_bigjoiner_crtc_state_modeset(struct 
> > intel_atomic_state *state,
> >   _crtc_state->hw.adjusted_mode);
> > slave_crtc_state->hw.scaling_filter = 
> > master_crtc_state->hw.scaling_filter;
> >  
> > +   if (master_crtc_state->dp_tunnel_ref.tunnel)
> > +   drm_dp_tunnel_ref_get(master_crtc_state->dp_tunnel_ref.tunnel,
> > +  

Re: [PATCH 02/19] drm/dp: Add support for DP tunneling

2024-02-05 Thread Imre Deak
On Mon, Feb 05, 2024 at 06:13:30PM +0200, Ville Syrjälä wrote:
> On Wed, Jan 31, 2024 at 08:49:16PM +0200, Imre Deak wrote:
> > On Wed, Jan 31, 2024 at 06:09:04PM +0200, Ville Syrjälä wrote:
> > > On Tue, Jan 23, 2024 at 12:28:33PM +0200, Imre Deak wrote:
> > > > +static void untrack_tunnel_ref(struct drm_dp_tunnel *tunnel,
> > > > +  struct ref_tracker **tracker)
> > > > +{
> > > > +   ref_tracker_free(>group->mgr->ref_tracker,
> > > > +tracker);
> > > > +}
> > > > +
> > > > +struct drm_dp_tunnel *
> > > > +drm_dp_tunnel_get_untracked(struct drm_dp_tunnel *tunnel)
> > > > +{
> > > > +   track_tunnel_ref(tunnel, NULL);
> > > > +
> > > > +   return tunnel_get(tunnel);
> > > > +}
> > > > +EXPORT_SYMBOL(drm_dp_tunnel_get_untracked);
> > > 
> > > Why do these exist?
> > 
> > They implement drm_dp_tunnel_get()/put() if
> > CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE=n.
> 
> Why does that kind of irrelevant detail need to be visible
> in the exported api?

In non-debug builds the ref_tracker object isn't needed and so
drm_dp_tunnel_ref won't contain a pointer to it either.
drm_dp_tunnel_get/put_untracked() provide a way to get/put a tunnel
reference without having to pass a ref_tracker pointer.

> 
> -- 
> Ville Syrjälä
> Intel


Re: [PATCH 02/19] drm/dp: Add support for DP tunneling

2024-01-31 Thread Imre Deak
On Wed, Jan 31, 2024 at 06:09:04PM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:33PM +0200, Imre Deak wrote:
> > Add support for Display Port DP tunneling. For now this includes the
> > support for Bandwidth Allocation Mode, leaving adding Panel Replay
> > support for later.
> > 
> > BWA allows using displays that share the same (Thunderbolt) link with
> > their maximum resolution. Atm, this may not be possible due to the
> > coarse granularity of partitioning the link BW among the displays on the
> > link: the BW allocation policy is in a SW/FW/HW component on the link
> > (on Thunderbolt it's the SW or FW Connection Manager), independent of
> > the driver. This policy will set the DPRX maximum rate and lane count
> > DPCD registers the GFX driver will see (0x0, 0x1, 0x02200,
> > 0x02201) based on the available link BW.
> > 
> > The granularity of the current BW allocation policy is course, based on
> > the required link rate in the 1.62Gbs..8.1Gbps range and it may prevent
> > using higher resolutions all together: the display connected first will
> > get a share of the link BW which corresponds to its full DPRX capability
> > (regardless of the actual mode it uses). A subsequent display connected
> > will only get the remaining BW, which could be well below its full
> > capability.
> > 
> > BWA solves the above course granularity (reducing it to a 250Mbs..1Gps
> > range) and first-come/first-served issues by letting the driver request
> > the BW for each display on a link which reflects the actual modes the
> > displays use.
> > 
> > This patch adds the DRM core helper functions, while a follow-up change
> > in the patchset takes them into use in the i915 driver.
> > 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/display/Kconfig |   17 +
> >  drivers/gpu/drm/display/Makefile|2 +
> >  drivers/gpu/drm/display/drm_dp_tunnel.c | 1715 +++
> >  include/drm/display/drm_dp.h|   60 +
> >  include/drm/display/drm_dp_tunnel.h |  270 
> >  5 files changed, 2064 insertions(+)
> >  create mode 100644 drivers/gpu/drm/display/drm_dp_tunnel.c
> >  create mode 100644 include/drm/display/drm_dp_tunnel.h
> > 
> > diff --git a/drivers/gpu/drm/display/Kconfig 
> > b/drivers/gpu/drm/display/Kconfig
> > index 09712b88a5b83..b024a84b94c1c 100644
> > --- a/drivers/gpu/drm/display/Kconfig
> > +++ b/drivers/gpu/drm/display/Kconfig
> > @@ -17,6 +17,23 @@ config DRM_DISPLAY_DP_HELPER
> > help
> >   DRM display helpers for DisplayPort.
> >  
> > +config DRM_DISPLAY_DP_TUNNEL
> > +   bool
> > +   select DRM_DISPLAY_DP_HELPER
> > +   help
> > + Enable support for DisplayPort tunnels.
> > +
> > +config DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
> > +   bool "Enable debugging the DP tunnel state"
> > +   depends on REF_TRACKER
> > +   depends on DRM_DISPLAY_DP_TUNNEL
> > +   depends on DEBUG_KERNEL
> > +   depends on EXPERT
> > +   help
> > + Enables debugging the DP tunnel manager's status.
> > +
> > + If in doubt, say "N".
> 
> It's not exactly clear what a "DP tunnel" is.
> Shouldn't thunderbolt be mentioned here somewhere?

The only way I'm aware of tunneling can work is through a TBT link yes,
however I'm not sure if it couldn't work on any DP link, the interface -
to request BW - is simply the AUX bus after all and AFAIR the standard
doesn't mention TBT either (but have to reread that). The above
descriptions should be extended anyway and the usual TBT scenario
mentioned at least, so will do that.

> > +
> >  config DRM_DISPLAY_HDCP_HELPER
> > bool
> > depends on DRM_DISPLAY_HELPER
> > diff --git a/drivers/gpu/drm/display/Makefile 
> > b/drivers/gpu/drm/display/Makefile
> > index 17ac4a1006a80..7ca61333c6696 100644
> > --- a/drivers/gpu/drm/display/Makefile
> > +++ b/drivers/gpu/drm/display/Makefile
> > @@ -8,6 +8,8 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \
> > drm_dp_helper.o \
> > drm_dp_mst_topology.o \
> > drm_dsc_helper.o
> > +drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_TUNNEL) += \
> > +   drm_dp_tunnel.o
> >  drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
> >  drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
> > drm_hdmi_helper.o \
> > diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c 
> > b/drivers/gpu/drm/display/drm_dp_tunnel.c
> > new file mode 100644
> > index 000

Re: [PATCH 18/19] drm/i915/dp: Suspend/resume DP tunnels

2024-01-31 Thread Imre Deak
On Wed, Jan 31, 2024 at 06:18:22PM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:49PM +0200, Imre Deak wrote:
> > Suspend and resume DP tunnels during system suspend/resume, disabling
> > the BW allocation mode during suspend, re-enabling it after resume. This
> > reflects the link's BW management component (Thunderbolt CM) disabling
> > BWA during suspend. Before any BW requests the driver must read the
> > sink's DPRX capabilities (since the BW manager requires this
> > information, so snoops for it on AUX), so ensure this read takes place.
> 
> Isn't that going to screw up the age old problem of .compute_config()
> potentially failing during the resume modeset if we no longer have
> the same amount of bandwidth available as we had before suspend?
> So far we've been getting away with this exactly by not updating 
> the dpcd stuff before the modeset during resume.

Right, in the case where this would be a problem (so not counting where
the caps haven't been read out yet and so we update here
intel_dp->dpcd), the caps in intel_dp->dpcd will be preserved, not
actually updated with the read-out values, see intel_dp_tunnel_resume()
in patch 11.

The same goes for the tunnel (group) BW: it will not be updated during
resume (by way of the connector/tunnel detection being blocked during
the restore modeset), so the restore modeset should see the same amount
of BW as there was during suspend.

> 
> > 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/i915/display/intel_dp.c | 16 +++-
> >  1 file changed, 11 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 8ebfb039000f6..bc138a54f8d7b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -36,6 +36,7 @@
> >  #include 
> >  
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -3320,18 +3321,21 @@ void intel_dp_sync_state(struct intel_encoder 
> > *encoder,
> >  const struct intel_crtc_state *crtc_state)
> >  {
> > struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > -
> > -   if (!crtc_state)
> > -   return;
> > +   bool dpcd_updated = false;
> >  
> > /*
> >  * Don't clobber DPCD if it's been already read out during output
> >  * setup (eDP) or detect.
> >  */
> > -   if (intel_dp->dpcd[DP_DPCD_REV] == 0)
> > +   if (crtc_state && intel_dp->dpcd[DP_DPCD_REV] == 0) {
> > intel_dp_get_dpcd(intel_dp);
> > +   dpcd_updated = true;
> > +   }
> >  
> > -   intel_dp_reset_max_link_params(intel_dp);
> > +   intel_dp_tunnel_resume(intel_dp, dpcd_updated);
> > +
> > +   if (crtc_state)
> > +   intel_dp_reset_max_link_params(intel_dp);
> >  }
> >  
> >  bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
> > @@ -5973,6 +5977,8 @@ void intel_dp_encoder_suspend(struct intel_encoder 
> > *intel_encoder)
> > struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> >  
> > intel_pps_vdd_off_sync(intel_dp);
> > +
> > +   intel_dp_tunnel_suspend(intel_dp);
> >  }
> >  
> >  void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
> > -- 
> > 2.39.2
> 
> -- 
> Ville Syrjälä
> Intel


Re: [PATCH 02/19] drm/dp: Add support for DP tunneling

2024-01-31 Thread Imre Deak
On Wed, Jan 31, 2024 at 02:50:16PM +0200, Hogander, Jouni wrote:
> [...]
> > +
> > +struct drm_dp_tunnel_group;
> > +
> > +struct drm_dp_tunnel {
> > +   struct drm_dp_tunnel_group *group;
> > +
> > +   struct list_head node;
> > +
> > +   struct kref kref;
> > +#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
> > +   struct ref_tracker *tracker;
> > +#endif
> > +   struct drm_dp_aux *aux;
> > +   char name[8];
> > +
> > +   int bw_granularity;
> > +   int estimated_bw;
> > +   int allocated_bw;
> > +
> > +   int max_dprx_rate;
> > +   u8 max_dprx_lane_count;
> > +
> > +   u8 adapter_id;
> > +
> > +   bool bw_alloc_supported:1;
> > +   bool bw_alloc_enabled:1;
> > +   bool has_io_error:1;
> > +   bool destroyed:1;
> > +};
> > +
> > +struct drm_dp_tunnel_group_state;
> > +
> > +struct drm_dp_tunnel_state {
> > +   struct drm_dp_tunnel_group_state *group_state;
> > +
> > +   struct drm_dp_tunnel_ref tunnel_ref;
> > +
> > +   struct list_head node;
> > +
> > +   u32 stream_mask;
> 
> I'm wondering if drm_dp_tunnel_state can really contain several streams
> and what kind of scenario this would be? From i915 point of view I
> would understand that several pipes are routed to DP tunnel.

Yes, multiple pipes through the same tunnel and the use case for that is
MST with multiple streams. The "stream" term is only an abstraction
where it could be a different physical thing in various drivers, but for
i915 it just means pipes. Not 100% sure if that's the best mapping,
since in case of bigjoiner there would be multiple pipes, but possibly
(in the SST case) only one stream from the tunneling POV.

> Is it bigjoiner case?

IIUC in that (SST) case the streams would be joined already before going
to the TBT DP_IN adapter, so that's only one stream in stream_mask above
(unless MST + bigjoiner, where you could have 2 MST/DP tunnel streams
each consisting of 2 pipes).

> BR,
> 
> Jouni Högander
> 
> > +   int *stream_bw;
> > +};
> > +
> > +struct drm_dp_tunnel_group_state {
> > +   struct drm_private_state base;
> > +
> > +   struct list_head tunnel_states;
> > +};
> > +
> > +struct drm_dp_tunnel_group {
> > +   struct drm_private_obj base;
> > +   struct drm_dp_tunnel_mgr *mgr;
> > +
> > +   struct list_head tunnels;
> > +
> > +   int available_bw;   /* available BW including the
> > allocated_bw of all tunnels */
> > +   int drv_group_id;
> > +
> > +   char name[8];
> > +
> > +   bool active:1;
> > +};
> > +
> > +struct drm_dp_tunnel_mgr {
> > +   struct drm_device *dev;
> > +
> > +   int group_count;
> > +   struct drm_dp_tunnel_group *groups;
> > +   wait_queue_head_t bw_req_queue;
> > +
> > +#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
> > +   struct ref_tracker_dir ref_tracker;
> > +#endif
> > +};
> > +
> > +static int next_reg_area(int *offset)
> > +{
> > +   *offset = find_next_bit(dptun_info_regs, 64, *offset);
> > +
> > +   return find_next_zero_bit(dptun_info_regs, 64, *offset + 1) -
> > *offset;
> > +}
> > +
> > +#define tunnel_reg_ptr(__regs, __address) ({ \
> > +   WARN_ON(!test_bit((__address) - DP_TUNNELING_BASE,
> > dptun_info_regs)); \
> > +   &(__regs)->buf[bitmap_weight(dptun_info_regs, (__address) -
> > DP_TUNNELING_BASE)]; \
> > +})
> > +
> > +static int read_tunnel_regs(struct drm_dp_aux *aux, struct
> > drm_dp_tunnel_regs *regs)
> > +{
> > +   int offset = 0;
> > +   int len;
> > +
> > +   while ((len = next_reg_area())) {
> > +   int address = DP_TUNNELING_BASE + offset;
> > +
> > +   if (drm_dp_dpcd_read(aux, address,
> > tunnel_reg_ptr(regs, address), len) < 0)
> > +   return -EIO;
> > +
> > +   offset += len;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static u8 tunnel_reg(const struct drm_dp_tunnel_regs *regs, int
> > address)
> > +{
> > +   return *tunnel_reg_ptr(regs, address);
> > +}
> > +
> > +static int tunnel_reg_drv_group_id(const struct drm_dp_tunnel_regs
> > *regs)
> > +{
> > +   int drv_id = tunnel_reg(regs, DP_USB4_DRIVER_ID) &
> > DP_USB4_DRIVER_ID_MASK;
> > +   int group_id = tunnel_reg(regs,
> > DP_IN_ADAPTER_TUNNEL_INFORMATION) & DP_GROUP_ID_MASK;
> > +
> > +   if (!group_id)
> > +   return 0;
> > +
> > +   return (drv_id << DP_GROUP_ID_BITS) | group_id;
> > +}
> > +
> > +/* Return granularity in kB/s units */
> > +static int tunnel_reg_bw_granularity(const struct drm_dp_tunnel_regs
> > *regs)
> > +{
> > +   int gr = tunnel_reg(regs, DP_BW_GRANULARITY) &
> > DP_BW_GRANULARITY_MASK;
> > +
> > +   WARN_ON(gr > 2);
> > +
> > +   return (25 << gr) / 8;
> > +}
> > +
> > +static int tunnel_reg_max_dprx_rate(const struct drm_dp_tunnel_regs
> > *regs)
> > +{
> > +   u8 bw_code = tunnel_reg(regs, DP_TUNNELING_MAX_LINK_RATE);
> > +
> > +   return drm_dp_bw_code_to_link_rate(bw_code);
> > +}
> 

Re: [PATCH 03/19] drm/i915/dp: Add support to notify MST connectors to retry modesets

2024-01-29 Thread Imre Deak
On Mon, Jan 29, 2024 at 12:36:12PM +0200, Hogander, Jouni wrote:
> On Tue, 2024-01-23 at 12:28 +0200, Imre Deak wrote:
> > [...]
> > +void
> > +intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
> > + struct intel_encoder *encoder,
> > + const struct intel_crtc_state 
> > *crtc_state,
> > + const struct drm_connector_state 
> > *conn_state)
> > +{
> > +   struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
> > +   struct intel_connector *connector;
> > +   struct intel_digital_connector_state *iter_conn_state;
> > +   struct intel_dp *intel_dp;
> > +   int i;
> > +
> > +   if (conn_state) {
> > +   connector = to_intel_connector(conn_state->connector);
> > +   intel_dp_queue_modeset_retry_work(connector);
> > +
> > +   return;
> > +   }
> > +
> > +   if (drm_WARN_ON(>drm,
> > +   !intel_crtc_has_type(crtc_state, 
> > INTEL_OUTPUT_DP_MST)))
> > +   return;
> > +
> > +   intel_dp = enc_to_intel_dp(encoder);
> > +
> > +   for_each_new_intel_connector_in_state(state, connector, 
> > iter_conn_state, i) {
> > +   (void)iter_conn_state;
> 
> Checked iter_conn_state->base->crtc documentation:
> 
> @crtc: CRTC to connect connector to, NULL if disabled.
> 
> Do we need to check if connector is "disabled" or is it impossible
> scenario?

Yes, it does show if the connector is disabled and it would make sense
to not notify those. However the check for that would be racy, at least
during a non-blocking commit, but I think also in general where
userspace could be in the middle of enabling this connector.

The point of the notification is that userspace re-checks the mode it
wants on each MST connector to be enabled, so to prevent that it would
miss the re-check on connectors with a pending enabling like above, the
notification is simply sent to all the connectors in the MST topology.

> 
> BR,
> 
> Jouni Högander
> 
> 
> > +
> > +   if (connector->mst_port != intel_dp)
> > +   continue;
> > +
> > +   intel_dp_queue_modeset_retry_work(connector);
> > +   }
> > +}
> > +
> >  int
> >  intel_dp_compute_config(struct intel_encoder *encoder,
> > struct intel_crtc_state *pipe_config,
> > @@ -6436,6 +6480,14 @@ static void
> > intel_dp_modeset_retry_work_fn(struct work_struct *work)
> > mutex_unlock(>dev->mode_config.mutex);
> > /* Send Hotplug uevent so userspace can reprobe */
> > drm_kms_helper_connector_hotplug_event(connector);
> > +
> > +   drm_connector_put(connector);
> > +}
> > +
> > +void intel_dp_init_modeset_retry_work(struct intel_connector
> > *connector)
> > +{
> > +   INIT_WORK(>modeset_retry_work,
> > + intel_dp_modeset_retry_work_fn);
> >  }
> >
> >  bool
> > @@ -6452,8 +6504,7 @@ intel_dp_init_connector(struct
> > intel_digital_port *dig_port,
> > int type;
> >
> > /* Initialize the work for modeset in case of link train
> > failure */
> > -   INIT_WORK(_connector->modeset_retry_work,
> > - intel_dp_modeset_retry_work_fn);
> > +   intel_dp_init_modeset_retry_work(intel_connector);
> >
> > if (drm_WARN(dev, dig_port->max_lanes < 1,
> >  "Not enough lanes (%d) for DP on
> > [ENCODER:%d:%s]\n",
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h
> > b/drivers/gpu/drm/i915/display/intel_dp.h
> > index 530cc97bc42f4..105c2086310db 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > @@ -23,6 +23,8 @@ struct intel_digital_port;
> >  struct intel_dp;
> >  struct intel_encoder;
> >
> > +struct work_struct;
> > +
> >  struct link_config_limits {
> > int min_rate, max_rate;
> > int min_lane_count, max_lane_count;
> > @@ -43,6 +45,12 @@ void intel_dp_adjust_compliance_config(struct
> > intel_dp *intel_dp,
> >  bool intel_dp_limited_color_range(const struct intel_crtc_state
> > *crtc_state,
> >   const struct drm_connector_state
> > *conn_state);
> >  int intel_dp_min_bpp(enum intel_output_format outp

Re: [PATCH 01/19] drm/dp: Add drm_dp_max_dprx_data_rate()

2024-01-26 Thread Imre Deak
On Fri, Jan 26, 2024 at 01:36:02PM +0200, Ville Syrjälä wrote:
> On Tue, Jan 23, 2024 at 12:28:32PM +0200, Imre Deak wrote:
> > Copy intel_dp_max_data_rate() to DRM core. It will be needed by a
> > follow-up DP tunnel patch, checking the maximum rate the DPRX (sink)
> > supports. Accordingly use the drm_dp_max_dprx_data_rate() name for
> > clarity. This patchset will also switch calling the new DRM function
> > in i915 instead of intel_dp_max_data_rate().
> > 
> > Signed-off-by: Imre Deak 
> > ---
> >  drivers/gpu/drm/display/drm_dp_helper.c | 58 +
> >  include/drm/display/drm_dp_helper.h |  2 +
> >  2 files changed, 60 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> > b/drivers/gpu/drm/display/drm_dp_helper.c
> > index b1ca3a1100dab..24911243d4d3a 100644
> > --- a/drivers/gpu/drm/display/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> > @@ -4058,3 +4058,61 @@ int drm_dp_bw_channel_coding_efficiency(bool is_uhbr)
> > return 80;
> >  }
> >  EXPORT_SYMBOL(drm_dp_bw_channel_coding_efficiency);
> > +
> > +/*
> > + * Given a link rate and lanes, get the data bandwidth.
> > + *
> > + * Data bandwidth is the actual payload rate, which depends on the data
> > + * bandwidth efficiency and the link rate.
> > + *
> > + * For 8b/10b channel encoding, SST and non-FEC, the data bandwidth 
> > efficiency
> > + * is 80%. For example, for a 1.62 Gbps link, 1.62*10^9 bps * 0.80 * (1/8) 
> > =
> > + * 162000 kBps. With 8-bit symbols, we have 162000 kHz symbol clock. Just 
> > by
> > + * coincidence, the port clock in kHz matches the data bandwidth in kBps, 
> > and
> > + * they equal the link bit rate in Gbps multiplied by 10. (Note that 
> > this no
> > + * longer holds for data bandwidth as soon as FEC or MST is taken into 
> > account!)
> > + *
> > + * For 128b/132b channel encoding, the data bandwidth efficiency is 
> > 96.71%. For
> > + * example, for a 10 Gbps link, 10*10^9 bps * 0.9671 * (1/8) = 1208875
> > + * kBps. With 32-bit symbols, we have 312500 kHz symbol clock. The value 
> > 100
> > + * does not match the symbol clock, the port clock (not even if you think 
> > in
> > + * terms of a byte clock), nor the data bandwidth. It only matches the 
> > link bit
> > + * rate in units of 1 bps.
> > + *
> > + * Note that protocol layers above the DPRX link level considered here can
> > + * further limit the maximum data rate. Such layers are the MST topology 
> > (with
> > + * limits on the link between the source and first branch device as well 
> > as on
> > + * the whole MST path until the DPRX link) and (Thunderbolt) DP tunnels -
> > + * which in turn can encapsulate an MST link with its own limit - with each
> > + * SST or MST encapsulated tunnel sharing the BW of a tunnel group.
> > + *
> > + * TODO: Add support for querying the max data rate with the above limits 
> > as
> > + * well.
> > + *
> > + * Returns the maximum data rate in kBps units.
> > + */
> > +int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes)
> > +{
> > +   int ch_coding_efficiency =
> > +   
> > drm_dp_bw_channel_coding_efficiency(drm_dp_is_uhbr_rate(max_link_rate));
> > +   int max_link_rate_kbps = max_link_rate * 10;
> 
> That x10 value seems rather pointless.

I suppose the point was to make the units clearer, but it could be
clarified instead in max_link_rates' documentation, which is missing
atm.

> > +
> > +   /*
> > +* UHBR rates always use 128b/132b channel encoding, and have
> > +* 97.71% data bandwidth efficiency. Consider max_link_rate the
> > +* link bit rate in units of 1 bps.
> > +*/
> > +   /*
> > +* Lower than UHBR rates always use 8b/10b channel encoding, and have
> > +* 80% data bandwidth efficiency for SST non-FEC. However, this turns
> > +* out to be a nop by coincidence:
> > +*
> > +*  int max_link_rate_kbps = max_link_rate * 10;
> > +*  max_link_rate_kbps = DIV_ROUND_DOWN_ULL(max_link_rate_kbps * 8, 
> > 10);
> > +*  max_link_rate = max_link_rate_kbps / 8;
> > +*/
> 
> Not sure why we are repeating the nuts and bolts detils in the
> comments so much? Doesn't drm_dp_bw_channel_coding_efficiency()
> explain all this already?

I simply copied the function, but yes in this context there is
duplication, thanks for reading through all that. Will consolidate both
the above and the bigger comment b

[PATCH 19/19] drm/i915/dp: Enable DP tunnel BW allocation mode

2024-01-23 Thread Imre Deak
Detect DP tunnels and enable the BW allocation mode on them. Send a
hotplug notification to userspace in response to a BW change.

Signed-off-by: Imre Deak 
---
 .../drm/i915/display/intel_display_driver.c   | 20 +++
 drivers/gpu/drm/i915/display/intel_dp.c   | 14 +++--
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c 
b/drivers/gpu/drm/i915/display/intel_display_driver.c
index ecf9cb74734b6..62987b8427f7b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -35,6 +35,7 @@
 #include "intel_dkl_phy.h"
 #include "intel_dmc.h"
 #include "intel_dp.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpll.h"
 #include "intel_dpll_mgr.h"
 #include "intel_fb.h"
@@ -435,10 +436,8 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
 
for_each_pipe(i915, pipe) {
ret = intel_crtc_init(i915, pipe);
-   if (ret) {
-   intel_mode_config_cleanup(i915);
-   return ret;
-   }
+   if (ret)
+   goto err_mode_config;
}
 
intel_plane_possible_crtcs_init(i915);
@@ -460,6 +459,10 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
intel_vga_disable(i915);
intel_setup_outputs(i915);
 
+   ret = intel_dp_tunnel_mgr_init(i915);
+   if (ret)
+   goto err_hdcp;
+
intel_display_driver_disable_user_access(i915);
 
drm_modeset_lock_all(dev);
@@ -482,6 +485,13 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
ilk_wm_sanitize(i915);
 
return 0;
+
+err_hdcp:
+   intel_hdcp_component_fini(i915);
+err_mode_config:
+   intel_mode_config_cleanup(i915);
+
+   return ret;
 }
 
 /* part #3: call after gem init */
@@ -598,6 +608,8 @@ void intel_display_driver_remove_noirq(struct 
drm_i915_private *i915)
 
intel_mode_config_cleanup(i915);
 
+   intel_dp_tunnel_mgr_cleanup(i915);
+
intel_overlay_cleanup(i915);
 
intel_gmbus_teardown(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index bc138a54f8d7b..6133266d78276 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5752,6 +5752,7 @@ intel_dp_detect(struct drm_connector *connector,
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = _port->base;
enum drm_connector_status status;
+   int ret;
 
drm_dbg_kms(_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
@@ -5787,9 +5788,18 @@ intel_dp_detect(struct drm_connector *connector,
intel_dp->is_mst);
}
 
+   intel_dp_tunnel_disconnect(intel_dp);
+
goto out;
}
 
+   ret = intel_dp_tunnel_detect(intel_dp, ctx);
+   if (ret == -EDEADLK)
+   return ret;
+
+   if (ret == 1)
+   intel_connector->base.epoch_counter++;
+
intel_dp_detect_dsc_caps(intel_dp, intel_connector);
 
intel_dp_configure_mst(intel_dp);
@@ -5820,8 +5830,6 @@ intel_dp_detect(struct drm_connector *connector,
 * with an IRQ_HPD, so force a link status check.
 */
if (!intel_dp_is_edp(intel_dp)) {
-   int ret;
-
ret = intel_dp_retrain_link(encoder, ctx);
if (ret)
return ret;
@@ -5961,6 +5969,8 @@ void intel_dp_encoder_flush_work(struct drm_encoder 
*encoder)
 
intel_dp_mst_encoder_cleanup(dig_port);
 
+   intel_dp_tunnel_destroy(intel_dp);
+
intel_pps_vdd_off_sync(intel_dp);
 
/*
-- 
2.39.2



[PATCH 16/19] drm/i915/dp: Handle DP tunnel IRQs

2024-01-23 Thread Imre Deak
Handle DP tunnel IRQs a sink (or rather a BW management component like
the Thunderbolt Connection Manager) raises to signal the completion of a
BW request by the driver, or to signal any state change related to the
link BW.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 37 +++--
 include/drm/display/drm_dp.h|  1 +
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 6968fdb7ffcdf..8ebfb039000f6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4911,13 +4911,15 @@ static bool intel_dp_mst_link_status(struct intel_dp 
*intel_dp)
  * - %true if pending interrupts were serviced (or no interrupts were
  *   pending) w/o detecting an error condition.
  * - %false if an error condition - like AUX failure or a loss of link - is
- *   detected, which needs servicing from the hotplug work.
+ *   detected, or another condition - like a DP tunnel BW state change - needs
+ *   servicing from the hotplug work.
  */
 static bool
 intel_dp_check_mst_status(struct intel_dp *intel_dp)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
bool link_ok = true;
+   bool reprobe_needed = false;
 
drm_WARN_ON_ONCE(>drm, intel_dp->active_mst_links < 0);
 
@@ -4944,6 +4946,13 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 
intel_dp_mst_hpd_irq(intel_dp, esi, ack);
 
+   if (esi[3] & DP_TUNNELING_IRQ) {
+   if 
(drm_dp_tunnel_handle_irq(i915->display.dp_tunnel_mgr,
+_dp->aux))
+   reprobe_needed = true;
+   ack[3] |= DP_TUNNELING_IRQ;
+   }
+
if (!memchr_inv(ack, 0, sizeof(ack)))
break;
 
@@ -4954,7 +4963,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
drm_dp_mst_hpd_irq_send_new_request(_dp->mst_mgr);
}
 
-   return link_ok;
+   return link_ok && !reprobe_needed;
 }
 
 static void
@@ -5330,23 +5339,32 @@ static void intel_dp_check_device_service_irq(struct 
intel_dp *intel_dp)
drm_dbg_kms(>drm, "Sink specific irq unhandled\n");
 }
 
-static void intel_dp_check_link_service_irq(struct intel_dp *intel_dp)
+static bool intel_dp_check_link_service_irq(struct intel_dp *intel_dp)
 {
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   bool reprobe_needed = false;
u8 val;
 
if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
-   return;
+   return false;
 
if (drm_dp_dpcd_readb(_dp->aux,
  DP_LINK_SERVICE_IRQ_VECTOR_ESI0, ) != 1 || 
!val)
-   return;
+   return false;
+
+   if ((val & DP_TUNNELING_IRQ) &&
+   drm_dp_tunnel_handle_irq(i915->display.dp_tunnel_mgr,
+_dp->aux))
+   reprobe_needed = true;
 
if (drm_dp_dpcd_writeb(_dp->aux,
   DP_LINK_SERVICE_IRQ_VECTOR_ESI0, val) != 1)
-   return;
+   return reprobe_needed;
 
if (val & HDMI_LINK_STATUS_CHANGED)
intel_dp_handle_hdmi_link_status_change(intel_dp);
+
+   return reprobe_needed;
 }
 
 /*
@@ -5367,6 +5385,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 old_sink_count = intel_dp->sink_count;
+   bool reprobe_needed = false;
bool ret;
 
/*
@@ -5389,7 +5408,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
}
 
intel_dp_check_device_service_irq(intel_dp);
-   intel_dp_check_link_service_irq(intel_dp);
+   reprobe_needed = intel_dp_check_link_service_irq(intel_dp);
 
/* Handle CEC interrupts, if any */
drm_dp_cec_irq(_dp->aux);
@@ -5416,10 +5435,10 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 * FIXME get rid of the ad-hoc phy test modeset code
 * and properly incorporate it into the normal modeset.
 */
-   return false;
+   reprobe_needed = true;
}
 
-   return true;
+   return !reprobe_needed;
 }
 
 /* XXX this is probably wrong for multiple downstream ports */
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 8bfd5d007be8d..4891bd916d26a 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -1081,6 +1081,7 @@
 # define STREAM_STATUS_CHANGED   (1 << 2)
 # define HDMI_LINK_STATUS_CHANGED(1 << 3)
 # define CONNECTED_OFF_ENTRY_REQUESTED   (1 << 4)
+# define DP_TUNNELING_IRQ(1 <&l

[PATCH 18/19] drm/i915/dp: Suspend/resume DP tunnels

2024-01-23 Thread Imre Deak
Suspend and resume DP tunnels during system suspend/resume, disabling
the BW allocation mode during suspend, re-enabling it after resume. This
reflects the link's BW management component (Thunderbolt CM) disabling
BWA during suspend. Before any BW requests the driver must read the
sink's DPRX capabilities (since the BW manager requires this
information, so snoops for it on AUX), so ensure this read takes place.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 8ebfb039000f6..bc138a54f8d7b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -36,6 +36,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3320,18 +3321,21 @@ void intel_dp_sync_state(struct intel_encoder *encoder,
 const struct intel_crtc_state *crtc_state)
 {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-   if (!crtc_state)
-   return;
+   bool dpcd_updated = false;
 
/*
 * Don't clobber DPCD if it's been already read out during output
 * setup (eDP) or detect.
 */
-   if (intel_dp->dpcd[DP_DPCD_REV] == 0)
+   if (crtc_state && intel_dp->dpcd[DP_DPCD_REV] == 0) {
intel_dp_get_dpcd(intel_dp);
+   dpcd_updated = true;
+   }
 
-   intel_dp_reset_max_link_params(intel_dp);
+   intel_dp_tunnel_resume(intel_dp, dpcd_updated);
+
+   if (crtc_state)
+   intel_dp_reset_max_link_params(intel_dp);
 }
 
 bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
@@ -5973,6 +5977,8 @@ void intel_dp_encoder_suspend(struct intel_encoder 
*intel_encoder)
struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
 
intel_pps_vdd_off_sync(intel_dp);
+
+   intel_dp_tunnel_suspend(intel_dp);
 }
 
 void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
-- 
2.39.2



[PATCH 13/19] drm/i915/dp: Account for tunnel BW limit in intel_dp_max_link_data_rate()

2024-01-23 Thread Imre Deak
Take any link BW limitation into account in
intel_dp_max_link_data_rate(). Such a limitation can be due to multiple
displays on (Thunderbolt) links with DP tunnels sharing the link BW.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 32 +
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 323475569ee7f..78dfe8be6031d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -63,6 +63,7 @@
 #include "intel_dp_hdcp.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_dpll.h"
 #include "intel_fifo_underrun.h"
@@ -152,6 +153,22 @@ int intel_dp_link_symbol_clock(int rate)
return DIV_ROUND_CLOSEST(rate * 10, intel_dp_link_symbol_size(rate));
 }
 
+static int max_dprx_rate(struct intel_dp *intel_dp)
+{
+   if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
+   return drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel);
+
+   return drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+}
+
+static int max_dprx_lane_count(struct intel_dp *intel_dp)
+{
+   if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
+   return drm_dp_tunnel_max_dprx_lane_count(intel_dp->tunnel);
+
+   return drm_dp_max_lane_count(intel_dp->dpcd);
+}
+
 static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
 {
intel_dp->sink_rates[0] = 162000;
@@ -180,7 +197,7 @@ static void intel_dp_set_dpcd_sink_rates(struct intel_dp 
*intel_dp)
/*
 * Sink rates for 8b/10b.
 */
-   max_rate = 
drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+   max_rate = max_dprx_rate(intel_dp);
max_lttpr_rate = 
drm_dp_lttpr_max_link_rate(intel_dp->lttpr_common_caps);
if (max_lttpr_rate)
max_rate = min(max_rate, max_lttpr_rate);
@@ -259,7 +276,7 @@ static void intel_dp_set_max_sink_lane_count(struct 
intel_dp *intel_dp)
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = _dig_port->base;
 
-   intel_dp->max_sink_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+   intel_dp->max_sink_lane_count = max_dprx_lane_count(intel_dp);
 
switch (intel_dp->max_sink_lane_count) {
case 1:
@@ -389,14 +406,21 @@ int intel_dp_effective_data_rate(int pixel_clock, int 
bpp_x16,
  * @max_dprx_rate: Maximum data rate of the DPRX
  * @max_dprx_lanes: Maximum lane count of the DPRX
  *
- * Calculate the maximum data rate for the provided link parameters.
+ * Calculate the maximum data rate for the provided link parameters taking into
+ * account any BW limitations by a DP tunnel attached to @intel_dp.
  *
  * Returns the maximum data rate in kBps units.
  */
 int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
int max_dprx_rate, int max_dprx_lanes)
 {
-   return drm_dp_max_dprx_data_rate(max_dprx_rate, max_dprx_lanes);
+   int max_rate = drm_dp_max_dprx_data_rate(max_dprx_rate, max_dprx_lanes);
+
+   if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
+   max_rate = min(max_rate,
+  drm_dp_tunnel_available_bw(intel_dp->tunnel));
+
+   return max_rate;
 }
 
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
-- 
2.39.2



[PATCH 12/19] drm/i915/dp: Add DP tunnel atomic state and check BW limit

2024-01-23 Thread Imre Deak
Add the atomic state during a modeset required to enable the DP tunnel
BW allocation mode on links where such a tunnel was detected.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_atomic.c  |  8 
 drivers/gpu/drm/i915/display/intel_display.c | 19 +++
 drivers/gpu/drm/i915/display/intel_link_bw.c |  5 +
 3 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 96ab37e158995..4236740ede9ed 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -260,6 +260,10 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
if (crtc_state->post_csc_lut)
drm_property_blob_get(crtc_state->post_csc_lut);
 
+   if (crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_get(old_crtc_state->dp_tunnel_ref.tunnel,
+   _state->dp_tunnel_ref);
+
crtc_state->update_pipe = false;
crtc_state->update_m_n = false;
crtc_state->update_lrr = false;
@@ -311,6 +315,8 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
 
__drm_atomic_helper_crtc_destroy_state(_state->uapi);
intel_crtc_free_hw_state(crtc_state);
+   if (crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_put(_state->dp_tunnel_ref);
kfree(crtc_state);
 }
 
@@ -346,6 +352,8 @@ void intel_atomic_state_clear(struct drm_atomic_state *s)
/* state->internal not reset on purpose */
 
state->dpll_set = state->modeset = false;
+
+   intel_dp_tunnel_atomic_cleanup_inherited_state(state);
 }
 
 struct intel_crtc_state *
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index b9f985a5e705b..46b27a32c8640 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -33,6 +33,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -73,6 +74,7 @@
 #include "intel_dp.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpll.h"
 #include "intel_dpll_mgr.h"
 #include "intel_dpt.h"
@@ -4490,6 +4492,8 @@ copy_bigjoiner_crtc_state_modeset(struct 
intel_atomic_state *state,
saved_state->crc_enabled = slave_crtc_state->crc_enabled;
 
intel_crtc_free_hw_state(slave_crtc_state);
+   if (slave_crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_put(_crtc_state->dp_tunnel_ref);
memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state));
kfree(saved_state);
 
@@ -4505,6 +4509,10 @@ copy_bigjoiner_crtc_state_modeset(struct 
intel_atomic_state *state,
  _crtc_state->hw.adjusted_mode);
slave_crtc_state->hw.scaling_filter = 
master_crtc_state->hw.scaling_filter;
 
+   if (master_crtc_state->dp_tunnel_ref.tunnel)
+   drm_dp_tunnel_ref_get(master_crtc_state->dp_tunnel_ref.tunnel,
+   _crtc_state->dp_tunnel_ref);
+
copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc);
 
slave_crtc_state->uapi.mode_changed = 
master_crtc_state->uapi.mode_changed;
@@ -4533,6 +4541,13 @@ intel_crtc_prepare_cleared_state(struct 
intel_atomic_state *state,
/* free the old crtc_state->hw members */
intel_crtc_free_hw_state(crtc_state);
 
+   if (crtc_state->dp_tunnel_ref.tunnel) {
+   drm_dp_tunnel_atomic_set_stream_bw(>base,
+  
crtc_state->dp_tunnel_ref.tunnel,
+  crtc->pipe, 0);
+   drm_dp_tunnel_ref_put(_state->dp_tunnel_ref);
+   }
+
/* FIXME: before the switch to atomic started, a new pipe_config was
 * kzalloc'd. Code that depends on any field being zero should be
 * fixed, so that the crtc_state can be safely duplicated. For now,
@@ -5374,6 +5389,10 @@ static int intel_modeset_pipe(struct intel_atomic_state 
*state,
if (ret)
return ret;
 
+   ret = intel_dp_tunnel_atomic_add_state_for_crtc(state, crtc);
+   if (ret)
+   return ret;
+
ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c 
b/drivers/gpu/drm/i915/display/intel_link_bw.c
index 9c6d35a405a18..5b539ba996ddf 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -8,6 +8,7 @@
 #include "intel_atomic.h"
 #include "intel_display_types.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h&q

[PATCH 15/19] drm/i915/dp: Allocate/free DP tunnel BW in the encoder enable/disable hooks

2024-01-23 Thread Imre Deak
Allocate and free the DP tunnel BW required by a stream while
enabling/disabling the stream during a modeset.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/g4x_dp.c| 28 
 drivers/gpu/drm/i915/display/intel_ddi.c |  7 ++
 2 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c 
b/drivers/gpu/drm/i915/display/g4x_dp.c
index dfe0b07a122d1..1e498e1510adf 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -19,6 +19,7 @@
 #include "intel_dp.h"
 #include "intel_dp_aux.h"
 #include "intel_dp_link_training.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_fifo_underrun.h"
 #include "intel_hdmi.h"
@@ -729,6 +730,24 @@ static void vlv_enable_dp(struct intel_atomic_state *state,
encoder->audio_enable(encoder, pipe_config, conn_state);
 }
 
+static void g4x_dp_pre_pll_enable(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *new_crtc_state,
+ const struct drm_connector_state 
*new_conn_state)
+{
+   intel_dp_tunnel_atomic_alloc_bw(state, encoder,
+   new_crtc_state, new_conn_state);
+}
+
+static void g4x_dp_post_pll_disable(struct intel_atomic_state *state,
+   struct intel_encoder *encoder,
+   const struct intel_crtc_state 
*old_crtc_state,
+   const struct drm_connector_state 
*old_conn_state)
+{
+   intel_dp_tunnel_atomic_free_bw(state, encoder,
+  old_crtc_state, old_conn_state);
+}
+
 static void g4x_pre_enable_dp(struct intel_atomic_state *state,
  struct intel_encoder *encoder,
  const struct intel_crtc_state *pipe_config,
@@ -762,6 +781,8 @@ static void vlv_dp_pre_pll_enable(struct intel_atomic_state 
*state,
intel_dp_prepare(encoder, pipe_config);
 
vlv_phy_pre_pll_enable(encoder, pipe_config);
+
+   g4x_dp_pre_pll_enable(state, encoder, pipe_config, conn_state);
 }
 
 static void chv_pre_enable_dp(struct intel_atomic_state *state,
@@ -785,6 +806,8 @@ static void chv_dp_pre_pll_enable(struct intel_atomic_state 
*state,
intel_dp_prepare(encoder, pipe_config);
 
chv_phy_pre_pll_enable(encoder, pipe_config);
+
+   g4x_dp_pre_pll_enable(state, encoder, pipe_config, conn_state);
 }
 
 static void chv_dp_post_pll_disable(struct intel_atomic_state *state,
@@ -792,6 +815,8 @@ static void chv_dp_post_pll_disable(struct 
intel_atomic_state *state,
const struct intel_crtc_state 
*old_crtc_state,
const struct drm_connector_state 
*old_conn_state)
 {
+   g4x_dp_post_pll_disable(state, encoder, old_crtc_state, old_conn_state);
+
chv_phy_post_pll_disable(encoder, old_crtc_state);
 }
 
@@ -1349,11 +1374,14 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
intel_encoder->enable = vlv_enable_dp;
intel_encoder->disable = vlv_disable_dp;
intel_encoder->post_disable = vlv_post_disable_dp;
+   intel_encoder->post_pll_disable = g4x_dp_post_pll_disable;
} else {
+   intel_encoder->pre_pll_enable = g4x_dp_pre_pll_enable;
intel_encoder->pre_enable = g4x_pre_enable_dp;
intel_encoder->enable = g4x_enable_dp;
intel_encoder->disable = g4x_disable_dp;
intel_encoder->post_disable = g4x_post_disable_dp;
+   intel_encoder->post_pll_disable = g4x_dp_post_pll_disable;
}
intel_encoder->audio_enable = g4x_dp_audio_enable;
intel_encoder->audio_disable = g4x_dp_audio_disable;
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 922194b957be2..aa6e7da08fbce 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -54,6 +54,7 @@
 #include "intel_dp_aux.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_dsi.h"
 #include "intel_fdi.h"
@@ -3141,6 +3142,9 @@ static void intel_ddi_post_pll_disable(struct 
intel_atomic_state *state,
 
main_link_aux_power_domain_put(dig_port, old_crtc_state);
 
+   intel_dp_tunnel_atomic_free_bw(state, encoder,
+  old_crtc_state, old_conn_state);
+
if (is_tc_port)
intel_tc_port_put_link(dig_port);
 }
@@ -3480,6 +3484,9 @@ intel_ddi_pre_pll_ena

[PATCH 17/19] drm/i915/dp: Call intel_dp_sync_state() always for DDI DP encoders

2024-01-23 Thread Imre Deak
A follow-up change will need to resume DP tunnels during system resume,
so call intel_dp_sync_state() always for DDI encoders, so this function
can resume the tunnels for all DP connectors.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index aa6e7da08fbce..1e26e62b82d48 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4131,7 +4131,7 @@ static void intel_ddi_sync_state(struct intel_encoder 
*encoder,
intel_tc_port_sanitize_mode(enc_to_dig_port(encoder),
crtc_state);
 
-   if (crtc_state && intel_crtc_has_dp_encoder(crtc_state))
+   if (intel_encoder_is_dp(encoder))
intel_dp_sync_state(encoder, crtc_state);
 }
 
-- 
2.39.2



[PATCH 09/19] drm/i915/dp: Add intel_dp_max_link_data_rate()

2024-01-23 Thread Imre Deak
Add intel_dp_max_link_data_rate() to get the link BW vs. the sink DPRX
BW used by a follow-up patch enabling the DP tunnel BW allocation mode.
The link BW can be below the DPRX BW due to a BW limitation on a link
shared by multiple sinks.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 32 +
 drivers/gpu/drm/i915/display/intel_dp.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c |  3 +-
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 23434d0aba188..9cd675c6d0ee8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -383,6 +383,22 @@ int intel_dp_effective_data_rate(int pixel_clock, int 
bpp_x16,
100 * 16 * 8);
 }
 
+/**
+ * intel_dp_max_link_data_rate: Calculate the maximum rate for the given link 
params
+ * @intel_dp: Intel DP object
+ * @max_dprx_rate: Maximum data rate of the DPRX
+ * @max_dprx_lanes: Maximum lane count of the DPRX
+ *
+ * Calculate the maximum data rate for the provided link parameters.
+ *
+ * Returns the maximum data rate in kBps units.
+ */
+int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
+   int max_dprx_rate, int max_dprx_lanes)
+{
+   return drm_dp_max_dprx_data_rate(max_dprx_rate, max_dprx_lanes);
+}
+
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
 {
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -612,7 +628,7 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct 
intel_dp *intel_dp,
int mode_rate, max_rate;
 
mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
-   max_rate = drm_dp_max_dprx_data_rate(link_rate, lane_count);
+   max_rate = intel_dp_max_link_data_rate(intel_dp, link_rate, lane_count);
if (mode_rate > max_rate)
return false;
 
@@ -1214,7 +1230,8 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
 
-   max_rate = drm_dp_max_dprx_data_rate(max_link_clock, max_lanes);
+   max_rate = intel_dp_max_link_data_rate(intel_dp, max_link_clock, 
max_lanes);
+
mode_rate = intel_dp_link_required(target_clock,
   
intel_dp_mode_min_output_bpp(connector, mode));
 
@@ -1564,8 +1581,10 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
for (lane_count = limits->min_lane_count;
 lane_count <= limits->max_lane_count;
 lane_count <<= 1) {
-   link_avail = 
drm_dp_max_dprx_data_rate(link_rate,
-  
lane_count);
+   link_avail = 
intel_dp_max_link_data_rate(intel_dp,
+
link_rate,
+
lane_count);
+
 
if (mode_rate <= link_avail) {
pipe_config->lane_count = lane_count;
@@ -2422,8 +2441,9 @@ intel_dp_compute_link_config(struct intel_encoder 
*encoder,
pipe_config->pipe_bpp,
BPP_X16_ARGS(pipe_config->dsc.compressed_bpp_x16),
intel_dp_config_required_rate(pipe_config),
-   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
- pipe_config->lane_count));
+   intel_dp_max_link_data_rate(intel_dp,
+   pipe_config->port_clock,
+   pipe_config->lane_count));
 
return 0;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 49553e43add22..8b0dfbf06afff 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -117,6 +117,8 @@ bool intel_dp_get_colorimetry_status(struct intel_dp 
*intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
 int bw_overhead);
+int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
+   int max_dprx_rate, int max_dprx_lanes);
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp);
 bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index cfcc157b7d41d..520393dc8b453 100644
--- a/driv

[PATCH 07/19] drm/i915/dp: Factor out intel_dp_update_sink_caps()

2024-01-23 Thread Imre Deak
Factor out a function updating the sink's link rate and lane count
capabilities, used by a follow-up patch enabling the DP tunnel BW
allocation mode.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 11 ---
 drivers/gpu/drm/i915/display/intel_dp.h |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f40706c5d1aad..23434d0aba188 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3949,6 +3949,13 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp)
  _dp->desc);
 }
 
+void intel_dp_update_sink_caps(struct intel_dp *intel_dp)
+{
+   intel_dp_set_sink_rates(intel_dp);
+   intel_dp_set_max_sink_lane_count(intel_dp);
+   intel_dp_set_common_rates(intel_dp);
+}
+
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
@@ -3965,9 +3972,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
drm_dp_read_desc(_dp->aux, _dp->desc,
 drm_dp_is_branch(intel_dp->dpcd));
 
-   intel_dp_set_sink_rates(intel_dp);
-   intel_dp_set_max_sink_lane_count(intel_dp);
-   intel_dp_set_common_rates(intel_dp);
+   intel_dp_update_sink_caps(intel_dp);
}
 
if (intel_dp_has_sink_count(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index a7906d8738c4a..49553e43add22 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -106,6 +106,7 @@ int intel_dp_config_required_rate(const struct 
intel_crtc_state *crtc_state);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 int intel_dp_max_common_rate(struct intel_dp *intel_dp);
 int intel_dp_max_common_lane_count(struct intel_dp *intel_dp);
+void intel_dp_update_sink_caps(struct intel_dp *intel_dp);
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
   u8 *link_bw, u8 *rate_select);
-- 
2.39.2



[PATCH 14/19] drm/i915/dp: Compute DP tunel BW during encoder state computation

2024-01-23 Thread Imre Deak
Compute the BW required through a DP tunnel on links with such tunnels
detected and add the corresponding atomic state during a modeset.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 16 +---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 78dfe8be6031d..6968fdb7ffcdf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2880,6 +2880,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_atomic_state *state = 
to_intel_atomic_state(conn_state->state);
struct drm_display_mode *adjusted_mode = _config->hw.adjusted_mode;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
const struct drm_display_mode *fixed_mode;
@@ -2980,6 +2981,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, 
conn_state);
 
+   intel_dp_tunnel_atomic_compute_stream_bw(state, intel_dp, connector,
+pipe_config);
+
return 0;
 }
 
@@ -6087,6 +6091,15 @@ static int intel_dp_connector_atomic_check(struct 
drm_connector *conn,
return ret;
}
 
+   if (!intel_connector_needs_modeset(state, conn))
+   return 0;
+
+   ret = intel_dp_tunnel_atomic_check_state(state,
+intel_dp,
+intel_conn);
+   if (ret)
+   return ret;
+
/*
 * We don't enable port sync on BDW due to missing w/as and
 * due to not having adjusted the modeset sequence appropriately.
@@ -6094,9 +6107,6 @@ static int intel_dp_connector_atomic_check(struct 
drm_connector *conn,
if (DISPLAY_VER(dev_priv) < 9)
return 0;
 
-   if (!intel_connector_needs_modeset(state, conn))
-   return 0;
-
if (conn->has_tile) {
ret = intel_modeset_tile_group(state, conn->tile_group->id);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 520393dc8b453..cbfab3173b9ef 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -42,6 +42,7 @@
 #include "intel_dp.h"
 #include "intel_dp_hdcp.h"
 #include "intel_dp_mst.h"
+#include "intel_dp_tunnel.h"
 #include "intel_dpio_phy.h"
 #include "intel_hdcp.h"
 #include "intel_hotplug.h"
@@ -523,6 +524,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder 
*encoder,
   struct drm_connector_state *conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_atomic_state *state = 
to_intel_atomic_state(conn_state->state);
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
struct intel_dp *intel_dp = _mst->primary->dp;
const struct intel_connector *connector =
@@ -619,6 +621,9 @@ static int intel_dp_mst_compute_config(struct intel_encoder 
*encoder,
 
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
 
+   intel_dp_tunnel_atomic_compute_stream_bw(state, intel_dp, connector,
+pipe_config);
+
return 0;
 }
 
@@ -876,6 +881,14 @@ intel_dp_mst_atomic_check(struct drm_connector *connector,
if (ret)
return ret;
 
+   if (intel_connector_needs_modeset(state, connector)) {
+   ret = intel_dp_tunnel_atomic_check_state(state,
+
intel_connector->mst_port,
+intel_connector);
+   if (ret)
+   return ret;
+   }
+
return drm_dp_atomic_release_time_slots(>base,

_connector->mst_port->mst_mgr,
intel_connector->port);
-- 
2.39.2



[PATCH 10/19] drm/i915/dp: Add way to get active pipes with syncing commits

2024-01-23 Thread Imre Deak
Add a way to get the active pipes through a given DP port by syncing
against a related pending non-blocking commit. Atm
intel_dp_get_active_pipes() will only try to sync a given pipe and if
that would block ignore the pipe. A follow-up change enabling the DP
tunnel BW allocation mode will need to ensure that all active pipes are
returned.

A follow-up patchset will add a no-sync mode as well, needed by the
current intel_tc_port_link_reset() user of it, which atm incorrectly
ignores active pipes for which the syncing would block (but otherwise
doesn't require an actual syncing).

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 25 +
 drivers/gpu/drm/i915/display/intel_dp.h |  6 ++
 drivers/gpu/drm/i915/display/intel_tc.c |  4 +++-
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 9cd675c6d0ee8..323475569ee7f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5019,6 +5019,7 @@ static bool intel_dp_has_connector(struct intel_dp 
*intel_dp,
 
 int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
  struct drm_modeset_acquire_ctx *ctx,
+ enum intel_dp_get_pipes_mode mode,
  u8 *pipe_mask)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -5053,9 +5054,23 @@ int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
if (!crtc_state->hw.active)
continue;
 
-   if (conn_state->commit &&
-   !try_wait_for_completion(_state->commit->hw_done))
-   continue;
+   if (conn_state->commit) {
+   bool synced;
+
+   switch (mode) {
+   case INTEL_DP_GET_PIPES_TRY_SYNC:
+   if 
(!try_wait_for_completion(_state->commit->hw_done))
+   continue;
+   break;
+   case INTEL_DP_GET_PIPES_SYNC:
+   synced = 
wait_for_completion_timeout(_state->commit->hw_done,
+
msecs_to_jiffies(5000));
+   drm_WARN_ON(>drm, !synced);
+   break;
+   default:
+   MISSING_CASE(mode);
+   }
+   }
 
*pipe_mask |= BIT(crtc->pipe);
}
@@ -5092,7 +5107,9 @@ int intel_dp_retrain_link(struct intel_encoder *encoder,
if (!intel_dp_needs_link_retrain(intel_dp))
return 0;
 
-   ret = intel_dp_get_active_pipes(intel_dp, ctx, _mask);
+   ret = intel_dp_get_active_pipes(intel_dp, ctx,
+   INTEL_DP_GET_PIPES_TRY_SYNC,
+   _mask);
if (ret)
return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 8b0dfbf06afff..1a7b87787dfa9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -25,6 +25,11 @@ struct intel_encoder;
 
 struct work_struct;
 
+enum intel_dp_get_pipes_mode {
+   INTEL_DP_GET_PIPES_TRY_SYNC,
+   INTEL_DP_GET_PIPES_SYNC,
+};
+
 struct link_config_limits {
int min_rate, max_rate;
int min_lane_count, max_lane_count;
@@ -59,6 +64,7 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp 
*intel_dp,
int link_rate, u8 lane_count);
 int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
  struct drm_modeset_acquire_ctx *ctx,
+ enum intel_dp_get_pipes_mode mode,
  u8 *pipe_mask);
 int intel_dp_retrain_link(struct intel_encoder *encoder,
  struct drm_modeset_acquire_ctx *ctx);
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f34743e6eeed2..561d6f97ff189 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -1655,7 +1655,9 @@ static int reset_link_commit(struct intel_tc_port *tc,
if (ret)
return ret;
 
-   ret = intel_dp_get_active_pipes(intel_dp, ctx, _mask);
+   ret = intel_dp_get_active_pipes(intel_dp, ctx,
+   INTEL_DP_GET_PIPES_TRY_SYNC,
+   _mask);
if (ret)
return ret;
 
-- 
2.39.2



[PATCH 11/19] drm/i915/dp: Add support for DP tunnel BW allocation

2024-01-23 Thread Imre Deak
Add support to enable the DP tunnel BW allocation mode. Follow-up
patches will call the required helpers added here to prepare for a
modeset on a link with DP tunnels, the last change in the patchset
actually enabling BWA.

With BWA enabled, the driver will expose the full mode list a display
supports, regardless of any BW limitation on a shared (Thunderbolt)
link. Such BW limits will be checked against only during a modeset, when
the driver has the full knowledge of each display's BW requirement.

If the link BW changes in a way that a connector's modelist may also
change, userspace will get a hotplug notification for all the connectors
sharing the same link (so it can adjust the mode used for a display).

The BW limitation can change at any point, asynchronously to modesets
on a given connector, so a modeset can fail even though the atomic check
for it passed. In such scenarios userspace will get a bad link
notification and in response is supposed to retry the modeset.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/Kconfig  |  13 +
 drivers/gpu/drm/i915/Kconfig.debug|   1 +
 drivers/gpu/drm/i915/Makefile |   3 +
 drivers/gpu/drm/i915/display/intel_atomic.c   |   2 +
 .../gpu/drm/i915/display/intel_display_core.h |   1 +
 .../drm/i915/display/intel_display_types.h|   9 +
 .../gpu/drm/i915/display/intel_dp_tunnel.c| 642 ++
 .../gpu/drm/i915/display/intel_dp_tunnel.h| 131 
 8 files changed, 802 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.h

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index b5d6e3352071f..4636913c17868 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -155,6 +155,19 @@ config DRM_I915_PXP
  protected session and manage the status of the alive software session,
  as well as its life cycle.
 
+config DRM_I915_DP_TUNNEL
+   bool "Enable DP tunnel support"
+   depends on DRM_I915
+   select DRM_DISPLAY_DP_TUNNEL
+   default y
+   help
+ Choose this option to detect DP tunnels and enable the Bandwidth
+ Allocation mode for such tunnels. This allows using the maximum
+ resolution allowed by the link BW on all displays sharing the
+ link BW, for instance on a Thunderbolt link.
+
+ If in doubt, say "Y".
+
 menu "drm/i915 Debugging"
 depends on DRM_I915
 depends on EXPERT
diff --git a/drivers/gpu/drm/i915/Kconfig.debug 
b/drivers/gpu/drm/i915/Kconfig.debug
index 5b7162076850c..bc18e2d9ea05d 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -28,6 +28,7 @@ config DRM_I915_DEBUG
select STACKDEPOT
select STACKTRACE
select DRM_DP_AUX_CHARDEV
+   select DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE if DRM_I915_DP_TUNNEL
select X86_MSR # used by igt/pm_rpm
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
select DRM_DEBUG_MM if DRM=y
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index c13f14edb5088..3ef6ed41e62b4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -369,6 +369,9 @@ i915-y += \
display/vlv_dsi.o \
display/vlv_dsi_pll.o
 
+i915-$(CONFIG_DRM_I915_DP_TUNNEL) += \
+   display/intel_dp_tunnel.o
+
 i915-y += \
i915_perf.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index ec0d5168b5035..96ab37e158995 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -29,6 +29,7 @@
  * See intel_atomic_plane.c for the plane-specific atomic functionality.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -38,6 +39,7 @@
 #include "intel_atomic.h"
 #include "intel_cdclk.h"
 #include "intel_display_types.h"
+#include "intel_dp_tunnel.h"
 #include "intel_global_state.h"
 #include "intel_hdcp.h"
 #include "intel_psr.h"
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h 
b/drivers/gpu/drm/i915/display/intel_display_core.h
index a90f1aa201be8..0993d25a0a686 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -522,6 +522,7 @@ struct intel_display {
} wq;
 
/* Grouping using named structs. Keep sorted. */
+   struct drm_dp_tunnel_mgr *dp_tunnel_mgr;
struct intel_audio audio;
struct intel_dpll dpll;
struct intel_fbc *fbc[I915_MAX_FBCS];
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index ae2e8cff9d691..b79db78b27728 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/dis

[PATCH 04/19] drm/i915/dp: Use drm_dp_max_dprx_data_rate()

2024-01-23 Thread Imre Deak
Instead of intel_dp_max_data_rate() use the equivalent
drm_dp_max_dprx_data_rate() which was copied from the former one in a
previous patch.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_display.c |  2 +-
 drivers/gpu/drm/i915/display/intel_dp.c  | 62 +++-
 drivers/gpu/drm/i915/display/intel_dp.h  |  1 -
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  2 +-
 4 files changed, 10 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 0caebbb3e2dbb..b9f985a5e705b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2478,7 +2478,7 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
u32 link_symbol_clock = intel_dp_link_symbol_clock(link_clock);
u32 data_m = intel_dp_effective_data_rate(pixel_clock, 
bits_per_pixel_x16,
  bw_overhead);
-   u32 data_n = intel_dp_max_data_rate(link_clock, nlanes);
+   u32 data_n = drm_dp_max_dprx_data_rate(link_clock, nlanes);
 
/*
 * Windows/BIOS uses fixed M/N values always. Follow suit.
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 4e36c2c39888e..c7b06a9b197cc 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -383,52 +383,6 @@ int intel_dp_effective_data_rate(int pixel_clock, int 
bpp_x16,
100 * 16 * 8);
 }
 
-/*
- * Given a link rate and lanes, get the data bandwidth.
- *
- * Data bandwidth is the actual payload rate, which depends on the data
- * bandwidth efficiency and the link rate.
- *
- * For 8b/10b channel encoding, SST and non-FEC, the data bandwidth efficiency
- * is 80%. For example, for a 1.62 Gbps link, 1.62*10^9 bps * 0.80 * (1/8) =
- * 162000 kBps. With 8-bit symbols, we have 162000 kHz symbol clock. Just by
- * coincidence, the port clock in kHz matches the data bandwidth in kBps, and
- * they equal the link bit rate in Gbps multiplied by 10. (Note that this 
no
- * longer holds for data bandwidth as soon as FEC or MST is taken into 
account!)
- *
- * For 128b/132b channel encoding, the data bandwidth efficiency is 96.71%. For
- * example, for a 10 Gbps link, 10*10^9 bps * 0.9671 * (1/8) = 1208875
- * kBps. With 32-bit symbols, we have 312500 kHz symbol clock. The value 
100
- * does not match the symbol clock, the port clock (not even if you think in
- * terms of a byte clock), nor the data bandwidth. It only matches the link bit
- * rate in units of 1 bps.
- */
-int
-intel_dp_max_data_rate(int max_link_rate, int max_lanes)
-{
-   int ch_coding_efficiency =
-   
drm_dp_bw_channel_coding_efficiency(drm_dp_is_uhbr_rate(max_link_rate));
-   int max_link_rate_kbps = max_link_rate * 10;
-
-   /*
-* UHBR rates always use 128b/132b channel encoding, and have
-* 97.71% data bandwidth efficiency. Consider max_link_rate the
-* link bit rate in units of 1 bps.
-*/
-   /*
-* Lower than UHBR rates always use 8b/10b channel encoding, and have
-* 80% data bandwidth efficiency for SST non-FEC. However, this turns
-* out to be a nop by coincidence:
-*
-*  int max_link_rate_kbps = max_link_rate * 10;
-*  max_link_rate_kbps = DIV_ROUND_DOWN_ULL(max_link_rate_kbps * 8, 
10);
-*  max_link_rate = max_link_rate_kbps / 8;
-*/
-   return DIV_ROUND_DOWN_ULL(mul_u32_u32(max_link_rate_kbps * max_lanes,
- ch_coding_efficiency),
- 100 * 8);
-}
-
 bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
 {
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -658,7 +612,7 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct 
intel_dp *intel_dp,
int mode_rate, max_rate;
 
mode_rate = intel_dp_link_required(fixed_mode->clock, 18);
-   max_rate = intel_dp_max_data_rate(link_rate, lane_count);
+   max_rate = drm_dp_max_dprx_data_rate(link_rate, lane_count);
if (mode_rate > max_rate)
return false;
 
@@ -1260,7 +1214,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
 
-   max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+   max_rate = drm_dp_max_dprx_data_rate(max_link_clock, max_lanes);
mode_rate = intel_dp_link_required(target_clock,
   
intel_dp_mode_min_output_bpp(connector, mode));
 
@@ -1610,8 +1564,8 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
for (lane_count = limits->min_l

[PATCH 02/19] drm/dp: Add support for DP tunneling

2024-01-23 Thread Imre Deak
Add support for Display Port DP tunneling. For now this includes the
support for Bandwidth Allocation Mode, leaving adding Panel Replay
support for later.

BWA allows using displays that share the same (Thunderbolt) link with
their maximum resolution. Atm, this may not be possible due to the
coarse granularity of partitioning the link BW among the displays on the
link: the BW allocation policy is in a SW/FW/HW component on the link
(on Thunderbolt it's the SW or FW Connection Manager), independent of
the driver. This policy will set the DPRX maximum rate and lane count
DPCD registers the GFX driver will see (0x0, 0x1, 0x02200,
0x02201) based on the available link BW.

The granularity of the current BW allocation policy is course, based on
the required link rate in the 1.62Gbs..8.1Gbps range and it may prevent
using higher resolutions all together: the display connected first will
get a share of the link BW which corresponds to its full DPRX capability
(regardless of the actual mode it uses). A subsequent display connected
will only get the remaining BW, which could be well below its full
capability.

BWA solves the above course granularity (reducing it to a 250Mbs..1Gps
range) and first-come/first-served issues by letting the driver request
the BW for each display on a link which reflects the actual modes the
displays use.

This patch adds the DRM core helper functions, while a follow-up change
in the patchset takes them into use in the i915 driver.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/Kconfig |   17 +
 drivers/gpu/drm/display/Makefile|2 +
 drivers/gpu/drm/display/drm_dp_tunnel.c | 1715 +++
 include/drm/display/drm_dp.h|   60 +
 include/drm/display/drm_dp_tunnel.h |  270 
 5 files changed, 2064 insertions(+)
 create mode 100644 drivers/gpu/drm/display/drm_dp_tunnel.c
 create mode 100644 include/drm/display/drm_dp_tunnel.h

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index 09712b88a5b83..b024a84b94c1c 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -17,6 +17,23 @@ config DRM_DISPLAY_DP_HELPER
help
  DRM display helpers for DisplayPort.
 
+config DRM_DISPLAY_DP_TUNNEL
+   bool
+   select DRM_DISPLAY_DP_HELPER
+   help
+ Enable support for DisplayPort tunnels.
+
+config DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE
+   bool "Enable debugging the DP tunnel state"
+   depends on REF_TRACKER
+   depends on DRM_DISPLAY_DP_TUNNEL
+   depends on DEBUG_KERNEL
+   depends on EXPERT
+   help
+ Enables debugging the DP tunnel manager's status.
+
+ If in doubt, say "N".
+
 config DRM_DISPLAY_HDCP_HELPER
bool
depends on DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 17ac4a1006a80..7ca61333c6696 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -8,6 +8,8 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \
drm_dp_helper.o \
drm_dp_mst_topology.o \
drm_dsc_helper.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_TUNNEL) += \
+   drm_dp_tunnel.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
 drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
drm_hdmi_helper.o \
diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c 
b/drivers/gpu/drm/display/drm_dp_tunnel.c
new file mode 100644
index 0..58f6330db7d9d
--- /dev/null
+++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
@@ -0,0 +1,1715 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define to_group(__private_obj) \
+   container_of(__private_obj, struct drm_dp_tunnel_group, base)
+
+#define to_group_state(__private_state) \
+   container_of(__private_state, struct drm_dp_tunnel_group_state, base)
+
+#define is_dp_tunnel_private_obj(__obj) \
+   ((__obj)->funcs == _group_funcs)
+
+#define for_each_new_group_in_state(__state, __new_group_state, __i) \
+   for ((__i) = 0; \
+(__i) < (__state)->num_private_objs; \
+(__i)++) \
+   for_each_if ((__state)->private_objs[__i].ptr && \
+
is_dp_tunnel_private_obj((__state)->private_objs[__i].ptr) && \
+((__new_group_state) = \
+   
to_group_state((__state)->private_objs[__i].new_state), 1))
+
+#define for_each_old_group_in_state(__state, __old_group_state, __i) \
+   for ((__i) = 0; \
+(__i) < (__state)->num_private_objs; \
+(__i)++) \
+   for_each_if ((__state)->private_objs[__i].ptr && \
+   

[PATCH 06/19] drm/i915/dp: Export intel_dp_max_common_rate/lane_count()

2024-01-23 Thread Imre Deak
Export intel_dp_max_common_rate() and intel_dp_max_lane_count() used by
a follow-up patch enabling the DP tunnel BW allocation mode.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 ++--
 drivers/gpu/drm/i915/display/intel_dp.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 0a5c60428ffb7..f40706c5d1aad 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -309,7 +309,7 @@ static int intel_dp_common_rate(struct intel_dp *intel_dp, 
int index)
 }
 
 /* Theoretical max between source and sink */
-static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
+int intel_dp_max_common_rate(struct intel_dp *intel_dp)
 {
return intel_dp_common_rate(intel_dp, intel_dp->num_common_rates - 1);
 }
@@ -326,7 +326,7 @@ static int intel_dp_max_source_lane_count(struct 
intel_digital_port *dig_port)
 }
 
 /* Theoretical max between source and sink */
-static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
+int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
 {
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
int source_max = intel_dp_max_source_lane_count(dig_port);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 37274e3c2902f..a7906d8738c4a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -104,6 +104,8 @@ int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 int intel_dp_max_lane_count(struct intel_dp *intel_dp);
 int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
+int intel_dp_max_common_rate(struct intel_dp *intel_dp);
+int intel_dp_max_common_lane_count(struct intel_dp *intel_dp);
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
   u8 *link_bw, u8 *rate_select);
-- 
2.39.2



[PATCH 08/19] drm/i915/dp: Factor out intel_dp_read_dprx_caps()

2024-01-23 Thread Imre Deak
Factor out a function to read the sink's DPRX capabilities used by a
follow-up patch enabling the DP tunnel BW allocation mode.

Signed-off-by: Imre Deak 
---
 .../drm/i915/display/intel_dp_link_training.c | 30 +++
 .../drm/i915/display/intel_dp_link_training.h |  1 +
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 7b140cbf8dd31..fb84ca98bb7ab 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -162,6 +162,28 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, 
const u8 dpcd[DP_RECEI
return lttpr_count;
 }
 
+int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 
dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+   if (intel_dp_is_edp(intel_dp))
+   return 0;
+
+   /*
+* Detecting LTTPRs must be avoided on platforms with an AUX timeout
+* period < 3.2ms. (see DP Standard v2.0, 2.11.2, 3.6.6.1).
+*/
+   if (DISPLAY_VER(i915) >= 10 && !IS_GEMINILAKE(i915))
+   if (drm_dp_dpcd_probe(_dp->aux,
+ 
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV))
+   return -EIO;
+
+   if (drm_dp_read_dpcd_caps(_dp->aux, dpcd))
+   return -EIO;
+
+   return 0;
+}
+
 /**
  * intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the 
LTTPR link training mode
  * @intel_dp: Intel DP struct
@@ -192,12 +214,10 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp 
*intel_dp)
if (!intel_dp_is_edp(intel_dp) &&
(DISPLAY_VER(i915) >= 10 && !IS_GEMINILAKE(i915))) {
u8 dpcd[DP_RECEIVER_CAP_SIZE];
+   int err = intel_dp_read_dprx_caps(intel_dp, dpcd);
 
-   if (drm_dp_dpcd_probe(_dp->aux, 
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV))
-   return -EIO;
-
-   if (drm_dp_read_dpcd_caps(_dp->aux, dpcd))
-   return -EIO;
+   if (err != 0)
+   return err;
 
lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
index 2c8f2775891b0..19836a8a4f904 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
@@ -11,6 +11,7 @@
 struct intel_crtc_state;
 struct intel_dp;
 
+int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 
dpcd[DP_RECEIVER_CAP_SIZE]);
 int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp);
 
 void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
-- 
2.39.2



[PATCH 05/19] drm/i915/dp: Factor out intel_dp_config_required_rate()

2024-01-23 Thread Imre Deak
Factor out intel_dp_config_required_rate() used by a follow-up patch
enabling the DP tunnel BW allocation mode.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 43 +++--
 drivers/gpu/drm/i915/display/intel_dp.h |  1 +
 2 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index c7b06a9b197cc..0a5c60428ffb7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2338,6 +2338,17 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
   limits);
 }
 
+int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
+{
+   const struct drm_display_mode *adjusted_mode =
+   _state->hw.adjusted_mode;
+   int bpp = crtc_state->dsc.compression_enable ?
+   to_bpp_int_roundup(crtc_state->dsc.compressed_bpp_x16) :
+   crtc_state->pipe_bpp;
+
+   return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
+}
+
 static int
 intel_dp_compute_link_config(struct intel_encoder *encoder,
 struct intel_crtc_state *pipe_config,
@@ -2405,31 +2416,15 @@ intel_dp_compute_link_config(struct intel_encoder 
*encoder,
return ret;
}
 
-   if (pipe_config->dsc.compression_enable) {
-   drm_dbg_kms(>drm,
-   "DP lane count %d clock %d Input bpp %d Compressed 
bpp " BPP_X16_FMT "\n",
-   pipe_config->lane_count, pipe_config->port_clock,
-   pipe_config->pipe_bpp,
-   BPP_X16_ARGS(pipe_config->dsc.compressed_bpp_x16));
+   drm_dbg_kms(>drm,
+   "DP lane count %d clock %d bpp input %d compressed " 
BPP_X16_FMT " link rate required %d available %d\n",
+   pipe_config->lane_count, pipe_config->port_clock,
+   pipe_config->pipe_bpp,
+   BPP_X16_ARGS(pipe_config->dsc.compressed_bpp_x16),
+   intel_dp_config_required_rate(pipe_config),
+   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
+ pipe_config->lane_count));
 
-   drm_dbg_kms(>drm,
-   "DP link rate required %i available %i\n",
-   intel_dp_link_required(adjusted_mode->crtc_clock,
-  
to_bpp_int_roundup(pipe_config->dsc.compressed_bpp_x16)),
-   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
- pipe_config->lane_count));
-   } else {
-   drm_dbg_kms(>drm, "DP lane count %d clock %d bpp %d\n",
-   pipe_config->lane_count, pipe_config->port_clock,
-   pipe_config->pipe_bpp);
-
-   drm_dbg_kms(>drm,
-   "DP link rate required %i available %i\n",
-   intel_dp_link_required(adjusted_mode->crtc_clock,
-  pipe_config->pipe_bpp),
-   drm_dp_max_dprx_data_rate(pipe_config->port_clock,
- pipe_config->lane_count));
-   }
return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 46f79747f807d..37274e3c2902f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -102,6 +102,7 @@ void intel_dp_mst_suspend(struct drm_i915_private 
*dev_priv);
 void intel_dp_mst_resume(struct drm_i915_private *dev_priv);
 int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 int intel_dp_max_lane_count(struct intel_dp *intel_dp);
+int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
-- 
2.39.2



[PATCH 03/19] drm/i915/dp: Add support to notify MST connectors to retry modesets

2024-01-23 Thread Imre Deak
On shared (Thunderbolt) links with DP tunnels, the modeset may need to
be retried on all connectors on the link due to a link BW limitation
arising only after the atomic check phase. To support this add a helper
function queuing a work to retry the modeset on a given port's connector
and at the same time any MST connector with streams through the same
port. A follow-up change enabling the DP tunnel Bandwidth Allocation
Mode will take this into use.

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_display.c  |  5 +-
 drivers/gpu/drm/i915/display/intel_dp.c   | 55 ++-
 drivers/gpu/drm/i915/display/intel_dp.h   |  8 +++
 .../drm/i915/display/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  2 +
 5 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index a92e959c8ac7b..0caebbb3e2dbb 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8060,8 +8060,9 @@ void intel_hpd_poll_fini(struct drm_i915_private *i915)
/* Kill all the work that may have been queued by hpd. */
drm_connector_list_iter_begin(>drm, _iter);
for_each_intel_connector_iter(connector, _iter) {
-   if (connector->modeset_retry_work.func)
-   cancel_work_sync(>modeset_retry_work);
+   if (connector->modeset_retry_work.func &&
+   cancel_work_sync(>modeset_retry_work))
+   drm_connector_put(>base);
if (connector->hdcp.shim) {
cancel_delayed_work_sync(>hdcp.check_work);
cancel_work_sync(>hdcp.prop_work);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index ab415f41924d7..4e36c2c39888e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2837,6 +2837,50 @@ intel_dp_audio_compute_config(struct intel_encoder 
*encoder,
intel_dp_is_uhbr(pipe_config);
 }
 
+void intel_dp_queue_modeset_retry_work(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+
+   drm_connector_get(>base);
+   if (!queue_work(i915->unordered_wq, >modeset_retry_work))
+   drm_connector_put(>base);
+}
+
+void
+intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state 
*conn_state)
+{
+   struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+   struct intel_connector *connector;
+   struct intel_digital_connector_state *iter_conn_state;
+   struct intel_dp *intel_dp;
+   int i;
+
+   if (conn_state) {
+   connector = to_intel_connector(conn_state->connector);
+   intel_dp_queue_modeset_retry_work(connector);
+
+   return;
+   }
+
+   if (drm_WARN_ON(>drm,
+   !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
+   return;
+
+   intel_dp = enc_to_intel_dp(encoder);
+
+   for_each_new_intel_connector_in_state(state, connector, 
iter_conn_state, i) {
+   (void)iter_conn_state;
+
+   if (connector->mst_port != intel_dp)
+   continue;
+
+   intel_dp_queue_modeset_retry_work(connector);
+   }
+}
+
 int
 intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
@@ -6436,6 +6480,14 @@ static void intel_dp_modeset_retry_work_fn(struct 
work_struct *work)
mutex_unlock(>dev->mode_config.mutex);
/* Send Hotplug uevent so userspace can reprobe */
drm_kms_helper_connector_hotplug_event(connector);
+
+   drm_connector_put(connector);
+}
+
+void intel_dp_init_modeset_retry_work(struct intel_connector *connector)
+{
+   INIT_WORK(>modeset_retry_work,
+ intel_dp_modeset_retry_work_fn);
 }
 
 bool
@@ -6452,8 +6504,7 @@ intel_dp_init_connector(struct intel_digital_port 
*dig_port,
int type;
 
/* Initialize the work for modeset in case of link train failure */
-   INIT_WORK(_connector->modeset_retry_work,
- intel_dp_modeset_retry_work_fn);
+   intel_dp_init_modeset_retry_work(intel_connector);
 
if (drm_WARN(dev, dig_port->max_lanes < 1,
 "Not enough lanes (%d) for DP on [ENCODER:%d:%s]\n",
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 530cc97bc42f4..105c2086

[PATCH 01/19] drm/dp: Add drm_dp_max_dprx_data_rate()

2024-01-23 Thread Imre Deak
Copy intel_dp_max_data_rate() to DRM core. It will be needed by a
follow-up DP tunnel patch, checking the maximum rate the DPRX (sink)
supports. Accordingly use the drm_dp_max_dprx_data_rate() name for
clarity. This patchset will also switch calling the new DRM function
in i915 instead of intel_dp_max_data_rate().

Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/display/drm_dp_helper.c | 58 +
 include/drm/display/drm_dp_helper.h |  2 +
 2 files changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index b1ca3a1100dab..24911243d4d3a 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -4058,3 +4058,61 @@ int drm_dp_bw_channel_coding_efficiency(bool is_uhbr)
return 80;
 }
 EXPORT_SYMBOL(drm_dp_bw_channel_coding_efficiency);
+
+/*
+ * Given a link rate and lanes, get the data bandwidth.
+ *
+ * Data bandwidth is the actual payload rate, which depends on the data
+ * bandwidth efficiency and the link rate.
+ *
+ * For 8b/10b channel encoding, SST and non-FEC, the data bandwidth efficiency
+ * is 80%. For example, for a 1.62 Gbps link, 1.62*10^9 bps * 0.80 * (1/8) =
+ * 162000 kBps. With 8-bit symbols, we have 162000 kHz symbol clock. Just by
+ * coincidence, the port clock in kHz matches the data bandwidth in kBps, and
+ * they equal the link bit rate in Gbps multiplied by 10. (Note that this 
no
+ * longer holds for data bandwidth as soon as FEC or MST is taken into 
account!)
+ *
+ * For 128b/132b channel encoding, the data bandwidth efficiency is 96.71%. For
+ * example, for a 10 Gbps link, 10*10^9 bps * 0.9671 * (1/8) = 1208875
+ * kBps. With 32-bit symbols, we have 312500 kHz symbol clock. The value 
100
+ * does not match the symbol clock, the port clock (not even if you think in
+ * terms of a byte clock), nor the data bandwidth. It only matches the link bit
+ * rate in units of 1 bps.
+ *
+ * Note that protocol layers above the DPRX link level considered here can
+ * further limit the maximum data rate. Such layers are the MST topology (with
+ * limits on the link between the source and first branch device as well as on
+ * the whole MST path until the DPRX link) and (Thunderbolt) DP tunnels -
+ * which in turn can encapsulate an MST link with its own limit - with each
+ * SST or MST encapsulated tunnel sharing the BW of a tunnel group.
+ *
+ * TODO: Add support for querying the max data rate with the above limits as
+ * well.
+ *
+ * Returns the maximum data rate in kBps units.
+ */
+int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes)
+{
+   int ch_coding_efficiency =
+   
drm_dp_bw_channel_coding_efficiency(drm_dp_is_uhbr_rate(max_link_rate));
+   int max_link_rate_kbps = max_link_rate * 10;
+
+   /*
+* UHBR rates always use 128b/132b channel encoding, and have
+* 97.71% data bandwidth efficiency. Consider max_link_rate the
+* link bit rate in units of 1 bps.
+*/
+   /*
+* Lower than UHBR rates always use 8b/10b channel encoding, and have
+* 80% data bandwidth efficiency for SST non-FEC. However, this turns
+* out to be a nop by coincidence:
+*
+*  int max_link_rate_kbps = max_link_rate * 10;
+*  max_link_rate_kbps = DIV_ROUND_DOWN_ULL(max_link_rate_kbps * 8, 
10);
+*  max_link_rate = max_link_rate_kbps / 8;
+*/
+   return DIV_ROUND_DOWN_ULL(mul_u32_u32(max_link_rate_kbps * max_lanes,
+ ch_coding_efficiency),
+ 100 * 8);
+}
+EXPORT_SYMBOL(drm_dp_max_dprx_data_rate);
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index 863b2e7add29e..454ae7517419a 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -813,4 +813,6 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
   int bpp_x16, unsigned long flags);
 int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
 
+int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes);
+
 #endif /* _DRM_DP_HELPER_H_ */
-- 
2.39.2



[PATCH 00/19] drm/i915: Add Display Port tunnel BW allocation support

2024-01-23 Thread Imre Deak
Add support for detecting DP tunnels on (Thunderbolt) display links and
enabling the Bandwidth Allocation mode on the link. This helps in
enabling the maximum resolution in any scenario on displays sharing the
BW on such links.

Kudos to all Cc'd for advices, co-development and testing.

Cc: Mika Westerberg 
Cc: Ville Syrjälä 
Cc: Saranya Gopal 
Cc: Rajaram Regupathy 
Cc: Gil Fine 
Cc: Naama Shachar 
Cc: Pengfei Xu 

Imre Deak (19):
  drm/dp: Add drm_dp_max_dprx_data_rate()
  drm/dp: Add support for DP tunneling
  drm/i915/dp: Add support to notify MST connectors to retry modesets
  drm/i915/dp: Use drm_dp_max_dprx_data_rate()
  drm/i915/dp: Factor out intel_dp_config_required_rate()
  drm/i915/dp: Export intel_dp_max_common_rate/lane_count()
  drm/i915/dp: Factor out intel_dp_update_sink_caps()
  drm/i915/dp: Factor out intel_dp_read_dprx_caps()
  drm/i915/dp: Add intel_dp_max_link_data_rate()
  drm/i915/dp: Add way to get active pipes with syncing commits
  drm/i915/dp: Add support for DP tunnel BW allocation
  drm/i915/dp: Add DP tunnel atomic state and check BW limit
  drm/i915/dp: Account for tunnel BW limit in
intel_dp_max_link_data_rate()
  drm/i915/dp: Compute DP tunel BW during encoder state computation
  drm/i915/dp: Allocate/free DP tunnel BW in the encoder enable/disable
hooks
  drm/i915/dp: Handle DP tunnel IRQs
  drm/i915/dp: Call intel_dp_sync_state() always for DDI DP encoders
  drm/i915/dp: Suspend/resume DP tunnels
  drm/i915/dp: Enable DP tunnel BW allocation mode

 drivers/gpu/drm/display/Kconfig   |   17 +
 drivers/gpu/drm/display/Makefile  |2 +
 drivers/gpu/drm/display/drm_dp_helper.c   |   58 +
 drivers/gpu/drm/display/drm_dp_tunnel.c   | 1715 +
 drivers/gpu/drm/i915/Kconfig  |   13 +
 drivers/gpu/drm/i915/Kconfig.debug|1 +
 drivers/gpu/drm/i915/Makefile |3 +
 drivers/gpu/drm/i915/display/g4x_dp.c |   28 +
 drivers/gpu/drm/i915/display/intel_atomic.c   |   10 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |9 +-
 drivers/gpu/drm/i915/display/intel_display.c  |   26 +-
 .../gpu/drm/i915/display/intel_display_core.h |1 +
 .../drm/i915/display/intel_display_driver.c   |   20 +-
 .../drm/i915/display/intel_display_types.h|9 +
 drivers/gpu/drm/i915/display/intel_dp.c   |  309 ++-
 drivers/gpu/drm/i915/display/intel_dp.h   |   21 +-
 .../drm/i915/display/intel_dp_link_training.c |   33 +-
 .../drm/i915/display/intel_dp_link_training.h |1 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   18 +-
 .../gpu/drm/i915/display/intel_dp_tunnel.c|  642 ++
 .../gpu/drm/i915/display/intel_dp_tunnel.h|  131 ++
 drivers/gpu/drm/i915/display/intel_link_bw.c  |5 +
 drivers/gpu/drm/i915/display/intel_tc.c   |4 +-
 include/drm/display/drm_dp.h  |   61 +
 include/drm/display/drm_dp_helper.h   |2 +
 include/drm/display/drm_dp_tunnel.h   |  270 +++
 26 files changed, 3292 insertions(+), 117 deletions(-)
 create mode 100644 drivers/gpu/drm/display/drm_dp_tunnel.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_tunnel.h
 create mode 100644 include/drm/display/drm_dp_tunnel.h

-- 
2.39.2



[PATCH] drm/amd/display: Fix assignment of integer to fixed point pbn_div

2024-01-05 Thread Imre Deak
Fix the merge conflict resolution in

commit 13feae00ee99e0fc8b6f1748fc4c70281a7d6939
Merge: eb284f4b37817 3c064aea46d07
Author: Dave Airlie 
Date:   Fri Jan 5 13:19:40 2024 +1000

Merge remote-tracking branch 'drm/drm-next' into drm-tip

# Conflicts:
#   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
#   drivers/gpu/drm/i915/display/intel_dmc.c

@@@ -6916,7 -7007,8 +7009,7 @@@ static int dm_encoder_helper_atomic_che
if (IS_ERR(mst_state))
return PTR_ERR(mst_state);

 -  if (!mst_state->pbn_div.full)
 -  mst_state->pbn_div.full = 
dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link));
 +  mst_state->pbn_div = 
dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);

resulting from the following two changes:

commit 191dc43935d1ece82bc6c9653463b3b1cd8198fb
Author: Imre Deak 
Date:   Thu Nov 16 15:18:31 2023 +0200

drm/dp_mst: Store the MST PBN divider value in fixed point format

commit 9cdef4f720376ef0fb0febce1ed2377c19e531f9
Author: Wayne Lin 
Date:   Mon Dec 4 10:09:33 2023 +0800

drm/amd/display: pbn_div need be updated for hotplug event

Cc: Wayne Lin 
Cc: amd-...@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Cc: Dave Airlie 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5d82bac1a51ab..f9714dd6fe8ed 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7009,7 +7009,7 @@ static int dm_encoder_helper_atomic_check(struct 
drm_encoder *encoder,
if (IS_ERR(mst_state))
return PTR_ERR(mst_state);
 
-   mst_state->pbn_div = 
dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
+   mst_state->pbn_div.full = 
dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link));
 
if (!state->duplicated) {
int max_bpc = conn_state->max_requested_bpc;
-- 
2.39.2



Re: ✓ Fi.CI.BAT: success for drm/i915: Fix UHBR data, link M/N/TU and PBN values (rev6)

2023-11-21 Thread Imre Deak
On Tue, Nov 21, 2023 at 02:37:33AM +, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915: Fix UHBR data, link M/N/TU and PBN values (rev6)
> URL   : https://patchwork.freedesktop.org/series/126526/
> State : success

Thanks for the reviews and acks, the patchset is pushed to drm-intel-next.

I had to rebase patch 1 on drm-intel-next as described in
https://lore.kernel.org/all/zvy2rgfvp2cxa...@ideak-desk.fi.intel.com/

and then resolve the corresponding conflict merging drm-intel-next and
drm-misc-next (resulting in the original change in patch 1):

diff --cc drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index c7a29bb737e2,53e323b71d26..
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@@ -209,11 -210,11 +210,11 @@@ static void dm_helpers_construct_old_pa
struct drm_dp_mst_atomic_payload *new_payload,
struct drm_dp_mst_atomic_payload *old_payload)
  {
 -  struct link_mst_stream_allocation_table current_link_table =
 -  
link->mst_stream_alloc_table;
 -  struct link_mst_stream_allocation *dc_alloc;
 -  int pbn_per_slot = dfixed_trunc(pbn_per_slot_fp);
 -  int i;
 +  struct drm_dp_mst_atomic_payload *pos;
-   int pbn_per_slot = mst_state->pbn_div;
++  int pbn_per_slot = dfixed_trunc(mst_state->pbn_div);
 +  u8 next_payload_vc_start = mgr->next_start_slot;
 +  u8 payload_vc_start = new_payload->vc_start_slot;
 +  u8 allocated_time_slots;

*old_payload = *new_payload;

The IGT full test results using CI_DRM_13898_full as base (thanks to
Jani for the help with this) with one unrelated failure commented on
inline:

*  CI Bug Log - changes from CI_DRM_13898_full -> Patchwork_126526v6_full
*  Summary
*  FAILURE
*  
*  Serious unknown changes coming with Patchwork_126526v6_full absolutely need 
to be
*  verified manually.
*  
*  If you think the reported changes have nothing to do with the changes
*  introduced in Patchwork_126526v6_full, please notify your bug team 
(lgci.bug.fil...@intel.com) to allow them
*  to document this new failure mode, which will reduce false positives in CI.
*  
*  External URL: 
https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_126526v6/index.html
*  
*  Participating hosts (10 -> 11)
*  Additional (1): shard-mtlp0
*  
*  Possible new issues
*  Here are the unknown changes that may have been introduced in 
Patchwork_126526v6_full:
*  
*  IGT changes
*  Possible regressions
*  igt@i915_selftest@live@requests:
*  shard-mtlp: NOTRUN -> DMESG-FAIL +1 other test dmesg-fail

https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_126526v6/shard-mtlp-8/igt@i915_selftest@l...@requests.html

<6> [411.388436] i915: Running i915_request_live_selftests/live_cancel_request
<3> [411.398207] i915 :00:02.0: [drm] *ERROR* GT1: 
live_cancel_request(rcs0): engine 'other0' was reset -1 times!
<3> [411.423402] i915/i915_request_live_selftests: live_cancel_request failed 
with error -5


The platform doesn't have any external monitors attached, so can't see how the 
changes
in the patchset would be related. The closest issue (without a ticket filed for 
it) looks
to be:

https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13906/bat-mtlp-6/igt@i915_selftest@l...@requests.html#dmesg-warnings741

<7> [266.125209] i915 :00:02.0: [drm:i915_gem_open [i915]] 
<6> [267.264820] Completed 281 waits for 8482 fences across 6 engines and 4 cpus
<3> [267.265605] i915 :00:02.0: [drm] *ERROR* GT1: 
live_breadcrumbs_smoketest(): engine 'other0' was reset -1 times!
<3> [267.276018] i915/i915_request_live_selftests: live_breadcrumbs_smoketest 
failed with error -5


*  New tests
*  New tests have been introduced between CI_DRM_13898_full and 
Patchwork_126526v6_full:
*  
*  New IGT tests (15)
*  igt@kms_cursor_crc@cursor-offscreen-128x128@pipe-a-dp-4:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_cursor_crc@cursor-onscreen-256x256@pipe-a-dp-4:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_cursor_crc@cursor-random-128x128@pipe-a-dp-4:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_cursor_crc@cursor-rapid-movement-256x256@pipe-a-dp-4:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_cursor_crc@cursor-sliding-128x128@pipe-a-dp-4:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_plane_alpha_blend@coverage-vs-premult-vs-constant@pipe-a-dp-4:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_plane_cursor@overlay@pipe-a-dp-4-size-128:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_plane_cursor@overlay@pipe-a-dp-4-size-256:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_plane_cursor@overlay@pipe-a-dp-4-size-64:
*  
*  Statuses : 1 pass(s)
*  Exec time: [0.0] s
*  igt@kms_plane_cursor@viewport@pipe-a-dp-4-size-128:
*  
*  Statuses : 1 pass(s)
*  

Re: [PATCH v2 01/11] drm/dp_mst: Store the MST PBN divider value in fixed point format

2023-11-21 Thread Imre Deak
On Thu, Nov 16, 2023 at 03:18:31PM +0200, Imre Deak wrote:
[...]
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> index ed784cf27d396..63024393b516e 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> @@ -31,6 +31,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include "dm_services.h"
>  #include "amdgpu.h"
> @@ -210,7 +211,7 @@ static void dm_helpers_construct_old_payload(
>   struct drm_dp_mst_atomic_payload *old_payload)
>  {
>   struct drm_dp_mst_atomic_payload *pos;
> - int pbn_per_slot = mst_state->pbn_div;
> + int pbn_per_slot = dfixed_trunc(mst_state->pbn_div);
>   u8 next_payload_vc_start = mgr->next_start_slot;
>   u8 payload_vc_start = new_payload->vc_start_slot;
>   u8 allocated_time_slots;

I'm planning to merge this patchset today via drm-intel-next and for
that I'll need to rebase the above change to:

@@ -205,13 +206,14 @@ void dm_helpers_dp_update_branch_info(

 static void dm_helpers_construct_old_payload(
struct dc_link *link,
-   int pbn_per_slot,
+   fixed20_12 pbn_per_slot_fp,
struct drm_dp_mst_atomic_payload *new_payload,
struct drm_dp_mst_atomic_payload *old_payload)
 {
struct link_mst_stream_allocation_table current_link_table =

link->mst_stream_alloc_table;
struct link_mst_stream_allocation *dc_alloc;
+   int pbn_per_slot = dfixed_trunc(pbn_per_slot_fp);
int i;

*old_payload = *new_payload;

and then apply the original changes in the patch above while merging
drm-intel-next to drm-tip. This is required due to

commit 9031e0013f819c ("drm/amd/display: Fix mst hub unplug warning")

being only in drm-misc-next, but not yet in drm-intel-next.

Let me know if you have a concern with this.

--Imre


  1   2   3   4   5   6   >