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

drm/tegra: Properly align stride for framebuffers

Tegra20 and Tegra30 both required the buffer line stride to be aligned
on 8 byte boundaries. Tegra114 and Tegra124 increased the alignment to
64 bytes. Introduce a parameter to specify the alignment requirements
for each display controller and round up the pitch of newly allocated
framebuffers appropriately.

Originally-by: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>

+27 -1
+19
drivers/gpu/drm/tegra/dc.c
··· 19 19 bool supports_interlacing; 20 20 bool supports_cursor; 21 21 bool supports_block_linear; 22 + unsigned int pitch_align; 22 23 }; 23 24 24 25 struct tegra_plane { ··· 1284 1283 { 1285 1284 struct drm_device *drm = dev_get_drvdata(client->parent); 1286 1285 struct tegra_dc *dc = host1x_client_to_dc(client); 1286 + struct tegra_drm *tegra = drm->dev_private; 1287 1287 int err; 1288 1288 1289 1289 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); 1290 1290 drm_mode_crtc_set_gamma_size(&dc->base, 256); 1291 1291 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); 1292 + 1293 + /* 1294 + * Keep track of the minimum pitch alignment across all display 1295 + * controllers. 1296 + */ 1297 + if (dc->soc->pitch_align > tegra->pitch_align) 1298 + tegra->pitch_align = dc->soc->pitch_align; 1292 1299 1293 1300 err = tegra_dc_rgb_init(drm, dc); 1294 1301 if (err < 0 && err != -ENODEV) { ··· 1356 1347 .supports_interlacing = false, 1357 1348 .supports_cursor = false, 1358 1349 .supports_block_linear = false, 1350 + .pitch_align = 8, 1359 1351 }; 1360 1352 1361 1353 static const struct tegra_dc_soc_info tegra30_dc_soc_info = { 1362 1354 .supports_interlacing = false, 1363 1355 .supports_cursor = false, 1364 1356 .supports_block_linear = false, 1357 + .pitch_align = 8, 1358 + }; 1359 + 1360 + static const struct tegra_dc_soc_info tegra114_dc_soc_info = { 1361 + .supports_interlacing = false, 1362 + .supports_cursor = false, 1363 + .supports_block_linear = false, 1364 + .pitch_align = 64, 1365 1365 }; 1366 1366 1367 1367 static const struct tegra_dc_soc_info tegra124_dc_soc_info = { 1368 1368 .supports_interlacing = true, 1369 1369 .supports_cursor = true, 1370 1370 .supports_block_linear = true, 1371 + .pitch_align = 64, 1371 1372 }; 1372 1373 1373 1374 static const struct of_device_id tegra_dc_of_match[] = {
+2
drivers/gpu/drm/tegra/drm.h
··· 45 45 #ifdef CONFIG_DRM_TEGRA_FBDEV 46 46 struct tegra_fbdev *fbdev; 47 47 #endif 48 + 49 + unsigned int pitch_align; 48 50 }; 49 51 50 52 struct tegra_drm_client;
+3 -1
drivers/gpu/drm/tegra/fb.c
··· 194 194 struct drm_fb_helper_surface_size *sizes) 195 195 { 196 196 struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); 197 + struct tegra_drm *tegra = helper->dev->dev_private; 197 198 struct drm_device *drm = helper->dev; 198 199 struct drm_mode_fb_cmd2 cmd = { 0 }; 199 200 unsigned int bytes_per_pixel; ··· 209 208 210 209 cmd.width = sizes->surface_width; 211 210 cmd.height = sizes->surface_height; 212 - cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; 211 + cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, 212 + tegra->pitch_align); 213 213 cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 214 214 sizes->surface_depth); 215 215
+3
drivers/gpu/drm/tegra/gem.c
··· 16 16 #include <linux/dma-buf.h> 17 17 #include <drm/tegra_drm.h> 18 18 19 + #include "drm.h" 19 20 #include "gem.h" 20 21 21 22 static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) ··· 260 259 struct drm_mode_create_dumb *args) 261 260 { 262 261 int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); 262 + struct tegra_drm *tegra = drm->dev_private; 263 263 struct tegra_bo *bo; 264 264 265 + min_pitch = round_up(min_pitch, tegra->pitch_align); 265 266 if (args->pitch < min_pitch) 266 267 args->pitch = min_pitch; 267 268