[PATCH] drm/probe-helper: Call drm_mode_validate_ycbcr420() before connector->mode_valid()

2024-05-16 Thread Ville Syrjala
From: Ville Syrjälä 

Make life easier for drivers by filtering out unwanted YCbCr 4:2:0
only modes prior to calling the connector->mode_valid() hook.
Currently drivers will still see YCbCr 4:2:0 only modes in said
hook, which will likely come as a suprise when the driver has
declared no support for such modes (via setting
connector->ycbcr_420_allowed to false).

Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10992
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_probe_helper.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index 4f75a1cfd820..249c8c2cb319 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -474,6 +474,10 @@ static int __drm_helper_update_and_validate(struct 
drm_connector *connector,
if (mode->status != MODE_OK)
continue;
 
+   mode->status = drm_mode_validate_ycbcr420(mode, connector);
+   if (mode->status != MODE_OK)
+   continue;
+
ret = drm_mode_validate_pipeline(mode, connector, ctx,
 >status);
if (ret) {
@@ -486,10 +490,6 @@ static int __drm_helper_update_and_validate(struct 
drm_connector *connector,
else
return -EDEADLK;
}
-
-   if (mode->status != MODE_OK)
-   continue;
-   mode->status = drm_mode_validate_ycbcr420(mode, connector);
}
 
return 0;
-- 
2.44.1



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

2024-05-13 Thread Ville Syrjala
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()).

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);
-   }
-
switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR:
case I915_FORMAT_MOD_X_TILED:
-- 
2.43.2



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

