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

drm/tegra: Support sector layout on Tegra194

Tegra194 has a special physical address bit that enables some memory
swizzling logic to support different sector layouts. Support the bit
that selects the sector layout which is passed in the framebuffer
modifier.

Signed-off-by: Thierry Reding <treding@nvidia.com>

+78
+7
drivers/gpu/drm/tegra/dc.c
··· 2325 2325 .supports_interlacing = false, 2326 2326 .supports_cursor = false, 2327 2327 .supports_block_linear = false, 2328 + .supports_sector_layout = false, 2328 2329 .has_legacy_blending = true, 2329 2330 .pitch_align = 8, 2330 2331 .has_powergate = false, ··· 2345 2344 .supports_interlacing = false, 2346 2345 .supports_cursor = false, 2347 2346 .supports_block_linear = false, 2347 + .supports_sector_layout = false, 2348 2348 .has_legacy_blending = true, 2349 2349 .pitch_align = 8, 2350 2350 .has_powergate = false, ··· 2365 2363 .supports_interlacing = false, 2366 2364 .supports_cursor = false, 2367 2365 .supports_block_linear = false, 2366 + .supports_sector_layout = false, 2368 2367 .has_legacy_blending = true, 2369 2368 .pitch_align = 64, 2370 2369 .has_powergate = true, ··· 2385 2382 .supports_interlacing = true, 2386 2383 .supports_cursor = true, 2387 2384 .supports_block_linear = true, 2385 + .supports_sector_layout = false, 2388 2386 .has_legacy_blending = false, 2389 2387 .pitch_align = 64, 2390 2388 .has_powergate = true, ··· 2405 2401 .supports_interlacing = true, 2406 2402 .supports_cursor = true, 2407 2403 .supports_block_linear = true, 2404 + .supports_sector_layout = false, 2408 2405 .has_legacy_blending = false, 2409 2406 .pitch_align = 64, 2410 2407 .has_powergate = true, ··· 2459 2454 .supports_interlacing = true, 2460 2455 .supports_cursor = true, 2461 2456 .supports_block_linear = true, 2457 + .supports_sector_layout = false, 2462 2458 .has_legacy_blending = false, 2463 2459 .pitch_align = 64, 2464 2460 .has_powergate = false, ··· 2508 2502 .supports_interlacing = true, 2509 2503 .supports_cursor = true, 2510 2504 .supports_block_linear = true, 2505 + .supports_sector_layout = true, 2511 2506 .has_legacy_blending = false, 2512 2507 .pitch_align = 64, 2513 2508 .has_powergate = false,
+1
drivers/gpu/drm/tegra/dc.h
··· 52 52 bool supports_interlacing; 53 53 bool supports_cursor; 54 54 bool supports_block_linear; 55 + bool supports_sector_layout; 55 56 bool has_legacy_blending; 56 57 unsigned int pitch_align; 57 58 bool has_powergate;
+3
drivers/gpu/drm/tegra/drm.h
··· 24 24 #include "hub.h" 25 25 #include "trace.h" 26 26 27 + /* XXX move to include/uapi/drm/drm_fourcc.h? */ 28 + #define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT(22) 29 + 27 30 struct reset_control; 28 31 29 32 #ifdef CONFIG_DRM_FBDEV_EMULATION
+9
drivers/gpu/drm/tegra/fb.c
··· 44 44 { 45 45 uint64_t modifier = framebuffer->modifier; 46 46 47 + if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) { 48 + if ((modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) == 0) 49 + tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_TEGRA; 50 + else 51 + tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_GPU; 52 + 53 + modifier &= ~DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT; 54 + } 55 + 47 56 switch (modifier) { 48 57 case DRM_FORMAT_MOD_LINEAR: 49 58 tiling->mode = TEGRA_BO_TILING_MODE_PITCH;
+6
drivers/gpu/drm/tegra/gem.h
··· 21 21 TEGRA_BO_TILING_MODE_BLOCK, 22 22 }; 23 23 24 + enum tegra_bo_sector_layout { 25 + TEGRA_BO_SECTOR_LAYOUT_TEGRA, 26 + TEGRA_BO_SECTOR_LAYOUT_GPU, 27 + }; 28 + 24 29 struct tegra_bo_tiling { 25 30 enum tegra_bo_tiling_mode mode; 26 31 unsigned long value; 32 + enum tegra_bo_sector_layout sector_layout; 27 33 }; 28 34 29 35 struct tegra_bo {
+28
drivers/gpu/drm/tegra/hub.c
··· 55 55 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3), 56 56 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4), 57 57 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5), 58 + /* 59 + * The GPU sector layout is only supported on Tegra194, but these will 60 + * be filtered out later on by ->format_mod_supported() on SoCs where 61 + * it isn't supported. 62 + */ 63 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, 64 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, 65 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, 66 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, 67 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, 68 + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, 69 + /* sentinel */ 58 70 DRM_FORMAT_MOD_INVALID 59 71 }; 60 72 ··· 378 366 return -EINVAL; 379 367 } 380 368 369 + if (tiling->sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU && 370 + !dc->soc->supports_sector_layout) { 371 + DRM_ERROR("hardware doesn't support GPU sector layout\n"); 372 + return -EINVAL; 373 + } 374 + 381 375 /* 382 376 * Tegra doesn't support different strides for U and V planes so we 383 377 * error out if the user tries to display a framebuffer with such a ··· 502 484 tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL); 503 485 504 486 base = tegra_plane_state->iova[0] + fb->offsets[0]; 487 + 488 + #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 489 + /* 490 + * Physical address bit 39 in Tegra194 is used as a switch for special 491 + * logic that swizzles the memory using either the legacy Tegra or the 492 + * dGPU sector layout. 493 + */ 494 + if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU) 495 + base |= BIT(39); 496 + #endif 505 497 506 498 tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH); 507 499 tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);
+24
drivers/gpu/drm/tegra/plane.c
··· 83 83 kfree(state); 84 84 } 85 85 86 + static bool tegra_plane_supports_sector_layout(struct drm_plane *plane) 87 + { 88 + struct drm_crtc *crtc; 89 + 90 + drm_for_each_crtc(crtc, plane->dev) { 91 + if (plane->possible_crtcs & drm_crtc_mask(crtc)) { 92 + struct tegra_dc *dc = to_tegra_dc(crtc); 93 + 94 + if (!dc->soc->supports_sector_layout) 95 + return false; 96 + } 97 + } 98 + 99 + return true; 100 + } 101 + 86 102 static bool tegra_plane_format_mod_supported(struct drm_plane *plane, 87 103 uint32_t format, 88 104 uint64_t modifier) ··· 107 91 108 92 if (modifier == DRM_FORMAT_MOD_LINEAR) 109 93 return true; 94 + 95 + /* check for the sector layout bit */ 96 + if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) { 97 + if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) { 98 + if (!tegra_plane_supports_sector_layout(plane)) 99 + return false; 100 + } 101 + } 110 102 111 103 if (info->num_planes == 1) 112 104 return true;