Skip to content

Commit

Permalink
drm/tegra: Support sector layout on Tegra194
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
thierryreding committed Mar 31, 2021
1 parent 05d1adf commit 7b6f846
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/gpu/drm/tegra/dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2325,6 +2325,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
.supports_block_linear = false,
.supports_sector_layout = false,
.has_legacy_blending = true,
.pitch_align = 8,
.has_powergate = false,
Expand All @@ -2344,6 +2345,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
.supports_block_linear = false,
.supports_sector_layout = false,
.has_legacy_blending = true,
.pitch_align = 8,
.has_powergate = false,
Expand All @@ -2363,6 +2365,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
.supports_block_linear = false,
.supports_sector_layout = false,
.has_legacy_blending = true,
.pitch_align = 64,
.has_powergate = true,
Expand All @@ -2382,6 +2385,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.supports_interlacing = true,
.supports_cursor = true,
.supports_block_linear = true,
.supports_sector_layout = false,
.has_legacy_blending = false,
.pitch_align = 64,
.has_powergate = true,
Expand All @@ -2401,6 +2405,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
.supports_interlacing = true,
.supports_cursor = true,
.supports_block_linear = true,
.supports_sector_layout = false,
.has_legacy_blending = false,
.pitch_align = 64,
.has_powergate = true,
Expand Down Expand Up @@ -2454,6 +2459,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
.supports_interlacing = true,
.supports_cursor = true,
.supports_block_linear = true,
.supports_sector_layout = false,
.has_legacy_blending = false,
.pitch_align = 64,
.has_powergate = false,
Expand Down Expand Up @@ -2502,6 +2508,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
.supports_interlacing = true,
.supports_cursor = true,
.supports_block_linear = true,
.supports_sector_layout = true,
.has_legacy_blending = false,
.pitch_align = 64,
.has_powergate = false,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/tegra/dc.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct tegra_dc_soc_info {
bool supports_interlacing;
bool supports_cursor;
bool supports_block_linear;
bool supports_sector_layout;
bool has_legacy_blending;
unsigned int pitch_align;
bool has_powergate;
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/tegra/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include "hub.h"
#include "trace.h"

/* XXX move to include/uapi/drm/drm_fourcc.h? */
#define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT(22)

struct reset_control;

#ifdef CONFIG_DRM_FBDEV_EMULATION
Expand Down
9 changes: 9 additions & 0 deletions drivers/gpu/drm/tegra/fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
{
uint64_t modifier = framebuffer->modifier;

if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) {
if ((modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) == 0)
tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_TEGRA;
else
tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_GPU;

modifier &= ~DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT;
}

switch (modifier) {
case DRM_FORMAT_MOD_LINEAR:
tiling->mode = TEGRA_BO_TILING_MODE_PITCH;
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/tegra/gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ enum tegra_bo_tiling_mode {
TEGRA_BO_TILING_MODE_BLOCK,
};

enum tegra_bo_sector_layout {
TEGRA_BO_SECTOR_LAYOUT_TEGRA,
TEGRA_BO_SECTOR_LAYOUT_GPU,
};

struct tegra_bo_tiling {
enum tegra_bo_tiling_mode mode;
unsigned long value;
enum tegra_bo_sector_layout sector_layout;
};

struct tegra_bo {
Expand Down
28 changes: 28 additions & 0 deletions drivers/gpu/drm/tegra/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ static const u64 tegra_shared_plane_modifiers[] = {
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
/*
* The GPU sector layout is only supported on Tegra194, but these will
* be filtered out later on by ->format_mod_supported() on SoCs where
* it isn't supported.
*/
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
/* sentinel */
DRM_FORMAT_MOD_INVALID
};

Expand Down Expand Up @@ -366,6 +378,12 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}

if (tiling->sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU &&
!dc->soc->supports_sector_layout) {
DRM_ERROR("hardware doesn't support GPU sector layout\n");
return -EINVAL;
}

/*
* Tegra doesn't support different strides for U and V planes so we
* error out if the user tries to display a framebuffer with such a
Expand Down Expand Up @@ -485,6 +503,16 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,

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

#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
/*
* Physical address bit 39 in Tegra194 is used as a switch for special
* logic that swizzles the memory using either the legacy Tegra or the
* dGPU sector layout.
*/
if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU)
base |= BIT(39);
#endif

tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);
tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);

Expand Down
24 changes: 24 additions & 0 deletions drivers/gpu/drm/tegra/plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
kfree(state);
}

static bool tegra_plane_supports_sector_layout(struct drm_plane *plane)
{
struct drm_crtc *crtc;

drm_for_each_crtc(crtc, plane->dev) {
if (plane->possible_crtcs & drm_crtc_mask(crtc)) {
struct tegra_dc *dc = to_tegra_dc(crtc);

if (!dc->soc->supports_sector_layout)
return false;
}
}

return true;
}

static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
Expand All @@ -92,6 +108,14 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane,
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;

/* check for the sector layout bit */
if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) {
if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) {
if (!tegra_plane_supports_sector_layout(plane))
return false;
}
}

if (info->num_planes == 1)
return true;

Expand Down

0 comments on commit 7b6f846

Please sign in to comment.