Commit 08d76915 authored by Bas Nieuwenhuizen's avatar Bas Nieuwenhuizen Committed by Alex Deucher

drm/amd/display: Convert tiling_flags to modifiers.

This way the modifier path gets exercised all the time, improving
testing. Furthermore, for modifiers this is required as getfb2
will always return the modifier if the driver sets allow_fb_modifiers.

This only triggers once allow_fb_modifiers is set.
Signed-off-by: default avatarBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6eed95b0
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h> #include <drm/drm_vblank.h>
static void amdgpu_display_flip_callback(struct dma_fence *f, static void amdgpu_display_flip_callback(struct dma_fence *f,
...@@ -541,6 +542,121 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev, ...@@ -541,6 +542,121 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
return domain; return domain;
} }
static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
{
struct amdgpu_device *adev = drm_to_adev(afb->base.dev);
uint64_t modifier = 0;
if (!afb->tiling_flags || !AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE)) {
modifier = DRM_FORMAT_MOD_LINEAR;
} else {
int swizzle = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE);
bool has_xor = swizzle >= 16;
int block_size_bits;
int version;
int pipe_xor_bits = 0;
int bank_xor_bits = 0;
int packers = 0;
uint32_t dcc_offset = AMDGPU_TILING_GET(afb->tiling_flags, DCC_OFFSET_256B);
switch (swizzle >> 2) {
case 0: /* 256B */
block_size_bits = 8;
break;
case 1: /* 4KiB */
case 5: /* 4KiB _X */
block_size_bits = 12;
break;
case 2: /* 64KiB */
case 4: /* 64 KiB _T */
case 6: /* 64 KiB _X */
block_size_bits = 16;
break;
default:
/* RESERVED or VAR */
return -EINVAL;
}
if (adev->asic_type >= CHIP_SIENNA_CICHLID)
version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS;
else if (adev->family == AMDGPU_FAMILY_NV)
version = AMD_FMT_MOD_TILE_VER_GFX10;
else
version = AMD_FMT_MOD_TILE_VER_GFX9;
switch (swizzle & 3) {
case 0: /* Z microtiling */
return -EINVAL;
case 1: /* S microtiling */
if (!has_xor)
version = AMD_FMT_MOD_TILE_VER_GFX9;
break;
case 2:
if (!has_xor && afb->base.format->cpp[0] != 4)
version = AMD_FMT_MOD_TILE_VER_GFX9;
break;
case 3:
break;
}
if (has_xor) {
switch (version) {
case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS:
pipe_xor_bits = min(block_size_bits - 8,
ilog2(adev->gfx.config.gb_addr_config_fields.num_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:
pipe_xor_bits = min(block_size_bits - 8,
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes));
break;
case AMD_FMT_MOD_TILE_VER_GFX9:
pipe_xor_bits = min(block_size_bits - 8,
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes) +
ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
bank_xor_bits = min(block_size_bits - 8 - pipe_xor_bits,
ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
break;
}
}
modifier = AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE)) |
AMD_FMT_MOD_SET(TILE_VERSION, version) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, packers);
if (dcc_offset != 0) {
bool dcc_i64b = AMDGPU_TILING_GET(afb->tiling_flags, DCC_INDEPENDENT_64B) != 0;
bool dcc_i128b = version >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS;
/* Enable constant encode on RAVEN2 and later. */
bool dcc_constant_encode = adev->asic_type > CHIP_RAVEN ||
(adev->asic_type == CHIP_RAVEN &&
adev->external_rev_id >= 0x81);
int max_cblock_size = dcc_i64b ? AMD_FMT_MOD_DCC_BLOCK_64B :
dcc_i128b ? AMD_FMT_MOD_DCC_BLOCK_128B :
AMD_FMT_MOD_DCC_BLOCK_256B;
modifier |= AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, dcc_constant_encode) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, dcc_i64b) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, dcc_i128b) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_cblock_size);
afb->base.offsets[1] = dcc_offset * 256 + afb->base.offsets[0];
afb->base.pitches[1] = AMDGPU_TILING_GET(afb->tiling_flags, DCC_PITCH_MAX) + 1;
}
}
afb->base.modifier = modifier;
afb->base.flags |= DRM_MODE_FB_MODIFIERS;
return 0;
}
static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
uint64_t *tiling_flags, bool *tmz_surface) uint64_t *tiling_flags, bool *tmz_surface)
{ {
...@@ -590,6 +706,13 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev, ...@@ -590,6 +706,13 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev,
if (ret) if (ret)
goto fail; goto fail;
if (dev->mode_config.allow_fb_modifiers &&
!(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) {
ret = convert_tiling_flags_to_modifier(rfb);
if (ret)
goto fail;
}
return 0; return 0;
fail: fail:
......
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