Commit 543036a2 authored by Aurabindo Pillai's avatar Aurabindo Pillai Committed by Alex Deucher

drm/amd: Add GFX11 modifiers support to AMDGPU (v3)

GFX11 IP introduces new tiling mode. Various combinations of DCC
settings are possible and the most preferred settings must be exposed
for optimal use of the hardware.

add_gfx11_modifiers() is based on recommendation from Marek for the
preferred tiling modifier that are most efficient for the hardware.

v2: microtiling fix noticed by Marek
v3: keep Z tiling check
Signed-off-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 49401d3a
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#include "atom.h" #include "atom.h"
#include "amdgpu_connectors.h" #include "amdgpu_connectors.h"
#include "amdgpu_display.h" #include "amdgpu_display.h"
#include "soc15_common.h"
#include "gc/gc_11_0_0_offset.h"
#include "gc/gc_11_0_0_sh_mask.h"
#include <asm/div64.h> #include <asm/div64.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -663,6 +666,11 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) ...@@ -663,6 +666,11 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
{ {
struct amdgpu_device *adev = drm_to_adev(afb->base.dev); struct amdgpu_device *adev = drm_to_adev(afb->base.dev);
uint64_t modifier = 0; uint64_t modifier = 0;
int num_pipes = 0;
int num_pkrs = 0;
num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
num_pipes = adev->gfx.config.gb_addr_config_fields.num_pipes;
if (!afb->tiling_flags || !AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE)) { if (!afb->tiling_flags || !AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE)) {
modifier = DRM_FORMAT_MOD_LINEAR; modifier = DRM_FORMAT_MOD_LINEAR;
...@@ -675,7 +683,7 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) ...@@ -675,7 +683,7 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
int bank_xor_bits = 0; int bank_xor_bits = 0;
int packers = 0; int packers = 0;
int rb = 0; int rb = 0;
int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes); int pipes = ilog2(num_pipes);
uint32_t dcc_offset = AMDGPU_TILING_GET(afb->tiling_flags, DCC_OFFSET_256B); uint32_t dcc_offset = AMDGPU_TILING_GET(afb->tiling_flags, DCC_OFFSET_256B);
switch (swizzle >> 2) { switch (swizzle >> 2) {
...@@ -691,12 +699,17 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) ...@@ -691,12 +699,17 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
case 6: /* 64 KiB _X */ case 6: /* 64 KiB _X */
block_size_bits = 16; block_size_bits = 16;
break; break;
case 7: /* 256 KiB */
block_size_bits = 18;
break;
default: default:
/* RESERVED or VAR */ /* RESERVED or VAR */
return -EINVAL; return -EINVAL;
} }
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0))
version = AMD_FMT_MOD_TILE_VER_GFX11;
else if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS; version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS;
else if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0)) else if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0))
version = AMD_FMT_MOD_TILE_VER_GFX10; version = AMD_FMT_MOD_TILE_VER_GFX10;
...@@ -707,19 +720,33 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) ...@@ -707,19 +720,33 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
case 0: /* Z microtiling */ case 0: /* Z microtiling */
return -EINVAL; return -EINVAL;
case 1: /* S microtiling */ case 1: /* S microtiling */
if (!has_xor) if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0)) {
version = AMD_FMT_MOD_TILE_VER_GFX9; if (!has_xor)
version = AMD_FMT_MOD_TILE_VER_GFX9;
}
break; break;
case 2: case 2:
if (!has_xor && afb->base.format->cpp[0] != 4) if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0)) {
version = AMD_FMT_MOD_TILE_VER_GFX9; if (!has_xor && afb->base.format->cpp[0] != 4)
version = AMD_FMT_MOD_TILE_VER_GFX9;
}
break; break;
case 3: case 3:
break; break;
} }
if (has_xor) { if (has_xor) {
if (num_pipes == num_pkrs && num_pkrs == 0) {
DRM_ERROR("invalid number of pipes and packers\n");
return -EINVAL;
}
switch (version) { switch (version) {
case AMD_FMT_MOD_TILE_VER_GFX11:
pipe_xor_bits = min(block_size_bits - 8, pipes);
packers = min(block_size_bits - 8 - pipe_xor_bits,
ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs));
break;
case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS:
pipe_xor_bits = min(block_size_bits - 8, pipes); pipe_xor_bits = min(block_size_bits - 8, pipes);
packers = min(block_size_bits - 8 - pipe_xor_bits, packers = min(block_size_bits - 8 - pipe_xor_bits,
...@@ -753,9 +780,10 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) ...@@ -753,9 +780,10 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
u64 render_dcc_offset; u64 render_dcc_offset;
/* Enable constant encode on RAVEN2 and later. */ /* Enable constant encode on RAVEN2 and later. */
bool dcc_constant_encode = adev->asic_type > CHIP_RAVEN || bool dcc_constant_encode = (adev->asic_type > CHIP_RAVEN ||
(adev->asic_type == CHIP_RAVEN && (adev->asic_type == CHIP_RAVEN &&
adev->external_rev_id >= 0x81); adev->external_rev_id >= 0x81)) &&
adev->ip_versions[GC_HWIP][0] < IP_VERSION(11, 0, 0);
int max_cblock_size = dcc_i64b ? AMD_FMT_MOD_DCC_BLOCK_64B : int max_cblock_size = dcc_i64b ? AMD_FMT_MOD_DCC_BLOCK_64B :
dcc_i128b ? AMD_FMT_MOD_DCC_BLOCK_128B : dcc_i128b ? AMD_FMT_MOD_DCC_BLOCK_128B :
...@@ -870,10 +898,11 @@ static unsigned int get_dcc_block_size(uint64_t modifier, bool rb_aligned, ...@@ -870,10 +898,11 @@ static unsigned int get_dcc_block_size(uint64_t modifier, bool rb_aligned,
return max(10 + (rb_aligned ? (int)AMD_FMT_MOD_GET(RB, modifier) : 0), 12); return max(10 + (rb_aligned ? (int)AMD_FMT_MOD_GET(RB, modifier) : 0), 12);
} }
case AMD_FMT_MOD_TILE_VER_GFX10: case AMD_FMT_MOD_TILE_VER_GFX10:
case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: { case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS:
case AMD_FMT_MOD_TILE_VER_GFX11: {
int pipes_log2 = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier); int pipes_log2 = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
if (ver == AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS && pipes_log2 > 1 && if (ver >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS && pipes_log2 > 1 &&
AMD_FMT_MOD_GET(PACKERS, modifier) == pipes_log2) AMD_FMT_MOD_GET(PACKERS, modifier) == pipes_log2)
++pipes_log2; ++pipes_log2;
...@@ -966,6 +995,9 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb) ...@@ -966,6 +995,9 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
case DC_SW_64KB_S_X: case DC_SW_64KB_S_X:
block_size_log2 = 16; block_size_log2 = 16;
break; break;
case DC_SW_VAR_S_X:
block_size_log2 = 18;
break;
default: default:
drm_dbg_kms(rfb->base.dev, drm_dbg_kms(rfb->base.dev,
"Swizzle mode with unknown block size: %d\n", swizzle); "Swizzle mode with unknown block size: %d\n", swizzle);
......
...@@ -89,10 +89,14 @@ ...@@ -89,10 +89,14 @@
#include "dcn/dcn_1_0_offset.h" #include "dcn/dcn_1_0_offset.h"
#include "dcn/dcn_1_0_sh_mask.h" #include "dcn/dcn_1_0_sh_mask.h"
#include "soc15_hw_ip.h" #include "soc15_hw_ip.h"
#include "soc15_common.h"
#include "vega10_ip_offset.h" #include "vega10_ip_offset.h"
#include "soc15_common.h" #include "soc15_common.h"
#include "gc/gc_11_0_0_offset.h"
#include "gc/gc_11_0_0_sh_mask.h"
#include "modules/inc/mod_freesync.h" #include "modules/inc/mod_freesync.h"
#include "modules/power/power_helpers.h" #include "modules/power/power_helpers.h"
#include "modules/inc/mod_info_packet.h" #include "modules/inc/mod_info_packet.h"
...@@ -4888,7 +4892,9 @@ fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev, ...@@ -4888,7 +4892,9 @@ fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier); unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier); unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier); unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
unsigned int pipes_log2 = min(4u, mod_pipe_xor_bits); unsigned int pipes_log2;
pipes_log2 = min(5u, mod_pipe_xor_bits);
fill_gfx9_tiling_info_from_device(adev, tiling_info); fill_gfx9_tiling_info_from_device(adev, tiling_info);
...@@ -5224,8 +5230,69 @@ add_gfx10_3_modifiers(const struct amdgpu_device *adev, ...@@ -5224,8 +5230,69 @@ add_gfx10_3_modifiers(const struct amdgpu_device *adev,
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
} }
static void
add_gfx11_modifiers(struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
{
int num_pipes = 0;
int pipe_xor_bits = 0;
int num_pkrs = 0;
int pkrs = 0;
u32 gb_addr_config;
unsigned swizzle_r_x;
uint64_t modifier_r_x;
uint64_t modifier_dcc_best;
uint64_t modifier_dcc_4k;
/* TODO: GFX11 IP HW init hasnt finish and we get zero if we read from
* adev->gfx.config.gb_addr_config_fields.num_{pkrs,pipes} */
gb_addr_config = RREG32_SOC15(GC, 0, regGB_ADDR_CONFIG);
ASSERT(gb_addr_config != 0);
num_pkrs = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
pkrs = ilog2(num_pkrs);
num_pipes = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PIPES);
pipe_xor_bits = ilog2(num_pipes);
/* R_X swizzle modes are the best for rendering and DCC requires them. */
swizzle_r_x = num_pipes > 16 ? AMD_FMT_MOD_TILE_GFX11_256K_R_X :
AMD_FMT_MOD_TILE_GFX9_64K_R_X;
modifier_r_x = AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
AMD_FMT_MOD_SET(TILE, swizzle_r_x) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs);
/* DCC_CONSTANT_ENCODE is not set because it can't vary with gfx11 (it's implied to be 1). */
modifier_dcc_best = modifier_r_x |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 0) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B);
/* DCC settings for 4K and greater resolutions. (required by display hw) */
modifier_dcc_4k = modifier_r_x |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B);
add_modifier(mods, size, capacity, modifier_dcc_best);
add_modifier(mods, size, capacity, modifier_dcc_4k);
add_modifier(mods, size, capacity, modifier_dcc_best | AMD_FMT_MOD_SET(DCC_RETILE, 1));
add_modifier(mods, size, capacity, modifier_dcc_4k | AMD_FMT_MOD_SET(DCC_RETILE, 1));
add_modifier(mods, size, capacity, modifier_r_x);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D));
}
static int static int
get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods) get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
{ {
uint64_t size = 0, capacity = 128; uint64_t size = 0, capacity = 128;
*mods = NULL; *mods = NULL;
...@@ -5257,6 +5324,9 @@ get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, u ...@@ -5257,6 +5324,9 @@ get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, u
else else
add_gfx10_1_modifiers(adev, mods, &size, &capacity); add_gfx10_1_modifiers(adev, mods, &size, &capacity);
break; break;
case AMDGPU_FAMILY_GC_11_0_0:
add_gfx11_modifiers(adev, mods, &size, &capacity);
break;
} }
add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR); add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
...@@ -5295,7 +5365,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, ...@@ -5295,7 +5365,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
dcc->enable = 1; dcc->enable = 1;
dcc->meta_pitch = afb->base.pitches[1]; dcc->meta_pitch = afb->base.pitches[1];
dcc->independent_64b_blks = independent_64b_blks; dcc->independent_64b_blks = independent_64b_blks;
if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) { if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) {
if (independent_64b_blks && independent_128b_blks) if (independent_64b_blks && independent_128b_blks)
dcc->dcc_ind_blk = hubp_ind_block_64b_no_128bcl; dcc->dcc_ind_blk = hubp_ind_block_64b_no_128bcl;
else if (independent_128b_blks) else if (independent_128b_blks)
......
...@@ -1363,6 +1363,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) ...@@ -1363,6 +1363,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
#define AMD_FMT_MOD_TILE_VER_GFX9 1 #define AMD_FMT_MOD_TILE_VER_GFX9 1
#define AMD_FMT_MOD_TILE_VER_GFX10 2 #define AMD_FMT_MOD_TILE_VER_GFX10 2
#define AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS 3 #define AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS 3
#define AMD_FMT_MOD_TILE_VER_GFX11 4
/* /*
* 64K_S is the same for GFX9/GFX10/GFX10_RBPLUS and hence has GFX9 as canonical * 64K_S is the same for GFX9/GFX10/GFX10_RBPLUS and hence has GFX9 as canonical
...@@ -1378,6 +1379,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) ...@@ -1378,6 +1379,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
#define AMD_FMT_MOD_TILE_GFX9_64K_S_X 25 #define AMD_FMT_MOD_TILE_GFX9_64K_S_X 25
#define AMD_FMT_MOD_TILE_GFX9_64K_D_X 26 #define AMD_FMT_MOD_TILE_GFX9_64K_D_X 26
#define AMD_FMT_MOD_TILE_GFX9_64K_R_X 27 #define AMD_FMT_MOD_TILE_GFX9_64K_R_X 27
#define AMD_FMT_MOD_TILE_GFX11_256K_R_X 31
#define AMD_FMT_MOD_DCC_BLOCK_64B 0 #define AMD_FMT_MOD_DCC_BLOCK_64B 0
#define AMD_FMT_MOD_DCC_BLOCK_128B 1 #define AMD_FMT_MOD_DCC_BLOCK_128B 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment