Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Introduce the plane->min_alignment() vfunc

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 <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240612204712.31404-4-ville.syrjala@linux.intel.com
Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

+89 -37
+5 -3
drivers/gpu/drm/i915/display/i9xx_plane.c
··· 225 225 226 226 int i9xx_check_plane_surface(struct intel_plane_state *plane_state) 227 227 { 228 - struct drm_i915_private *dev_priv = 229 - to_i915(plane_state->uapi.plane->dev); 228 + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 229 + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 230 230 const struct drm_framebuffer *fb = plane_state->hw.fb; 231 231 int src_x, src_y, src_w; 232 232 u32 offset; ··· 267 267 * despite them not using the linear offset anymore. 268 268 */ 269 269 if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { 270 - unsigned int alignment = intel_surf_alignment(fb, 0); 270 + unsigned int alignment = plane->min_alignment(plane, fb, 0); 271 271 int cpp = fb->format->cpp[0]; 272 272 273 273 while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) { ··· 868 868 else 869 869 plane->max_stride = ilk_primary_max_stride; 870 870 } 871 + 872 + plane->min_alignment = intel_surf_alignment; 871 873 872 874 if (IS_I830(dev_priv) || IS_I845G(dev_priv)) { 873 875 plane->update_arm = i830_plane_update_arm;
+2
drivers/gpu/drm/i915/display/intel_cursor.c
··· 954 954 cursor->check_plane = i9xx_check_cursor; 955 955 } 956 956 957 + cursor->min_alignment = intel_cursor_alignment; 958 + 957 959 cursor->cursor.base = ~0; 958 960 cursor->cursor.cntl = ~0; 959 961
+3
drivers/gpu/drm/i915/display/intel_display_types.h
··· 1566 1566 int (*max_height)(const struct drm_framebuffer *fb, 1567 1567 int color_plane, 1568 1568 unsigned int rotation); 1569 + unsigned int (*min_alignment)(struct intel_plane *plane, 1570 + const struct drm_framebuffer *fb, 1571 + int color_plane); 1569 1572 unsigned int (*max_stride)(struct intel_plane *plane, 1570 1573 u32 pixel_format, u64 modifier, 1571 1574 unsigned int rotation);
+11 -11
drivers/gpu/drm/i915/display/intel_fb.c
··· 776 776 intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier); 777 777 } 778 778 779 - unsigned int intel_cursor_alignment(const struct drm_i915_private *i915) 779 + unsigned int intel_cursor_alignment(struct intel_plane *plane, 780 + const struct drm_framebuffer *fb, 781 + int color_plane) 780 782 { 783 + struct drm_i915_private *i915 = to_i915(plane->base.dev); 784 + 781 785 if (IS_I830(i915)) 782 786 return 16 * 1024; 783 787 else if (IS_I85X(i915)) ··· 805 801 return 0; 806 802 } 807 803 808 - unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, 804 + unsigned int intel_surf_alignment(struct intel_plane *plane, 805 + const struct drm_framebuffer *fb, 809 806 int color_plane) 810 807 { 811 - struct drm_i915_private *dev_priv = to_i915(fb->dev); 808 + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 812 809 813 810 if (intel_fb_uses_dpt(fb)) { 814 811 /* AUX_DIST needs only 4K alignment */ ··· 1104 1099 const struct intel_plane_state *state, 1105 1100 int color_plane) 1106 1101 { 1107 - struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane); 1108 - struct drm_i915_private *i915 = to_i915(intel_plane->base.dev); 1102 + struct intel_plane *plane = to_intel_plane(state->uapi.plane); 1103 + struct drm_i915_private *i915 = to_i915(plane->base.dev); 1109 1104 const struct drm_framebuffer *fb = state->hw.fb; 1110 1105 unsigned int rotation = state->hw.rotation; 1111 1106 unsigned int pitch = state->view.color_plane[color_plane].mapping_stride; 1112 - unsigned int alignment; 1113 - 1114 - if (intel_plane->id == PLANE_CURSOR) 1115 - alignment = intel_cursor_alignment(i915); 1116 - else 1117 - alignment = intel_surf_alignment(fb, color_plane); 1107 + unsigned int alignment = plane->min_alignment(plane, fb, color_plane); 1118 1108 1119 1109 return intel_compute_aligned_offset(i915, x, y, fb, color_plane, 1120 1110 pitch, rotation, alignment);
+5 -2
drivers/gpu/drm/i915/display/intel_fb.h
··· 60 60 unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane); 61 61 unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, 62 62 int color_plane, unsigned int height); 63 - unsigned int intel_cursor_alignment(const struct drm_i915_private *i915); 64 - unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, 63 + unsigned int intel_cursor_alignment(struct intel_plane *plane, 64 + const struct drm_framebuffer *fb, 65 + int color_plane); 66 + unsigned int intel_surf_alignment(struct intel_plane *plane, 67 + const struct drm_framebuffer *fb, 65 68 int color_plane); 66 69 67 70 void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
+29 -11
drivers/gpu/drm/i915/display/intel_fb_pin.c
··· 103 103 104 104 struct i915_vma * 105 105 intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, 106 - bool phys_cursor, 107 106 const struct i915_gtt_view *view, 107 + unsigned int alignment, 108 + unsigned int phys_alignment, 108 109 bool uses_fence, 109 110 unsigned long *out_flags) 110 111 { ··· 114 113 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 115 114 intel_wakeref_t wakeref; 116 115 struct i915_gem_ww_ctx ww; 117 - unsigned int alignment; 118 116 struct i915_vma *vma; 119 117 unsigned int pinctl; 120 118 int ret; ··· 121 121 if (drm_WARN_ON(dev, !i915_gem_object_is_framebuffer(obj))) 122 122 return ERR_PTR(-EINVAL); 123 123 124 - if (phys_cursor) 125 - alignment = intel_cursor_alignment(dev_priv); 126 - else 127 - alignment = intel_surf_alignment(fb, 0); 128 124 if (drm_WARN_ON(dev, alignment && !is_power_of_2(alignment))) 129 125 return ERR_PTR(-EINVAL); 130 126 ··· 158 162 i915_gem_ww_ctx_init(&ww, true); 159 163 retry: 160 164 ret = i915_gem_object_lock(obj, &ww); 161 - if (!ret && phys_cursor) 162 - ret = i915_gem_object_attach_phys(obj, alignment); 165 + if (!ret && phys_alignment) 166 + ret = i915_gem_object_attach_phys(obj, phys_alignment); 163 167 else if (!ret && HAS_LMEM(dev_priv)) 164 168 ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0); 165 169 if (!ret) ··· 230 234 i915_vma_put(vma); 231 235 } 232 236 237 + static unsigned int 238 + intel_plane_fb_min_alignment(const struct intel_plane_state *plane_state) 239 + { 240 + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 241 + const struct drm_framebuffer *fb = plane_state->hw.fb; 242 + 243 + return plane->min_alignment(plane, fb, 0); 244 + } 245 + 246 + static unsigned int 247 + intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state) 248 + { 249 + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 250 + const struct drm_framebuffer *fb = plane_state->hw.fb; 251 + 252 + if (!intel_plane_needs_physical(plane)) 253 + return 0; 254 + 255 + return plane->min_alignment(plane, fb, 0); 256 + } 257 + 233 258 int intel_plane_pin_fb(struct intel_plane_state *plane_state) 234 259 { 235 260 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); ··· 259 242 struct i915_vma *vma; 260 243 261 244 if (!intel_fb_uses_dpt(&fb->base)) { 262 - vma = intel_fb_pin_to_ggtt(&fb->base, intel_plane_needs_physical(plane), 263 - &plane_state->view.gtt, 245 + vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt, 246 + intel_plane_fb_min_alignment(plane_state), 247 + intel_plane_fb_min_phys_alignment(plane_state), 264 248 intel_plane_uses_fence(plane_state), 265 249 &plane_state->flags); 266 250 if (IS_ERR(vma)) ··· 279 261 plane_state->phys_dma_addr = 280 262 i915_gem_object_get_dma_address(intel_fb_obj(&fb->base), 0); 281 263 } else { 282 - unsigned int alignment = intel_surf_alignment(&fb->base, 0); 264 + unsigned int alignment = intel_plane_fb_min_alignment(plane_state); 283 265 284 266 vma = intel_dpt_pin_to_ggtt(fb->dpt_vm, alignment / 512); 285 267 if (IS_ERR(vma))
+2 -1
drivers/gpu/drm/i915/display/intel_fb_pin.h
··· 15 15 16 16 struct i915_vma * 17 17 intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, 18 - bool phys_cursor, 19 18 const struct i915_gtt_view *view, 19 + unsigned int alignment, 20 + unsigned int phys_alignment, 20 21 bool uses_fence, 21 22 unsigned long *out_flags); 22 23
+19 -2
drivers/gpu/drm/i915/display/intel_fbdev.c
··· 47 47 #include "gem/i915_gem_object.h" 48 48 49 49 #include "i915_drv.h" 50 + #include "intel_crtc.h" 50 51 #include "intel_display_types.h" 51 52 #include "intel_fb.h" 52 53 #include "intel_fb_pin.h" ··· 173 172 174 173 __diag_pop(); 175 174 175 + static unsigned int intel_fbdev_min_alignment(const struct drm_framebuffer *fb) 176 + { 177 + struct drm_i915_private *i915 = to_i915(fb->dev); 178 + struct intel_plane *plane; 179 + struct intel_crtc *crtc; 180 + 181 + crtc = intel_first_crtc(i915); 182 + if (!crtc) 183 + return 0; 184 + 185 + plane = to_intel_plane(crtc->base.primary); 186 + 187 + return plane->min_alignment(plane, fb, 0); 188 + } 189 + 176 190 static int intelfb_create(struct drm_fb_helper *helper, 177 191 struct drm_fb_helper_surface_size *sizes) 178 192 { ··· 244 228 * This also validates that any existing fb inherited from the 245 229 * BIOS is suitable for own access. 246 230 */ 247 - vma = intel_fb_pin_to_ggtt(&fb->base, false, 248 - &view, false, &flags); 231 + vma = intel_fb_pin_to_ggtt(&fb->base, &view, 232 + intel_fbdev_min_alignment(&fb->base), 0, 233 + false, &flags); 249 234 if (IS_ERR(vma)) { 250 235 ret = PTR_ERR(vma); 251 236 goto out_unlock;
+2
drivers/gpu/drm/i915/display/intel_sprite.c
··· 1622 1622 } 1623 1623 } 1624 1624 1625 + plane->min_alignment = intel_surf_alignment; 1626 + 1625 1627 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { 1626 1628 supported_rotations = 1627 1629 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+7 -4
drivers/gpu/drm/i915/display/skl_universal_plane.c
··· 1680 1680 int main_x, int main_y, u32 main_offset, 1681 1681 int ccs_plane) 1682 1682 { 1683 + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1683 1684 const struct drm_framebuffer *fb = plane_state->hw.fb; 1684 1685 int aux_x = plane_state->view.color_plane[ccs_plane].x; 1685 1686 int aux_y = plane_state->view.color_plane[ccs_plane].y; 1686 1687 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 1687 - unsigned int alignment = intel_surf_alignment(fb, ccs_plane); 1688 + unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane); 1688 1689 int hsub; 1689 1690 int vsub; 1690 1691 ··· 1729 1728 const struct drm_framebuffer *fb = plane_state->hw.fb; 1730 1729 int aux_plane = skl_main_to_aux_plane(fb, 0); 1731 1730 u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; 1732 - unsigned int alignment = intel_surf_alignment(fb, 0); 1731 + unsigned int alignment = plane->min_alignment(plane, fb, 0); 1733 1732 int w = drm_rect_width(&plane_state->uapi.src) >> 16; 1734 1733 1735 1734 intel_add_fb_offsets(x, y, plane_state, 0); ··· 1785 1784 int min_width = intel_plane_min_width(plane, fb, 0, rotation); 1786 1785 int max_width = intel_plane_max_width(plane, fb, 0, rotation); 1787 1786 int max_height = intel_plane_max_height(plane, fb, 0, rotation); 1788 - unsigned int alignment = intel_surf_alignment(fb, 0); 1787 + unsigned int alignment = plane->min_alignment(plane, fb, 0); 1789 1788 int aux_plane = skl_main_to_aux_plane(fb, 0); 1790 1789 u32 offset; 1791 1790 int ret; ··· 1874 1873 1875 1874 if (ccs_plane) { 1876 1875 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 1877 - unsigned int alignment = intel_surf_alignment(fb, uv_plane); 1876 + unsigned int alignment = plane->min_alignment(plane, fb, uv_plane); 1878 1877 1879 1878 if (offset > aux_offset) 1880 1879 offset = intel_plane_adjust_aligned_offset(&x, &y, ··· 2430 2429 plane->max_stride = adl_plane_max_stride; 2431 2430 else 2432 2431 plane->max_stride = skl_plane_max_stride; 2432 + 2433 + plane->min_alignment = intel_surf_alignment; 2433 2434 2434 2435 if (DISPLAY_VER(dev_priv) >= 11) { 2435 2436 plane->update_noarm = icl_plane_update_noarm;
+2 -1
drivers/gpu/drm/xe/display/xe_fb_pin.c
··· 334 334 335 335 struct i915_vma * 336 336 intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, 337 - bool phys_cursor, 338 337 const struct i915_gtt_view *view, 338 + unsigned int alignment, 339 + unsigned int phys_alignment, 339 340 bool uses_fence, 340 341 unsigned long *out_flags) 341 342 {
+2 -2
drivers/gpu/drm/xe/display/xe_plane_initial.c
··· 210 210 intel_fb_fill_view(to_intel_framebuffer(fb), 211 211 plane_state->uapi.rotation, &plane_state->view); 212 212 213 - vma = intel_fb_pin_to_ggtt(fb, false, &plane_state->view.gtt, 214 - false, &plane_state->flags); 213 + vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt, 214 + 0, 0, false, &plane_state->flags); 215 215 if (IS_ERR(vma)) 216 216 goto nofb; 217 217