]> www.infradead.org Git - nvme.git/commitdiff
drm/tegra: Support sector layout on Tegra194
authorThierry Reding <treding@nvidia.com>
Fri, 26 Mar 2021 14:51:39 +0000 (15:51 +0100)
committerThierry Reding <treding@nvidia.com>
Wed, 31 Mar 2021 15:42:14 +0000 (17:42 +0200)
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>
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/dc.h
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/gem.h
drivers/gpu/drm/tegra/hub.c
drivers/gpu/drm/tegra/plane.c

index aacbe5e202d2eb576a418ee59edd7608e4a38d1f..f9120dc2468288acb4e0feefd990a97dbf7c5172 100644 (file)
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
index 21074cd2ce5e739c4c5d04063b81987963606582..29f19c3c614937bd3bc5963388fad122abf8b245 100644 (file)
@@ -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;
index eef933303a3c552699e4dac89c7152f6f51a568f..87df251c1fcf5589cd96f335ffcaf8be21895e5d 100644 (file)
@@ -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
index 350f33206076245399a037949c22c234a207d4d5..cae8b8cbe9dd096b7e1008090d1c07eb216864d3 100644 (file)
@@ -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;
index fafb5724499be51fdb2099801a06807fda0816d1..c15fd99d6cb2b4be67983e4577611bfb157562ad 100644 (file)
@@ -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 {
index 500c9d37e654336cbc5798a7d233db2d8edaac24..79bff8b48271a47071818131505b79e2a0be4b18 100644 (file)
@@ -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
 };
 
@@ -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
@@ -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);
 
index 793da5d675d2f4c1263c3e71bba32091c8029790..2e11b4b1f7025608a70561a2f5564cf802633296 100644 (file)
@@ -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)
@@ -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;