[PATCH v3 2/9] drm: Export drm_plane_has_format()
From: Ville Syrjälä Export drm_plane_has_format() so that drivers can use it. v2: add kerneldoc Reviewed-by: Jani Nikula Reviewed-by: Daniel Vetter Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_crtc_internal.h | 2 -- drivers/gpu/drm/drm_plane.c | 10 ++ include/drm/drm_plane.h | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index cdd60f2a4052..1f73b8d6d750 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..a28b22fdd7a4 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -877,6 +877,15 @@ int drm_mode_getplane(struct drm_device *dev, void *data, return 0; } +/** + * drm_plane_has_format - Check whether the plane supports this format and modifier combination + * @plane: drm plane + * @format: pixel format (DRM_FORMAT_*) + * @modifier: data layout modifier + * + * Returns: + * Whether the plane supports the specified format and modifier combination. + */ bool drm_plane_has_format(struct drm_plane *plane, u32 format, u64 modifier) { @@ -906,6 +915,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.44.2
[PATCH v2 9/9] drm/i915: Nuke the TGL+ chroma plane tile row alignment stuff
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()). Reviewed-by: Imre Deak 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 | 14 -- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index a11c1cf6f548..f23547a88b1f 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -585,12 +585,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 || @@ -1020,11 +1014,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 a1c4778cf656..ba5a628b4757 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -515,20 +515,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)) { - if (intel_fb_uses_dpt(fb)) - return 512 * 4 * 1024; - - /* -* 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.44.2
[PATCH v2 8/9] drm/i915: Update plane alignment requirements for TGL+
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. v2: Don't screw up DPT+semiplanar 2MiB alignment Reviewed-by: Imre Deak Signed-off-by: Ville Syrjälä --- .../drm/i915/display/skl_universal_plane.c| 109 ++ 1 file changed, 61 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 d4c1db3fb9e3..a1c4778cf656 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -503,75 +503,85 @@ 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)) { + if (intel_fb_uses_dpt(fb)) + return 512 * 4 * 1024; + /* * 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(&dev_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_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_4_TILED_DG2_RC_CCS: + case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: + case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: + /* +* Align to at least 4x1 main surface +* tiles (16K) to 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) +{ + /* +* A
[PATCH v2 7/9] drm/i915: Move intel_surf_alignment() into skl_univerals_plane.c
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). Reviewed-by: Imre Deak 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 7f6a3de07cad..a11c1cf6f548 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -585,7 +585,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; @@ -777,81 +777,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(&dev_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(cons
[PATCH v2 6/9] drm/i915: Split pre-skl platforms out from intel_surf_alignment()
From: Ville Syrjälä Extract the necessary chunks from intel_surf_alignment() into per-platform variants for all pre-skl primary/sprite planes. Reviewed-by: Imre Deak 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 53b18efaa88c..9447f7229b60 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -764,6 +764,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, @@ -869,7 +929,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 b5d31ccf013a..7f6a3de07cad 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -777,19 +777,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) @@ -825,7 +812,7 @@ unsigned int intel_surf_alignment(struct intel_plane *plane, */ if (DISPLAY_VER(dev_priv) >= 12) { if (fb->modif
[PATCH v2 5/9] drm/i915: Split cursor alignment to per-platform vfuncs
From: Ville Syrjälä Split intel_cursor_alignment() into per-platform variants. Reviewed-by: Imre Deak 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 5f8c23296b61..8e95ed0beeb9 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -194,6 +194,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; @@ -344,6 +351,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); @@ -942,20 +971,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 0abb80972885..b5d31ccf013a 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -777,22 +777,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); unsig
[PATCH v2 4/9] drm/i915: Introduce fb->min_alignment
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 is satisfactory to all those planes. So far this was sort of handle by making sure intel_surf_alignment() declares the superset of all planes' alignment requirements, but maintaining that manually is annoying. So we're going to move towards each plane declaring only its own requirements, and thus we need code to generate the superset. v2: Drop the borked per-plane vma optimization (Imre) Assert that the plane's declared alignment is POT (Imre) Cc: Imre Deak Signed-off-by: Ville Syrjälä --- .../drm/i915/display/intel_display_types.h| 2 ++ drivers/gpu/drm/i915/display/intel_fb.c | 29 +++ drivers/gpu/drm/i915/display/intel_fb_pin.c | 5 ++-- drivers/gpu/drm/i915/display/intel_fbdev.c| 18 +--- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 0c165572fbd0..af7cc3d6c82b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -146,6 +146,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 b3a48754a417..0abb80972885 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -11,6 +11,7 @@ #include "gem/i915_gem_object.h" #include "i915_drv.h" +#include "intel_atomic_plane.h" #include "intel_display.h" #include "intel_display_types.h" #include "intel_dpt.h" @@ -1617,6 +1618,32 @@ 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(&i915->drm, plane) { + unsigned int plane_min_alignment; + + if (!drm_plane_has_format(&plane->base, fb->format->format, fb->modifier)) + continue; + + plane_min_alignment = plane->min_alignment(plane, fb, 0); + + drm_WARN_ON(&i915->drm, plane_min_alignment && + !is_power_of_2(plane_min_alignment)); + + if (intel_plane_needs_physical(plane)) + continue; + + min_alignment = max(min_alignment, plane_min_alignment); + } + + 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(&fb->base); @@ -1699,6 +1726,8 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * return -EINVAL; } + fb->min_alignment = intel_fb_min_alignment(&fb->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..575b271e012b 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -233,10 +233,9 @@ void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) 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); + return fb->min_alignment; } static unsigned int diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 6e5f88f20482..49a1ac4f5491 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -47,7 +47,6 @@ #include "gem/i915_gem_object.h" #include "i915_drv.h" -#include "intel_crtc.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fb_pin.h" @@ -173,21 +172,6 @@ static const struct fb_ops intelfb_ops = { __diag_pop(); -static unsigned int intel_fbdev_min_alignment(const struct drm_framebuffer *fb) -{ - struct drm_i915_private *i915 = to_i915(fb->dev); - struct intel_plane *plane; - struct intel_crtc *crtc; - - crtc = intel_first_crtc(i915); - if (!crtc) - return 0; - - plane = to_intel_plane(crtc->base.primary); - - return plane->min_alignment(plan
[PATCH v2 3/9] drm/i915: Introduce the plane->min_alignment() vfunc
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 Reviewed-by: Imre Deak 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 864d94406894..53b18efaa88c 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -225,8 +225,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; @@ -267,7 +267,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) { @@ -869,6 +869,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 7f7fc710350c..5f8c23296b61 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -954,6 +954,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 4fa785fd664e..0c165572fbd0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1560,6 +1560,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 8069abf91c5e..b3a48754a417 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -776,8 +776,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) {
[PATCH v2 1/9] drm: Rename drm_plane_check_pixel_format() to drm_plane_has_format()
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. Reviewed-by: Jani Nikula 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 07b4b394e3bf..6e516c39a372 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, &fb->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", &fb->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 20e9d7b206a2..cdd60f2a4052 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; }
[PATCH v2 2/9] drm: Export drm_plane_has_format()
From: Ville Syrjälä Export drm_plane_has_format() so that drivers can use it. Reviewed-by: Jani Nikula 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 cdd60f2a4052..1f73b8d6d750 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.44.2
[PATCH v2 0/9] drm/i915: Polish plane surface alignment handling
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. v2: Drop the per-plane vma stuff as it was borked Don't temporarily remove the 2MiB DPT alignment for UV on TGL 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 the 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 | 151 -- drivers/gpu/drm/i915/display/intel_fb.h | 3 - drivers/gpu/drm/i915/display/intel_fb_pin.c | 39 +++-- 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| 85 +- 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, 309 insertions(+), 168 deletions(-) -- 2.44.2
[PATCH 2/2] drm/doc: Document that userspace should utilize CRTCs bottom up
From: Ville Syrjälä At leat on Intel GPUs it is best to allocate CRTCs bottom up as it will generally lead to lower power consumption. Recommend userspace does so. Not sure if this is strictly the best order for other hardware, but drivers could always rearrange the CRTC list into some kind of priority order to make it work. Should that turn out to be insufficient we might need some kind of more complex priority scheme. Probably the ideal solution would be to have the driver be responsible for resource allocation entirely. Ie. the CRTCs visible via uapi would be virtual and the driver could make the final choice on which hardware CRTC to use for each. Unfortunately the kms uapi is geared towards exposing hardware directly. Eg. when CRTCs are non-uniform in hardware there is no good way to expose their capabilities. The virtual CRTCs would more or less either have to expose a superset or a subset of the capabilities across all hardware CRTCs. Also the crtc->encoder->connector routing information exposed in the uapi is all about the actual hardware signal routing. I think robust virtualized CRTCs would require some new form of uapi where userspace could declare ahead of time which features wants on the CRTC (even if not enabling all of them from the start), and the driver would then have enough information to make the optimal choice. Cc: Simon Ser Cc: Daniel Stone Signed-off-by: Ville Syrjälä --- include/uapi/drm/drm_mode.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index fe5e210396b2..aa90f11950d6 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -386,6 +386,9 @@ struct drm_mode_get_encoder { /** * @possible_crtcs: Bitmask of CRTCs compatible with the encoder. +* If multiple CRTCs are possible userspace should generally try +* to utilize CRTCs bottom up as that may result in lower power +* consumption on some systems. * CRTCs are created and they receive an index, which corresponds * to their position in the bitmask. Bit N corresponds to * :ref:`CRTC index` N. -- 2.44.2
[PATCH 1/2] drm/doc: Document drm_get_encoder ioctl more thoroughly
From: Ville Syrjälä Document all the fields of the drm_get_encoder ioctl. Cc: Simon Ser Cc: Daniel Stone Signed-off-by: Ville Syrjälä --- Documentation/gpu/drm-uapi.rst | 13 + include/uapi/drm/drm_mode.h| 22 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 370d820be248..ebe318757b2a 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -564,6 +564,19 @@ CRTC ID's, and the CRTC index is its position in this array. .. kernel-doc:: include/uapi/drm/drm_mode.h :internal: +encoder index +- + +encoders have both an object ID and an index, and they are not the same thing. +The index is used in cases where a densely packed identifier for an encoder is +needed, for instance a bitmask of encoders. The member possible_clones of struct +drm_mode_get_encoder is an example. + +:c:macro:`DRM_IOCTL_MODE_GETRESOURCES` populates a structure with an array of +encoder IDs, and the encoder index is its position in this array. + +.. kernel-doc:: include/uapi/drm/drm_mode.h + :internal: dma-buf interoperability diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index d390011b89b4..fe5e210396b2 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -373,12 +373,32 @@ struct drm_mode_get_plane_res { #define DRM_MODE_ENCODER_DPI 8 struct drm_mode_get_encoder { + /** +* @encoder_id: Object ID of the encoder whose information +* should be retrieved. Set by caller. +*/ __u32 encoder_id; + /** @encoder_type: Type of the encoder */ __u32 encoder_type; - __u32 crtc_id; /**< Id of crtc */ + /** @crtc_id: Object ID of the current CRTC. */ + __u32 crtc_id; + /** +* @possible_crtcs: Bitmask of CRTCs compatible with the encoder. +* CRTCs are created and they receive an index, which corresponds +* to their position in the bitmask. Bit N corresponds to +* :ref:`CRTC index` N. +*/ __u32 possible_crtcs; + /** +* @possible_clones: Bitmask of encoders compatible with the +* encoder for cloning. A set of cloned encoders all source +* their data from the same CRTC. +* Encoders are created and they receive an index, which corresponds +* to their position in the bitmask. Bit N corresponds to +* :ref:`encoder index` N. +*/ __u32 possible_clones; }; -- 2.44.2
[PATCH] drm/probe-helper: Call drm_mode_validate_ycbcr420() before connector->mode_valid()
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, &mode->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
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+
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(&dev_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 I915_FORMAT_MO
[PATCH 7/9] drm/i915: Move intel_surf_alignment() into skl_univerals_plane.c
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(&dev_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()
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 == DRM_FORMAT_MOD_LI
[PATCH 4/9] drm/i915: Introduce fb->min_alignment
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(&i915->drm, plane) { + if (!drm_plane_has_format(&plane->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(&fb->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(&fb->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, &fb->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
[PATCH 3/9] drm/i915: Introduce plane->min_alignment() vfunc
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 drm_i915
[PATCH 5/9] drm/i915: Split cursor alignment to per-platform vfuncs
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 intel_fb_align_h
[PATCH 2/9] drm: Export drm_plane_has_format()
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()
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, &fb->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", &fb->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
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
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
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
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()
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 = &dev->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, &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 = &vkmsdev->output; - struct drm_vblank_crtc *vblank = &dev->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()
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 = &crtc->dev->vblank[drm_crtc_index(crtc)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); struct nvif_head *head = &nouveau_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()
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 = &dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&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 = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->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 = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->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(&crtc->base); + const struct drm_display_mode *mode = &vblank->hwmode; enum pipe pipe = crtc->pipe; int position, vtotal; if (!crtc->active) return 0; - vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - mode = &vblank->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 = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->hwmode; int vtotal; -- 2.43.2
[PATCH 2/5] drm/amdgpu: Use drm_crtc_vblank_crtc()
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 = &dev->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 = &dev->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 = &drm_dev->vblank[acrtc->base.index]; + vblank = drm_crtc_vblank_crtc(&acrtc->base); previous_timestamp = atomic64_read(&irq_params->previous_timestamp); frame_duration_ns = vblank->time - previous_timestamp; -- 2.43.2
[PATCH 1/5] drm/vblank: Introduce drm_crtc_vblank_crtc()
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 &dev->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 = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); assert_spin_locked(&dev->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 = &dev->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 = &dev->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 = &dev->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 = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); unsigned long irqflags; assert_spin_locked(&dev->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 = &dev->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 = &dev->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 = &crtc->dev->vblank[pipe]; + vblank = drm_crtc_vblank_crtc(crtc); mode = &vblank->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 = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); int ret = 0; assert_spin_locked
[PATCH 17/21] drm/fsl-dcu: Allow build with COMPILE_TEST=y
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
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
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
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
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
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
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()
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
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
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()
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
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
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, &temp); + 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()
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
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
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()
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
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
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
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
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
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
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", + connector->b
[PATCH 08/12] drm/client: Extract drm_connector_first_mode()
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(&connector->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(&connector->modes)) { - list_for_each_entry(modes[i], &connector->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(&connector->modes)) { DRM_DEBUG_KMS("using first mode listed on connector %s\n", connector->name); - modes[i] = list_first_entry(&connector->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
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
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(&ctx, 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(&dev->mode_config.connection_mutex, &ctx); @@ -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, &connector->modes, false); goto exit; @@ -697,8 +696,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, drm_mode_sort(&connector->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, &connector->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
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
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, &connector->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, &connector->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, &connector->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, +c
[PATCH 11/12] drm/client: Streamline mode selection debugs
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? %s)\n",
[PATCH 05/12] drm/client: Nuke outdated fastboot comment
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
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()
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/
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(&connector->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
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(&dev->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(&dev->mode_config.mutex); mutex_unlock(&client->modeset_mutex); out: -- 2.43.2
[PATCH 00/12] drm/client: Use after free and debug improvements
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
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. + * &DRM_CAP_CURSOR_WIDTH and &DRM_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 = &dev->mode_config; + struct dr
[PATCH v3 2/2] drm/i915: Add SIZE_HINTS property for cursors
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 = &i915->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(&i915->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(&plane->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(&cursor->base, zpos); -- 2.43.2
[PATCH v3 0/2] drm: Add plane SIZE_HINTS property
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
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, &places[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
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 = &i915->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(&i915->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(&plane->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(&cursor->base, zpos); -- 2.43.0
[PATCH v2 1/2] drm: Introduce plane SIZE_HINTS property
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. + * &DRM_CAP_CURSOR_WIDTH and &DRM_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 = &dev->mode_config; + struct drm_property_blob *blob; + + blob = drm_property_create_blob(
[PATCH v2 0/2] drm: Add plane SIZE_HINTS property
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
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
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(&arg.work, drm_mode_rmfb_work_fn); INIT_LIST_HEAD(&arg.fbs); + drm_WARN_ON(dev, !list_empty(&fb->filp_head)); list_add_tail(&fb->filp_head, &arg.fbs); schedule_work(&arg.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(&fb->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(&fb->filp_head)); + drm_WARN_ON(dev, !list_empty(&fb->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
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
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(&lut[i]) : glk_degamma_lut(&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(&lut[i], val); + else + glk_degamma_lut_pack(&lut[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()
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
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
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 * &drm_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
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
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(&i915->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(&i915->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->dtds[index]); + fill_detail_timing_data(i915, panel_fixed_mode, &dtds->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
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
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
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(&vblank->dev->event_lock); + drm_WARN_ONCE(vblank->dev, !list_empty(&vblank->pending_work), + "Cancelling pending vblank works!\n"); + list_for_each_entry_safe(work, next, &vblank->pending_work, node) { list_del_init(&work->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
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(&plane->base, &plane_state->uapi); + + if (atomic_dec_and_test(&plane->cursor.pending_unpins)) + wake_up_var(&plane->cursor.pending_unpins); +} + +void intel_cursor_wait_unpin_works(struct intel_plane *plane) +{ + wait_var_event(&plane->cursor.pending_unpins, + !atomic_read(&plane->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(&old_plane_state->unpin_work, &crtc->base, +intel_cursor_unpin_work); + + atomic_inc(&plane->cursor.pending_unpins); + drm_vblank_work_schedule(&old_plane_state->unpin_work, + drm_crtc_accurate_vblank_count(&crtc->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(&crtc->base, &new_crtc_state->uapi); if (ret) intel_plane_destroy_state(&plane->base, &new_plane_state->uapi); - else + else if (old_plane_state) intel_plane_destroy_state(&plane->base, &old_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
[PATCH v2 03/12] drm/i915: Call the DDC bus i2c adapter "ddc"
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 = intel_gmbu
[PATCH 11/12] drm/i915/hdmi: Remove old i2c symlink
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 = &ddc->dev.kobj; - struct kobject *connector_kobj = &connector->kdev->kobj; - int ret; - - ret = sysfs_create_link(connector_kobj, i2c_kobj, i2c_kobj->name); - if (ret) - drm_err(&i915->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 = &ddc->dev.kobj; - struct kobject *connector_kobj = &connector->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
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 = &dev_priv->display.vbt.sdvo_mappings[0]; -- 2.41.0
[PATCH 10/12] drm/i915/hdmi: Nuke hdmi->ddc_bus
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(&i915->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(&dev_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, &intel_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, &intel_hdmi_connector_helper_funcs); -- 2.41.0
[PATCH 09/12] drm/i915/hdmi: Use connector->ddc everwhere
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 = &dig_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 = &dig_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 = &dig_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 = &hdmi_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(&dev_priv->drm, ddc); + struct i2c_adapter *ddc = connector->ddc; + enum drm_dp_dual_mode_type type; + + type = drm_dp_dual_mode_detect(&dev_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_ad
[PATCH 08/12] drm/i915/mst: Populate connector->ddc
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 = &intel_connector->base; - ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, -DRM_MODE_CONNECTOR_DisplayPort); + ret = drm_connector_init_with_ddc(dev, connector, + &intel_dp_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort, + &port->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
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(&dev_priv->drm.mode_config.mutex); - drm_edid = drm_edid_read_ddc(connector, &intel_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(&dev_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, &intel_dp_connector_funcs, type); + drm_connector_init_with_ddc(dev, connector, &intel_dp_connector_funcs, + type, &intel_dp->aux.ddc); drm_connector_helper_add(connector, &intel_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
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(&connector->base, - intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC)); + num_modes = intel_ddc_get_modes(&connector->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(&i915->drm, &connector->base, - &intel_dvo_connector_funcs, - intel_dvo_connector_type(&intel_dvo->dev)); + drm_connector_init_with_ddc(&i915->drm, &connector->base, + &intel_dvo_connector_funcs, + intel_dvo_connector_type(&intel_dvo->dev), + intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC)); drm_connector_helper_add(&connector->base, &intel_dvo_connector_helper_funcs); -- 2.41.0
[PATCH 05/12] drm/i915/crt: Populate connector->ddc
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 = &intel_connector->base; crt->connector = intel_connector; - drm_connector_init(&dev_priv->drm, &intel_connector->base, - &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); + drm_connector_init_with_ddc(&dev_priv->drm, connector, + &intel_crt_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + intel_gmbus_get_adapter(dev_priv, ddc_pin)); drm_encoder_init(&dev_priv->drm, &crt->base.base, &intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC, "CRT"); -- 2.41.0
[PATCH 03/12] drm/i915: Call the DDC bus i2c adapter "ddc"
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); - drm_edi
[PATCH 04/12] drm/i915/lvds: Populate connector->ddc
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, &pin)) { + ddc_pin = GMBUS_PIN_PANEL; + if (!intel_bios_is_lvds_present(i915, &ddc_pin)) { if ((lvds & LVDS_PORT_EN) == 0) { drm_dbg_kms(&i915->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 = &lvds_encoder->base; - drm_connector_init(&i915->drm, &connector->base, &intel_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); + drm_connector_init_with_ddc(&i915->drm, &connector->base, + &intel_lvds_connector_funcs, + DRM_MODE_CONNECTOR_LVDS, + intel_gmbus_get_adapter(i915, ddc_pin)); drm_encoder_init(&i915->drm, &encoder->base, &intel_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(&i915->drm.mode_config.mutex); - if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) { - drm_edid = drm_edid_read_switcheroo(&connector->base, - intel_gmbus_get_adapter(i915, pin)); - } else { - drm_edid = drm_edid_read_ddc(&connector->base, -intel_gmbus_get_adapter(i915, pin)); - } + if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) + drm_edid = drm_edid_read_switcheroo(&connector->base, connector->base.ddc); + else + drm_edid = drm_edid_read_ddc(&connector->base, connector->base.ddc); if (drm_edid) { if (drm_edid_connector_update(&connector->base, drm_edid) || !drm_edid_connector_add_modes(&connector->base)) { -- 2.41.0
[PATCH 02/12] drm/sysfs: Register "ddc" symlink later
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, &connector->base); connector->registration_state = DRM_CONNECTOR_REGISTERED; @@ -647,6 +651,9 @@ int drm_connector_register(struct drm_connector *connector) mutex_unlock(&connector_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, &connector->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(&connector->kdev->kobj, -&connector->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(&connector->kdev->kobj, +&connector->ddc->dev.kobj, "ddc"); + + return 0; +} + +void drm_sysfs_connector_remove_early(struct drm_connector *connector) +{ + if (connector->ddc) + sysfs_remove_link(&connector->kdev->kobj, "ddc"); +} + void drm_sysfs_connector_remove(struct drm_connector *connector) { if (!connector->kdev) return; - if (connector->ddc) - sysfs_remove_link(&connector->kdev->kobj, "ddc"); - if (dev_fwnode(connector->kdev)) component_del(connector->kdev, &typec_connector_ops); -- 2.41.0
[PATCH 01/12] drm: Reorder drm_sysfs_connector_remove() vs. drm_debugfs_connector_remove()
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(&connector->mutex); -- 2.41.0