2024-05-13 Thread Ville Syrjala
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))
+   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 */
+   return max(mult * 4 * 1024, 16 * 1024);
+   default:
+   MISSING_CASE(fb->modifier);
+   return 0;
+   }
+}
+
+static u32 skl_plane_min_alignment(struct intel_plane *plane,
+  const struct drm_framebuffer *fb,
+  int color_plane)
+{
+   /*
+* AUX_DIST needs only 4K alignment,
+* as does ICL UV PLANE_SURF.
+*/
+   if (color_plane != 0)
+   return 4 * 1024;
+
+   switch (fb->modifier) {
+   case DRM_FORMAT_MOD_LINEAR:
+   case 

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

2024-05-13 Thread Ville Syrjala
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ä 
---
 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
index 16ebb573643f..1b1fef2dc39a 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.h
+++ b/drivers/gpu/drm/i915/display/intel_fb.h
@@ -34,6 +34,7 @@ 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);
 
@@ -60,9 +61,6 @@ unsigned int intel_tile_height(const struct drm_framebuffer 

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

2024-05-13 Thread Ville Syrjala
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))
+   return 256 * 1024;
+   return 4 * 1024;
+   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 drm_i915_private 
*dev_priv)
-{
-   if (DISPLAY_VER(dev_priv) >= 9)
-   return 256 * 1024;
-   else if (IS_I965G(dev_priv) || IS_I965GM(dev_priv) ||
-IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-   return 128 * 1024;
-   else if (DISPLAY_VER(dev_priv) >= 4)
-   return 4 * 1024;
-   else
-   return 0;
-}
-
 unsigned int intel_surf_alignment(struct intel_plane *plane,
  const struct drm_framebuffer *fb,
  int color_plane)
@@ -824,7 +811,7 @@ unsigned int intel_surf_alignment(struct intel_plane *plane,
 */
if (DISPLAY_VER(dev_priv) >= 12) {
if (fb->modifier == 

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

2024-05-13 Thread Ville Syrjala
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;
+
+   return plane_state->view.gtt.type != I915_GTT_VIEW_NORMAL;
+}
+
 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;
+
+   return plane->min_alignment(plane, >base, 0);
 }
 
 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)
-{
-   

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

2024-05-13 Thread Ville Syrjala
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ä 
---
 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/i915/display/intel_fb.c
index b6638726949d..3f3a9cd534f4 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -775,8 +775,12 @@ 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(const struct drm_i915_private *i915)
+unsigned int intel_cursor_alignment(struct intel_plane *plane,
+   const struct drm_framebuffer *fb,
+   int color_plane)
 {
+   struct 

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

2024-05-13 Thread Ville Syrjala
From: Ville Syrjälä 

Split intel_cursor_alignment() into per-platform variants.

Signed-off-by: Ville Syrjälä 
---
 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))
-   return 32;
-   else
-   return 4 * 1024;
-}
-
 static unsigned int intel_linear_alignment(const struct drm_i915_private 
*dev_priv)
 {
if (DISPLAY_VER(dev_priv) >= 9)
diff --git a/drivers/gpu/drm/i915/display/intel_fb.h 
b/drivers/gpu/drm/i915/display/intel_fb.h
index 86c01a3ce81e..16ebb573643f 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.h
+++ b/drivers/gpu/drm/i915/display/intel_fb.h
@@ -60,9 +60,6 @@ unsigned int intel_tile_height(const struct drm_framebuffer 
*fb, int color_plane
 unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int 
color_plane);
 unsigned int 

[PATCH 2/9] drm: Export drm_plane_has_format()

2024-05-13 Thread Ville Syrjala
From: Ville Syrjälä 

Export drm_plane_has_format() so that drivers can use it.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_crtc_internal.h | 2 --
 drivers/gpu/drm/drm_plane.c | 1 +
 include/drm/drm_plane.h | 2 ++
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_internal.h 
b/drivers/gpu/drm/drm_crtc_internal.h
index 898e0e8b51be..e207759ca045 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -272,8 +272,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 /* drm_plane.c */
 int drm_plane_register_all(struct drm_device *dev);
 void drm_plane_unregister_all(struct drm_device *dev);
-bool drm_plane_has_format(struct drm_plane *plane,
- u32 format, u64 modifier);
 struct drm_mode_rect *
 __drm_plane_get_damage_clips(const struct drm_plane_state *state);
 
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 268aa2299df5..a51d4dd3f7de 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -906,6 +906,7 @@ bool drm_plane_has_format(struct drm_plane *plane,
 
return true;
 }
+EXPORT_SYMBOL(drm_plane_has_format);
 
 static int __setplane_check(struct drm_plane *plane,
struct drm_crtc *crtc,
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 9507542121fa..dd718c62ac31 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -972,6 +972,8 @@ static inline struct drm_plane *drm_plane_find(struct 
drm_device *dev,
 #define drm_for_each_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
 
+bool drm_plane_has_format(struct drm_plane *plane,
+ u32 format, u64 modifier);
 bool drm_any_plane_has_format(struct drm_device *dev,
  u32 format, u64 modifier);
 
-- 
2.43.2



[PATCH 1/9] drm: Rename drm_plane_check_pixel_format() to drm_plane_has_format()

2024-05-13 Thread Ville Syrjala
From: Ville Syrjälä 

Rename drm_plane_check_pixel_format() to drm_plane_has_format()
and change the return type accordingly. Allows one to write
more natural code.

Also matches drm_any_plane_has_format() better.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_atomic.c|  7 ++-
 drivers/gpu/drm/drm_crtc.c  |  6 ++
 drivers/gpu/drm/drm_crtc_internal.h |  4 ++--
 drivers/gpu/drm/drm_plane.c | 22 ++
 4 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a91737adf8e7..e22560213b8e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -608,7 +608,6 @@ static int drm_atomic_plane_check(const struct 
drm_plane_state *old_plane_state,
unsigned int fb_width, fb_height;
struct drm_mode_rect *clips;
uint32_t num_clips;
-   int ret;
 
/* either *both* CRTC and FB must be set, or neither */
if (crtc && !fb) {
@@ -635,14 +634,12 @@ static int drm_atomic_plane_check(const struct 
drm_plane_state *old_plane_state,
}
 
/* Check whether this plane supports the fb pixel format. */
-   ret = drm_plane_check_pixel_format(plane, fb->format->format,
-  fb->modifier);
-   if (ret) {
+   if (!drm_plane_has_format(plane, fb->format->format, fb->modifier)) {
drm_dbg_atomic(plane->dev,
   "[PLANE:%d:%s] invalid pixel format %p4cc, 
modifier 0x%llx\n",
   plane->base.id, plane->name,
   >format->format, fb->modifier);
-   return ret;
+   return -EINVAL;
}
 
/* Give drivers some help against integer overflows */
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 483969b84a30..3488ff067c69 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -789,12 +789,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 * case.
 */
if (!plane->format_default) {
-   ret = drm_plane_check_pixel_format(plane,
-  fb->format->format,
-  fb->modifier);
-   if (ret) {
+   if (!drm_plane_has_format(plane, fb->format->format, 
fb->modifier)) {
drm_dbg_kms(dev, "Invalid pixel format %p4cc, 
modifier 0x%llx\n",
>format->format, fb->modifier);
+   ret = -EINVAL;
goto out;
}
}
diff --git a/drivers/gpu/drm/drm_crtc_internal.h 
b/drivers/gpu/drm/drm_crtc_internal.h
index 25aaae937ceb..898e0e8b51be 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -272,8 +272,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 /* drm_plane.c */
 int drm_plane_register_all(struct drm_device *dev);
 void drm_plane_unregister_all(struct drm_device *dev);
-int drm_plane_check_pixel_format(struct drm_plane *plane,
-u32 format, u64 modifier);
+bool drm_plane_has_format(struct drm_plane *plane,
+ u32 format, u64 modifier);
 struct drm_mode_rect *
 __drm_plane_get_damage_clips(const struct drm_plane_state *state);
 
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 57662a1fd345..268aa2299df5 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -877,8 +877,8 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
return 0;
 }
 
-int drm_plane_check_pixel_format(struct drm_plane *plane,
-u32 format, u64 modifier)
+bool drm_plane_has_format(struct drm_plane *plane,
+ u32 format, u64 modifier)
 {
unsigned int i;
 
@@ -887,24 +887,24 @@ int drm_plane_check_pixel_format(struct drm_plane *plane,
break;
}
if (i == plane->format_count)
-   return -EINVAL;
+   return false;
 
if (plane->funcs->format_mod_supported) {
if (!plane->funcs->format_mod_supported(plane, format, 
modifier))
-   return -EINVAL;
+   return false;
} else {
if (!plane->modifier_count)
-   return 0;
+   return true;
 
for (i = 0; i < plane->modifier_count; i++) {
if (modifier == plane->modifiers[i])
break;
}
if (i == plane->modifier_count)
-   return -EINVAL;
+   return false;
}
 
-   return 0;
+   

[PATCH 0/9] drm/i915: Polish plane surface alignment handling

2024-05-13 Thread Ville Syrjala
From: Ville Syrjälä 

intel_surf_alignment() in particular has devolved into
a complete mess. Redesign the code so that we can handle
alignment restrictions in a nicer. Also adjust alignment
for TGL+ to actually match the hardware requirements.

Ville Syrjälä (9):
  drm: Rename drm_plane_check_pixel_format() to drm_plane_has_format()
  drm: Export drm_plane_has_format()
  drm/i915: Introduce plane->min_alignment() vfunc
  drm/i915: Introduce fb->min_alignment
  drm/i915: Split cursor alignment to per-platform vfuncs
  drm/i915: Split pre-skl platforms out from intel_surf_alignment()
  drm/i915: Move intel_surf_alignment() into skl_univerals_plane.c
  drm/i915: Update plane alignment requirements for TGL+
  drm/i915: Nuke the TGL+ chroma plane tile row alignment stuff

 drivers/gpu/drm/drm_atomic.c  |   7 +-
 drivers/gpu/drm/drm_crtc.c|   6 +-
 drivers/gpu/drm/drm_crtc_internal.h   |   2 -
 drivers/gpu/drm/drm_plane.c   |  23 ++-
 drivers/gpu/drm/i915/display/i9xx_plane.c |  75 -
 drivers/gpu/drm/i915/display/intel_cursor.c   |  38 +
 .../drm/i915/display/intel_display_types.h|   5 +
 drivers/gpu/drm/i915/display/intel_fb.c   | 145 --
 drivers/gpu/drm/i915/display/intel_fb.h   |   3 -
 drivers/gpu/drm/i915/display/intel_fb_pin.c   |  63 ++--
 drivers/gpu/drm/i915/display/intel_fb_pin.h   |   3 +-
 drivers/gpu/drm/i915/display/intel_fbdev.c|   5 +-
 drivers/gpu/drm/i915/display/intel_sprite.c   |  26 
 .../drm/i915/display/skl_universal_plane.c|  82 +-
 drivers/gpu/drm/xe/display/xe_fb_pin.c|   3 +-
 drivers/gpu/drm/xe/display/xe_plane_initial.c |   4 +-
 include/drm/drm_plane.h   |   2 +
 17 files changed, 324 insertions(+), 168 deletions(-)

-- 
2.43.2



[PATCH] drm/uapi: Move drm_color_ctm_3x4 out from drm_mode.h

2024-04-22 Thread Ville Syrjala
From: Ville Syrjälä 

drm_color_ctm_3x4 is some undocumented amgdpu private
uapi and thus has no business being in drm_mode.h.
At least move it to some amdgpu specific header, albeit
with the wrong namespace as maybe something somewhere
is using this already?

Cc: Harry Wentland 
Cc: Joshua Ashton 
Cc: Alex Deucher 
Fixes: 6872a189be50 ("drm/amd/display: Add 3x4 CTM support for plane CTM")
Signed-off-by: Ville Syrjälä 
---
 include/uapi/drm/amdgpu_drm.h | 9 +
 include/uapi/drm/drm_mode.h   | 8 
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 96e32dafd4f0..d5ebafacdd70 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -1269,6 +1269,15 @@ struct drm_amdgpu_info_gpuvm_fault {
 #define AMDGPU_FAMILY_GC_10_3_7151 /* GC 10.3.7 */
 #define AMDGPU_FAMILY_GC_11_5_0150 /* GC 11.5.0 */
 
+/* FIXME wrong namespace! */
+struct drm_color_ctm_3x4 {
+   /*
+* Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
+* (not two's complement!) format.
+*/
+   __u64 matrix[12];
+};
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 1ca5c7e418fd..d390011b89b4 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -846,14 +846,6 @@ struct drm_color_ctm {
__u64 matrix[9];
 };
 
-struct drm_color_ctm_3x4 {
-   /*
-* Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
-* (not two's complement!) format.
-*/
-   __u64 matrix[12];
-};
-
 struct drm_color_lut {
/*
 * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and
-- 
2.43.2



[PATCH] drm: Fix plane SIZE_HINTS property docs

2024-04-18 Thread Ville Syrjala
From: Ville Syrjälä 

Fix the typos in the plane SIZE_HINTS kernel docs.

Reported-by: Stephen Rothwell 
Fixes: 9677547d8362 ("drm: Introduce plane SIZE_HINTS property")
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_plane.c   | 2 +-
 include/drm/drm_mode_config.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index eecc24c54efd..57662a1fd345 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -1750,7 +1750,7 @@ int drm_plane_create_scaling_filter_property(struct 
drm_plane *plane,
 EXPORT_SYMBOL(drm_plane_create_scaling_filter_property);
 
 /**
- * drm_plane_add_size_hint_property - create a size hint property
+ * drm_plane_add_size_hints_property - create a size hints property
  *
  * @plane: drm plane
  * @hints: size hints
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 06da881f..8de3c9a5f61b 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -953,7 +953,7 @@ struct drm_mode_config {
struct drm_property *modifiers_property;
 
/**
-* @size_hints_propertty: Plane SIZE_HINTS property.
+* @size_hints_property: Plane SIZE_HINTS property.
 */
struct drm_property *size_hints_property;
 
-- 
2.43.2



[PATCH] drm/edid: Parse topology block for all DispID structure v1.x

2024-04-10 Thread Ville Syrjala
From: Ville Syrjälä 

DisplayID spec v1.3 revision history notes do claim that
the toplogy block was added in v1.3 so requiring structure
v1.2 would seem correct, but there is at least one EDID in
edid.tv with a topology block and structure v1.0. And
there are also EDIDs with DisplayID structure v1.3 which
seems to be totally incorrect as DisplayID spec v1.3 lists
structure v1.2 as the only legal value.

Unfortunately I couldn't find copies of DisplayID spec
v1.0-v1.2 anywhere (even on vesa.org), so I'll have to
go on empirical evidence alone.

We used to parse the topology block on all v1.x
structures until the check for structure v2.0 was added.
Let's go back to doing that as the evidence does suggest
that there are DisplayIDs in the wild that would miss
out on the topology stuff otherwise.

Also toss out DISPLAY_ID_STRUCTURE_VER_12 entirely as
it doesn't appear we can really use it for anything.

I *think* we could technically skip all the structure
version checks as the block tags shouldn't conflict
between v2.0 and v1.x. But no harm in having a bit of
extra sanity checks I guess.

So far I'm not aware of any user reported regressions
from overly strict check, but I do know that it broke
igt/kms_tiled_display's fake DisplayID as that one
gets generated with structure v1.0.

Cc: Jani Nikula 
Cc: Dmitry Osipenko 
Fixes: c5a486af9df7 ("drm/edid: parse Tiled Display Topology Data Block for 
DisplayID 2.0")
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_edid.c  | 2 +-
 include/drm/drm_displayid.h | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ea77577a3786..f0948ab214b3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -7405,7 +7405,7 @@ static void drm_parse_tiled_block(struct drm_connector 
*connector,
 static bool displayid_is_tiled_block(const struct displayid_iter *iter,
 const struct displayid_block *block)
 {
-   return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 &&
+   return (displayid_version(iter) < DISPLAY_ID_STRUCTURE_VER_20 &&
block->tag == DATA_BLOCK_TILED_DISPLAY) ||
(displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 &&
 block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY);
diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h
index 566497eeb3b8..bc1f6b378195 100644
--- a/include/drm/drm_displayid.h
+++ b/include/drm/drm_displayid.h
@@ -30,7 +30,6 @@ struct drm_edid;
 #define VESA_IEEE_OUI  0x3a0292
 
 /* DisplayID Structure versions */
-#define DISPLAY_ID_STRUCTURE_VER_120x12
 #define DISPLAY_ID_STRUCTURE_VER_200x20
 
 /* DisplayID Structure v1r2 Data Blocks */
-- 
2.43.2



[PATCH 5/5] drm/vkms: Use drm_crtc_vblank_crtc()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the open coded drm_crtc_vblank_crtc() with the real
thing.

Cc: Rodrigo Siqueira 
Cc: Melissa Wen 
Cc: "Maíra Canal" 
Cc: Haneen Mohammed 
Cc: Daniel Vetter 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/vkms/vkms_crtc.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 61e500b8c9da..40b4d084e3ce 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -61,9 +61,7 @@ static enum hrtimer_restart vkms_vblank_simulate(struct 
hrtimer *timer)
 
 static int vkms_enable_vblank(struct drm_crtc *crtc)
 {
-   struct drm_device *dev = crtc->dev;
-   unsigned int pipe = drm_crtc_index(crtc);
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
 
drm_calc_timestamping_constants(crtc, >mode);
@@ -88,10 +86,9 @@ static bool vkms_get_vblank_timestamp(struct drm_crtc *crtc,
  bool in_vblank_irq)
 {
struct drm_device *dev = crtc->dev;
-   unsigned int pipe = crtc->index;
struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev);
struct vkms_output *output = >output;
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
 
if (!READ_ONCE(vblank->enabled)) {
*vblank_time = ktime_get();
-- 
2.43.2



[PATCH 4/5] drm/nouveau: Use drm_crtc_vblank_crtc()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the open coded drm_crtc_vblank_crtc() with the real
thing.

Cc: Karol Herbst 
Cc: Lyude Paul 
Cc: Danilo Krummrich 
Cc: nouv...@lists.freedesktop.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/nouveau/nouveau_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index f28f9a857458..aed5d5b51b43 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -83,7 +83,7 @@ static bool
 nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime)
 {
-   struct drm_vblank_crtc *vblank = 
>dev->vblank[drm_crtc_index(crtc)];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct nvif_head *head = _crtc(crtc)->head;
struct nvif_head_scanoutpos_v0 args;
int retry = 20;
-- 
2.43.2



[PATCH 3/5] drm/i915: Use drm_crtc_vblank_crtc()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the open coded drm_crtc_vblank_crtc() with the real
thing.

Cc: intel-...@lists.freedesktop.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_crtc.c   |  3 +--
 drivers/gpu/drm/i915/display/intel_vblank.c | 16 +---
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c 
b/drivers/gpu/drm/i915/display/intel_crtc.c
index 25593f6aae7d..339010384b86 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -78,8 +78,7 @@ void intel_wait_for_vblank_if_active(struct drm_i915_private 
*i915,
 
 u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
 {
-   struct drm_device *dev = crtc->base.dev;
-   struct drm_vblank_crtc *vblank = 
>vblank[drm_crtc_index(>base)];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(>base);
 
if (!crtc->active)
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c 
b/drivers/gpu/drm/i915/display/intel_vblank.c
index baf7354cb6e2..951190bcbc50 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -132,8 +132,7 @@ u32 g4x_get_vblank_counter(struct drm_crtc *crtc)
 static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc)
 {
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-   struct drm_vblank_crtc *vblank =
-   >base.dev->vblank[drm_crtc_index(>base)];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(>base);
const struct drm_display_mode *mode = >hwmode;
u32 htotal = mode->crtc_htotal;
u32 clock = mode->crtc_clock;
@@ -178,8 +177,7 @@ static u32 
intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc)
  */
 static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc)
 {
-   struct drm_vblank_crtc *vblank =
-   >base.dev->vblank[drm_crtc_index(>base)];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(>base);
const struct drm_display_mode *mode = >hwmode;
u32 vblank_start = mode->crtc_vblank_start;
u32 vtotal = mode->crtc_vtotal;
@@ -200,17 +198,14 @@ static int __intel_get_crtc_scanline(struct intel_crtc 
*crtc)
 {
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
-   const struct drm_display_mode *mode;
-   struct drm_vblank_crtc *vblank;
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(>base);
+   const struct drm_display_mode *mode = >hwmode;
enum pipe pipe = crtc->pipe;
int position, vtotal;
 
if (!crtc->active)
return 0;
 
-   vblank = >base.dev->vblank[drm_crtc_index(>base)];
-   mode = >hwmode;
-
if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP)
return __intel_get_crtc_scanline_from_timestamp(crtc);
 
@@ -254,8 +249,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc 
*crtc)
 
 int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline)
 {
-   const struct drm_vblank_crtc *vblank =
-   >base.dev->vblank[drm_crtc_index(>base)];
+   const struct drm_vblank_crtc *vblank = 
drm_crtc_vblank_crtc(>base);
const struct drm_display_mode *mode = >hwmode;
int vtotal;
 
-- 
2.43.2



[PATCH 2/5] drm/amdgpu: Use drm_crtc_vblank_crtc()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the open coded drm_crtc_vblank_crtc() with the real
thing.

Cc: Alex Deucher 
Cc: "Christian König" 
Cc: "Pan, Xinhui" 
Cc: amd-...@lists.freedesktop.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c  | 8 ++--
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index 8baa2e0935cc..258703145161 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -65,9 +65,7 @@ static enum hrtimer_restart 
amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
 
 static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
 {
-   struct drm_device *dev = crtc->dev;
-   unsigned int pipe = drm_crtc_index(crtc);
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
@@ -91,10 +89,8 @@ static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc 
*crtc,
 ktime_t *vblank_time,
 bool in_vblank_irq)
 {
-   struct drm_device *dev = crtc->dev;
-   unsigned int pipe = crtc->index;
struct amdgpu_vkms_output *output = 
drm_crtc_to_amdgpu_vkms_output(crtc);
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
if (!READ_ONCE(vblank->enabled)) {
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 71d2d44681b2..662d2d83473b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -528,7 +528,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
if (acrtc) {
vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
drm_dev = acrtc->base.dev;
-   vblank = _dev->vblank[acrtc->base.index];
+   vblank = drm_crtc_vblank_crtc(>base);
previous_timestamp = 
atomic64_read(_params->previous_timestamp);
frame_duration_ns = vblank->time - previous_timestamp;
 
-- 
2.43.2



[PATCH 1/5] drm/vblank: Introduce drm_crtc_vblank_crtc()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Make life easier by providing a function that hands
out the the correct drm_vblank_crtc for a given a drm_crtc.

Also abstract the lower level internals of the vblank
code in a similar fashion.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_vblank.c  | 58 ++-
 drivers/gpu/drm/drm_vblank_work.c |  2 +-
 include/drm/drm_vblank.h  |  1 +
 3 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 702a12bc93bd..cc3571e25a9a 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -166,11 +166,24 @@ module_param_named(timestamp_precision_usec, 
drm_timestamp_precision, int, 0600)
 MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] 
(0: never disable, <0: disable immediately)");
 MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
 
+static struct drm_vblank_crtc *
+drm_vblank_crtc(struct drm_device *dev, unsigned int pipe)
+{
+   return >vblank[pipe];
+}
+
+struct drm_vblank_crtc *
+drm_crtc_vblank_crtc(struct drm_crtc *crtc)
+{
+   return drm_vblank_crtc(crtc->dev, drm_crtc_index(crtc));
+}
+EXPORT_SYMBOL(drm_crtc_vblank_crtc);
+
 static void store_vblank(struct drm_device *dev, unsigned int pipe,
 u32 vblank_count_inc,
 ktime_t t_vblank, u32 last)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 
assert_spin_locked(>vblank_time_lock);
 
@@ -184,7 +197,7 @@ static void store_vblank(struct drm_device *dev, unsigned 
int pipe,
 
 static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 
return vblank->max_vblank_count ?: dev->max_vblank_count;
 }
@@ -273,7 +286,7 @@ static void drm_reset_vblank_timestamp(struct drm_device 
*dev, unsigned int pipe
 static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
bool in_vblank_irq)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
u32 cur_vblank, diff;
bool rc;
ktime_t t_vblank;
@@ -364,7 +377,7 @@ static void drm_update_vblank_count(struct drm_device *dev, 
unsigned int pipe,
 
 u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
u64 count;
 
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
@@ -438,7 +451,7 @@ static void __disable_vblank(struct drm_device *dev, 
unsigned int pipe)
  */
 void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
unsigned long irqflags;
 
assert_spin_locked(>vbl_lock);
@@ -600,7 +613,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
 {
struct drm_device *dev = crtc->dev;
unsigned int pipe = drm_crtc_index(crtc);
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
int linedur_ns = 0, framedur_ns = 0;
int dotclock = mode->crtc_clock;
 
@@ -930,7 +943,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_count);
 static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
 ktime_t *vblanktime)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
u64 vblank_count;
unsigned int seq;
 
@@ -985,7 +998,6 @@ EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
  */
 int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
 {
-   unsigned int pipe = drm_crtc_index(crtc);
struct drm_vblank_crtc *vblank;
struct drm_display_mode *mode;
u64 vblank_start;
@@ -993,7 +1005,7 @@ int drm_crtc_next_vblank_start(struct drm_crtc *crtc, 
ktime_t *vblanktime)
if (!drm_dev_has_vblank(crtc->dev))
return -EINVAL;
 
-   vblank = >dev->vblank[pipe];
+   vblank = drm_crtc_vblank_crtc(crtc);
mode = >hwmode;
 
if (!vblank->framedur_ns || !vblank->linedur_ns)
@@ -1147,7 +1159,7 @@ static int __enable_vblank(struct drm_device *dev, 
unsigned int pipe)
 
 static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
 {
-   struct drm_vblank_crtc *vblank = >vblank[pipe];
+   struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
int ret = 0;
 
assert_spin_locked(>vbl_lock);
@@ -1185,7 +1197,7 @@ static int 

[PATCH 17/21] drm/fsl-dcu: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow fsl-dcu to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Stefan Agner 
Cc: Alison Wang 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/fsl-dcu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
index 5ca71ef87325..9c9954a5e9bc 100644
--- a/drivers/gpu/drm/fsl-dcu/Kconfig
+++ b/drivers/gpu/drm/fsl-dcu/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_FSL_DCU
tristate "DRM Support for Freescale DCU"
-   depends on DRM && OF && ARM && COMMON_CLK
+   depends on DRM && OF && (ARM || COMPILE_TEST) && COMMON_CLK
select BACKLIGHT_CLASS_DEVICE
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
-- 
2.43.2



[PATCH 15/21] drm/omap: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow omapdrm to be built with COMPILE_TEST=y for greater
coverage.

FIXME: Still borked due to ?

Cc: Tomi Valkeinen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/omapdrm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig
index 6c49270cb290..85ed92042b74 100644
--- a/drivers/gpu/drm/omapdrm/Kconfig
+++ b/drivers/gpu/drm/omapdrm/Kconfig
@@ -2,7 +2,7 @@
 config DRM_OMAP
tristate "OMAP DRM"
depends on DRM && OF
-   depends on ARCH_OMAP2PLUS
+   depends on ARCH_OMAP2PLUS || COMPILE_TEST
select DRM_KMS_HELPER
select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
select VIDEOMODE_HELPERS
-- 
2.43.2



[PATCH 20/21] drm/rcar-du: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow rcar-du to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Laurent Pinchart 
Cc: Kieran Bingham 
Cc: linux-renesas-...@vger.kernel.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/renesas/rcar-du/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig 
b/drivers/gpu/drm/renesas/rcar-du/Kconfig
index 2dc739db2ba3..df8b08b1e537 100644
--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
+++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
@@ -2,7 +2,7 @@
 config DRM_RCAR_DU
tristate "DRM Support for R-Car Display Unit"
depends on DRM && OF
-   depends on ARM || ARM64
+   depends on ARM || ARM64 || COMPILE_TEST
depends on ARCH_RENESAS || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
-- 
2.43.2



[PATCH 21/21] drm/stm: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow stm to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Yannick Fertre 
Cc: Raphael Gallais-Pou 
Cc: Philippe Cornu 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/stm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig
index fa49cde43bb2..4c906d602825 100644
--- a/drivers/gpu/drm/stm/Kconfig
+++ b/drivers/gpu/drm/stm/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_STM
tristate "DRM Support for STMicroelectronics SoC Series"
-   depends on DRM && ARCH_STM32
+   depends on DRM && (ARCH_STM32 || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_PANEL_BRIDGE
-- 
2.43.2



[PATCH 19/21] drm/meson: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow meson to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Neil Armstrong 
Cc: linux-amlo...@lists.infradead.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/meson/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
index 5520b9e3f010..d8f67bd9c755 100644
--- a/drivers/gpu/drm/meson/Kconfig
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_MESON
tristate "DRM Support for Amlogic Meson Display Controller"
-   depends on DRM && OF && (ARM || ARM64)
+   depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
depends on ARCH_MESON || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
-- 
2.43.2



[PATCH 18/21] drm/mediatek: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow mediatek to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Chun-Kuang Hu 
Cc: Philipp Zabel 
Cc: linux-media...@lists.infradead.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/mediatek/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 6caab8d4d4e0..d770936e238b 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -2,9 +2,9 @@
 config DRM_MEDIATEK
tristate "DRM Support for Mediatek SoCs"
depends on DRM
-   depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST)
+   depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
depends on COMMON_CLK
-   depends on HAVE_ARM_SMCCC
+   depends on HAVE_ARM_SMCCC || COMPILE_TEST
depends on OF
depends on MTK_MMSYS
select DRM_KMS_HELPER
-- 
2.43.2



[PATCH 13/21] drm/tilcdc: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow tilcdc to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Jyri Sarha 
Cc: Tomi Valkeinen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/tilcdc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
index d3bd2d7a181e..1897ef91c70b 100644
--- a/drivers/gpu/drm/tilcdc/Kconfig
+++ b/drivers/gpu/drm/tilcdc/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_TILCDC
tristate "DRM Support for TI LCDC Display Controller"
-   depends on DRM && OF && ARM
+   depends on DRM && OF && (ARM || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_BRIDGE
-- 
2.43.2



[PATCH 14/21] drm/omap: Open code phys_to_page()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

phys_to_page() is not available on most architectures.
Just open code it like msm does. Allows COMPILE_TEST=y
builds of omapdrm on other architectures.

Cc: Tomi Valkeinen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/omapdrm/omap_gem.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c 
b/drivers/gpu/drm/omapdrm/omap_gem.c
index 3421e8389222..c4454e7f1c94 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -1022,8 +1022,8 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object 
*obj,
 
if (addr) {
for_each_sg(sgt->sgl, sg, count, i) {
-   sg_set_page(sg, phys_to_page(addr), len,
-   offset_in_page(addr));
+   sg_set_page(sg, pfn_to_page(__phys_to_pfn(addr)),
+   len, offset_in_page(addr));
sg_dma_address(sg) = addr;
sg_dma_len(sg) = len;
 
-- 
2.43.2



[PATCH 16/21] drm/atmel-hlcdc: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow atmel-hlcdc to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Sam Ravnborg 
Cc: Boris Brezillon 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/atmel-hlcdc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig 
b/drivers/gpu/drm/atmel-hlcdc/Kconfig
index 3bdbab3a6333..945f3aa7bb24 100644
--- a/drivers/gpu/drm/atmel-hlcdc/Kconfig
+++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_ATMEL_HLCDC
tristate "DRM Support for ATMEL HLCDC Display Controller"
-   depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM
+   depends on DRM && OF && COMMON_CLK && ((MFD_ATMEL_HLCDC && ARM) || 
COMPILE_TEST)
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
-- 
2.43.2



[PATCH 10/21] drm/hisilicon/kirin: Fix MASK(32) on 32bit architectures

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

BIT(32) is illegal when sizeof(long)==4. Use BIT_ULL(32)
instead.

Cc: Xinliang Liu 
Cc: Tian Tao 
Cc: Xinwei Kong 
Cc: Sumit Semwal 
Cc: Yongqin Liu 
Cc: John Stultz 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h 
b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
index be9e789c2d04..36f923cc7594 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
@@ -10,7 +10,7 @@
 /*
  * ADE Registers
  */
-#define MASK(x)(BIT(x) - 1)
+#define MASK(x)(BIT_ULL(x) - 1)
 
 #define ADE_CTRL   0x0004
 #define FRM_END_START_OFST 0
-- 
2.43.2



[PATCH 12/21] drm/tilcdc: Allow build without __iowmb()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

__iowmb() isn't available on most architectures. Make
its use optional so that the driver can be built on
other architectures with COMPILE_TEST=y.

Cc: Jyri Sarha 
Cc: Tomi Valkeinen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/tilcdc/tilcdc_regs.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h 
b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
index f90e2dc3457c..44e4ada30fba 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
@@ -125,7 +125,9 @@ static inline void tilcdc_write64(struct drm_device *dev, 
u32 reg, u64 data)
 #if defined(iowrite64) && !defined(iowrite64_is_nonatomic)
iowrite64(data, addr);
 #else
+#ifdef __iowmb
__iowmb();
+#endif
/* This compiles to strd (=64-bit write) on ARM7 */
*(volatile u64 __force *)addr = __cpu_to_le64(data);
 #endif
-- 
2.43.2



[PATCH 11/21] drm/hisilicon/kirin: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow kirin to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Xinliang Liu 
Cc: Tian Tao 
Cc: Xinwei Kong 
Cc: Sumit Semwal 
Cc: Yongqin Liu 
Cc: John Stultz 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/hisilicon/kirin/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig 
b/drivers/gpu/drm/hisilicon/kirin/Kconfig
index c5265675bf0c..0772f79567ef 100644
--- a/drivers/gpu/drm/hisilicon/kirin/Kconfig
+++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_HISI_KIRIN
tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
-   depends on DRM && OF && ARM64
+   depends on DRM && OF && (ARM64 || COMPILE_TEST)
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DSI
-- 
2.43.2



[PATCH 09/21] drm/hisilicon/kirin: Fix 64bit divisions

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Use the appropriate 64bit division helpers to make the code
build on 32bit architectures.

Cc: Xinliang Liu 
Cc: Tian Tao 
Cc: Xinwei Kong 
Cc: Sumit Semwal 
Cc: Yongqin Liu 
Cc: John Stultz 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c 
b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 566de4658719..a39cc549c20b 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -157,8 +157,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct 
mipi_phy_params *phy)
q_pll = 0x10 >> (7 - phy->hstx_ckg_sel);
 
temp = f_kHz * (u64)q_pll * (u64)ref_clk_ps;
-   m_n_int = temp / (u64)10;
-   m_n = (temp % (u64)10) / (u64)1;
+   m_n_int = div64_u64_rem(temp, 10, );
+   m_n = div_u64(temp, 1);
 
if (m_n_int % 2 == 0) {
if (m_n * 6 >= 50) {
@@ -229,9 +229,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct 
mipi_phy_params *phy)
phy->pll_fbd_div5f = 1;
}
 
-   f_kHz = (u64)10 * (u64)m_pll /
-   ((u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
-
+   f_kHz = div64_u64((u64)10 * (u64)m_pll,
+ (u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
if (f_kHz >= req_kHz)
break;
 
@@ -490,7 +489,7 @@ static void dsi_set_mode_timing(void __iomem *base,
hsa_time = (hsw * lane_byte_clk_kHz) / pixel_clk_kHz;
hbp_time = (hbp * lane_byte_clk_kHz) / pixel_clk_kHz;
tmp = (u64)htot * (u64)lane_byte_clk_kHz;
-   hline_time = DIV_ROUND_UP(tmp, pixel_clk_kHz);
+   hline_time = DIV_ROUND_UP_ULL(tmp, pixel_clk_kHz);
 
/* all specified in byte-lane clocks */
writel(hsa_time, base + VID_HSA_TIME);
-- 
2.43.2



[PATCH 08/21] drm/hisilicon/kirin: Include linux/io.h for readl()/writel()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Include linux/io.h for readl()/writel().

When built on x86_64 w/ COMPILE_TEST=y:
../drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h:93:16: error: implicit 
declaration of function ‘readl’ [-Werror=implicit-function-declaration]
   93 | orig = readl(addr);
  |^
../drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h:96:9: error: implicit 
declaration of function ‘writel’ [-Werror=implicit-function-declaration]
   96 | writel(tmp, addr);
  | ^~

Cc: Xinliang Liu 
Cc: Tian Tao 
Cc: Xinwei Kong 
Cc: Sumit Semwal 
Cc: Yongqin Liu 
Cc: John Stultz 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h 
b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
index d79fc031e53d..a87d1135856f 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
@@ -7,6 +7,8 @@
 #ifndef __DW_DSI_REG_H__
 #define __DW_DSI_REG_H__
 
+#include 
+
 #define MASK(x)(BIT(x) - 1)
 
 /*
-- 
2.43.2



[PATCH 07/21] drm/sti: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow sti to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Alain Volmat 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/sti/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index 3c7a5feff8de..75c301aadcbc 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_STI
tristate "DRM Support for STMicroelectronics SoC stiH4xx Series"
-   depends on OF && DRM && ARCH_STI
+   depends on OF && DRM && (ARCH_STI || COMPILE_TEST)
select RESET_CONTROLLER
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
-- 
2.43.2



[PATCH 05/21] drm/imx/dcss: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow imx/dcss to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Laurentiu Palcu 
Cc: Lucas Stach 
Signed-off-by: Ville Syrjälä 
dpiormw.cocci
---
 drivers/gpu/drm/imx/dcss/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig
index 3ffc061d392b..502612747007 100644
--- a/drivers/gpu/drm/imx/dcss/Kconfig
+++ b/drivers/gpu/drm/imx/dcss/Kconfig
@@ -4,7 +4,7 @@ config DRM_IMX_DCSS
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select VIDEOMODE_HELPERS
-   depends on DRM && ARCH_MXC && ARM64
+   depends on DRM && ((ARCH_MXC && ARM64) || COMPILE_TEST)
help
  Choose this if you have a NXP i.MX8MQ based system and want to use the
  Display Controller Subsystem. This option enables DCSS support.
-- 
2.43.2



[PATCH 06/21] drm/sti: Include linux/io.h for devm_ioremap()

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Include linux/io.h for devm_ioremap().

When built on x86_64 w/ COMPILE_TEST=y:
../drivers/gpu/drm/sti/sti_dvo.c:531:21: error: implicit declaration of 
function ‘devm_ioremap’ [-Werror=implicit-function-declaration]
  531 | dvo->regs = devm_ioremap(dev, res->start,
  | ^~~~
../drivers/gpu/drm/sti/sti_dvo.c:531:19: error: assignment to ‘void *’ from 
‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  531 | dvo->regs = devm_ioremap(dev, res->start,
  |   ^

Cc: Alain Volmat 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/sti/sti_dvo.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index fd1df4ce3852..48a5d49fc131 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-- 
2.43.2



[PATCH 04/21] drm/imx/dcss: Fix 64bit divisions

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Use the appropriate 64bit division helpers to make the code
build on 32bit architectures.

Cc: Laurentiu Palcu 
Cc: Lucas Stach 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/imx/dcss/dcss-scaler.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c 
b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
index 825728c356ff..32c3f46b21da 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
@@ -136,7 +136,7 @@ static int div_q(int A, int B)
else
temp -= B / 2;
 
-   result = (int)(temp / B);
+   result = div_s64(temp, B);
return result;
 }
 
@@ -239,7 +239,7 @@ static void dcss_scaler_gaussian_filter(int fc_q, bool 
use_5_taps,
ll_temp = coef[phase][i];
ll_temp <<= PSC_COEFF_PRECISION;
ll_temp += sum >> 1;
-   ll_temp /= sum;
+   ll_temp = div_s64(ll_temp, sum);
coef[phase][i] = (int)ll_temp;
}
}
-- 
2.43.2



[PATCH 03/21] drm/armada: Allow build with COMPILE_TEST=y

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Allow armada to be built with COMPILE_TEST=y for greater
coverage. Builds fine on x86/x86_64 at least.

Cc: Russell King 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/armada/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index e5597d7c9ae1..043ca103ab3f 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config DRM_ARMADA
tristate "DRM support for Marvell Armada SoCs"
-   depends on DRM && HAVE_CLK && ARM && MMU
+   depends on DRM && HAVE_CLK && MMU && (ARM || COMPILE_TEST)
select DRM_KMS_HELPER
select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
help
-- 
2.43.2



[PATCH 02/21] drm/armada: Fix armada_debugfs_crtc_reg_write() return type

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

Change the armada_debugfs_crtc_reg_write() return type to
the correct ssize_t. This makes the code actually build on
certain architectures.

Cc: Russell King 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/armada/armada_debugfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/armada/armada_debugfs.c 
b/drivers/gpu/drm/armada/armada_debugfs.c
index 29f4b52e3c8d..338f0f6ca441 100644
--- a/drivers/gpu/drm/armada/armada_debugfs.c
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -48,7 +48,7 @@ static int armada_debugfs_crtc_reg_open(struct inode *inode, 
struct file *file)
   inode->i_private);
 }
 
-static int armada_debugfs_crtc_reg_write(struct file *file,
+static ssize_t armada_debugfs_crtc_reg_write(struct file *file,
const char __user *ptr, size_t len, loff_t *off)
 {
struct armada_crtc *dcrtc;
-- 
2.43.2



[PATCH 01/21] drm/armada: Fix printk arguments

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

../drivers/gpu/drm/armada/armada_gem.c: In function ‘armada_gem_pwrite_ioctl’:
../drivers/gpu/drm/armada/armada_gem.c:367:27: warning: format ‘%u’ expects 
argument of type ‘unsigned int’, but argument 2 has type ‘size_t’ {aka ‘long 
unsigned int’} [-Wformat=]
  367 | DRM_ERROR("invalid size: object size %u\n", 
dobj->obj.size);
  |   ^~~~  
~~
  |  |
  |  
size_t {aka long unsigned int}

Cc: Russell King 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/armada/armada_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/armada/armada_gem.c 
b/drivers/gpu/drm/armada/armada_gem.c
index 26d10065d534..e9575ef5aaef 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -364,7 +364,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void 
*data,
 
if (args->offset > dobj->obj.size ||
args->size > dobj->obj.size - args->offset) {
-   DRM_ERROR("invalid size: object size %u\n", dobj->obj.size);
+   DRM_ERROR("invalid size: object size %zu\n", dobj->obj.size);
ret = -EINVAL;
goto unref;
}
-- 
2.43.2



[PATCH 00/21] drm: Increase COMPILE_TEST=y coverage

2024-04-08 Thread Ville Syrjala
From: Ville Syrjälä 

I got fed up having to build multiple architectures when
doing subsystem wide refactoring. So I decided to attack
the low hanging COMPILE_TEST=y fruit. Here are the
results. All of these drivers now build with COMPILE_TEST=y
on x86/x86_64

Ville Syrjälä (21):
  drm/armada: Fix printk arguments
  drm/armada: Fix armada_debugfs_crtc_reg_write() return type
  drm/armada: Allow build with COMPILE_TEST=y
  drm/imx/dcss: Fix 64bit divisions
  drm/imx/dcss: Allow build with COMPILE_TEST=y
  drm/sti: Include linux/io.h for devm_ioremap()
  drm/sti: Allow build with COMPILE_TEST=y
  drm/hisilicon/kirin: Include linux/io.h for readl()/writel()
  drm/hisilicon/kirin: Fix 64bit divisions
  drm/hisilicon/kirin: Fix MASK(32) on 32bit architectures
  drm/hisilicon/kirin: Allow build with COMPILE_TEST=y
  drm/tilcdc: Allow build without __iowmb()
  drm/tilcdc: Allow build with COMPILE_TEST=y
  drm/omap: Open code phys_to_page()
  drm/omap: Allow build with COMPILE_TEST=y
  drm/atmel-hlcdc: Allow build with COMPILE_TEST=y
  drm/fsl-dcu: Allow build with COMPILE_TEST=y
  drm/mediatek: Allow build with COMPILE_TEST=y
  drm/meson: Allow build with COMPILE_TEST=y
  drm/rcar-du: Allow build with COMPILE_TEST=y
  drm/stm: Allow build with COMPILE_TEST=y

 drivers/gpu/drm/armada/Kconfig  |  2 +-
 drivers/gpu/drm/armada/armada_debugfs.c |  2 +-
 drivers/gpu/drm/armada/armada_gem.c |  2 +-
 drivers/gpu/drm/atmel-hlcdc/Kconfig |  2 +-
 drivers/gpu/drm/fsl-dcu/Kconfig |  2 +-
 drivers/gpu/drm/hisilicon/kirin/Kconfig |  2 +-
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c| 11 +--
 drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h|  2 ++
 drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h |  2 +-
 drivers/gpu/drm/imx/dcss/Kconfig|  2 +-
 drivers/gpu/drm/imx/dcss/dcss-scaler.c  |  4 ++--
 drivers/gpu/drm/mediatek/Kconfig|  4 ++--
 drivers/gpu/drm/meson/Kconfig   |  2 +-
 drivers/gpu/drm/omapdrm/Kconfig |  2 +-
 drivers/gpu/drm/omapdrm/omap_gem.c  |  4 ++--
 drivers/gpu/drm/renesas/rcar-du/Kconfig |  2 +-
 drivers/gpu/drm/sti/Kconfig |  2 +-
 drivers/gpu/drm/sti/sti_dvo.c   |  1 +
 drivers/gpu/drm/stm/Kconfig |  2 +-
 drivers/gpu/drm/tilcdc/Kconfig  |  2 +-
 drivers/gpu/drm/tilcdc/tilcdc_regs.h|  2 ++
 21 files changed, 30 insertions(+), 26 deletions(-)

-- 
2.43.2



[PATCH 10/12] drm/client: Use [CONNECTOR:%d:%s] formatting

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Switch to the canonical [CONNECTOR:%d:%s] etc. format for
printing out kms objects.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 65 +++-
 1 file changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 1751162b7d5c..415d1799337b 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -251,8 +251,10 @@ static void drm_client_connectors_enabled(struct 
drm_device *dev,
for (i = 0; i < connector_count; i++) {
connector = connectors[i];
enabled[i] = drm_connector_enabled(connector, true);
-   drm_dbg_kms(dev, "connector %d enabled? %s\n", 
connector->base.id,
-   connector->display_info.non_desktop ? "non desktop" 
: str_yes_no(enabled[i]));
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] enabled? %s\n",
+   connector->base.id, connector->name,
+   connector->display_info.non_desktop ?
+   "non desktop" : str_yes_no(enabled[i]));
 
any_enabled |= enabled[i];
}
@@ -368,8 +370,8 @@ static int drm_client_get_tile_offsets(struct drm_device 
*dev,
continue;
 
if (!modes[i] && (h_idx || v_idx)) {
-   drm_dbg_kms(dev, "no modes for connector tiled %d %d\n",
-   i, connector->base.id);
+   drm_dbg_kms(dev, "no modes for tiled 
[CONNECTOR:%d:%s]\n",
+   connector->base.id, connector->name);
continue;
}
if (connector->tile_h_loc < h_idx)
@@ -438,14 +440,15 @@ static bool drm_client_target_preferred(struct drm_device 
*dev,
drm_client_get_tile_offsets(dev, connectors, 
connector_count, modes, offsets, i,
connector->tile_h_loc, 
connector->tile_v_loc);
}
-   drm_dbg_kms(dev, "looking for cmdline mode on connector %d\n",
-   connector->base.id);
+   drm_dbg_kms(dev, "looking for cmdline mode on 
[CONNECTOR:%d:%s]\n",
+   connector->base.id, connector->name);
 
/* got for command line mode first */
modes[i] = drm_connector_pick_cmdline_mode(connector);
if (!modes[i]) {
-   drm_dbg_kms(dev, "looking for preferred mode on 
connector %d %d\n",
-   connector->base.id, connector->tile_group ? 
connector->tile_group->id : 0);
+   drm_dbg_kms(dev, "looking for preferred mode on 
[CONNECTOR:%d:%s] (tile group: %d)\n",
+   connector->base.id, connector->name,
+   connector->tile_group ? 
connector->tile_group->id : 0);
modes[i] = drm_connector_preferred_mode(connector, 
width, height);
}
/* No preferred modes, pick one off the list */
@@ -465,8 +468,8 @@ static bool drm_client_target_preferred(struct drm_device 
*dev,
(connector->tile_h_loc == 0 &&
 connector->tile_v_loc == 0 &&
 !drm_connector_get_tiled_mode(connector))) {
-   drm_dbg_kms(dev, "Falling back to non tiled 
mode on Connector %d\n",
-   connector->base.id);
+   drm_dbg_kms(dev, "Falling back to non tiled 
mode on [CONNECTOR:%d:%s]\n",
+   connector->base.id, 
connector->name);
modes[i] = 
drm_connector_fallback_non_tiled_mode(connector);
} else {
modes[i] = 
drm_connector_get_tiled_mode(connector);
@@ -634,15 +637,15 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
num_connectors_detected++;
 
if (!enabled[i]) {
-   drm_dbg_kms(dev, "connector %s not enabled, skipping\n",
-   connector->name);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] not enabled, 
skipping\n",
+   connector->base.id, connector->name);
conn_configured |= BIT(i);
continue;
}
 
if (connector->force == DRM_FORCE_OFF) {
-   drm_dbg_kms(dev, "connector %s is disabled by user, 
skipping\n",
-   connector->name);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] is disabled by 
user, skipping\n",
+   

[PATCH 08/12] drm/client: Extract drm_connector_first_mode()

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Use a consistent method for picking the first mode from the
connnector's mode list.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 08fc896885dd..1fba6cd8d761 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -159,6 +159,13 @@ drm_connector_preferred_mode(struct drm_connector 
*connector, int width, int hei
return NULL;
 }
 
+static const struct drm_display_mode *
+drm_connector_first_mode(struct drm_connector *connector)
+{
+   return list_first_entry_or_null(>modes,
+   struct drm_display_mode, head);
+}
+
 static const struct drm_display_mode *
 drm_connector_pick_cmdline_mode(struct drm_connector *connector)
 {
@@ -439,10 +446,8 @@ static bool drm_client_target_preferred(struct 
drm_connector *connectors[],
modes[i] = drm_connector_preferred_mode(connector, 
width, height);
}
/* No preferred modes, pick one off the list */
-   if (!modes[i] && !list_empty(>modes)) {
-   list_for_each_entry(modes[i], >modes, head)
-   break;
-   }
+   if (!modes[i])
+   modes[i] = drm_connector_first_mode(connector);
/*
 * In case of tiled mode if all tiles not present fallback to
 * first available non tiled mode.
@@ -684,9 +689,7 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
if (!modes[i] && !list_empty(>modes)) {
DRM_DEBUG_KMS("using first mode listed on connector 
%s\n",
  connector->name);
-   modes[i] = list_first_entry(>modes,
-   struct drm_display_mode,
-   head);
+   modes[i] = drm_connector_first_mode(connector);
}
 
/* last resort: use current mode */
-- 
2.43.2



[PATCH 07/12] drm/client: Use array notation for function arguments

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Use the array notation rather that the pointer notation for
function arguments. This makes it clear to the reader that
we are in fact dealing with an array rather than a single
pointer. Functionally the two are equivalent.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 42 ++--
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 384a9f8227a0..08fc896885dd 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -232,9 +232,9 @@ static bool drm_connector_enabled(struct drm_connector 
*connector, bool strict)
return enable;
 }
 
-static void drm_client_connectors_enabled(struct drm_connector **connectors,
+static void drm_client_connectors_enabled(struct drm_connector *connectors[],
  unsigned int connector_count,
- bool *enabled)
+ bool enabled[])
 {
bool any_enabled = false;
struct drm_connector *connector;
@@ -257,11 +257,11 @@ static void drm_client_connectors_enabled(struct 
drm_connector **connectors,
 }
 
 static bool drm_client_target_cloned(struct drm_device *dev,
-struct drm_connector **connectors,
+struct drm_connector *connectors[],
 unsigned int connector_count,
-const struct drm_display_mode **modes,
-struct drm_client_offset *offsets,
-bool *enabled, int width, int height)
+const struct drm_display_mode *modes[],
+struct drm_client_offset offsets[],
+bool enabled[], int width, int height)
 {
int count, i, j;
bool can_clone = false;
@@ -342,10 +342,10 @@ static bool drm_client_target_cloned(struct drm_device 
*dev,
return false;
 }
 
-static int drm_client_get_tile_offsets(struct drm_connector **connectors,
+static int drm_client_get_tile_offsets(struct drm_connector *connectors[],
   unsigned int connector_count,
-  const struct drm_display_mode **modes,
-  struct drm_client_offset *offsets,
+  const struct drm_display_mode *modes[],
+  struct drm_client_offset offsets[],
   int idx,
   int h_idx, int v_idx)
 {
@@ -375,11 +375,11 @@ static int drm_client_get_tile_offsets(struct 
drm_connector **connectors,
return 0;
 }
 
-static bool drm_client_target_preferred(struct drm_connector **connectors,
+static bool drm_client_target_preferred(struct drm_connector *connectors[],
unsigned int connector_count,
-   const struct drm_display_mode **modes,
-   struct drm_client_offset *offsets,
-   bool *enabled, int width, int height)
+   const struct drm_display_mode *modes[],
+   struct drm_client_offset offsets[],
+   bool enabled[], int width, int height)
 {
const u64 mask = BIT_ULL(connector_count) - 1;
struct drm_connector *connector;
@@ -491,10 +491,10 @@ static bool connector_has_possible_crtc(struct 
drm_connector *connector,
 }
 
 static int drm_client_pick_crtcs(struct drm_client_dev *client,
-struct drm_connector **connectors,
+struct drm_connector *connectors[],
 unsigned int connector_count,
-struct drm_crtc **best_crtcs,
-const struct drm_display_mode **modes,
+struct drm_crtc *best_crtcs[],
+const struct drm_display_mode *modes[],
 int n, int width, int height)
 {
struct drm_device *dev = client->dev;
@@ -566,12 +566,12 @@ static int drm_client_pick_crtcs(struct drm_client_dev 
*client,
 
 /* Try to read the BIOS display configuration and use it for the initial 
config */
 static bool drm_client_firmware_config(struct drm_client_dev *client,
-  struct drm_connector **connectors,
+  struct drm_connector *connectors[],
   unsigned int connector_count,
-  struct drm_crtc **crtcs,
-

[PATCH 12/12] drm/probe-helper: Switch to per-device debugs

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Switch to per-device debugs so that we know which
device we're dealing with.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_probe_helper.c | 35 ++
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index 968a3ee66b1e..0860f7367511 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -567,8 +567,8 @@ int drm_helper_probe_single_connector_modes(struct 
drm_connector *connector,
 
drm_modeset_acquire_init(, 0);
 
-   DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
-   connector->name);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s]\n",
+   connector->base.id, connector->name);
 
 retry:
ret = drm_modeset_lock(>mode_config.connection_mutex, );
@@ -611,11 +611,10 @@ int drm_helper_probe_single_connector_modes(struct 
drm_connector *connector,
 * check here, and if anything changed start the hotplug code.
 */
if (old_status != connector->status) {
-   DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to 
%s\n",
- connector->base.id,
- connector->name,
- drm_get_connector_status_name(old_status),
- drm_get_connector_status_name(connector->status));
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to 
%s\n",
+   connector->base.id, connector->name,
+   drm_get_connector_status_name(old_status),
+   drm_get_connector_status_name(connector->status));
 
/*
 * The hotplug event code might call into the fb
@@ -638,8 +637,8 @@ int drm_helper_probe_single_connector_modes(struct 
drm_connector *connector,
drm_kms_helper_poll_enable(dev);
 
if (connector->status == connector_status_disconnected) {
-   DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
-   connector->base.id, connector->name);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] disconnected\n",
+   connector->base.id, connector->name);
drm_connector_update_edid_property(connector, NULL);
drm_mode_prune_invalid(dev, >modes, false);
goto exit;
@@ -697,8 +696,8 @@ int drm_helper_probe_single_connector_modes(struct 
drm_connector *connector,
 
drm_mode_sort(>modes);
 
-   DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
-   connector->name);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] probed modes :\n",
+   connector->base.id, connector->name);
list_for_each_entry(mode, >modes, head) {
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
drm_mode_debug_printmodeline(mode);
@@ -834,14 +833,12 @@ static void output_poll_execute(struct work_struct *work)
old = drm_get_connector_status_name(old_status);
new = drm_get_connector_status_name(connector->status);
 
-   DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
- "status updated from %s to %s\n",
- connector->base.id,
- connector->name,
- old, new);
-   DRM_DEBUG_KMS("[CONNECTOR:%d:%s] epoch counter %llu -> 
%llu\n",
- connector->base.id, connector->name,
- old_epoch_counter, 
connector->epoch_counter);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from 
%s to %s\n",
+   connector->base.id, connector->name,
+   old, new);
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] epoch counter %llu 
-> %llu\n",
+   connector->base.id, connector->name,
+   old_epoch_counter, 
connector->epoch_counter);
 
changed = true;
}
-- 
2.43.2



[PATCH 09/12] drm/client: Switch to per-device debugs

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Use drm_dev_dbg() & co. so that we know which device we're
dealing with.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 117 ++-
 1 file changed, 60 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 1fba6cd8d761..1751162b7d5c 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -239,7 +239,8 @@ static bool drm_connector_enabled(struct drm_connector 
*connector, bool strict)
return enable;
 }
 
-static void drm_client_connectors_enabled(struct drm_connector *connectors[],
+static void drm_client_connectors_enabled(struct drm_device *dev,
+ struct drm_connector *connectors[],
  unsigned int connector_count,
  bool enabled[])
 {
@@ -250,8 +251,8 @@ static void drm_client_connectors_enabled(struct 
drm_connector *connectors[],
for (i = 0; i < connector_count; i++) {
connector = connectors[i];
enabled[i] = drm_connector_enabled(connector, true);
-   DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
- connector->display_info.non_desktop ? "non 
desktop" : str_yes_no(enabled[i]));
+   drm_dbg_kms(dev, "connector %d enabled? %s\n", 
connector->base.id,
+   connector->display_info.non_desktop ? "non desktop" 
: str_yes_no(enabled[i]));
 
any_enabled |= enabled[i];
}
@@ -312,7 +313,7 @@ static bool drm_client_target_cloned(struct drm_device *dev,
}
 
if (can_clone) {
-   DRM_DEBUG_KMS("can clone using command line\n");
+   drm_dbg_kms(dev, "can clone using command line\n");
return true;
}
 
@@ -341,15 +342,16 @@ static bool drm_client_target_cloned(struct drm_device 
*dev,
drm_mode_destroy(dev, dmt_mode);
 
if (can_clone) {
-   DRM_DEBUG_KMS("can clone using 1024x768\n");
+   drm_dbg_kms(dev, "can clone using 1024x768\n");
return true;
}
 fail:
-   DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
+   drm_info(dev, "kms: can't enable cloning when we probably wanted 
to.\n");
return false;
 }
 
-static int drm_client_get_tile_offsets(struct drm_connector *connectors[],
+static int drm_client_get_tile_offsets(struct drm_device *dev,
+  struct drm_connector *connectors[],
   unsigned int connector_count,
   const struct drm_display_mode *modes[],
   struct drm_client_offset offsets[],
@@ -366,8 +368,8 @@ static int drm_client_get_tile_offsets(struct drm_connector 
*connectors[],
continue;
 
if (!modes[i] && (h_idx || v_idx)) {
-   DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
- connector->base.id);
+   drm_dbg_kms(dev, "no modes for connector tiled %d %d\n",
+   i, connector->base.id);
continue;
}
if (connector->tile_h_loc < h_idx)
@@ -378,11 +380,12 @@ static int drm_client_get_tile_offsets(struct 
drm_connector *connectors[],
}
offsets[idx].x = hoffset;
offsets[idx].y = voffset;
-   DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, 
v_idx);
+   drm_dbg_kms(dev, "returned %d %d for %d %d\n", hoffset, voffset, h_idx, 
v_idx);
return 0;
 }
 
-static bool drm_client_target_preferred(struct drm_connector *connectors[],
+static bool drm_client_target_preferred(struct drm_device *dev,
+   struct drm_connector *connectors[],
unsigned int connector_count,
const struct drm_display_mode *modes[],
struct drm_client_offset offsets[],
@@ -432,17 +435,17 @@ static bool drm_client_target_preferred(struct 
drm_connector *connectors[],
 * find the tile offsets for this pass - need to find
 * all tiles left and above
 */
-   drm_client_get_tile_offsets(connectors, 
connector_count, modes, offsets, i,
+   drm_client_get_tile_offsets(dev, connectors, 
connector_count, modes, offsets, i,
connector->tile_h_loc, 
connector->tile_v_loc);
}
-   DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
- connector->base.id);
+  

[PATCH 06/12] drm/client: Constify modes

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

The modes used by the client code live on the connectors' mode
lists, which are not owned by the client code, and thus it has
no business modifying the modes. Mark the modes const to make
that fact abundantly clear.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 36 +++-
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index cf1de06f99aa..384a9f8227a0 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -117,10 +117,10 @@ drm_client_find_modeset(struct drm_client_dev *client, 
struct drm_crtc *crtc)
return NULL;
 }
 
-static struct drm_display_mode *
+static const struct drm_display_mode *
 drm_connector_get_tiled_mode(struct drm_connector *connector)
 {
-   struct drm_display_mode *mode;
+   const struct drm_display_mode *mode;
 
list_for_each_entry(mode, >modes, head) {
if (mode->hdisplay == connector->tile_h_size &&
@@ -130,10 +130,10 @@ drm_connector_get_tiled_mode(struct drm_connector 
*connector)
return NULL;
 }
 
-static struct drm_display_mode *
+static const struct drm_display_mode *
 drm_connector_fallback_non_tiled_mode(struct drm_connector *connector)
 {
-   struct drm_display_mode *mode;
+   const struct drm_display_mode *mode;
 
list_for_each_entry(mode, >modes, head) {
if (mode->hdisplay == connector->tile_h_size &&
@@ -144,10 +144,10 @@ drm_connector_fallback_non_tiled_mode(struct 
drm_connector *connector)
return NULL;
 }
 
-static struct drm_display_mode *
+static const struct drm_display_mode *
 drm_connector_preferred_mode(struct drm_connector *connector, int width, int 
height)
 {
-   struct drm_display_mode *mode;
+   const struct drm_display_mode *mode;
 
list_for_each_entry(mode, >modes, head) {
if (mode->hdisplay > width ||
@@ -159,10 +159,11 @@ drm_connector_preferred_mode(struct drm_connector 
*connector, int width, int hei
return NULL;
 }
 
-static struct drm_display_mode *drm_connector_pick_cmdline_mode(struct 
drm_connector *connector)
+static const struct drm_display_mode *
+drm_connector_pick_cmdline_mode(struct drm_connector *connector)
 {
-   struct drm_cmdline_mode *cmdline_mode;
-   struct drm_display_mode *mode;
+   const struct drm_cmdline_mode *cmdline_mode;
+   const struct drm_display_mode *mode;
bool prefer_non_interlace;
 
/*
@@ -258,13 +259,14 @@ static void drm_client_connectors_enabled(struct 
drm_connector **connectors,
 static bool drm_client_target_cloned(struct drm_device *dev,
 struct drm_connector **connectors,
 unsigned int connector_count,
-struct drm_display_mode **modes,
+const struct drm_display_mode **modes,
 struct drm_client_offset *offsets,
 bool *enabled, int width, int height)
 {
int count, i, j;
bool can_clone = false;
-   struct drm_display_mode *dmt_mode, *mode;
+   const struct drm_display_mode *mode;
+   struct drm_display_mode *dmt_mode;
 
/* only contemplate cloning in the single crtc case */
if (dev->mode_config.num_crtc > 1)
@@ -342,7 +344,7 @@ static bool drm_client_target_cloned(struct drm_device *dev,
 
 static int drm_client_get_tile_offsets(struct drm_connector **connectors,
   unsigned int connector_count,
-  struct drm_display_mode **modes,
+  const struct drm_display_mode **modes,
   struct drm_client_offset *offsets,
   int idx,
   int h_idx, int v_idx)
@@ -375,7 +377,7 @@ static int drm_client_get_tile_offsets(struct drm_connector 
**connectors,
 
 static bool drm_client_target_preferred(struct drm_connector **connectors,
unsigned int connector_count,
-   struct drm_display_mode **modes,
+   const struct drm_display_mode **modes,
struct drm_client_offset *offsets,
bool *enabled, int width, int height)
 {
@@ -492,7 +494,7 @@ static int drm_client_pick_crtcs(struct drm_client_dev 
*client,
 struct drm_connector **connectors,
 unsigned int connector_count,
 struct drm_crtc **best_crtcs,
-struct drm_display_mode **modes,
+const struct drm_display_mode 

[PATCH 11/12] drm/client: Streamline mode selection debugs

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Get rid of all the redundant debugs and just wait until the end
to print which mode (and of which type) we picked.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 65 +---
 1 file changed, 31 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 415d1799337b..ad88c11037d8 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -408,6 +408,8 @@ static bool drm_client_target_preferred(struct drm_device 
*dev,
 
 retry:
for (i = 0; i < connector_count; i++) {
+   const char *mode_type;
+
connector = connectors[i];
 
if (conn_configured & BIT_ULL(i))
@@ -440,20 +442,20 @@ static bool drm_client_target_preferred(struct drm_device 
*dev,
drm_client_get_tile_offsets(dev, connectors, 
connector_count, modes, offsets, i,
connector->tile_h_loc, 
connector->tile_v_loc);
}
-   drm_dbg_kms(dev, "looking for cmdline mode on 
[CONNECTOR:%d:%s]\n",
-   connector->base.id, connector->name);
 
-   /* got for command line mode first */
+   mode_type = "cmdline";
modes[i] = drm_connector_pick_cmdline_mode(connector);
+
if (!modes[i]) {
-   drm_dbg_kms(dev, "looking for preferred mode on 
[CONNECTOR:%d:%s] (tile group: %d)\n",
-   connector->base.id, connector->name,
-   connector->tile_group ? 
connector->tile_group->id : 0);
+   mode_type = "preferred";
modes[i] = drm_connector_preferred_mode(connector, 
width, height);
}
-   /* No preferred modes, pick one off the list */
-   if (!modes[i])
+
+   if (!modes[i]) {
+   mode_type = "first";
modes[i] = drm_connector_first_mode(connector);
+   }
+
/*
 * In case of tiled mode if all tiles not present fallback to
 * first available non tiled mode.
@@ -468,16 +470,20 @@ static bool drm_client_target_preferred(struct drm_device 
*dev,
(connector->tile_h_loc == 0 &&
 connector->tile_v_loc == 0 &&
 !drm_connector_get_tiled_mode(connector))) {
-   drm_dbg_kms(dev, "Falling back to non tiled 
mode on [CONNECTOR:%d:%s]\n",
-   connector->base.id, 
connector->name);
+   mode_type = "non tiled";
modes[i] = 
drm_connector_fallback_non_tiled_mode(connector);
} else {
+   mode_type = "tiled";
modes[i] = 
drm_connector_get_tiled_mode(connector);
}
}
 
-   drm_dbg_kms(dev, "found mode %s\n",
-   modes[i] ? modes[i]->name : "none");
+   if (!modes[i])
+   mode_type = "no";
+
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] found %s mode: %s\n",
+   connector->base.id, connector->name,
+   mode_type, modes[i] ? modes[i]->name : "none");
conn_configured |= BIT_ULL(i);
}
 
@@ -624,6 +630,7 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_crtc *new_crtc;
+   const char *mode_type;
 
connector = connectors[i];
 
@@ -673,29 +680,22 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
 */
for (j = 0; j < count; j++) {
if (crtcs[j] == new_crtc) {
-   drm_dbg_kms(dev, "fallback: cloned 
configuration\n");
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] fallback: 
cloned configuration\n",
+   connector->base.id, 
connector->name);
goto bail;
}
}
 
-   drm_dbg_kms(dev, "looking for cmdline mode on 
[CONNECTOR:%d:%s]\n",
-   connector->base.id, connector->name);
-
-   /* go for command line mode first */
+   mode_type = "cmdline";
modes[i] = drm_connector_pick_cmdline_mode(connector);
 
-   /* try for preferred next */
if (!modes[i]) {
-   drm_dbg_kms(dev, "looking for preferred mode on 
[CONNECTOR:%d:%s] (tiled? 

[PATCH 05/12] drm/client: Nuke outdated fastboot comment

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Remove the tall tale about fastboot vs. user mode vs.
adjusted mode. crtc->mode == crtc->state->mode, so none
of this makes any sense. I suppose it may have been true
long ago in the past.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 8ef03608b424..cf1de06f99aa 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -690,16 +690,6 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
/* last resort: use current mode */
if (!modes[i]) {
/*
-* IMPORTANT: We want to use the adjusted mode (i.e.
-* after the panel fitter upscaling) as the initial
-* config, not the input mode, which is what crtc->mode
-* usually contains. But since our current
-* code puts a mode derived from the post-pfit timings
-* into crtc->mode this works out correctly.
-*
-* This is crtc->mode and not crtc->state->mode for the
-* fastboot check to work correctly.
-*
 * FIXME using legacy crtc->mode with atomic drivers
 * is dodgy. Switch to crtc->state->mode, after taking
 * care of the resulting locking/lifetime issues.
-- 
2.43.2



[PATCH 04/12] drm/client: Add a FIXME around crtc->mode usage

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

crtc->mode is legacy junk and shouldn't really be used with
atomic drivers.

Most (all?) atomic drivers do end up still calling
drm_atomic_helper_update_legacy_modeset_state() at some
point, so crtc->mode does still get populated, and this
does work for now. But eventually would be nice to eliminate
all the legacy stuff from atomic drivers.

Switching to crtc->state->mode would require some bigger
changes however, as we currently drop the crtc->mutex
before we're done using the mode. So leave the junk in
for now and just add a FIXME to remind us that this
needs fixing.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 2b7d0be04911..8ef03608b424 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -699,6 +699,10 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
 *
 * This is crtc->mode and not crtc->state->mode for the
 * fastboot check to work correctly.
+*
+* FIXME using legacy crtc->mode with atomic drivers
+* is dodgy. Switch to crtc->state->mode, after taking
+* care of the resulting locking/lifetime issues.
 */
DRM_DEBUG_KMS("looking for current mode on connector 
%s\n",
  connector->name);
-- 
2.43.2



[PATCH 03/12] drm/client: Use drm_mode_destroy()

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Prefer drm_mode_destroy() over bare kfree(), for consistency
and setting a good example.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 1c3aeb2dfa57..2b7d0be04911 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -329,7 +329,7 @@ static bool drm_client_target_cloned(struct drm_device *dev,
if (!modes[i])
can_clone = false;
}
-   kfree(dmt_mode);
+   drm_mode_destroy(dev, dmt_mode);
 
if (can_clone) {
DRM_DEBUG_KMS("can clone using 1024x768\n");
@@ -867,7 +867,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, 
unsigned int width,
break;
}
 
-   kfree(modeset->mode);
+   drm_mode_destroy(dev, modeset->mode);
modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = 
connector;
-- 
2.43.2



[PATCH 02/12] drm/client: s/drm_connector_has_preferred_mode/drm_connector_preferred_mode/

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Drop the "has" from drm_connector_has_preferred_mode() to better
describe what it does.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 0683a129b362..1c3aeb2dfa57 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -145,7 +145,7 @@ drm_connector_fallback_non_tiled_mode(struct drm_connector 
*connector)
 }
 
 static struct drm_display_mode *
-drm_connector_has_preferred_mode(struct drm_connector *connector, int width, 
int height)
+drm_connector_preferred_mode(struct drm_connector *connector, int width, int 
height)
 {
struct drm_display_mode *mode;
 
@@ -434,7 +434,7 @@ static bool drm_client_target_preferred(struct 
drm_connector **connectors,
if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector 
%d %d\n",
  connector->base.id, connector->tile_group 
? connector->tile_group->id : 0);
-   modes[i] = drm_connector_has_preferred_mode(connector, 
width, height);
+   modes[i] = drm_connector_preferred_mode(connector, 
width, height);
}
/* No preferred modes, pick one off the list */
if (!modes[i] && !list_empty(>modes)) {
@@ -522,7 +522,7 @@ static int drm_client_pick_crtcs(struct drm_client_dev 
*client,
my_score++;
if (connector->cmdline_mode.specified)
my_score++;
-   if (drm_connector_has_preferred_mode(connector, width, height))
+   if (drm_connector_preferred_mode(connector, width, height))
my_score++;
 
/*
@@ -675,7 +675,7 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector 
%s %d\n",
  connector->name, connector->has_tile);
-   modes[i] = drm_connector_has_preferred_mode(connector, 
width, height);
+   modes[i] = drm_connector_preferred_mode(connector, 
width, height);
}
 
/* No preferred mode marked by the EDID? Are there any modes? */
-- 
2.43.2



[PATCH 01/12] drm/client: Fully protect modes[] with dev->mode_config.mutex

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

The modes[] array contains pointers to modes on the connectors'
mode lists, which are protected by dev->mode_config.mutex.
Thus we need to extend modes[] the same protection or by the
time we use it the elements may already be pointing to
freed/reused memory.

Cc: sta...@vger.kernel.org
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10583
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_client_modeset.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 871e4e2129d6..0683a129b362 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -777,6 +777,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, 
unsigned int width,
unsigned int total_modes_count = 0;
struct drm_client_offset *offsets;
unsigned int connector_count = 0;
+   /* points to modes protected by mode_config.mutex */
struct drm_display_mode **modes;
struct drm_crtc **crtcs;
int i, ret = 0;
@@ -845,7 +846,6 @@ int drm_client_modeset_probe(struct drm_client_dev *client, 
unsigned int width,
drm_client_pick_crtcs(client, connectors, connector_count,
  crtcs, modes, 0, width, height);
}
-   mutex_unlock(>mode_config.mutex);
 
drm_client_modeset_release(client);
 
@@ -875,6 +875,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, 
unsigned int width,
modeset->y = offset->y;
}
}
+   mutex_unlock(>mode_config.mutex);
 
mutex_unlock(>modeset_mutex);
 out:
-- 
2.43.2



[PATCH 00/12] drm/client: Use after free and debug improvements

2024-04-04 Thread Ville Syrjala
From: Ville Syrjälä 

Various improvements to the drm/client code:
- Fix a use after free (fairly routinely hit by i915 CI)
- Debug print improvements
- Cleanups/etc.

Ville Syrjälä (12):
  drm/client: Fully protect modes[] with dev->mode_config.mutex
  drm/client:
s/drm_connector_has_preferred_mode/drm_connector_preferred_mode/
  drm/client: Use drm_mode_destroy()
  drm/client: Add a FIXME around crtc->mode usage
  drm/client: Nuke outdated fastboot comment
  drm/client: Constify modes
  drm/client: Use array notation for function arguments
  drm/client: Extract drm_connector_first_mode()
  drm/client: Switch to per-device debugs
  drm/client: Use [CONNECTOR:%d:%s] formatting
  drm/client: Streamline mode selection debugs
  drm/probe-helper: Switch to per-device debugs

 drivers/gpu/drm/drm_client_modeset.c | 237 ++-
 drivers/gpu/drm/drm_probe_helper.c   |  35 ++--
 2 files changed, 137 insertions(+), 135 deletions(-)

-- 
2.43.2



[PATCH v3 1/2] drm: Introduce plane SIZE_HINTS property

2024-03-19 Thread Ville Syrjala
From: Ville Syrjälä 

Add a new immutable plane property by which a plane can advertise
a handful of recommended plane sizes. This would be mostly exposed
by cursor planes as a slightly more capable replacement for
the DRM_CAP_CURSOR_WIDTH/HEIGHT caps, which can only declare
a one size fits all limit for the whole device.

Currently eg. amdgpu/i915/nouveau just advertize the max cursor
size via the cursor size caps. But always using the max sized
cursor can waste a surprising amount of power, so a better
strategy is desirable.

Most other drivers don't specify any cursor size at all, in
which case the ioctl code just claims that 64x64 is a great
choice. Whether that is actually true is debatable.

A poll of various compositor developers informs us that
blindly probing with setcursor/atomic ioctl to determine
suitable cursor sizes is not acceptable, thus the
introduction of the new property to supplant the cursor
size caps. The compositor will now be free to select a
more optimal cursor size from the short list of options.

Note that the reported sizes (either via the property or the
caps) make no claims about things such as plane scaling. So
these things should only really be consulted for simple
"cursor like" use cases.

Userspace consumer in the form of mutter seems ready:
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3165

v2: Try to add some docs
v3: Specify that value 0 is reserved for future use (basic idea from Jonas)
Drop the note about typical hardware (Pekka)
v4: Update the docs to indicate the list is "in order of preference"
Add a a link to the mutter MR
v5: Limit to cursors only for now (Simon)

Cc: Jonas Ådahl 
Cc: Sameer Lattannavar 
Reviewed-by: Sebastian Wick 
Reviewed-by: Simon Ser 
Acked-by: Daniel Stone 
Acked-by: Harry Wentland 
Acked-by: Pekka Paalanen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_mode_config.c |  7 
 drivers/gpu/drm/drm_plane.c   | 56 +++
 include/drm/drm_mode_config.h |  5 +++
 include/drm/drm_plane.h   |  4 +++
 include/uapi/drm/drm_mode.h   | 11 ++
 5 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/drm_mode_config.c 
b/drivers/gpu/drm/drm_mode_config.c
index 48fd2d67f352..568972258222 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -372,6 +372,13 @@ static int drm_mode_create_standard_properties(struct 
drm_device *dev)
return -ENOMEM;
dev->mode_config.modifiers_property = prop;
 
+   prop = drm_property_create(dev,
+  DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
+  "SIZE_HINTS", 0);
+   if (!prop)
+   return -ENOMEM;
+   dev->mode_config.size_hints_property = prop;
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 672c655c7a8e..eecc24c54efd 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -140,6 +140,25 @@
  * DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have been
  * various bugs in this area with inconsistencies between the capability
  * flag and per-plane properties.
+ *
+ * SIZE_HINTS:
+ * Blob property which contains the set of recommended plane size
+ * which can used for simple "cursor like" use cases (eg. no scaling).
+ * Using these hints frees userspace from extensive probing of
+ * supported plane sizes through atomic/setcursor ioctls.
+ *
+ * The blob contains an array of struct drm_plane_size_hint, in
+ * order of preference. For optimal usage userspace should pick
+ * the first size that satisfies its own requirements.
+ *
+ * Drivers should only attach this property to planes that
+ * support a very limited set of sizes.
+ *
+ * Note that property value 0 (ie. no blob) is reserved for potential
+ * future use. Current userspace is expected to ignore the property
+ * if the value is 0, and fall back to some other means (eg.
+ * _CAP_CURSOR_WIDTH and _CAP_CURSOR_HEIGHT) to determine
+ * the appropriate plane size to use.
  */
 
 static unsigned int drm_num_planes(struct drm_device *dev)
@@ -1729,3 +1748,40 @@ int drm_plane_create_scaling_filter_property(struct 
drm_plane *plane,
return 0;
 }
 EXPORT_SYMBOL(drm_plane_create_scaling_filter_property);
+
+/**
+ * drm_plane_add_size_hint_property - create a size hint property
+ *
+ * @plane: drm plane
+ * @hints: size hints
+ * @num_hints: number of size hints
+ *
+ * Create a size hints property for the plane.
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+int drm_plane_add_size_hints_property(struct drm_plane *plane,
+ const struct drm_plane_size_hint *hints,
+ int num_hints)
+{
+   struct drm_device *dev = plane->dev;
+   struct drm_mode_config *config = >mode_config;
+   struct 

[PATCH v3 2/2] drm/i915: Add SIZE_HINTS property for cursors

2024-03-19 Thread Ville Syrjala
From: Ville Syrjälä 

Advertize more suitable cursor sizes via the new SIZE_HINTS
plane property.

We can't really enumerate all supported cursor sizes on
the platforms where the cursor height can vary freely, so
for simplicity we'll just expose all square+POT sizes between
each platform's min and max cursor limits.

Depending on the platform this will give us one of three
results:
- 64x64,128x128,256x256,512x512
- 64x64,128x128,256x256
- 64x64

Cc: Simon Ser 
Cc: Jonas Ådahl 
Cc: Daniel Stone 
Cc: Sameer Lattannavar 
Cc: Sebastian Wick 
Cc: Harry Wentland 
Cc: Pekka Paalanen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_cursor.c | 24 +
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c 
b/drivers/gpu/drm/i915/display/intel_cursor.c
index f8b33999d43f..49e9b9be2235 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -823,6 +823,28 @@ static const struct drm_plane_funcs 
intel_cursor_plane_funcs = {
.format_mod_supported = intel_cursor_format_mod_supported,
 };
 
+static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
+{
+   struct drm_i915_private *i915 = to_i915(plane->base.dev);
+   const struct drm_mode_config *config = >drm.mode_config;
+   struct drm_plane_size_hint hints[4];
+   int size, max_size, num_hints = 0;
+
+   max_size = min(config->cursor_width, config->cursor_height);
+
+   /* for simplicity only enumerate the supported square+POT sizes */
+   for (size = 64; size <= max_size; size *= 2) {
+   if (drm_WARN_ON(>drm, num_hints >= ARRAY_SIZE(hints)))
+   break;
+
+   hints[num_hints].width = size;
+   hints[num_hints].height = size;
+   num_hints++;
+   }
+
+   drm_plane_add_size_hints_property(>base, hints, num_hints);
+}
+
 struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
  enum pipe pipe)
@@ -881,6 +903,8 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
   DRM_MODE_ROTATE_0 |
   DRM_MODE_ROTATE_180);
 
+   intel_cursor_add_size_hints_property(cursor);
+
zpos = DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
drm_plane_create_zpos_immutable_property(>base, zpos);
 
-- 
2.43.2


[PATCH v3 0/2] drm: Add plane SIZE_HINTS property

2024-03-19 Thread Ville Syrjala
From: Ville Syrjälä 

Final final version I hope. Mainly for CI to test against the
new IGTs.

Real userspace implementation:
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3165 
  

IGT:
https://patchwork.freedesktop.org/series/131199/

Changes from v2:
- Limit to cursor planes only (Simon)

Test-with: 20240315191505.27620-1-ville.syrj...@linux.intel.com
Cc: Simon Ser 
Cc: Jonas Ådahl 
Cc: Daniel Stone 
Cc: Sameer Lattannavar 
Cc: Sebastian Wick 
Cc: Harry Wentland 
Cc: Pekka Paalanen 

Ville Syrjälä (2):
  drm: Introduce plane SIZE_HINTS property
  drm/i915: Add SIZE_HINTS property for cursors

 drivers/gpu/drm/drm_mode_config.c   |  7 +++
 drivers/gpu/drm/drm_plane.c | 56 +
 drivers/gpu/drm/i915/display/intel_cursor.c | 24 +
 include/drm/drm_mode_config.h   |  5 ++
 include/drm/drm_plane.h |  4 ++
 include/uapi/drm/drm_mode.h | 11 
 6 files changed, 107 insertions(+)

-- 
2.43.2


[PATCH] drm/i915/ttm: Fix TTM_PL_FLAG_DESIRED

2024-02-27 Thread Ville Syrjala
From: Ville Syrjälä 

inlined from ‘i915_ttm_get_pages’ at 
../drivers/gpu/drm/i915/gem/i915_gem_ttm.c:847:2:
../drivers/gpu/drm/i915/gem/i915_gem_ttm.c:165:18: warning: ‘places[0].flags’ 
is used uninitialized [-Wuninitialized]
  165 | places[0].flags |= TTM_PL_FLAG_DESIRED;
  | ~^~
../drivers/gpu/drm/i915/gem/i915_gem_ttm.c: In function ‘i915_ttm_get_pages’:
../drivers/gpu/drm/i915/gem/i915_gem_ttm.c:837:26: note: ‘places’ declared here
  837 | struct ttm_place places[I915_TTM_MAX_PLACEMENTS + 1];
  |  ^~

Furhermore we then proceed to call i915_ttm_place_from_region() which
memset()s the whole thing back to zero anyway. So in the end we lose
the TTM_PL_FLAG_DESIRED flag (and fortunately also whatever else stack
garbage happened to be in the flags at this point).

No idea what functional changes this will result in...

Cc: Somalapuram Amaranath 
Cc: Christian König 
Cc: Zack Rusin 
Cc: Thomas Zimmermann 
Cc: Thomas Hellström 
Fixes: a78a8da51b36 ("drm/ttm: replace busy placement with flags v6")
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 27dcfd8a34bb..e6f177183c0f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -162,10 +162,10 @@ i915_ttm_placement_from_obj(const struct 
drm_i915_gem_object *obj,
unsigned int flags = obj->flags;
unsigned int i;
 
-   places[0].flags |= TTM_PL_FLAG_DESIRED;
i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] :
   obj->mm.region, [0], obj->bo_offset,
   obj->base.size, flags);
+   places[0].flags |= TTM_PL_FLAG_DESIRED;
 
/* Cache this on object? */
for (i = 0; i < num_allowed; ++i) {
-- 
2.43.0



[PATCH v2 2/2] drm/i915: Add SIZE_HINTS property for cursors

2024-02-27 Thread Ville Syrjala
From: Ville Syrjälä 

Advertize more suitable cursor sizes via the new SIZE_HINTS
plane property.

We can't really enumerate all supported cursor sizes on
the platforms where the cursor height can vary freely, so
for simplicity we'll just expose all square+POT sizes between
each platform's min and max cursor limits.

Depending on the platform this will give us one of three
results:
- 64x64,128x128,256x256,512x512
- 64x64,128x128,256x256
- 64x64

Cc: Simon Ser 
Cc: Jonas Ådahl 
Cc: Daniel Stone 
Cc: Sameer Lattannavar 
Cc: Sebastian Wick 
Cc: Harry Wentland 
Cc: Pekka Paalanen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_cursor.c | 24 +
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c 
b/drivers/gpu/drm/i915/display/intel_cursor.c
index f8b33999d43f..49e9b9be2235 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -823,6 +823,28 @@ static const struct drm_plane_funcs 
intel_cursor_plane_funcs = {
.format_mod_supported = intel_cursor_format_mod_supported,
 };
 
+static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
+{
+   struct drm_i915_private *i915 = to_i915(plane->base.dev);
+   const struct drm_mode_config *config = >drm.mode_config;
+   struct drm_plane_size_hint hints[4];
+   int size, max_size, num_hints = 0;
+
+   max_size = min(config->cursor_width, config->cursor_height);
+
+   /* for simplicity only enumerate the supported square+POT sizes */
+   for (size = 64; size <= max_size; size *= 2) {
+   if (drm_WARN_ON(>drm, num_hints >= ARRAY_SIZE(hints)))
+   break;
+
+   hints[num_hints].width = size;
+   hints[num_hints].height = size;
+   num_hints++;
+   }
+
+   drm_plane_add_size_hints_property(>base, hints, num_hints);
+}
+
 struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
  enum pipe pipe)
@@ -881,6 +903,8 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
   DRM_MODE_ROTATE_0 |
   DRM_MODE_ROTATE_180);
 
+   intel_cursor_add_size_hints_property(cursor);
+
zpos = DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
drm_plane_create_zpos_immutable_property(>base, zpos);
 
-- 
2.43.0



[PATCH v2 1/2] drm: Introduce plane SIZE_HINTS property

2024-02-27 Thread Ville Syrjala
From: Ville Syrjälä 

Add a new immutable plane property by which a plane can advertise
a handful of recommended plane sizes. This would be mostly exposed
by cursor planes as a slightly more capable replacement for
the DRM_CAP_CURSOR_WIDTH/HEIGHT caps, which can only declare
a one size fits all limit for the whole device.

Currently eg. amdgpu/i915/nouveau just advertize the max cursor
size via the cursor size caps. But always using the max sized
cursor can waste a surprising amount of power, so a better
stragey is desirable.

Most other drivers don't specify any cursor size at all, in
which case the ioctl code just claims that 64x64 is a great
choice. Whether that is actually true is debatable.

A poll of various compositor developers informs us that
blindly probing with setcursor/atomic ioctl to determine
suitable cursor sizes is not acceptable, thus the
introduction of the new property to supplant the cursor
size caps. The compositor will now be free to select a
more optimal cursor size from the short list of options.

Note that the reported sizes (either via the property or the
caps) make no claims about things such as plane scaling. So
these things should only really be consulted for simple
"cursor like" use cases.

Userspace consumer in the form of mutter seems ready:
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3165

v2: Try to add some docs
v3: Specify that value 0 is reserved for future use (basic idea from Jonas)
Drop the note about typical hardware (Pekka)
v4: Update the docs to indicate the list is "in order of preference"
Add a a link to the mutter MR

Cc: Simon Ser 
Cc: Jonas Ådahl 
Cc: Daniel Stone 
Cc: Sameer Lattannavar 
Cc: Sebastian Wick 
Acked-by: Harry Wentland 
Acked-by: Pekka Paalanen 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_mode_config.c |  7 +
 drivers/gpu/drm/drm_plane.c   | 52 +++
 include/drm/drm_mode_config.h |  5 +++
 include/drm/drm_plane.h   |  4 +++
 include/uapi/drm/drm_mode.h   | 11 +++
 5 files changed, 79 insertions(+)

diff --git a/drivers/gpu/drm/drm_mode_config.c 
b/drivers/gpu/drm/drm_mode_config.c
index 48fd2d67f352..568972258222 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -372,6 +372,13 @@ static int drm_mode_create_standard_properties(struct 
drm_device *dev)
return -ENOMEM;
dev->mode_config.modifiers_property = prop;
 
+   prop = drm_property_create(dev,
+  DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
+  "SIZE_HINTS", 0);
+   if (!prop)
+   return -ENOMEM;
+   dev->mode_config.size_hints_property = prop;
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 672c655c7a8e..4135ce16e608 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -140,6 +140,25 @@
  * DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have been
  * various bugs in this area with inconsistencies between the capability
  * flag and per-plane properties.
+ *
+ * SIZE_HINTS:
+ * Blob property which contains the set of recommended plane size
+ * which can used for simple "cursor like" use cases (eg. no scaling).
+ * Using these hints frees userspace from extensive probing of
+ * supported plane sizes through atomic/setcursor ioctls.
+ *
+ * The blob contains an array of struct drm_plane_size_hint, in
+ * order of preference. For optimal usage userspace should pick
+ * the first size that satisfies its own requirements.
+ *
+ * Drivers should only attach this property to planes that
+ * support a very limited set of sizes.
+ *
+ * Note that property value 0 (ie. no blob) is reserved for potential
+ * future use. Current userspace is expected to ignore the property
+ * if the value is 0, and fall back to some other means (eg.
+ * _CAP_CURSOR_WIDTH and _CAP_CURSOR_HEIGHT) to determine
+ * the appropriate plane size to use.
  */
 
 static unsigned int drm_num_planes(struct drm_device *dev)
@@ -1729,3 +1748,36 @@ int drm_plane_create_scaling_filter_property(struct 
drm_plane *plane,
return 0;
 }
 EXPORT_SYMBOL(drm_plane_create_scaling_filter_property);
+
+/**
+ * drm_plane_add_size_hint_property - create a size hint property
+ *
+ * @plane: drm plane
+ * @hints: size hints
+ * @num_hints: number of size hints
+ *
+ * Create a size hints property for the plane.
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+int drm_plane_add_size_hints_property(struct drm_plane *plane,
+ const struct drm_plane_size_hint *hints,
+ int num_hints)
+{
+   struct drm_device *dev = plane->dev;
+   struct drm_mode_config *config = >mode_config;
+   struct drm_property_blob *blob;
+
+   blob = drm_property_create_blob(dev,
+   

[PATCH v2 0/2] drm: Add plane SIZE_HINTS property

2024-02-27 Thread Ville Syrjala
From: Ville Syrjälä 

Final version for a new plane SIZE_HINTS property to
essentially replace the cursor size caps, based on recent
discussion in this gitlab bug:
https://gitlab.freedesktop.org/drm/intel/-/issues/7687

As for userspace, so far I only did a quick modetest
blob decoder (mainly to verify that it looks correct):
https://gitlab.freedesktop.org/vsyrjala/libdrm/-/commits/plane_size_hints

Sameer & co. have done a real mutter implementation:
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3165

This final version follows the original idea of having
just a list of sizes in a blob, rather than the mode
complex "2D bitmap" approach I also proposed later.
I think that's fair, the bitmap was probably overly
complicated.

The only difference to the previous version of this approach
is that the documentation now states that the list is sorted
in order of preference, and thus userspace should pick the
first suitable size from the list. This should match the
aforementioned mutter implementation.

Cc: Simon Ser 
Cc: Jonas Ådahl 
Cc: Daniel Stone 
Cc: Sameer Lattannavar 
Cc: Sebastian Wick 
Cc: Harry Wentland 
Cc: Pekka Paalanen 

Ville Syrjälä (2):
  drm: Introduce plane SIZE_HINTS property
  drm/i915: Add SIZE_HINTS property for cursors

 drivers/gpu/drm/drm_mode_config.c   |  7 +++
 drivers/gpu/drm/drm_plane.c | 52 +
 drivers/gpu/drm/i915/display/intel_cursor.c | 24 ++
 include/drm/drm_mode_config.h   |  5 ++
 include/drm/drm_plane.h |  4 ++
 include/uapi/drm/drm_mode.h | 11 +
 6 files changed, 103 insertions(+)

-- 
2.43.0



[PATCH] drm/mm: Allow CONFIG_DRM_MM_DEBUG with DRM=m

2023-12-15 Thread Ville Syrjala
From: Ville Syrjälä 

The original rationale for
commit cd456f8d06d2 ("drm: Restrict stackdepot usage to builtin drm.ko")
was that depot_save_stack() (which is what we used back then)
wasn't exported. stack_depot_save() (which is what we use now) is
exported however, so relax the dependency allow CONFIG_DRM_MM_DEBUG
with DRM=m.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 31cfe2c2a2af..4b8b8f8a0e72 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -42,7 +42,7 @@ config DRM_MIPI_DSI
 config DRM_DEBUG_MM
bool "Insert extra checks and debug info into the DRM range managers"
default n
-   depends on DRM=y
+   depends on DRM
depends on STACKTRACE_SUPPORT
select STACKDEPOT
help
-- 
2.41.0



[PATCH 2/2] drm: Warn when freeing a framebuffer that's still on a list

2023-12-11 Thread Ville Syrjala
From: Ville Syrjälä 

Sprinkle some extra WARNs around so that we might catch
premature framebuffer destruction more readily.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_framebuffer.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index 3cc0ffc28e86..888aadb6a4ac 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -461,6 +461,7 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
 
INIT_WORK_ONSTACK(, drm_mode_rmfb_work_fn);
INIT_LIST_HEAD();
+   drm_WARN_ON(dev, !list_empty(>filp_head));
list_add_tail(>filp_head, );
 
schedule_work();
@@ -827,6 +828,8 @@ void drm_framebuffer_free(struct kref *kref)
container_of(kref, struct drm_framebuffer, 
base.refcount);
struct drm_device *dev = fb->dev;
 
+   drm_WARN_ON(dev, !list_empty(>filp_head));
+
/*
 * The lookup idr holds a weak reference, which has not necessarily been
 * removed at this point. Check for that.
@@ -1119,7 +1122,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 
dev = fb->dev;
 
-   WARN_ON(!list_empty(>filp_head));
+   drm_WARN_ON(dev, !list_empty(>filp_head));
 
/*
 * drm ABI mandates that we remove any deleted framebuffers from active
-- 
2.41.0



[PATCH 1/2] drm: Don't unref the same fb many times by mistake due to deadlock handling

2023-12-11 Thread Ville Syrjala
From: Ville Syrjälä 

If we get a deadlock after the fb lookup in drm_mode_page_flip_ioctl()
we proceed to unref the fb and then retry the whole thing from the top.
But we forget to reset the fb pointer back to NULL, and so if we then
get another error during the retry, before the fb lookup, we proceed
the unref the same fb again without having gotten another reference.
The end result is that the fb will (eventually) end up being freed
while it's still in use.

Reset fb to NULL once we've unreffed it to avoid doing it again
until we've done another fb lookup.

This turned out to be pretty easy to hit on a DG2 when doing async
flips (and CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y). The first symptom I
saw that drm_closefb() simply got stuck in a busy loop while walking
the framebuffer list. Fortunately I was able to convince it to oops
instead, and from there it was easier to track down the culprit.

Cc: sta...@vger.kernel.org
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_plane.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 9e8e4c60983d..672c655c7a8e 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -1503,6 +1503,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 out:
if (fb)
drm_framebuffer_put(fb);
+   fb = NULL;
if (plane->old_fb)
drm_framebuffer_put(plane->old_fb);
plane->old_fb = NULL;
-- 
2.41.0



[PATCH 4/4] drm/i915: Fix glk+ degamma LUT conversions

2023-10-13 Thread Ville Syrjala
From: Ville Syrjälä 

The current implementation of change_lut_val_precision() is just
a convoluted way of shifting by 8. Implement the proper rounding
by just using drm_color_lut_extract() and intel_color_lut_pack()
like everyone else does.

And as the uapi can't handle >=1.0 values but the hardware
can we need to clamp the results appropriately in the readout
path.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_color.c | 54 +++---
 1 file changed, 28 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index a4b30614bd63..1cfbb3650304 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1526,14 +1526,27 @@ static int glk_degamma_lut_size(struct drm_i915_private 
*i915)
return 35;
 }
 
-/*
- * change_lut_val_precision: helper function to upscale or downscale lut 
values.
- * Parameters 'to' and 'from' needs to be less than 32. This should be 
sufficient
- * as currently there are no lut values exceeding 32 bit.
- */
-static u32 change_lut_val_precision(u32 lut_val, int to, int from)
+static u32 glk_degamma_lut(const struct drm_color_lut *color)
+{
+   return color->green;
+}
+
+static void glk_degamma_lut_pack(struct drm_color_lut *entry, u32 val)
+{
+   /* PRE_CSC_GAMC_DATA is 3.16, clamp to 0.16 */
+   entry->red = entry->green = entry->blue = min(val, 0xu);
+}
+
+static u32 mtl_degamma_lut(const struct drm_color_lut *color)
+{
+   return drm_color_lut_extract(color->green, 24);
+}
+
+static void mtl_degamma_lut_pack(struct drm_color_lut *entry, u32 val)
 {
-   return mul_u32_u32(lut_val, (1 << to)) / (1 << from);
+   /* PRE_CSC_GAMC_DATA is 3.24, clamp to 0.16 */
+   entry->red = entry->green = entry->blue =
+   intel_color_lut_pack(min(val, 0xffu), 24);
 }
 
 static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
@@ -1570,20 +1583,16 @@ static void glk_load_degamma_lut(const struct 
intel_crtc_state *crtc_state,
 * ToDo: Extend to max 7.0. Enable 32 bit input value
 * as compared to just 16 to achieve this.
 */
-   u32 lut_val;
-
-   if (DISPLAY_VER(i915) >= 14)
-   lut_val = change_lut_val_precision(lut[i].green, 24, 
16);
-   else
-   lut_val = lut[i].green;
-
ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
- lut_val);
+ DISPLAY_VER(i915) >= 14 ?
+ mtl_degamma_lut([i]) : 
glk_degamma_lut([i]));
}
 
/* Clamp values > 1.0. */
while (i++ < glk_degamma_lut_size(i915))
-   ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
+   ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
+ DISPLAY_VER(i915) >= 14 ?
+ 1 << 24 : 1 << 16);
 
ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0);
 }
@@ -3573,17 +3582,10 @@ static struct drm_property_blob 
*glk_read_degamma_lut(struct intel_crtc *crtc)
for (i = 0; i < lut_size; i++) {
u32 val = intel_de_read_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe));
 
-   /*
-* For MTL and beyond, convert back the 24 bit lut values
-* read from HW to 16 bit values to maintain parity with
-* userspace values
-*/
if (DISPLAY_VER(dev_priv) >= 14)
-   val = change_lut_val_precision(val, 16, 24);
-
-   lut[i].red = val;
-   lut[i].green = val;
-   lut[i].blue = val;
+   mtl_degamma_lut_pack([i], val);
+   else
+   glk_degamma_lut_pack([i], val);
}
 
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
-- 
2.41.0



[PATCH 3/4] drm/i915: s/clamp()/min()/ in i965_lut_11p6_max_pack()

2023-10-13 Thread Ville Syrjala
From: Ville Syrjälä 

Use min() instead of clamp() since the color values
involved are unsigned. No functional changes.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_color.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index b01f463af861..a4b30614bd63 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -909,7 +909,7 @@ static void i965_lut_10p6_pack(struct drm_color_lut *entry, 
u32 ldw, u32 udw)
 static u16 i965_lut_11p6_max_pack(u32 val)
 {
/* PIPEGCMAX is 11.6, clamp to 10.6 */
-   return clamp_val(val, 0, 0x);
+   return min(val, 0xu);
 }
 
 static u32 ilk_lut_10(const struct drm_color_lut *color)
-- 
2.41.0



[PATCH 2/4] drm/i915: Adjust LUT rounding rules

2023-10-13 Thread Ville Syrjala
From: Ville Syrjälä 

drm_color_lut_extract() rounding was changed to follow the
OpenGL int<->float conversion rules. Adjust intel_color_lut_pack()
to match.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_color.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index 2a2a163ea652..b01f463af861 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -785,14 +785,12 @@ static void chv_assign_csc(struct intel_crtc_state 
*crtc_state)
 /* convert hw value with given bit_precision to lut property val */
 static u32 intel_color_lut_pack(u32 val, int bit_precision)
 {
-   u32 max = 0x >> (16 - bit_precision);
-
-   val = clamp_val(val, 0, max);
-
-   if (bit_precision < 16)
-   val <<= 16 - bit_precision;
-
-   return val;
+   if (bit_precision > 16)
+   return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(val, (1 << 16) - 1),
+(1 << bit_precision) - 1);
+   else
+   return DIV_ROUND_CLOSEST(val * ((1 << 16) - 1),
+(1 << bit_precision) - 1);
 }
 
 static u32 i9xx_lut_8(const struct drm_color_lut *color)
-- 
2.41.0



[PATCH 1/4] drm: Fix color LUT rounding

2023-10-13 Thread Ville Syrjala
From: Ville Syrjälä 

The current implementation of drm_color_lut_extract()
generates weird results. Eg. if we go through all the
values for 16->8bpc conversion we see the following pattern:

inout (count)
   0 -   7f ->  0 (128)
  80 -  17f ->  1 (256)
 180 -  27f ->  2 (256)
 280 -  37f ->  3 (256)
...
fb80 - fc7f -> fc (256)
fc80 - fd7f -> fd (256)
fd80 - fe7f -> fe (256)
fe80 -  -> ff (384)

So less values map to 0 and more values map 0xff, which
doesn't seem particularly great.

To get just the same number of input values to map to
the same output values we'd just need to drop the rounding
entrirely. But perhaps a better idea would be to follow the
OpenGL int<->float conversion rules, in which case we get
the following results:

inout (count)
   0 -   80 ->  0 (129)
  81 -  181 ->  1 (257)
 182 -  282 ->  2 (257)
 283 -  383 ->  3 (257)
...
fc7c - fd7c -> fc (257)
fd7d - fe7d -> fd (257)
fe7e - ff7e -> fe (257)
ff7f -  -> ff (129)

Note that since the divisor is constant the compiler
is able to optimize away the integer division in most
cases. The only exception is the _ULL() case on 32bit
architectures since that gets emitted as inline asm
via do_div() and thus the compiler doesn't get to
optimize it.

Signed-off-by: Ville Syrjälä 
---
 include/drm/drm_color_mgmt.h | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 81c298488b0c..6be3cbe18944 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -36,20 +36,16 @@ struct drm_plane;
  *
  * Extract a degamma/gamma LUT value provided by user (in the form of
  * _color_lut entries) and round it to the precision supported by the
- * hardware.
+ * hardware, following OpenGL int<->float conversion rules.
  */
 static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision)
 {
-   u32 val = user_input;
-   u32 max = 0x >> (16 - bit_precision);
-
-   /* Round only if we're not using full precision. */
-   if (bit_precision < 16) {
-   val += 1UL << (16 - bit_precision - 1);
-   val >>= 16 - bit_precision;
-   }
-
-   return clamp_val(val, 0, max);
+   if (bit_precision > 16)
+   return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(user_input, (1 << 
bit_precision) - 1),
+(1 << 16) - 1);
+   else
+   return DIV_ROUND_CLOSEST(user_input * ((1 << bit_precision) - 
1),
+(1 << 16) - 1);
 }
 
 u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n);
-- 
2.41.0



[PATCH 0/4] drm/i915: Fix LUT rounding

2023-10-13 Thread Ville Syrjala
From: Ville Syrjälä 

The current LUT rounding is generating weird results. Adjust
it to follow the OpenGL int<->float conversion rules.

Ville Syrjälä (4):
  drm: Fix color LUT rounding
  drm/i915: Adjust LUT rounding rules
  drm/i915: s/clamp()/min()/ in i965_lut_11p6_max_pack()
  drm/i915: Fix glk+ degamma LUT conversions

 drivers/gpu/drm/i915/display/intel_color.c | 70 +++---
 include/drm/drm_color_mgmt.h   | 18 +++---
 2 files changed, 42 insertions(+), 46 deletions(-)

-- 
2.41.0



[PATCH v2 2/2] drm/i915/bios: Fixup h/vsync_end instead of h/vtotal

2023-09-20 Thread Ville Syrjala
From: Ville Syrjälä 

We have the same h/vsync_end vs. h/vtotal quirk in the VBT parser
that was also present in EDID parser. Adjust the VBT parser the
same way as was done for hte EDID parser to fixup h/vsync_end
instead of h/vtotal. While I'm not currently aware of any machines
that need this for the VBT it seems prudent to keep both parsers
in sync.

And while at it let's add some debugs here as well. A bit
lackluster but didn't feel like plumbing the connector all
the way down at this time.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index f735b035436c..863ff54fffd1 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -521,7 +521,8 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
 }
 
 static void
-fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
+fill_detail_timing_data(struct drm_i915_private *i915,
+   struct drm_display_mode *panel_fixed_mode,
const struct lvds_dvo_timing *dvo_timing)
 {
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
@@ -561,11 +562,17 @@ fill_detail_timing_data(struct drm_display_mode 
*panel_fixed_mode,
panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
dvo_timing->vimage_lo;
 
-   /* Some VBTs have bogus h/vtotal values */
-   if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
-   panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
-   if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
-   panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+   /* Some VBTs have bogus h/vsync_end values */
+   if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) {
+   drm_dbg_kms(>drm, "reducing hsync_end %d->%d\n",
+   panel_fixed_mode->hsync_end, 
panel_fixed_mode->htotal);
+   panel_fixed_mode->hsync_end = panel_fixed_mode->htotal;
+   }
+   if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) {
+   drm_dbg_kms(>drm, "reducing vsync_end %d->%d\n",
+   panel_fixed_mode->vsync_end, 
panel_fixed_mode->vtotal);
+   panel_fixed_mode->vsync_end = panel_fixed_mode->vtotal;
+   }
 
drm_mode_set_name(panel_fixed_mode);
 }
@@ -849,7 +856,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
if (!panel_fixed_mode)
return;
 
-   fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
+   fill_detail_timing_data(i915, panel_fixed_mode, panel_dvo_timing);
 
panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 
@@ -1134,7 +1141,7 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
if (!panel_fixed_mode)
return;
 
-   fill_detail_timing_data(panel_fixed_mode, >dtds[index]);
+   fill_detail_timing_data(i915, panel_fixed_mode, >dtds[index]);
 
panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
 
-- 
2.41.0



[PATCH v2 1/2] drm/edid: Fixup h/vsync_end instead of h/vtotal

2023-09-20 Thread Ville Syrjala
From: Ville Syrjälä 

There are some weird EDIDs floating around that have the sync
pulse extending beyond the end of the blanking period.

On the currently problemtic machine (HP Omni 120) EDID reports
the following mode:
"1600x900": 60 108000 1600 1780 1860 1800 900 910 913 1000 0x40 0x5
which is then "corrected" to have htotal=1861 by the current drm_edid.c
code.

The fixup code was originally added in commit 7064fef56369 ("drm: work
around EDIDs with bad htotal/vtotal values"). Googling around we end up in
https://bugs.launchpad.net/ubuntu/hardy/+source/xserver-xorg-video-intel/+bug/297245
where we find an EDID for a Dell Studio 15, which reports:
(II) VESA(0): clock: 65.0 MHz   Image Size:  331 x 207 mm
(II) VESA(0): h_active: 1280  h_sync: 1328  h_sync_end 1360 h_blank_end 1337 
h_border: 0
(II) VESA(0): v_active: 800  v_sync: 803  v_sync_end 809 v_blanking: 810 
v_border: 0

Note that if we use the hblank size (as opposed of the hsync_end)
from the DTD to determine htotal we get exactly 60Hz refresh rate in
both cases, whereas using hsync_end to determine htotal we get a
slightly lower refresh rates. This makes me believe the using the
hblank size is what was intended even in those cases.

Also note that in case of the HP Onmi 120 the VBIOS boots with these:
  crtc timings: 108000 1600 1780 1860 1800 900 910 913 1000, type: 0x40 flags: 
0x5
ie. it just blindly stuffs the bogus hsync_end and htotal from the DTD
into the transcoder timing registers, and the display works. I believe
the (at least more modern) hardware will automagically terminate the hsync
pulse when the timing generator reaches htotal, which again points that we
should use the hblank size to determine htotal. Unfortunatley the old bug
reports for the Dell machines are extremely lacking in useful details so
we have no idea what kind of timings the VBIOS programmed into the
hardware :(

Let's just flip this quirk around and reduce the length of the sync
pulse instead of extending the blanking period. This at least seems
to be the correct thing to do on more modern hardware. And if any
issues crop up on older hardware we need to debug them properly.

v2: Add debug message breadcrumbs (Jani)

Reviewed-by: Jani Nikula  #v1
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8895
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_edid.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 39dd3f694544..ec1cb4890acb 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3497,11 +3497,19 @@ static struct drm_display_mode 
*drm_mode_detailed(struct drm_connector *connecto
mode->vsync_end = mode->vsync_start + vsync_pulse_width;
mode->vtotal = mode->vdisplay + vblank;
 
-   /* Some EDIDs have bogus h/vtotal values */
-   if (mode->hsync_end > mode->htotal)
-   mode->htotal = mode->hsync_end + 1;
-   if (mode->vsync_end > mode->vtotal)
-   mode->vtotal = mode->vsync_end + 1;
+   /* Some EDIDs have bogus h/vsync_end values */
+   if (mode->hsync_end > mode->htotal) {
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] reducing hsync_end 
%d->%d\n",
+   connector->base.id, connector->name,
+   mode->hsync_end, mode->htotal);
+   mode->hsync_end = mode->htotal;
+   }
+   if (mode->vsync_end > mode->vtotal) {
+   drm_dbg_kms(dev, "[CONNECTOR:%d:%s] reducing vsync_end 
%d->%d\n",
+   connector->base.id, connector->name,
+   mode->vsync_end, mode->vtotal);
+   mode->vsync_end = mode->vtotal;
+   }
 
drm_mode_do_interlace_quirk(mode, pt);
 
-- 
2.41.0



[PATCH] drm/edid: Fixup h/vsync_end instead of h/vtotal

2023-09-14 Thread Ville Syrjala
From: Ville Syrjälä 

There are some weird EDIDs floating around that have the sync
pulse extending beyond the end of the blanking period.

On the currently problemtic machine (HP Omni 120) EDID reports
the following mode:
"1600x900": 60 108000 1600 1780 1860 1800 900 910 913 1000 0x40 0x5
which is then "corrected" to have htotal=1861 by the current drm_edid.c
code.

The fixup code was originally added in commit 7064fef56369 ("drm: work
around EDIDs with bad htotal/vtotal values"). Googling around we end up in
https://bugs.launchpad.net/ubuntu/hardy/+source/xserver-xorg-video-intel/+bug/297245
where we find an EDID for a Dell Studio 15, which reports:
(II) VESA(0): clock: 65.0 MHz   Image Size:  331 x 207 mm
(II) VESA(0): h_active: 1280  h_sync: 1328  h_sync_end 1360 h_blank_end 1337 
h_border: 0
(II) VESA(0): v_active: 800  v_sync: 803  v_sync_end 809 v_blanking: 810 
v_border: 0

Note that if we use the hblank size (as opposed of the hsync_end)
from the DTD to determine htotal we get exactly 60Hz refresh rate in
both cases, whereas using hsync_end to determine htotal we get a
slightly lower refresh rates. This makes me believe the using the
hblank size is what was intended even in those cases.

Also note that in case of the HP Onmi 120 the VBIOS boots with these:
  crtc timings: 108000 1600 1780 1860 1800 900 910 913 1000, type: 0x40 flags: 
0x5
ie. it just blindly stuffs the bogus hsync_end and htotal from the DTD
into the transcoder timing registers, and the display works. I believe
the (at least more modern) hardware will automagically terminate the hsync
pulse when the timing generator reaches htotal, which again points that we
should use the hblank size to determine htotal. Unfortunatley the old bug
reports for the Dell machines are extremely lacking in useful details so
we have no idea what kind of timings the VBIOS programmed into the
hardware :(

Let's just flip this quirk around and reduce the length of the sync
pulse instead of extending the blanking period. This at least seems
to be the correct thing to do on more modern hardware. And if any
issues crop up on older hardware we need to debug them properly.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8895
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_edid.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 39dd3f694544..0c5563b4d21e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3497,11 +3497,11 @@ static struct drm_display_mode 
*drm_mode_detailed(struct drm_connector *connecto
mode->vsync_end = mode->vsync_start + vsync_pulse_width;
mode->vtotal = mode->vdisplay + vblank;
 
-   /* Some EDIDs have bogus h/vtotal values */
+   /* Some EDIDs have bogus h/vsync_end values */
if (mode->hsync_end > mode->htotal)
-   mode->htotal = mode->hsync_end + 1;
+   mode->hsync_end = mode->htotal;
if (mode->vsync_end > mode->vtotal)
-   mode->vtotal = mode->vsync_end + 1;
+   mode->vsync_end = mode->vtotal;
 
drm_mode_do_interlace_quirk(mode, pt);
 
-- 
2.41.0



[PATCH v2 2/2] drm/vblank: Warn when silently cancelling vblank works

2023-09-03 Thread Ville Syrjala
From: Ville Syrjälä 

Silently cancelling vblank works is a bit rude, especially
if said works do any resource management (eg. free memory).
WARN if we ever hit this.

TODO: Maybe drm_crtc_vblank_off() should wait for any
pending work to reach its target vblank before actually
doing anything drastic?

Cc: Lyude Paul 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_vblank_work.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_vblank_work.c 
b/drivers/gpu/drm/drm_vblank_work.c
index bd481fdd6b87..43cd5c0f4f6f 100644
--- a/drivers/gpu/drm/drm_vblank_work.c
+++ b/drivers/gpu/drm/drm_vblank_work.c
@@ -73,6 +73,9 @@ void drm_vblank_cancel_pending_works(struct drm_vblank_crtc 
*vblank)
 
assert_spin_locked(>dev->event_lock);
 
+   drm_WARN_ONCE(vblank->dev, !list_empty(>pending_work),
+ "Cancelling pending vblank works!\n");
+
list_for_each_entry_safe(work, next, >pending_work, node) {
list_del_init(>node);
drm_vblank_put(vblank->dev, vblank->pipe);
-- 
2.41.0



[PATCH v2 1/2] drm/i915: Use vblank worker to unpin old legacy cursor fb safely

2023-09-03 Thread Ville Syrjala
From: Ville Syrjälä 

The cursor hardware only does sync updates, and thus the hardware
will be scanning out from the old fb until the next start of vblank.
So in order to make the legacy cursor fastpath actually safe we
should not unpin the old fb until we're sure the hardware has
ceased accessing it. The simplest approach is to just use a vblank
work here to do the delayed unpin.

Not 100% sure it's a good idea to put this onto the same high
priority vblank worker as eg. our timing critical gamma updates.
But let's keep it simple for now, and it we later discover that
this is causing problems we can think about adding a lower
priority worker for such things.

v2: wait for cursor unpins before turning off the vblank irq

Cc: Maarten Lankhorst 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_cursor.c   | 36 +--
 drivers/gpu/drm/i915/display/intel_cursor.h   |  2 ++
 drivers/gpu/drm/i915/display/intel_display.c  |  3 ++
 .../drm/i915/display/intel_display_types.h|  4 +++
 4 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c 
b/drivers/gpu/drm/i915/display/intel_cursor.c
index b342fad180ca..625540fd1dab 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -603,6 +603,26 @@ static bool intel_cursor_format_mod_supported(struct 
drm_plane *_plane,
return format == DRM_FORMAT_ARGB;
 }
 
+static void intel_cursor_unpin_work(struct kthread_work *base)
+{
+   struct drm_vblank_work *work = to_drm_vblank_work(base);
+   struct intel_plane_state *plane_state =
+   container_of(work, typeof(*plane_state), unpin_work);
+   struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+
+   intel_plane_unpin_fb(plane_state);
+   intel_plane_destroy_state(>base, _state->uapi);
+
+   if (atomic_dec_and_test(>cursor.pending_unpins))
+   wake_up_var(>cursor.pending_unpins);
+}
+
+void intel_cursor_wait_unpin_works(struct intel_plane *plane)
+{
+   wait_var_event(>cursor.pending_unpins,
+  !atomic_read(>cursor.pending_unpins));
+}
+
 static int
 intel_legacy_cursor_update(struct drm_plane *_plane,
   struct drm_crtc *_crtc,
@@ -730,14 +750,26 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
 
local_irq_enable();
 
-   intel_plane_unpin_fb(old_plane_state);
+   if (old_plane_state->hw.fb != new_plane_state->hw.fb) {
+   drm_vblank_work_init(_plane_state->unpin_work, >base,
+intel_cursor_unpin_work);
+
+   atomic_inc(>cursor.pending_unpins);
+   drm_vblank_work_schedule(_plane_state->unpin_work,
+
drm_crtc_accurate_vblank_count(>base) + 1,
+false);
+
+   old_plane_state = NULL;
+   } else {
+   intel_plane_unpin_fb(old_plane_state);
+   }
 
 out_free:
if (new_crtc_state)
intel_crtc_destroy_state(>base, _crtc_state->uapi);
if (ret)
intel_plane_destroy_state(>base, _plane_state->uapi);
-   else
+   else if (old_plane_state)
intel_plane_destroy_state(>base, _plane_state->uapi);
return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.h 
b/drivers/gpu/drm/i915/display/intel_cursor.h
index ce333bf4c2d5..e778aff77129 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.h
+++ b/drivers/gpu/drm/i915/display/intel_cursor.h
@@ -14,4 +14,6 @@ struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
  enum pipe pipe);
 
+void intel_cursor_wait_unpin_works(struct intel_plane *plane);
+
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index f6397462e4c2..90c1ed61ba0e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -63,6 +63,7 @@
 #include "intel_crt.h"
 #include "intel_crtc.h"
 #include "intel_crtc_state_dump.h"
+#include "intel_cursor.h"
 #include "intel_ddi.h"
 #include "intel_de.h"
 #include "intel_display_driver.h"
@@ -6618,6 +6619,8 @@ static void intel_commit_modeset_disables(struct 
intel_atomic_state *state)
 
intel_pre_plane_update(state, crtc);
intel_crtc_disable_planes(state, crtc);
+
+   
intel_cursor_wait_unpin_works(to_intel_plane(crtc->base.cursor));
}
 
/* Only disable port sync and MST slaves */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index c21064794f32..f6ca86f1d834 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -702,6 +702,9 @@ struct intel_plane_state {
 
struct 

[PATCH v2 03/12] drm/i915: Call the DDC bus i2c adapter "ddc"

2023-08-31 Thread Ville Syrjala
From: Ville Syrjälä 

Rename the various names we've used for the DDC bus
i2c adapter ("i2c", "adapter", etc.) to just "ddc".
This differentiates it from the various other i2c
busses we might have (DSI panel stuff, DVO control bus, etc.).

v2: Don't add a bogus drm_get_edid() call (Jani)

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_connector.c|  6 +--
 .../gpu/drm/i915/display/intel_connector.h|  2 +-
 drivers/gpu/drm/i915/display/intel_crt.c  | 32 ++--
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c | 51 ---
 drivers/gpu/drm/i915/display/intel_lspcon.c   | 14 ++---
 6 files changed, 51 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_connector.c 
b/drivers/gpu/drm/i915/display/intel_connector.c
index ff3bcadebe59..c65887870ddc 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -192,17 +192,17 @@ int intel_connector_update_modes(struct drm_connector 
*connector,
 /**
  * intel_ddc_get_modes - get modelist from monitor
  * @connector: DRM connector device to use
- * @adapter: i2c adapter
+ * @ddc: DDC bus i2c adapter
  *
  * Fetch the EDID information from @connector using the DDC bus.
  */
 int intel_ddc_get_modes(struct drm_connector *connector,
-   struct i2c_adapter *adapter)
+   struct i2c_adapter *ddc)
 {
const struct drm_edid *drm_edid;
int ret;
 
-   drm_edid = drm_edid_read_ddc(connector, adapter);
+   drm_edid = drm_edid_read_ddc(connector, ddc);
if (!drm_edid)
return 0;
 
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h 
b/drivers/gpu/drm/i915/display/intel_connector.h
index aaf7281462dc..bafde3f11ff4 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -26,7 +26,7 @@ bool intel_connector_get_hw_state(struct intel_connector 
*connector);
 enum pipe intel_connector_get_pipe(struct intel_connector *connector);
 int intel_connector_update_modes(struct drm_connector *connector,
 const struct drm_edid *drm_edid);
-int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
+int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *ddc);
 void intel_attach_force_audio_property(struct drm_connector *connector);
 void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 void intel_attach_aspect_ratio_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c 
b/drivers/gpu/drm/i915/display/intel_crt.c
index f66340b4caf0..8145511bd5c3 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -610,18 +610,18 @@ static bool intel_crt_detect_hotplug(struct drm_connector 
*connector)
 }
 
 static const struct drm_edid *intel_crt_get_edid(struct drm_connector 
*connector,
-struct i2c_adapter *i2c)
+struct i2c_adapter *ddc)
 {
const struct drm_edid *drm_edid;
 
-   drm_edid = drm_edid_read_ddc(connector, i2c);
+   drm_edid = drm_edid_read_ddc(connector, ddc);
 
-   if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
+   if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
drm_dbg_kms(connector->dev,
"CRT GMBUS EDID read failed, retry using GPIO 
bit-banging\n");
-   intel_gmbus_force_bit(i2c, true);
-   drm_edid = drm_edid_read_ddc(connector, i2c);
-   intel_gmbus_force_bit(i2c, false);
+   intel_gmbus_force_bit(ddc, true);
+   drm_edid = drm_edid_read_ddc(connector, ddc);
+   intel_gmbus_force_bit(ddc, false);
}
 
return drm_edid;
@@ -629,12 +629,12 @@ static const struct drm_edid *intel_crt_get_edid(struct 
drm_connector *connector
 
 /* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
 static int intel_crt_ddc_get_modes(struct drm_connector *connector,
-   struct i2c_adapter *adapter)
+  struct i2c_adapter *ddc)
 {
const struct drm_edid *drm_edid;
int ret;
 
-   drm_edid = intel_crt_get_edid(connector, adapter);
+   drm_edid = intel_crt_get_edid(connector, ddc);
if (!drm_edid)
return 0;
 
@@ -650,11 +650,11 @@ static bool intel_crt_detect_ddc(struct drm_connector 
*connector)
struct intel_crt *crt = 
intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
const struct drm_edid *drm_edid;
-   struct i2c_adapter *i2c;
+   struct i2c_adapter *ddc;
bool ret = false;
 
-   i2c = 

[PATCH 11/12] drm/i915/hdmi: Remove old i2c symlink

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Remove the i915 specific i2c-N symlink from HDMI connectors.
This was added to sort of mirror the DP connectors that alreayd
had their aux ch based i2c adapter sitting beneath them in the
sysfs hierarchy. But now that we have the standard "ddc" symlink
approach provided by the core let's switch to that fully.
I don't think anything beyond igt depends on this.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 25 ---
 1 file changed, 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 6b8754290304..e9dcd3d5f6e4 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2544,28 +2544,6 @@ static int intel_hdmi_get_modes(struct drm_connector 
*connector)
return drm_edid_connector_add_modes(connector);
 }
 
-static void intel_hdmi_create_i2c_symlink(struct drm_connector *connector)
-{
-   struct drm_i915_private *i915 = to_i915(connector->dev);
-   struct i2c_adapter *ddc = connector->ddc;
-   struct kobject *i2c_kobj = >dev.kobj;
-   struct kobject *connector_kobj = >kdev->kobj;
-   int ret;
-
-   ret = sysfs_create_link(connector_kobj, i2c_kobj, i2c_kobj->name);
-   if (ret)
-   drm_err(>drm, "Failed to create i2c symlink (%d)\n", ret);
-}
-
-static void intel_hdmi_remove_i2c_symlink(struct drm_connector *connector)
-{
-   struct i2c_adapter *ddc = connector->ddc;
-   struct kobject *i2c_kobj = >dev.kobj;
-   struct kobject *connector_kobj = >kdev->kobj;
-
-   sysfs_remove_link(connector_kobj, i2c_kobj->name);
-}
-
 static int
 intel_hdmi_connector_register(struct drm_connector *connector)
 {
@@ -2575,8 +2553,6 @@ intel_hdmi_connector_register(struct drm_connector 
*connector)
if (ret)
return ret;
 
-   intel_hdmi_create_i2c_symlink(connector);
-
return ret;
 }
 
@@ -2586,7 +2562,6 @@ static void intel_hdmi_connector_unregister(struct 
drm_connector *connector)
 
cec_notifier_conn_unregister(n);
 
-   intel_hdmi_remove_i2c_symlink(connector);
intel_connector_unregister(connector);
 }
 
-- 
2.41.0



[PATCH 12/12] drm/i915/sdvo: Constify mapping structs

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

We aren't intending to mutate the SDVO device mapping structs,
so make them const.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_sdvo.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c 
b/drivers/gpu/drm/i915/display/intel_sdvo.c
index b988e05274c1..0bd815bf2e69 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2579,7 +2579,7 @@ intel_sdvo_select_ddc_bus(struct intel_sdvo *sdvo,
  struct intel_sdvo_connector *connector)
 {
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
-   struct sdvo_device_mapping *mapping;
+   const struct sdvo_device_mapping *mapping;
int ddc_bus;
 
if (sdvo->base.port == PORT_B)
@@ -2602,7 +2602,7 @@ static void
 intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
 {
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
-   struct sdvo_device_mapping *mapping;
+   const struct sdvo_device_mapping *mapping;
u8 pin;
 
if (sdvo->base.port == PORT_B)
@@ -2647,7 +2647,7 @@ static u8
 intel_sdvo_get_slave_addr(struct intel_sdvo *sdvo)
 {
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
-   struct sdvo_device_mapping *my_mapping, *other_mapping;
+   const struct sdvo_device_mapping *my_mapping, *other_mapping;
 
if (sdvo->base.port == PORT_B) {
my_mapping = _priv->display.vbt.sdvo_mappings[0];
-- 
2.41.0



[PATCH 10/12] drm/i915/hdmi: Nuke hdmi->ddc_bus

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Remove the mostly redundant hdmi->ddc_bus. The only thing that needs
it anymore is get_encoder_by_ddc_bus(), but that can be replaced with
a slight detour through attached_connector+intel_gmbus_get_adapter().

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display_types.h |  1 -
 drivers/gpu/drm/i915/display/intel_hdmi.c  | 13 +
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index c62f4ec315e8..363b6573a5f9 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1581,7 +1581,6 @@ struct intel_watermark_params {
 
 struct intel_hdmi {
i915_reg_t hdmi_reg;
-   int ddc_bus;
struct {
enum drm_dp_dual_mode_type type;
int max_tmds_clock;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index efa9bb93cfb1..6b8754290304 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2900,13 +2900,17 @@ get_encoder_by_ddc_pin(struct intel_encoder *encoder, 
u8 ddc_pin)
struct intel_encoder *other;
 
for_each_intel_encoder(>drm, other) {
+   struct intel_connector *connector;
+
if (other == encoder)
continue;
 
if (!intel_encoder_is_dig_port(other))
continue;
 
-   if (enc_to_dig_port(other)->hdmi.ddc_bus == ddc_pin)
+   connector = enc_to_dig_port(other)->hdmi.attached_connector;
+
+   if (connector && connector->base.ddc == 
intel_gmbus_get_adapter(i915, ddc_pin))
return other;
}
 
@@ -3000,6 +3004,7 @@ void intel_hdmi_init_connector(struct intel_digital_port 
*dig_port,
struct drm_i915_private *dev_priv = to_i915(dev);
enum port port = intel_encoder->port;
struct cec_connector_info conn_info;
+   u8 ddc_pin;
 
drm_dbg_kms(_priv->drm,
"Adding HDMI connector on [ENCODER:%d:%s]\n",
@@ -3014,14 +3019,14 @@ void intel_hdmi_init_connector(struct 
intel_digital_port *dig_port,
 intel_encoder->base.name))
return;
 
-   intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder);
-   if (!intel_hdmi->ddc_bus)
+   ddc_pin = intel_hdmi_ddc_pin(intel_encoder);
+   if (!ddc_pin)
return;
 
drm_connector_init_with_ddc(dev, connector,
_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
-   intel_gmbus_get_adapter(dev_priv, 
intel_hdmi->ddc_bus));
+   intel_gmbus_get_adapter(dev_priv, ddc_pin));
 
drm_connector_helper_add(connector, _hdmi_connector_helper_funcs);
 
-- 
2.41.0



[PATCH 09/12] drm/i915/hdmi: Use connector->ddc everwhere

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

We already populate connector->ddc for HDMI ports, but
so far we've not taken full advantage of it. Do that by
eliminating a bunch of intel_gmbus_get_adapter() lookups.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |  3 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c | 37 ---
 2 files changed, 14 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index e6cc4dab3201..d86ce93fb57f 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4323,8 +4323,7 @@ static int intel_hdmi_reset_link(struct intel_encoder 
*encoder,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
struct intel_connector *connector = hdmi->attached_connector;
-   struct i2c_adapter *ddc =
-   intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
+   struct i2c_adapter *ddc = connector->base.ddc;
struct drm_connector_state *conn_state;
struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 82f9a40b34e3..efa9bb93cfb1 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -1240,7 +1240,7 @@ static void hsw_set_infoframes(struct intel_encoder 
*encoder,
 void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
 {
struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi);
-   struct i2c_adapter *ddc = intel_gmbus_get_adapter(dev_priv, 
hdmi->ddc_bus);
+   struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
 
if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI)
return;
@@ -1255,9 +1255,8 @@ void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi 
*hdmi, bool enable)
 static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
unsigned int offset, void *buffer, size_t size)
 {
-   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = _port->hdmi;
-   struct i2c_adapter *ddc = intel_gmbus_get_adapter(i915, hdmi->ddc_bus);
+   struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
int ret;
u8 start = offset & 0xff;
struct i2c_msg msgs[] = {
@@ -1283,9 +1282,8 @@ static int intel_hdmi_hdcp_read(struct intel_digital_port 
*dig_port,
 static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port,
 unsigned int offset, void *buffer, size_t size)
 {
-   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = _port->hdmi;
-   struct i2c_adapter *ddc = intel_gmbus_get_adapter(i915, hdmi->ddc_bus);
+   struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
int ret;
u8 *write_buf;
struct i2c_msg msg;
@@ -1318,7 +1316,7 @@ int intel_hdmi_hdcp_write_an_aksv(struct 
intel_digital_port *dig_port,
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = _port->hdmi;
-   struct i2c_adapter *ddc = intel_gmbus_get_adapter(i915, hdmi->ddc_bus);
+   struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
int ret;
 
ret = intel_hdmi_hdcp_write(dig_port, DRM_HDCP_DDC_AN, an,
@@ -2398,8 +2396,10 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector 
*connector)
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *hdmi = 
intel_attached_hdmi(to_intel_connector(connector));
struct intel_encoder *encoder = _to_dig_port(hdmi)->base;
-   struct i2c_adapter *ddc = intel_gmbus_get_adapter(dev_priv, 
hdmi->ddc_bus);
-   enum drm_dp_dual_mode_type type = 
drm_dp_dual_mode_detect(_priv->drm, ddc);
+   struct i2c_adapter *ddc = connector->ddc;
+   enum drm_dp_dual_mode_type type;
+
+   type = drm_dp_dual_mode_detect(_priv->drm, ddc);
 
/*
 * Type 1 DVI adaptors are not required to implement any
@@ -2447,7 +2447,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 {
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *intel_hdmi = 
intel_attached_hdmi(to_intel_connector(connector));
-   struct i2c_adapter *ddc = intel_gmbus_get_adapter(dev_priv, 
intel_hdmi->ddc_bus);
+   struct i2c_adapter *ddc = connector->ddc;
intel_wakeref_t wakeref;
const struct drm_edid *drm_edid;
const struct edid *edid;
@@ -2544,19 +2544,10 @@ static int intel_hdmi_get_modes(struct drm_connector 
*connector)
return drm_edid_connector_add_modes(connector);
 }
 
-static struct i2c_adapter *
-intel_hdmi_get_i2c_adapter(struct 

[PATCH 08/12] drm/i915/mst: Populate connector->ddc

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Populate connector->ddc, and thus create the "ddc" symlink
in sysfs for DP MST connectors.

TODO: test that this actually works

References: https://gitlab.freedesktop.org/drm/intel/-/issues/3605
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2d1c42a5e684..0bf02a29e371 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1104,8 +1104,10 @@ static struct drm_connector 
*intel_dp_add_mst_connector(struct drm_dp_mst_topolo
drm_dp_mst_get_port_malloc(port);
 
connector = _connector->base;
-   ret = drm_connector_init(dev, connector, _dp_mst_connector_funcs,
-DRM_MODE_CONNECTOR_DisplayPort);
+   ret = drm_connector_init_with_ddc(dev, connector,
+ _dp_mst_connector_funcs,
+ DRM_MODE_CONNECTOR_DisplayPort,
+ >aux.ddc);
if (ret) {
drm_dp_mst_put_port_malloc(port);
intel_connector_free(intel_connector);
-- 
2.41.0



[PATCH 07/12] drm/i915/dp: Populate connector->ddc

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Populate connector->ddc, and thus create the "ddc" symlink
in sysfs for analog DP SST connectors.

Let's also reorder intel_dp_aux_init() vs. drm_connector_init_with_ddc()
a bit to make sure the i2c aux ch is at least somewhat populated
before we pass it on, though drm_connector_init_with_ddc() does
not actually do anything with it.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 05694e0b6143..9b35b1d6adbb 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5914,7 +5914,7 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
}
 
mutex_lock(_priv->drm.mode_config.mutex);
-   drm_edid = drm_edid_read_ddc(connector, _dp->aux.ddc);
+   drm_edid = drm_edid_read_ddc(connector, connector->ddc);
if (!drm_edid) {
/* Fallback to EDID from ACPI OpRegion, if any */
drm_edid = intel_opregion_get_edid(intel_connector);
@@ -6053,12 +6053,15 @@ intel_dp_init_connector(struct intel_digital_port 
*dig_port,
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
 
+   intel_dp_aux_init(intel_dp);
+
drm_dbg_kms(_priv->drm,
"Adding %s connector on [ENCODER:%d:%s]\n",
type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP",
intel_encoder->base.base.id, intel_encoder->base.name);
 
-   drm_connector_init(dev, connector, _dp_connector_funcs, type);
+   drm_connector_init_with_ddc(dev, connector, _dp_connector_funcs,
+   type, _dp->aux.ddc);
drm_connector_helper_add(connector, _dp_connector_helper_funcs);
 
if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12)
@@ -6066,8 +6069,6 @@ intel_dp_init_connector(struct intel_digital_port 
*dig_port,
 
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-   intel_dp_aux_init(intel_dp);
-
intel_connector_attach_encoder(intel_connector, intel_encoder);
 
if (HAS_DDI(dev_priv))
-- 
2.41.0



[PATCH 06/12] drm/i915/dvo: Populate connector->ddc

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Populate connector->ddc, and thus create the "ddc" symlink
in sysfs for DVO connectors.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dvo.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c 
b/drivers/gpu/drm/i915/display/intel_dvo.c
index b386894c3a6d..d9f427856fb8 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.c
+++ b/drivers/gpu/drm/i915/display/intel_dvo.c
@@ -328,7 +328,6 @@ intel_dvo_detect(struct drm_connector *_connector, bool 
force)
 static int intel_dvo_get_modes(struct drm_connector *_connector)
 {
struct intel_connector *connector = to_intel_connector(_connector);
-   struct drm_i915_private *i915 = to_i915(connector->base.dev);
int num_modes;
 
/*
@@ -337,8 +336,7 @@ static int intel_dvo_get_modes(struct drm_connector 
*_connector)
 * (TV-out, for example), but for now with just TMDS and LVDS,
 * that's not the case.
 */
-   num_modes = intel_ddc_get_modes(>base,
-   intel_gmbus_get_adapter(i915, 
GMBUS_PIN_DPC));
+   num_modes = intel_ddc_get_modes(>base, connector->base.ddc);
if (num_modes)
return num_modes;
 
@@ -533,9 +531,10 @@ void intel_dvo_init(struct drm_i915_private *i915)
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
 
-   drm_connector_init(>drm, >base,
-  _dvo_connector_funcs,
-  intel_dvo_connector_type(_dvo->dev));
+   drm_connector_init_with_ddc(>drm, >base,
+   _dvo_connector_funcs,
+   intel_dvo_connector_type(_dvo->dev),
+   intel_gmbus_get_adapter(i915, 
GMBUS_PIN_DPC));
 
drm_connector_helper_add(>base,
 _dvo_connector_helper_funcs);
-- 
2.41.0



[PATCH 05/12] drm/i915/crt: Populate connector->ddc

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Populate connector->ddc, and thus create the "ddc" symlink
in sysfs for analog VGA connectors.

As a bonus we can replace a bunch of intel_gmbus_get_adapter()
lookups with just the connector->ddc pointer. Sadly one extra
lookup still remains due to the g4x DVI-I shenanigans. We could
perhaps consider borrowing the ddc proxy idea from SDVO to deal
with that in a perhaps nicer way, but can't really be bothered
right now at least. Also not sure exposing such a dual ddc bus
to userspace would be quite wise.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_crt.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_crt.c 
b/drivers/gpu/drm/i915/display/intel_crt.c
index 8145511bd5c3..ea3908fd2505 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -650,11 +650,9 @@ static bool intel_crt_detect_ddc(struct drm_connector 
*connector)
struct intel_crt *crt = 
intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
const struct drm_edid *drm_edid;
-   struct i2c_adapter *ddc;
bool ret = false;
 
-   ddc = intel_gmbus_get_adapter(dev_priv, 
dev_priv->display.vbt.crt_ddc_pin);
-   drm_edid = intel_crt_get_edid(connector, ddc);
+   drm_edid = intel_crt_get_edid(connector, connector->ddc);
 
if (drm_edid) {
const struct edid *edid = drm_edid_raw(drm_edid);
@@ -923,8 +921,7 @@ static int intel_crt_get_modes(struct drm_connector 
*connector)
wakeref = intel_display_power_get(dev_priv,
  intel_encoder->power_domain);
 
-   ddc = intel_gmbus_get_adapter(dev_priv, 
dev_priv->display.vbt.crt_ddc_pin);
-   ret = intel_crt_ddc_get_modes(connector, ddc);
+   ret = intel_crt_ddc_get_modes(connector, connector->ddc);
if (ret || !IS_G4X(dev_priv))
goto out;
 
@@ -988,6 +985,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
struct intel_crt *crt;
struct intel_connector *intel_connector;
i915_reg_t adpa_reg;
+   u8 ddc_pin;
u32 adpa;
 
if (HAS_PCH_SPLIT(dev_priv))
@@ -1024,10 +1022,14 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
return;
}
 
+   ddc_pin = dev_priv->display.vbt.crt_ddc_pin;
+
connector = _connector->base;
crt->connector = intel_connector;
-   drm_connector_init(_priv->drm, _connector->base,
-  _crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+   drm_connector_init_with_ddc(_priv->drm, connector,
+   _crt_connector_funcs,
+   DRM_MODE_CONNECTOR_VGA,
+   intel_gmbus_get_adapter(dev_priv, ddc_pin));
 
drm_encoder_init(_priv->drm, >base.base, _crt_enc_funcs,
 DRM_MODE_ENCODER_DAC, "CRT");
-- 
2.41.0



[PATCH 03/12] drm/i915: Call the DDC bus i2c adapter "ddc"

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Rename the various names we've used for the DDC bus
i2c adapter ("i2c", "adapter", etc.) to just "ddc".
This differentiates it from the various other i2c
busses we might have (DSI panel stuff, DVO control bus, etc.).

Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_connector.c|  6 +--
 .../gpu/drm/i915/display/intel_connector.h|  2 +-
 drivers/gpu/drm/i915/display/intel_crt.c  | 32 ++--
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c | 51 +--
 drivers/gpu/drm/i915/display/intel_lspcon.c   | 14 ++---
 6 files changed, 52 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_connector.c 
b/drivers/gpu/drm/i915/display/intel_connector.c
index ff3bcadebe59..c65887870ddc 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -192,17 +192,17 @@ int intel_connector_update_modes(struct drm_connector 
*connector,
 /**
  * intel_ddc_get_modes - get modelist from monitor
  * @connector: DRM connector device to use
- * @adapter: i2c adapter
+ * @ddc: DDC bus i2c adapter
  *
  * Fetch the EDID information from @connector using the DDC bus.
  */
 int intel_ddc_get_modes(struct drm_connector *connector,
-   struct i2c_adapter *adapter)
+   struct i2c_adapter *ddc)
 {
const struct drm_edid *drm_edid;
int ret;
 
-   drm_edid = drm_edid_read_ddc(connector, adapter);
+   drm_edid = drm_edid_read_ddc(connector, ddc);
if (!drm_edid)
return 0;
 
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h 
b/drivers/gpu/drm/i915/display/intel_connector.h
index aaf7281462dc..bafde3f11ff4 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -26,7 +26,7 @@ bool intel_connector_get_hw_state(struct intel_connector 
*connector);
 enum pipe intel_connector_get_pipe(struct intel_connector *connector);
 int intel_connector_update_modes(struct drm_connector *connector,
 const struct drm_edid *drm_edid);
-int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
+int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *ddc);
 void intel_attach_force_audio_property(struct drm_connector *connector);
 void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 void intel_attach_aspect_ratio_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c 
b/drivers/gpu/drm/i915/display/intel_crt.c
index f66340b4caf0..8145511bd5c3 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -610,18 +610,18 @@ static bool intel_crt_detect_hotplug(struct drm_connector 
*connector)
 }
 
 static const struct drm_edid *intel_crt_get_edid(struct drm_connector 
*connector,
-struct i2c_adapter *i2c)
+struct i2c_adapter *ddc)
 {
const struct drm_edid *drm_edid;
 
-   drm_edid = drm_edid_read_ddc(connector, i2c);
+   drm_edid = drm_edid_read_ddc(connector, ddc);
 
-   if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
+   if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
drm_dbg_kms(connector->dev,
"CRT GMBUS EDID read failed, retry using GPIO 
bit-banging\n");
-   intel_gmbus_force_bit(i2c, true);
-   drm_edid = drm_edid_read_ddc(connector, i2c);
-   intel_gmbus_force_bit(i2c, false);
+   intel_gmbus_force_bit(ddc, true);
+   drm_edid = drm_edid_read_ddc(connector, ddc);
+   intel_gmbus_force_bit(ddc, false);
}
 
return drm_edid;
@@ -629,12 +629,12 @@ static const struct drm_edid *intel_crt_get_edid(struct 
drm_connector *connector
 
 /* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
 static int intel_crt_ddc_get_modes(struct drm_connector *connector,
-   struct i2c_adapter *adapter)
+  struct i2c_adapter *ddc)
 {
const struct drm_edid *drm_edid;
int ret;
 
-   drm_edid = intel_crt_get_edid(connector, adapter);
+   drm_edid = intel_crt_get_edid(connector, ddc);
if (!drm_edid)
return 0;
 
@@ -650,11 +650,11 @@ static bool intel_crt_detect_ddc(struct drm_connector 
*connector)
struct intel_crt *crt = 
intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
const struct drm_edid *drm_edid;
-   struct i2c_adapter *i2c;
+   struct i2c_adapter *ddc;
bool ret = false;
 
-   i2c = intel_gmbus_get_adapter(dev_priv, 
dev_priv->display.vbt.crt_ddc_pin);
-   

[PATCH 04/12] drm/i915/lvds: Populate connector->ddc

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Populate connector->ddc, and thus create the "ddc" symlink
in sysfs for the LVDS port.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_lvds.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c 
b/drivers/gpu/drm/i915/display/intel_lvds.c
index 3ace56979b70..2306e133e3f6 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -837,7 +837,7 @@ void intel_lvds_init(struct drm_i915_private *i915)
struct intel_encoder *encoder;
i915_reg_t lvds_reg;
u32 lvds;
-   u8 pin;
+   u8 ddc_pin;
 
/* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds)) {
@@ -864,8 +864,8 @@ void intel_lvds_init(struct drm_i915_private *i915)
return;
}
 
-   pin = GMBUS_PIN_PANEL;
-   if (!intel_bios_is_lvds_present(i915, )) {
+   ddc_pin = GMBUS_PIN_PANEL;
+   if (!intel_bios_is_lvds_present(i915, _pin)) {
if ((lvds & LVDS_PORT_EN) == 0) {
drm_dbg_kms(>drm,
"LVDS is not present in VBT\n");
@@ -888,8 +888,10 @@ void intel_lvds_init(struct drm_i915_private *i915)
lvds_encoder->attached_connector = connector;
encoder = _encoder->base;
 
-   drm_connector_init(>drm, >base, 
_lvds_connector_funcs,
-  DRM_MODE_CONNECTOR_LVDS);
+   drm_connector_init_with_ddc(>drm, >base,
+   _lvds_connector_funcs,
+   DRM_MODE_CONNECTOR_LVDS,
+   intel_gmbus_get_adapter(i915, ddc_pin));
 
drm_encoder_init(>drm, >base, _lvds_enc_funcs,
 DRM_MODE_ENCODER_LVDS, "LVDS");
@@ -943,13 +945,10 @@ void intel_lvds_init(struct drm_i915_private *i915)
 * preferred mode is the right one.
 */
mutex_lock(>drm.mode_config.mutex);
-   if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) {
-   drm_edid = drm_edid_read_switcheroo(>base,
-   
intel_gmbus_get_adapter(i915, pin));
-   } else {
-   drm_edid = drm_edid_read_ddc(>base,
-intel_gmbus_get_adapter(i915, 
pin));
-   }
+   if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)
+   drm_edid = drm_edid_read_switcheroo(>base, 
connector->base.ddc);
+   else
+   drm_edid = drm_edid_read_ddc(>base, 
connector->base.ddc);
if (drm_edid) {
if (drm_edid_connector_update(>base, drm_edid) ||
!drm_edid_connector_add_modes(>base)) {
-- 
2.41.0



[PATCH 02/12] drm/sysfs: Register "ddc" symlink later

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Currently drm_sysfs_connector_add() attempts to register
the "ddc" symlink (based one connector->ddc) before the
driver's .early_register() hook has been called. That is
too early for i915 which only fully registers the aux ch
and associated i2c bus from said hook (to prevent half
initialized stuff getting exposed to userspace). This
causes my attempt at using drm_connector_init_with_ddc()
to fail, and the entire connector disappears from sysfs
on account of sysfs_create_link() failing.

To fix that split the sysfs symlink stuff into separate
functions (drm_sysfs_connector_add_late() and
drm_sysfs_connector_remove_early()) which are called
on the opposite side of the .later_register() and
.early_unregister() hooks.

Cc: Andrzej Pietrasiewicz 
Cc: Daniel Vetter 
Cc: Andrzej Hajda 
Cc: Emil Velikov 
Cc: Sam Ravnborg 
Cc: Neil Armstrong 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_connector.c |  9 +
 drivers/gpu/drm/drm_internal.h  |  2 ++
 drivers/gpu/drm/drm_sysfs.c | 22 +++---
 3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 988996cf6da5..9d4c7b0c5c05 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -631,6 +631,10 @@ int drm_connector_register(struct drm_connector *connector)
goto err_debugfs;
}
 
+   ret = drm_sysfs_connector_add_late(connector);
+   if (ret)
+   goto err_late_register;
+
drm_mode_object_register(connector->dev, >base);
 
connector->registration_state = DRM_CONNECTOR_REGISTERED;
@@ -647,6 +651,9 @@ int drm_connector_register(struct drm_connector *connector)
mutex_unlock(_list_lock);
goto unlock;
 
+err_late_register:
+   if (connector->funcs->early_unregister)
+   connector->funcs->early_unregister(connector);
 err_debugfs:
drm_debugfs_connector_remove(connector);
drm_sysfs_connector_remove(connector);
@@ -681,6 +688,8 @@ void drm_connector_unregister(struct drm_connector 
*connector)
connector->privacy_screen,
>privacy_screen_notifier);
 
+   drm_sysfs_connector_remove_early(connector);
+
if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);
 
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index ba12acd55139..4053cf8105ce 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -153,6 +153,8 @@ int drm_sysfs_init(void);
 void drm_sysfs_destroy(void);
 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
 int drm_sysfs_connector_add(struct drm_connector *connector);
+int drm_sysfs_connector_add_late(struct drm_connector *connector);
+void drm_sysfs_connector_remove_early(struct drm_connector *connector);
 void drm_sysfs_connector_remove(struct drm_connector *connector);
 
 void drm_sysfs_lease_event(struct drm_device *dev);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index b169b3e44a92..a953f69a34b6 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -400,10 +400,6 @@ int drm_sysfs_connector_add(struct drm_connector 
*connector)
drm_err(dev, "failed to add component to create link to 
typec connector\n");
}
 
-   if (connector->ddc)
-   return sysfs_create_link(>kdev->kobj,
->ddc->dev.kobj, "ddc");
-
return 0;
 
 err_free:
@@ -411,14 +407,26 @@ int drm_sysfs_connector_add(struct drm_connector 
*connector)
return r;
 }
 
+int drm_sysfs_connector_add_late(struct drm_connector *connector)
+{
+   if (connector->ddc)
+   return sysfs_create_link(>kdev->kobj,
+>ddc->dev.kobj, "ddc");
+
+   return 0;
+}
+
+void drm_sysfs_connector_remove_early(struct drm_connector *connector)
+{
+   if (connector->ddc)
+   sysfs_remove_link(>kdev->kobj, "ddc");
+}
+
 void drm_sysfs_connector_remove(struct drm_connector *connector)
 {
if (!connector->kdev)
return;
 
-   if (connector->ddc)
-   sysfs_remove_link(>kdev->kobj, "ddc");
-
if (dev_fwnode(connector->kdev))
component_del(connector->kdev, _connector_ops);
 
-- 
2.41.0



[PATCH 01/12] drm: Reorder drm_sysfs_connector_remove() vs. drm_debugfs_connector_remove()

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Use the standard onion peeling approach and call
drm_debugfs_connector_remove() and
drm_sysfs_connector_remove() in the reverse order in
drm_connector_unregister() than what we called their
add counterpartse in drm_connector_register().

The error unwiding in drm_connector_register() is
already doing this the correct way around.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_connector.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index c44d5bcf1284..988996cf6da5 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -684,8 +684,8 @@ void drm_connector_unregister(struct drm_connector 
*connector)
if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);
 
-   drm_sysfs_connector_remove(connector);
drm_debugfs_connector_remove(connector);
+   drm_sysfs_connector_remove(connector);
 
connector->registration_state = DRM_CONNECTOR_UNREGISTERED;
mutex_unlock(>mutex);
-- 
2.41.0



[PATCH 00/12] drm/i915: Populate connector->ddc always

2023-08-29 Thread Ville Syrjala
From: Ville Syrjälä 

Populate connector->ddc for all output types that don't already
do so, and clean up a bunch of code as a result of having the
ddc i2c adapter in easy reach. And this also provides the sysfs
"ddc" symlink.

There are potentially a few oddball (mostly DVI-I) cases where
the connector detection/EDID read uses an alternate DDC bus
internally, and so for those the symlink might not point at the
correct i2c adapter. I'm not interested in spending extra brain
cells on those, so we'll leave them as is for now.

Ville Syrjälä (12):
  drm: Reorder drm_sysfs_connector_remove() vs.
drm_debugfs_connector_remove()
  drm/sysfs: Register "ddc" symlink later
  drm/i915: Call the DDC bus i2c adapter "ddc"
  drm/i915/lvds: Populate connector->ddc
  drm/i915/crt: Populate connector->ddc
  drm/i915/dvo: Populate connector->ddc
  drm/i915/dp: Populate connector->ddc
  drm/i915/mst: Populate connector->ddc
  drm/i915/hdmi: Use connector->ddc everwhere
  drm/i915/hdmi: Nuke hdmi->ddc_bus
  drm/i915/hdmi: Remove old i2c symlink
  drm/i915/sdvo: Constify mapping structs

 drivers/gpu/drm/drm_connector.c   | 11 ++-
 drivers/gpu/drm/drm_internal.h|  2 +
 drivers/gpu/drm/drm_sysfs.c   | 22 +++--
 .../gpu/drm/i915/display/intel_connector.c|  6 +-
 .../gpu/drm/i915/display/intel_connector.h|  2 +-
 drivers/gpu/drm/i915/display/intel_crt.c  | 38 +++
 drivers/gpu/drm/i915/display/intel_ddi.c  |  5 +-
 .../drm/i915/display/intel_display_types.h|  1 -
 drivers/gpu/drm/i915/display/intel_dp.c   |  9 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  6 +-
 drivers/gpu/drm/i915/display/intel_dvo.c  | 11 +--
 drivers/gpu/drm/i915/display/intel_hdmi.c | 98 ++-
 drivers/gpu/drm/i915/display/intel_lspcon.c   | 14 +--
 drivers/gpu/drm/i915/display/intel_lvds.c | 23 +++--
 drivers/gpu/drm/i915/display/intel_sdvo.c |  6 +-
 15 files changed, 119 insertions(+), 135 deletions(-)

-- 
2.41.0



[PATCH] dma-buf/dma-resv: Stop leaking on krealloc() failure

2023-07-13 Thread Ville Syrjala
From: Ville Syrjälä 

Currently dma_resv_get_fences() will leak the previously
allocated array if the fence iteration got restarted and
the krealloc_array() fails.

Free the old array by hand, and make sure we still clear
the returned *fences so the caller won't end up accessing
freed memory. Some (but not all) of the callers of
dma_resv_get_fences() seem to still trawl through the
array even when dma_resv_get_fences() failed. And let's
zero out *num_fences as well for good measure.

Cc: Sumit Semwal 
Cc: Christian König 
Cc: linux-me...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linaro-mm-...@lists.linaro.org
Fixes: d3c80698c9f5 ("dma-buf: use new iterator in dma_resv_get_fences v3")
Signed-off-by: Ville Syrjälä 
---
 drivers/dma-buf/dma-resv.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index b6f71eb00866..38b4110378de 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum 
dma_resv_usage usage,
dma_resv_for_each_fence_unlocked(, fence) {
 
if (dma_resv_iter_is_restarted()) {
+   struct dma_fence **new_fences;
unsigned int count;
 
while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum 
dma_resv_usage usage,
count = cursor.num_fences + 1;
 
/* Eventually re-allocate the array */
-   *fences = krealloc_array(*fences, count,
-sizeof(void *),
-GFP_KERNEL);
-   if (count && !*fences) {
+   new_fences = krealloc_array(*fences, count,
+   sizeof(void *),
+   GFP_KERNEL);
+   if (count && !new_fences) {
+   kfree(*fences);
+   *fences = NULL;
+   *num_fences = 0;
dma_resv_iter_end();
return -ENOMEM;
}
+   *fences = new_fences;
}
 
(*fences)[(*num_fences)++] = dma_fence_get(fence);
-- 
2.39.3



[PATCH v2 08/11] drm/i915: Introduce crtc_state->enhanced_framing

2023-05-03 Thread Ville Syrjala
From: Ville Syrjälä 

Track DP enhanced framing properly in the crtc state instead
of relying just on the cached DPCD everywhere, and hook it
up into the state check and dump.

v2: Actually set enhanced_framing in .compute_config()

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/g4x_dp.c | 10 --
 drivers/gpu/drm/i915/display/intel_crt.c  |  2 ++
 drivers/gpu/drm/i915/display/intel_crtc_state_dump.c  |  5 +++--
 drivers/gpu/drm/i915/display/intel_ddi.c  | 11 +--
 drivers/gpu/drm/i915/display/intel_display.c  |  1 +
 drivers/gpu/drm/i915/display/intel_display_types.h|  2 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  3 +++
 drivers/gpu/drm/i915/display/intel_dp_link_training.c |  2 +-
 8 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c 
b/drivers/gpu/drm/i915/display/g4x_dp.c
index 920d570f7594..534546ea7d0b 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -141,7 +141,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
 
intel_de_rmw(dev_priv, TRANS_DP_CTL(crtc->pipe),
 TRANS_DP_ENH_FRAMING,
-drm_dp_enhanced_frame_cap(intel_dp->dpcd) ?
+pipe_config->enhanced_framing ?
 TRANS_DP_ENH_FRAMING : 0);
} else {
if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
@@ -153,7 +153,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
intel_dp->DP |= DP_SYNC_VS_HIGH;
intel_dp->DP |= DP_LINK_TRAIN_OFF;
 
-   if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+   if (pipe_config->enhanced_framing)
intel_dp->DP |= DP_ENHANCED_FRAMING;
 
if (IS_CHERRYVIEW(dev_priv))
@@ -351,6 +351,9 @@ static void intel_dp_get_config(struct intel_encoder 
*encoder,
u32 trans_dp = intel_de_read(dev_priv,
 TRANS_DP_CTL(crtc->pipe));
 
+   if (trans_dp & TRANS_DP_ENH_FRAMING)
+   pipe_config->enhanced_framing = true;
+
if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
@@ -361,6 +364,9 @@ static void intel_dp_get_config(struct intel_encoder 
*encoder,
else
flags |= DRM_MODE_FLAG_NVSYNC;
} else {
+   if (tmp & DP_ENHANCED_FRAMING)
+   pipe_config->enhanced_framing = true;
+
if (tmp & DP_SYNC_HS_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c 
b/drivers/gpu/drm/i915/display/intel_crt.c
index 13519f78cf9f..52af64aa9953 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -449,6 +449,8 @@ static int hsw_crt_compute_config(struct intel_encoder 
*encoder,
/* FDI must always be 2.7 GHz */
pipe_config->port_clock = 135000 * 2;
 
+   pipe_config->enhanced_framing = true;
+
adjusted_mode->crtc_clock = lpt_iclkip(pipe_config);
 
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c 
b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
index 91242ffe0768..14db2b481ff1 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
@@ -257,8 +257,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state 
*pipe_config,
intel_dump_m_n_config(pipe_config, "dp m2_n2",
  pipe_config->lane_count,
  _config->dp_m2_n2);
-   drm_dbg_kms(>drm, "fec: %s\n",
-   str_enabled_disabled(pipe_config->fec_enable));
+   drm_dbg_kms(>drm, "fec: %s, enhanced framing: %s\n",
+   str_enabled_disabled(pipe_config->fec_enable),
+   
str_enabled_disabled(pipe_config->enhanced_framing));
}
 
drm_dbg_kms(>drm, "framestart delay: %d, MSA timing delay: %d\n",
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 4246133950fd..51ae1aad7cc7 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3434,7 +3434,7 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp 
*intel_dp,
dp_tp_ctl |= DP_TP_CTL_MODE_MST;
} else {
dp_tp_ctl |= DP_TP_CTL_MODE_SST;
-   if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+   if (crtc_state->enhanced_framing)
dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
}

[PATCH 04/11] drm/i915: Fix FEC pipe A vs. DDI A mixup

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

On pre-TGL FEC is a port level feature, not a transcoder
level features, and it's DDI A which doesn't have it, not
trancodere A. Check for the correct thing when determining
whether FEC is supported or not.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 4361c1ac65c3..b27b4fb71ed7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1212,13 +1212,13 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, 
int port_clock,
 static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
 const struct intel_crtc_state 
*pipe_config)
 {
+   struct intel_encoder *encoder = _to_dig_port(intel_dp)->base;
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
-   /* On TGL, FEC is supported on all Pipes */
if (DISPLAY_VER(dev_priv) >= 12)
return true;
 
-   if (DISPLAY_VER(dev_priv) == 11 && pipe_config->cpu_transcoder != 
TRANSCODER_A)
+   if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A)
return true;
 
return false;
-- 
2.39.2



[PATCH 11/11] drm/i915: Reduce combo PHY log spam

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

We always check whether combo PHYs need to be re-initialized
after disabling DC states, which leads to log spam. Switch things
around so that we only log something when we actually have to
re-initialized a PHY.

The log spam was exacerbated by commit 41b4c7fe72b6 ("drm/i915:
Disable DC states for all commits") since we now disable DC
states far more often.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_combo_phy.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c 
b/drivers/gpu/drm/i915/display/intel_combo_phy.c
index 922a6d87b553..ee843f2b1af1 100644
--- a/drivers/gpu/drm/i915/display/intel_combo_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c
@@ -114,10 +114,6 @@ static bool icl_verify_procmon_ref_values(struct 
drm_i915_private *dev_priv,
 
procmon = icl_get_procmon_ref_values(dev_priv, phy);
 
-   drm_dbg_kms(_priv->drm,
-   "Combo PHY %c Voltage/Process Info : %s\n",
-   phy_name(phy), procmon->name);
-
ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
(0xff << 16) | 0xff, procmon->dw1);
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy),
@@ -312,14 +308,17 @@ static void icl_combo_phys_init(struct drm_i915_private 
*dev_priv)
enum phy phy;
 
for_each_combo_phy(dev_priv, phy) {
+   const struct icl_procmon *procmon;
u32 val;
 
-   if (icl_combo_phy_verify_state(dev_priv, phy)) {
-   drm_dbg(_priv->drm,
-   "Combo PHY %c already enabled, won't reprogram 
it.\n",
-   phy_name(phy));
+   if (icl_combo_phy_verify_state(dev_priv, phy))
continue;
-   }
+
+   procmon = icl_get_procmon_ref_values(dev_priv, phy);
+
+   drm_dbg(_priv->drm,
+   "Initializing combo PHY %c (Voltage/Process Info : 
%s)\n",
+   phy_name(phy), procmon->name);
 
if (!has_phy_misc(dev_priv, phy))
goto skip_phy_misc;
-- 
2.39.2



[PATCH 08/11] drm/i915: Introduce crtc_state->enhanced_framing

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

Track DP enhanced framing properly in the crtc state instead
of relying just on the cached DPCD everywhere, and hook it
up into the state check and dump.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/g4x_dp.c | 10 --
 drivers/gpu/drm/i915/display/intel_crt.c  |  2 ++
 drivers/gpu/drm/i915/display/intel_crtc_state_dump.c  |  5 +++--
 drivers/gpu/drm/i915/display/intel_ddi.c  | 11 +--
 drivers/gpu/drm/i915/display/intel_display.c  |  1 +
 drivers/gpu/drm/i915/display/intel_display_types.h|  2 ++
 drivers/gpu/drm/i915/display/intel_dp_link_training.c |  2 +-
 7 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c 
b/drivers/gpu/drm/i915/display/g4x_dp.c
index 920d570f7594..534546ea7d0b 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -141,7 +141,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
 
intel_de_rmw(dev_priv, TRANS_DP_CTL(crtc->pipe),
 TRANS_DP_ENH_FRAMING,
-drm_dp_enhanced_frame_cap(intel_dp->dpcd) ?
+pipe_config->enhanced_framing ?
 TRANS_DP_ENH_FRAMING : 0);
} else {
if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
@@ -153,7 +153,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
intel_dp->DP |= DP_SYNC_VS_HIGH;
intel_dp->DP |= DP_LINK_TRAIN_OFF;
 
-   if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+   if (pipe_config->enhanced_framing)
intel_dp->DP |= DP_ENHANCED_FRAMING;
 
if (IS_CHERRYVIEW(dev_priv))
@@ -351,6 +351,9 @@ static void intel_dp_get_config(struct intel_encoder 
*encoder,
u32 trans_dp = intel_de_read(dev_priv,
 TRANS_DP_CTL(crtc->pipe));
 
+   if (trans_dp & TRANS_DP_ENH_FRAMING)
+   pipe_config->enhanced_framing = true;
+
if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
@@ -361,6 +364,9 @@ static void intel_dp_get_config(struct intel_encoder 
*encoder,
else
flags |= DRM_MODE_FLAG_NVSYNC;
} else {
+   if (tmp & DP_ENHANCED_FRAMING)
+   pipe_config->enhanced_framing = true;
+
if (tmp & DP_SYNC_HS_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c 
b/drivers/gpu/drm/i915/display/intel_crt.c
index 13519f78cf9f..52af64aa9953 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -449,6 +449,8 @@ static int hsw_crt_compute_config(struct intel_encoder 
*encoder,
/* FDI must always be 2.7 GHz */
pipe_config->port_clock = 135000 * 2;
 
+   pipe_config->enhanced_framing = true;
+
adjusted_mode->crtc_clock = lpt_iclkip(pipe_config);
 
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c 
b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
index 91242ffe0768..14db2b481ff1 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
@@ -257,8 +257,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state 
*pipe_config,
intel_dump_m_n_config(pipe_config, "dp m2_n2",
  pipe_config->lane_count,
  _config->dp_m2_n2);
-   drm_dbg_kms(>drm, "fec: %s\n",
-   str_enabled_disabled(pipe_config->fec_enable));
+   drm_dbg_kms(>drm, "fec: %s, enhanced framing: %s\n",
+   str_enabled_disabled(pipe_config->fec_enable),
+   
str_enabled_disabled(pipe_config->enhanced_framing));
}
 
drm_dbg_kms(>drm, "framestart delay: %d, MSA timing delay: %d\n",
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 4246133950fd..51ae1aad7cc7 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3434,7 +3434,7 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp 
*intel_dp,
dp_tp_ctl |= DP_TP_CTL_MODE_MST;
} else {
dp_tp_ctl |= DP_TP_CTL_MODE_SST;
-   if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+   if (crtc_state->enhanced_framing)
dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
}
intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
@@ -3491,7 +3491,7 @@ static void 

[PATCH 10/11] drm/i915: Drop some redundant eDP checks

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

There's no need to check for both eDP and fixed_mode when
deciding whether to do the pfit calculations or not.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 9ac199444155..6bc7ff0c4320 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1044,7 +1044,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
return MODE_H_ILLEGAL;
 
fixed_mode = intel_panel_fixed_mode(connector, mode);
-   if (intel_dp_is_edp(intel_dp) && fixed_mode) {
+   if (fixed_mode) {
status = intel_panel_mode_valid(connector, mode);
if (status != MODE_OK)
return status;
@@ -2175,7 +2175,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_audio_compute_config(encoder, pipe_config, conn_state);
 
fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode);
-   if (intel_dp_is_edp(intel_dp) && fixed_mode) {
+   if (fixed_mode) {
ret = intel_panel_compute_config(connector, adjusted_mode);
if (ret)
return ret;
-- 
2.39.2



[PATCH 09/11] drm/i915: Stop spamming the logs with PLL state

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

encoder->get_config() is not the place where the state
should be dumped. Get rid of the spam.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 51ae1aad7cc7..65e031ff740c 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3863,11 +3863,9 @@ static void mtl_ddi_get_config(struct intel_encoder 
*encoder,
crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
} else if (intel_is_c10phy(i915, phy)) {
intel_c10pll_readout_hw_state(encoder, 
_state->cx0pll_state.c10);
-   intel_c10pll_dump_hw_state(i915, _state->cx0pll_state.c10);
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, 
_state->cx0pll_state.c10);
} else {
intel_c20pll_readout_hw_state(encoder, 
_state->cx0pll_state.c20);
-   intel_c20pll_dump_hw_state(i915, _state->cx0pll_state.c20);
crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, 
_state->cx0pll_state.c20);
}
 
-- 
2.39.2



[PATCH 07/11] drm/i915: Split some long lines

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

Split some overly long lines.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fdi.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c 
b/drivers/gpu/drm/i915/display/intel_fdi.c
index 55283677c45a..19ee78ba3936 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -765,7 +765,10 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
 * WaFDIAutoLinkSetTimingOverrride:hsw
 */
intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),
-  FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | 
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+  FDI_RX_PWRDN_LANE1_VAL(2) |
+  FDI_RX_PWRDN_LANE0_VAL(2) |
+  FDI_RX_TP1_TO_TP2_48 |
+  FDI_RX_FDI_DELAY_90);
 
/* Enable the PCH Receiver FDI PLL */
rx_ctl_val = dev_priv->display.fdi.rx_config | 
FDI_RX_ENHANCE_FRAME_ENABLE |
@@ -798,7 +801,9 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
 * achieved on the PCH side in FDI_RX_CTL, so no need to set the
 * port reversal bit */
intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),
-  DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 
1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));
+  DDI_BUF_CTL_ENABLE |
+  ((crtc_state->fdi_lanes - 1) << 1) |
+  DDI_BUF_TRANS_SELECT(i / 2));
intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
 
udelay(600);
-- 
2.39.2



[PATCH 06/11] drm/i915: Fix FEC state dump

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

Stop dumping state while reading it out. We have a proper
place for that stuff.

Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_crtc_state_dump.c|  2 ++
 drivers/gpu/drm/i915/display/intel_ddi.c| 13 +++--
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c 
b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
index 0cdcaa49656f..91242ffe0768 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
@@ -257,6 +257,8 @@ void intel_crtc_state_dump(const struct intel_crtc_state 
*pipe_config,
intel_dump_m_n_config(pipe_config, "dp m2_n2",
  pipe_config->lane_count,
  _config->dp_m2_n2);
+   drm_dbg_kms(>drm, "fec: %s\n",
+   str_enabled_disabled(pipe_config->fec_enable));
}
 
drm_dbg_kms(>drm, "framestart delay: %d, MSA timing delay: %d\n",
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 41cfa28166e4..4246133950fd 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3725,17 +3725,10 @@ static void intel_ddi_read_func_ctl(struct 
intel_encoder *encoder,
intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
   _config->dp_m2_n2);
 
-   if (DISPLAY_VER(dev_priv) >= 11) {
-   i915_reg_t dp_tp_ctl = dp_tp_ctl_reg(encoder, 
pipe_config);
-
+   if (DISPLAY_VER(dev_priv) >= 11)
pipe_config->fec_enable =
-   intel_de_read(dev_priv, dp_tp_ctl) & 
DP_TP_CTL_FEC_ENABLE;
-
-   drm_dbg_kms(_priv->drm,
-   "[ENCODER:%d:%s] Fec status: %u\n",
-   encoder->base.base.id, encoder->base.name,
-   pipe_config->fec_enable);
-   }
+   intel_de_read(dev_priv,
+ dp_tp_ctl_reg(encoder, 
pipe_config)) & DP_TP_CTL_FEC_ENABLE;
 
if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
pipe_config->infoframes.enable |=
-- 
2.39.2



[PATCH 05/11] drm/i915: Check lane count when determining FEC support

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

ICL doesn't support FEC with a x1 DP link. Make sure
we don't try to enable FEC in such cases.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index b27b4fb71ed7..9ac199444155 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1218,7 +1218,8 @@ static bool intel_dp_source_supports_fec(struct intel_dp 
*intel_dp,
if (DISPLAY_VER(dev_priv) >= 12)
return true;
 
-   if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A)
+   if (DISPLAY_VER(dev_priv) == 11 &&
+   encoder->port != PORT_A && pipe_config->lane_count != 1)
return true;
 
return false;
@@ -1234,7 +1235,7 @@ static bool intel_dp_supports_fec(struct intel_dp 
*intel_dp,
 static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
  const struct intel_crtc_state *crtc_state)
 {
-   if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP) && 
!crtc_state->fec_enable)
+   if (!intel_dp_is_edp(intel_dp) && !crtc_state->fec_enable)
return false;
 
return intel_dsc_source_support(crtc_state) &&
@@ -1580,15 +1581,6 @@ int intel_dp_dsc_compute_config(struct intel_dp 
*intel_dp,
int pipe_bpp;
int ret;
 
-   pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
-   intel_dp_supports_fec(intel_dp, pipe_config);
-
-   if (!intel_dp_supports_dsc(intel_dp, pipe_config))
-   return -EINVAL;
-
-   if (!intel_dp_dsc_supports_format(intel_dp, pipe_config->output_format))
-   return -EINVAL;
-
if (compute_pipe_bpp)
pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, 
conn_state->max_requested_bpc);
else
@@ -1615,6 +1607,15 @@ int intel_dp_dsc_compute_config(struct intel_dp 
*intel_dp,
pipe_config->port_clock = limits->max_rate;
pipe_config->lane_count = limits->max_lane_count;
 
+   pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
+   intel_dp_supports_fec(intel_dp, pipe_config);
+
+   if (!intel_dp_supports_dsc(intel_dp, pipe_config))
+   return -EINVAL;
+
+   if (!intel_dp_dsc_supports_format(intel_dp, pipe_config->output_format))
+   return -EINVAL;
+
if (intel_dp_is_edp(intel_dp)) {
pipe_config->dsc.compressed_bpp =
min_t(u16, 
drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd) >> 4,
-- 
2.39.2



[PATCH 03/11] drm/i915/mst: Read out FEC state

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

The MST codepath is missing FEC readout. Add it.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 55f36d9d509c..41cfa28166e4 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3763,6 +3763,11 @@ static void intel_ddi_read_func_ctl(struct intel_encoder 
*encoder,
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
   _config->dp_m_n);
 
+   if (DISPLAY_VER(dev_priv) >= 11)
+   pipe_config->fec_enable =
+   intel_de_read(dev_priv,
+ dp_tp_ctl_reg(encoder, 
pipe_config)) & DP_TP_CTL_FEC_ENABLE;
+
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
-- 
2.39.2



[PATCH 02/11] drm/i915/mst: Remove broken MST DSC support

2023-05-02 Thread Ville Syrjala
From: Ville Syrjälä 

The MST DSC code has a myriad of issues:
- Platform checks are wrong (MST+DSC is TGL+ only IIRC)
- Return values of .mode_valid_ctx() are wrong
- .mode_valid_ctx() assumes bigjoiner might be used, but ther rest
  of the code doesn't agree
- compressed bpp calculations don't make sense
- FEC handling needs to consider the entire link as opposed to just
  the single stream. Currently FEC would only get enabled if the
  first enabled stream is compressed. Also I'm not seeing anything
  that would account for the FEC overhead in any bandwidth calculations
- PPS SDP is only handled for the first stream via the dig_port
  hooks, other streams will not be transmittitng any PPS SDPs
- PPS SDP readout is missing (also missing for SST!)
- VDSC readout is missing (also missing for SST!)

The FEC issues is really the big one since we have no way currently
to apply such link wide configuration constraints. Changing that is
going to require a much bigger rework of the higher level modeset
.compute_config() logic. We will also need such a rework to properly
distribute the available bandwidth across all the streams on the
same link (which is a must to eg. enable deep color).

Cc: sta...@vger.kernel.org
Cc: Vinod Govindapillai 
Cc: Stanislav Lisovskiy 
Fixes: d51f25eb479a ("drm/i915: Add DSC support to MST path")
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 176 +---
 1 file changed, 5 insertions(+), 171 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 44c15d6faac4..d762f37fafb5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -72,8 +72,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
int min_bpp,
struct link_config_limits 
*limits,
struct drm_connector_state 
*conn_state,
-   int step,
-   bool dsc)
+   int step)
 {
struct drm_atomic_state *state = crtc_state->uapi.state;
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
@@ -104,7 +103,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
drm_dbg_kms(>drm, "Trying bpp %d\n", bpp);
 
-   ret = intel_dp_mst_check_constraints(i915, bpp, adjusted_mode, 
crtc_state, dsc);
+   ret = intel_dp_mst_check_constraints(i915, bpp, adjusted_mode, 
crtc_state, false);
if (ret)
continue;
 
@@ -136,11 +135,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
drm_dbg_kms(>drm, "failed finding vcpi slots:%d\n",
slots);
} else {
-   if (!dsc)
-   crtc_state->pipe_bpp = bpp;
-   else
-   crtc_state->dsc.compressed_bpp = bpp;
-   drm_dbg_kms(>drm, "Got %d slots for pipe bpp %d dsc 
%d\n", slots, bpp, dsc);
+   crtc_state->pipe_bpp = bpp;
+   drm_dbg_kms(>drm, "Got %d slots for pipe bpp %d\n", 
slots, bpp);
}
 
return slots;
@@ -157,7 +153,7 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
 
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, 
limits->max_bpp,
 limits->min_bpp, limits,
-conn_state, 2 * 3, false);
+conn_state, 2 * 3);
 
if (slots < 0)
return slots;
@@ -173,99 +169,6 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
return 0;
 }
 
-static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
-   struct intel_crtc_state 
*crtc_state,
-   struct drm_connector_state 
*conn_state,
-   struct link_config_limits 
*limits)
-{
-   struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
-   struct intel_dp *intel_dp = _mst->primary->dp;
-   struct intel_connector *connector =
-   to_intel_connector(conn_state->connector);
-   struct drm_i915_private *i915 = to_i915(connector->base.dev);
-   const struct drm_display_mode *adjusted_mode =
-   _state->hw.adjusted_mode;
-   int slots = -EINVAL;
-   int i, num_bpc;
-   u8 dsc_bpc[3] = {0};
-   int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
-   u8 dsc_max_bpc;

  1   2   3   4   5   6   7   8   9   10   >