Skip to content

Commit 7b6f846

Browse files
committed
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 <[email protected]>
1 parent 05d1adf commit 7b6f846

File tree

7 files changed

+78
-0
lines changed

7 files changed

+78
-0
lines changed

drivers/gpu/drm/tegra/dc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,6 +2325,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
23252325
.supports_interlacing = false,
23262326
.supports_cursor = false,
23272327
.supports_block_linear = false,
2328+
.supports_sector_layout = false,
23282329
.has_legacy_blending = true,
23292330
.pitch_align = 8,
23302331
.has_powergate = false,
@@ -2344,6 +2345,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
23442345
.supports_interlacing = false,
23452346
.supports_cursor = false,
23462347
.supports_block_linear = false,
2348+
.supports_sector_layout = false,
23472349
.has_legacy_blending = true,
23482350
.pitch_align = 8,
23492351
.has_powergate = false,
@@ -2363,6 +2365,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
23632365
.supports_interlacing = false,
23642366
.supports_cursor = false,
23652367
.supports_block_linear = false,
2368+
.supports_sector_layout = false,
23662369
.has_legacy_blending = true,
23672370
.pitch_align = 64,
23682371
.has_powergate = true,
@@ -2382,6 +2385,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
23822385
.supports_interlacing = true,
23832386
.supports_cursor = true,
23842387
.supports_block_linear = true,
2388+
.supports_sector_layout = false,
23852389
.has_legacy_blending = false,
23862390
.pitch_align = 64,
23872391
.has_powergate = true,
@@ -2401,6 +2405,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
24012405
.supports_interlacing = true,
24022406
.supports_cursor = true,
24032407
.supports_block_linear = true,
2408+
.supports_sector_layout = false,
24042409
.has_legacy_blending = false,
24052410
.pitch_align = 64,
24062411
.has_powergate = true,
@@ -2454,6 +2459,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
24542459
.supports_interlacing = true,
24552460
.supports_cursor = true,
24562461
.supports_block_linear = true,
2462+
.supports_sector_layout = false,
24572463
.has_legacy_blending = false,
24582464
.pitch_align = 64,
24592465
.has_powergate = false,
@@ -2502,6 +2508,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
25022508
.supports_interlacing = true,
25032509
.supports_cursor = true,
25042510
.supports_block_linear = true,
2511+
.supports_sector_layout = true,
25052512
.has_legacy_blending = false,
25062513
.pitch_align = 64,
25072514
.has_powergate = false,

drivers/gpu/drm/tegra/dc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct tegra_dc_soc_info {
5252
bool supports_interlacing;
5353
bool supports_cursor;
5454
bool supports_block_linear;
55+
bool supports_sector_layout;
5556
bool has_legacy_blending;
5657
unsigned int pitch_align;
5758
bool has_powergate;

drivers/gpu/drm/tegra/drm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "hub.h"
2525
#include "trace.h"
2626

27+
/* XXX move to include/uapi/drm/drm_fourcc.h? */
28+
#define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT(22)
29+
2730
struct reset_control;
2831

2932
#ifdef CONFIG_DRM_FBDEV_EMULATION

drivers/gpu/drm/tegra/fb.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
4444
{
4545
uint64_t modifier = framebuffer->modifier;
4646

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+
4756
switch (modifier) {
4857
case DRM_FORMAT_MOD_LINEAR:
4958
tiling->mode = TEGRA_BO_TILING_MODE_PITCH;

drivers/gpu/drm/tegra/gem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,15 @@ enum tegra_bo_tiling_mode {
2121
TEGRA_BO_TILING_MODE_BLOCK,
2222
};
2323

24+
enum tegra_bo_sector_layout {
25+
TEGRA_BO_SECTOR_LAYOUT_TEGRA,
26+
TEGRA_BO_SECTOR_LAYOUT_GPU,
27+
};
28+
2429
struct tegra_bo_tiling {
2530
enum tegra_bo_tiling_mode mode;
2631
unsigned long value;
32+
enum tegra_bo_sector_layout sector_layout;
2733
};
2834

2935
struct tegra_bo {

drivers/gpu/drm/tegra/hub.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ static const u64 tegra_shared_plane_modifiers[] = {
5555
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
5656
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
5757
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 */
5870
DRM_FORMAT_MOD_INVALID
5971
};
6072

@@ -366,6 +378,12 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane,
366378
return -EINVAL;
367379
}
368380

381+
if (tiling->sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU &&
382+
!dc->soc->supports_sector_layout) {
383+
DRM_ERROR("hardware doesn't support GPU sector layout\n");
384+
return -EINVAL;
385+
}
386+
369387
/*
370388
* Tegra doesn't support different strides for U and V planes so we
371389
* error out if the user tries to display a framebuffer with such a
@@ -485,6 +503,16 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
485503

486504
base = tegra_plane_state->iova[0] + fb->offsets[0];
487505

506+
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
507+
/*
508+
* Physical address bit 39 in Tegra194 is used as a switch for special
509+
* logic that swizzles the memory using either the legacy Tegra or the
510+
* dGPU sector layout.
511+
*/
512+
if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU)
513+
base |= BIT(39);
514+
#endif
515+
488516
tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);
489517
tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);
490518

drivers/gpu/drm/tegra/plane.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@ static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
8383
kfree(state);
8484
}
8585

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+
86102
static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
87103
uint32_t format,
88104
uint64_t modifier)
@@ -92,6 +108,14 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
92108
if (modifier == DRM_FORMAT_MOD_LINEAR)
93109
return true;
94110

111+
/* check for the sector layout bit */
112+
if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) {
113+
if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) {
114+
if (!tegra_plane_supports_sector_layout(plane))
115+
return false;
116+
}
117+
}
118+
95119
if (info->num_planes == 1)
96120
return true;
97121

0 commit comments

Comments
 (0)