diff mbox series

[8/8] drm/amd/display: Expose modifiers.

Message ID 20200804213119.25091-9-bas@basnieuwenhuizen.nl (mailing list archive)
State New, archived
Headers show
Series amd/display: Add GFX9+ modifier support. | expand

Commit Message

Bas Nieuwenhuizen Aug. 4, 2020, 9:31 p.m. UTC
This expose modifier support on GFX9+.

Only modifiers that can be rendered on the current GPU are
added. This is to reduce the number of modifiers exposed.

The HW could expose more, but the best mechanism to decide
what to expose without an explosion in modifiers is still
to be decided, and in the meantime this should not regress
things from pre-modifiers and does not risk regressions as
we make up our mind in the future.

Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++-
 1 file changed, 342 insertions(+), 1 deletion(-)

Comments

Marek Olšák Aug. 7, 2020, 7:42 p.m. UTC | #1
On Tue, Aug 4, 2020 at 5:32 PM Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
wrote:

> This expose modifier support on GFX9+.
>
> Only modifiers that can be rendered on the current GPU are
> added. This is to reduce the number of modifiers exposed.
>
> The HW could expose more, but the best mechanism to decide
> what to expose without an explosion in modifiers is still
> to be decided, and in the meantime this should not regress
> things from pre-modifiers and does not risk regressions as
> we make up our mind in the future.
>
> Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++-
>  1 file changed, 342 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index c38257081868..6594cbe625f9 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const struct
> amdgpu_device *adev,
>         }
>  }
>
> +enum dm_micro_swizzle {
> +       MICRO_SWIZZLE_Z = 0,
> +       MICRO_SWIZZLE_S = 1,
> +       MICRO_SWIZZLE_D = 2,
> +       MICRO_SWIZZLE_R = 3
> +};
> +
> +static bool dm_plane_format_mod_supported(struct drm_plane *plane,
> +                                         uint32_t format,
> +                                         uint64_t modifier)
> +{
> +       struct amdgpu_device *adev = plane->dev->dev_private;
> +       const struct drm_format_info *info = drm_format_info(format);
> +
> +       enum dm_micro_swizzle microtile =
> modifier_gfx9_swizzle_mode(modifier) & 3;
> +
> +       if (!info)
> +               return false;
> +
> +       /*
> +        * We always have to allow this modifier, because core DRM still
> +        * checks LINEAR support if userspace does not provide modifers.
> +        */
> +       if (modifier == DRM_FORMAT_MOD_LINEAR)
> +               return true;
> +
> +       /*
> +        * The arbitrary tiling support for multiplane formats has not
> been hooked
> +        * up.
> +        */
> +       if (info->num_planes > 1)
> +               return false;
> +
> +       /*
> +        * For D swizzle the canonical modifier depends on the bpp, so
> check
> +        * it here.
> +        */
> +       if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) ==
> AMD_FMT_MOD_TILE_VER_GFX9 &&
> +           adev->family >= AMDGPU_FAMILY_NV) {
> +               if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
> +                       return false;
> +       }
> +
> +       if (adev->family >= AMDGPU_FAMILY_RV && microtile ==
> MICRO_SWIZZLE_D &&
> +           info->cpp[0] < 8)
> +               return false;
> +
> +       if (modifier_has_dcc(modifier)) {
> +               /* Per radeonsi comments 16/64 bpp are more complicated. */
> +               if (info->cpp[0] != 4)
> +                       return false;
> +       }
> +
> +       return true;
> +}
> +
> +static void
> +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
> +{
> +       if (!*mods)
> +               return;
> +
> +       if (*cap - *size < 1) {
> +               uint64_t new_cap = *cap * 2;
> +               uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t),
> GFP_KERNEL);
> +
> +               if (!new_mods) {
> +                       kfree(*mods);
> +                       *mods = NULL;
> +                       return;
> +               }
> +
> +               memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
> +               kfree(*mods);
> +               *mods = new_mods;
> +               *cap = new_cap;
> +       }
> +
> +       (*mods)[*size] = mod;
> +       *size += 1;
> +}
> +
> +static void
> +add_gfx9_modifiers(const struct amdgpu_device *adev,
> +                 uint64_t **mods, uint64_t *size, uint64_t *capacity)
> +{
> +       int pipes =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
> +       int pipe_xor_bits = min(8, pipes +
> +
>  ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
> +       int bank_xor_bits = min(8 - pipe_xor_bits,
> +
>  ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
> +       int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
> +
> ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
> +
> +
> +       if (adev->family == AMDGPU_FAMILY_RV) {
> +               /*
> +                * No _D DCC swizzles yet because we only allow 32bpp,
> which
> +                * doesn't support _D on DCN
> +                */
> +
> +               /*
> +                * Always enable constant encoding, because the only unit
> that
> +                * didn't support it was CB. But on texture/display we can
> +                * always interpret it.
> +                */
> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
> +                           AMD_FMT_MOD_SET(DCC, 1) |
> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
>

I don't think Raven1 can do DCC constant encoding in DCN and GL2.

+
> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
> +                           AMD_FMT_MOD_SET(DCC, 1) |
> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
> +
> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
> +                           AMD_FMT_MOD_SET(DCC, 1) |
> +                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
> +                           AMD_FMT_MOD_SET(RB, rb) |
> +                           AMD_FMT_MOD_SET(PIPE, pipes));
> +
> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
> +                           AMD_FMT_MOD_SET(DCC, 1) |
> +                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
> +                           AMD_FMT_MOD_SET(RB, rb) |
> +                           AMD_FMT_MOD_SET(PIPE, pipes));
> +       }
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
>

Addrlib says that D swizzle modes are unsupported for 32bpp in DCN1. They
are only supported in DCE12. The swizzle modes between the two have no
intersection.


> +
> +       if (adev->family == AMDGPU_FAMILY_RV) {
> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
> +       }
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> +
> +       if (adev->family == AMDGPU_FAMILY_RV) {
> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S) |
> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> +       }
> +}
> +
> +static void
> +add_gfx10_1_modifiers(const struct amdgpu_device *adev,
> +                    uint64_t **mods, uint64_t *size, uint64_t *capacity)
> +{
> +       int pipe_xor_bits =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(DCC, 1) |
> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
> +                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> +                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(DCC, 1) |
> +                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
> +                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> +                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
>

D swizzle modes are unsupported according to Addrlib.


> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> +}
> +
> +static void
> +add_gfx10_3_modifiers(const struct amdgpu_device *adev,
> +                    uint64_t **mods, uint64_t *size, uint64_t *capacity)
> +{
> +       int pipe_xor_bits =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
> +       int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
> +                   AMD_FMT_MOD_SET(DCC, 1) |
> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
> +                   AMD_FMT_MOD_SET(DCC, 1) |
> +                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(PACKERS, pkrs));
> +
> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> +                   AMD_FMT_MOD_SET(PACKERS, pkrs));
>

D swizzle modes are unsupported.

Marek
Bas Nieuwenhuizen Sept. 2, 2020, 10:31 a.m. UTC | #2
On Fri, Aug 7, 2020 at 9:43 PM Marek Olšák <maraeo@gmail.com> wrote:
>
> On Tue, Aug 4, 2020 at 5:32 PM Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> wrote:
>>
>> This expose modifier support on GFX9+.
>>
>> Only modifiers that can be rendered on the current GPU are
>> added. This is to reduce the number of modifiers exposed.
>>
>> The HW could expose more, but the best mechanism to decide
>> what to expose without an explosion in modifiers is still
>> to be decided, and in the meantime this should not regress
>> things from pre-modifiers and does not risk regressions as
>> we make up our mind in the future.
>>
>> Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
>> ---
>>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++-
>>  1 file changed, 342 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index c38257081868..6594cbe625f9 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
>>         }
>>  }
>>
>> +enum dm_micro_swizzle {
>> +       MICRO_SWIZZLE_Z = 0,
>> +       MICRO_SWIZZLE_S = 1,
>> +       MICRO_SWIZZLE_D = 2,
>> +       MICRO_SWIZZLE_R = 3
>> +};
>> +
>> +static bool dm_plane_format_mod_supported(struct drm_plane *plane,
>> +                                         uint32_t format,
>> +                                         uint64_t modifier)
>> +{
>> +       struct amdgpu_device *adev = plane->dev->dev_private;
>> +       const struct drm_format_info *info = drm_format_info(format);
>> +
>> +       enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
>> +
>> +       if (!info)
>> +               return false;
>> +
>> +       /*
>> +        * We always have to allow this modifier, because core DRM still
>> +        * checks LINEAR support if userspace does not provide modifers.
>> +        */
>> +       if (modifier == DRM_FORMAT_MOD_LINEAR)
>> +               return true;
>> +
>> +       /*
>> +        * The arbitrary tiling support for multiplane formats has not been hooked
>> +        * up.
>> +        */
>> +       if (info->num_planes > 1)
>> +               return false;
>> +
>> +       /*
>> +        * For D swizzle the canonical modifier depends on the bpp, so check
>> +        * it here.
>> +        */
>> +       if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
>> +           adev->family >= AMDGPU_FAMILY_NV) {
>> +               if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
>> +                       return false;
>> +       }
>> +
>> +       if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
>> +           info->cpp[0] < 8)
>> +               return false;
>> +
>> +       if (modifier_has_dcc(modifier)) {
>> +               /* Per radeonsi comments 16/64 bpp are more complicated. */
>> +               if (info->cpp[0] != 4)
>> +                       return false;
>> +       }
>> +
>> +       return true;
>> +}
>> +
>> +static void
>> +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
>> +{
>> +       if (!*mods)
>> +               return;
>> +
>> +       if (*cap - *size < 1) {
>> +               uint64_t new_cap = *cap * 2;
>> +               uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL);
>> +
>> +               if (!new_mods) {
>> +                       kfree(*mods);
>> +                       *mods = NULL;
>> +                       return;
>> +               }
>> +
>> +               memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
>> +               kfree(*mods);
>> +               *mods = new_mods;
>> +               *cap = new_cap;
>> +       }
>> +
>> +       (*mods)[*size] = mod;
>> +       *size += 1;
>> +}
>> +
>> +static void
>> +add_gfx9_modifiers(const struct amdgpu_device *adev,
>> +                 uint64_t **mods, uint64_t *size, uint64_t *capacity)
>> +{
>> +       int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
>> +       int pipe_xor_bits = min(8, pipes +
>> +                               ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
>> +       int bank_xor_bits = min(8 - pipe_xor_bits,
>> +                               ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
>> +       int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
>> +                ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
>> +
>> +
>> +       if (adev->family == AMDGPU_FAMILY_RV) {
>> +               /*
>> +                * No _D DCC swizzles yet because we only allow 32bpp, which
>> +                * doesn't support _D on DCN
>> +                */
>> +
>> +               /*
>> +                * Always enable constant encoding, because the only unit that
>> +                * didn't support it was CB. But on texture/display we can
>> +                * always interpret it.
>> +                */
>> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
>> +                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
>> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
>> +                           AMD_FMT_MOD_SET(DCC, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
>> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
>
>
> I don't think Raven1 can do DCC constant encoding in DCN and GL2.
>
>> +
>> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
>> +                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
>> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
>> +                           AMD_FMT_MOD_SET(DCC, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
>> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
>> +
>> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
>> +                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
>> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
>> +                           AMD_FMT_MOD_SET(DCC, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
>> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
>> +                           AMD_FMT_MOD_SET(RB, rb) |
>> +                           AMD_FMT_MOD_SET(PIPE, pipes));
>> +
>> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
>> +                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
>> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
>> +                           AMD_FMT_MOD_SET(DCC, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
>> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
>> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
>> +                           AMD_FMT_MOD_SET(RB, rb) |
>> +                           AMD_FMT_MOD_SET(PIPE, pipes));
>> +       }
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
>
>
> Addrlib says that D swizzle modes are unsupported for 32bpp in DCN1. They are only supported in DCE12. The swizzle modes between the two have no intersection.

Right, but we don't have the format here. These get further filtered
by dm_plane_format_mod_supported, which does:

        if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
            info->cpp[0] < 8)
                return false;

(cpp is in bytes)

>
>>
>> +
>> +       if (adev->family == AMDGPU_FAMILY_RV) {
>> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
>> +                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
>> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
>> +       }
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
>> +
>> +       if (adev->family == AMDGPU_FAMILY_RV) {
>> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
>> +                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
>> +       }
>> +}
>> +
>> +static void
>> +add_gfx10_1_modifiers(const struct amdgpu_device *adev,
>> +                    uint64_t **mods, uint64_t *size, uint64_t *capacity)
>> +{
>> +       int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(DCC, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(DCC, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
>
>
> D swizzle modes are unsupported according to Addrlib.

Seems to be supported for DCN2:

https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/gfx10/gfx10addrlib.cpp#L1942

which seems to be both gfx10.1 and gfx10.3 GPUs:

https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/gfx10/gfx10addrlib.cpp#L923

>
>>
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
>> +}
>> +
>> +static void
>> +add_gfx10_3_modifiers(const struct amdgpu_device *adev,
>> +                    uint64_t **mods, uint64_t *size, uint64_t *capacity)
>> +{
>> +       int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
>> +       int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
>> +                   AMD_FMT_MOD_SET(DCC, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
>> +                   AMD_FMT_MOD_SET(DCC, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
>> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(PACKERS, pkrs));
>> +
>> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
>> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
>> +                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
>> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
>> +                   AMD_FMT_MOD_SET(PACKERS, pkrs));
>
>
> D swizzle modes are unsupported.

Same as above.
>
> Marek
>
Marek Olšák Sept. 3, 2020, 2:42 a.m. UTC | #3
OK. Reviewed-by: Marek Olšák <marek.olsak@amd.com>

Marek

On Wed, Sep 2, 2020 at 6:31 AM Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
wrote:

> On Fri, Aug 7, 2020 at 9:43 PM Marek Olšák <maraeo@gmail.com> wrote:
> >
> > On Tue, Aug 4, 2020 at 5:32 PM Bas Nieuwenhuizen <
> bas@basnieuwenhuizen.nl> wrote:
> >>
> >> This expose modifier support on GFX9+.
> >>
> >> Only modifiers that can be rendered on the current GPU are
> >> added. This is to reduce the number of modifiers exposed.
> >>
> >> The HW could expose more, but the best mechanism to decide
> >> what to expose without an explosion in modifiers is still
> >> to be decided, and in the meantime this should not regress
> >> things from pre-modifiers and does not risk regressions as
> >> we make up our mind in the future.
> >>
> >> Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
> >> ---
> >>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++-
> >>  1 file changed, 342 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> index c38257081868..6594cbe625f9 100644
> >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const
> struct amdgpu_device *adev,
> >>         }
> >>  }
> >>
> >> +enum dm_micro_swizzle {
> >> +       MICRO_SWIZZLE_Z = 0,
> >> +       MICRO_SWIZZLE_S = 1,
> >> +       MICRO_SWIZZLE_D = 2,
> >> +       MICRO_SWIZZLE_R = 3
> >> +};
> >> +
> >> +static bool dm_plane_format_mod_supported(struct drm_plane *plane,
> >> +                                         uint32_t format,
> >> +                                         uint64_t modifier)
> >> +{
> >> +       struct amdgpu_device *adev = plane->dev->dev_private;
> >> +       const struct drm_format_info *info = drm_format_info(format);
> >> +
> >> +       enum dm_micro_swizzle microtile =
> modifier_gfx9_swizzle_mode(modifier) & 3;
> >> +
> >> +       if (!info)
> >> +               return false;
> >> +
> >> +       /*
> >> +        * We always have to allow this modifier, because core DRM still
> >> +        * checks LINEAR support if userspace does not provide modifers.
> >> +        */
> >> +       if (modifier == DRM_FORMAT_MOD_LINEAR)
> >> +               return true;
> >> +
> >> +       /*
> >> +        * The arbitrary tiling support for multiplane formats has not
> been hooked
> >> +        * up.
> >> +        */
> >> +       if (info->num_planes > 1)
> >> +               return false;
> >> +
> >> +       /*
> >> +        * For D swizzle the canonical modifier depends on the bpp, so
> check
> >> +        * it here.
> >> +        */
> >> +       if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) ==
> AMD_FMT_MOD_TILE_VER_GFX9 &&
> >> +           adev->family >= AMDGPU_FAMILY_NV) {
> >> +               if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
> >> +                       return false;
> >> +       }
> >> +
> >> +       if (adev->family >= AMDGPU_FAMILY_RV && microtile ==
> MICRO_SWIZZLE_D &&
> >> +           info->cpp[0] < 8)
> >> +               return false;
> >> +
> >> +       if (modifier_has_dcc(modifier)) {
> >> +               /* Per radeonsi comments 16/64 bpp are more
> complicated. */
> >> +               if (info->cpp[0] != 4)
> >> +                       return false;
> >> +       }
> >> +
> >> +       return true;
> >> +}
> >> +
> >> +static void
> >> +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t
> mod)
> >> +{
> >> +       if (!*mods)
> >> +               return;
> >> +
> >> +       if (*cap - *size < 1) {
> >> +               uint64_t new_cap = *cap * 2;
> >> +               uint64_t *new_mods = kmalloc(new_cap *
> sizeof(uint64_t), GFP_KERNEL);
> >> +
> >> +               if (!new_mods) {
> >> +                       kfree(*mods);
> >> +                       *mods = NULL;
> >> +                       return;
> >> +               }
> >> +
> >> +               memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
> >> +               kfree(*mods);
> >> +               *mods = new_mods;
> >> +               *cap = new_cap;
> >> +       }
> >> +
> >> +       (*mods)[*size] = mod;
> >> +       *size += 1;
> >> +}
> >> +
> >> +static void
> >> +add_gfx9_modifiers(const struct amdgpu_device *adev,
> >> +                 uint64_t **mods, uint64_t *size, uint64_t *capacity)
> >> +{
> >> +       int pipes =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
> >> +       int pipe_xor_bits = min(8, pipes +
> >> +
>  ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
> >> +       int bank_xor_bits = min(8 - pipe_xor_bits,
> >> +
>  ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
> >> +       int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
> >> +
> ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
> >> +
> >> +
> >> +       if (adev->family == AMDGPU_FAMILY_RV) {
> >> +               /*
> >> +                * No _D DCC swizzles yet because we only allow 32bpp,
> which
> >> +                * doesn't support _D on DCN
> >> +                */
> >> +
> >> +               /*
> >> +                * Always enable constant encoding, because the only
> unit that
> >> +                * didn't support it was CB. But on texture/display we
> can
> >> +                * always interpret it.
> >> +                */
> >> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> >> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> >> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS,
> pipe_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS,
> bank_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(DCC, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> >> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
> >
> >
> > I don't think Raven1 can do DCC constant encoding in DCN and GL2.
> >
> >> +
> >> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> >> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> >> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS,
> pipe_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS,
> bank_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(DCC, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> >> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
> >> +
> >> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> >> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> >> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS,
> pipe_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS,
> bank_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(DCC, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> >> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
> >> +                           AMD_FMT_MOD_SET(RB, rb) |
> >> +                           AMD_FMT_MOD_SET(PIPE, pipes));
> >> +
> >> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> >> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> >> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS,
> pipe_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS,
> bank_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(DCC, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> >> +                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B) |
> >> +                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
> >> +                           AMD_FMT_MOD_SET(RB, rb) |
> >> +                           AMD_FMT_MOD_SET(PIPE, pipes));
> >> +       }
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
> >
> >
> > Addrlib says that D swizzle modes are unsupported for 32bpp in DCN1.
> They are only supported in DCE12. The swizzle modes between the two have no
> intersection.
>
> Right, but we don't have the format here. These get further filtered
> by dm_plane_format_mod_supported, which does:
>
>         if (adev->family >= AMDGPU_FAMILY_RV && microtile ==
> MICRO_SWIZZLE_D &&
>             info->cpp[0] < 8)
>                 return false;
>
> (cpp is in bytes)
>
> >
> >>
> >> +
> >> +       if (adev->family == AMDGPU_FAMILY_RV) {
> >> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> >> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9) |
> >> +                           AMD_FMT_MOD_SET(PIPE_XOR_BITS,
> pipe_xor_bits) |
> >> +                           AMD_FMT_MOD_SET(BANK_XOR_BITS,
> bank_xor_bits));
> >> +       }
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> >> +
> >> +       if (adev->family == AMDGPU_FAMILY_RV) {
> >> +               add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                           AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S) |
> >> +                           AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> >> +       }
> >> +}
> >> +
> >> +static void
> >> +add_gfx10_1_modifiers(const struct amdgpu_device *adev,
> >> +                    uint64_t **mods, uint64_t *size, uint64_t
> *capacity)
> >> +{
> >> +       int pipe_xor_bits =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(DCC, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(DCC, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
> AMD_FMT_MOD_DCC_BLOCK_64B));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
> >
> >
> > D swizzle modes are unsupported according to Addrlib.
>
> Seems to be supported for DCN2:
>
>
> https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/gfx10/gfx10addrlib.cpp#L1942
>
> which seems to be both gfx10.1 and gfx10.3 GPUs:
>
>
> https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/gfx10/gfx10addrlib.cpp#L923
>
> >
> >>
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX9));
> >> +}
> >> +
> >> +static void
> >> +add_gfx10_3_modifiers(const struct amdgpu_device *adev,
> >> +                    uint64_t **mods, uint64_t *size, uint64_t
> *capacity)
> >> +{
> >> +       int pipe_xor_bits =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
> >> +       int pkrs =
> ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
> >> +                   AMD_FMT_MOD_SET(DCC, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
> >> +                   AMD_FMT_MOD_SET(DCC, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
> >> +                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(PACKERS, pkrs));
> >> +
> >> +       add_modifier(mods, size, capacity, AMD_FMT_MOD |
> >> +                   AMD_FMT_MOD_SET(TILE,
> AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
> >> +                   AMD_FMT_MOD_SET(TILE_VERSION,
> AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
> >> +                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
> >> +                   AMD_FMT_MOD_SET(PACKERS, pkrs));
> >
> >
> > D swizzle modes are unsupported.
>
> Same as above.
> >
> > Marek
> >
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c38257081868..6594cbe625f9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3891,6 +3891,340 @@  fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
 	}
 }
 
+enum dm_micro_swizzle {
+	MICRO_SWIZZLE_Z = 0,
+	MICRO_SWIZZLE_S = 1,
+	MICRO_SWIZZLE_D = 2,
+	MICRO_SWIZZLE_R = 3
+};
+
+static bool dm_plane_format_mod_supported(struct drm_plane *plane,
+					  uint32_t format,
+					  uint64_t modifier)
+{
+	struct amdgpu_device *adev = plane->dev->dev_private;
+	const struct drm_format_info *info = drm_format_info(format);
+
+	enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
+
+	if (!info)
+		return false;
+
+	/*
+	 * We always have to allow this modifier, because core DRM still
+	 * checks LINEAR support if userspace does not provide modifers.
+	 */
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return true;
+
+	/*
+	 * The arbitrary tiling support for multiplane formats has not been hooked
+	 * up.
+	 */
+	if (info->num_planes > 1)
+		return false;
+
+	/*
+	 * For D swizzle the canonical modifier depends on the bpp, so check
+	 * it here.
+	 */
+	if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
+	    adev->family >= AMDGPU_FAMILY_NV) {
+		if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
+			return false;
+	}
+
+	if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
+	    info->cpp[0] < 8)
+		return false;
+
+	if (modifier_has_dcc(modifier)) {
+		/* Per radeonsi comments 16/64 bpp are more complicated. */
+		if (info->cpp[0] != 4)
+			return false;
+	}
+
+	return true;
+}
+
+static void
+add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
+{
+	if (!*mods)
+		return;
+
+	if (*cap - *size < 1) {
+		uint64_t new_cap = *cap * 2;
+		uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL);
+
+		if (!new_mods) {
+			kfree(*mods);
+			*mods = NULL;
+			return;
+		}
+
+		memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
+		kfree(*mods);
+		*mods = new_mods;
+		*cap = new_cap;
+	}
+
+	(*mods)[*size] = mod;
+	*size += 1;
+}
+
+static void
+add_gfx9_modifiers(const struct amdgpu_device *adev,
+		  uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
+	int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
+	int pipe_xor_bits = min(8, pipes +
+				ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
+	int bank_xor_bits = min(8 - pipe_xor_bits,
+				ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
+	int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
+		 ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
+
+
+	if (adev->family == AMDGPU_FAMILY_RV) {
+		/*
+		 * No _D DCC swizzles yet because we only allow 32bpp, which
+		 * doesn't support _D on DCN
+		 */
+
+		/*
+		 * Always enable constant encoding, because the only unit that
+		 * didn't support it was CB. But on texture/display we can
+		 * always interpret it.
+		 */
+		add_modifier(mods, size, capacity, AMD_FMT_MOD |
+			    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+			    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+			    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+			    AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+			    AMD_FMT_MOD_SET(DCC, 1) |
+			    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+			    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+			    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
+
+		add_modifier(mods, size, capacity, AMD_FMT_MOD |
+			    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+			    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+			    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+			    AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+			    AMD_FMT_MOD_SET(DCC, 1) |
+			    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+			    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+			    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
+
+		add_modifier(mods, size, capacity, AMD_FMT_MOD |
+			    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+			    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+			    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+			    AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+			    AMD_FMT_MOD_SET(DCC, 1) |
+			    AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+			    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+			    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+			    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+			    AMD_FMT_MOD_SET(RB, rb) |
+			    AMD_FMT_MOD_SET(PIPE, pipes));
+
+		add_modifier(mods, size, capacity, AMD_FMT_MOD |
+			    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+			    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+			    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+			    AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+			    AMD_FMT_MOD_SET(DCC, 1) |
+			    AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+			    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+			    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+			    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
+			    AMD_FMT_MOD_SET(RB, rb) |
+			    AMD_FMT_MOD_SET(PIPE, pipes));
+	}
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+
+	if (adev->family == AMDGPU_FAMILY_RV) {
+		add_modifier(mods, size, capacity, AMD_FMT_MOD |
+			    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+			    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+			    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+			    AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+	}
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+	if (adev->family == AMDGPU_FAMILY_RV) {
+		add_modifier(mods, size, capacity, AMD_FMT_MOD |
+			    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+			    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+	}
+}
+
+static void
+add_gfx10_1_modifiers(const struct amdgpu_device *adev,
+		     uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
+	int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(DCC, 1) |
+		    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+		    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+		    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(DCC, 1) |
+		    AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+		    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+		    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+		    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+}
+
+static void
+add_gfx10_3_modifiers(const struct amdgpu_device *adev,
+		     uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
+	int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
+	int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(PACKERS, pkrs) |
+		    AMD_FMT_MOD_SET(DCC, 1) |
+		    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(PACKERS, pkrs) |
+		    AMD_FMT_MOD_SET(DCC, 1) |
+		    AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+		    AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 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_128B));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+		    AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+		    AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+	add_modifier(mods, size, capacity, AMD_FMT_MOD |
+		    AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+		    AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+}
+
+static int
+get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
+{
+	uint64_t size = 0, capacity = 128;
+	*mods = NULL;
+
+	/* We have not hooked up any pre-GFX9 modifiers. */
+	if (adev->family < AMDGPU_FAMILY_AI)
+		return 0;
+
+	*mods = kmalloc(capacity * sizeof(uint64_t), GFP_KERNEL);
+
+	if (plane_type == DRM_PLANE_TYPE_CURSOR) {
+		add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
+		add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
+		return *mods ? 0 : -ENOMEM;
+	}
+
+	switch (adev->family) {
+	case AMDGPU_FAMILY_AI:
+	case AMDGPU_FAMILY_RV:
+		add_gfx9_modifiers(adev, mods, &size, &capacity);
+		break;
+	case AMDGPU_FAMILY_NV:
+		if (adev->asic_type >= CHIP_SIENNA_CICHLID)
+			add_gfx10_3_modifiers(adev, mods, &size, &capacity);
+		else
+			add_gfx10_1_modifiers(adev, mods, &size, &capacity);
+		break;
+	}
+
+	add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
+
+	/* INVALID marks the end of the list. */
+	add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
+
+	if (!*mods)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static void
 block_alignment(unsigned int blocksize_log2, unsigned int *width, unsigned int *height)
 {
@@ -5886,6 +6220,7 @@  static const struct drm_plane_funcs dm_plane_funcs = {
 	.reset = dm_drm_plane_reset,
 	.atomic_duplicate_state = dm_drm_plane_duplicate_state,
 	.atomic_destroy_state = dm_drm_plane_destroy_state,
+	.format_mod_supported = dm_plane_format_mod_supported,
 };
 
 static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
@@ -6154,13 +6489,19 @@  static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 	uint32_t formats[32];
 	int num_formats;
 	int res = -EPERM;
+	uint64_t *modifiers = NULL;
 
 	num_formats = get_plane_formats(plane, plane_cap, formats,
 					ARRAY_SIZE(formats));
 
+	res = get_plane_modifiers(dm->adev, plane->type, &modifiers);
+	if (res)
+		return res;
+
 	res = drm_universal_plane_init(dm->adev->ddev, plane, possible_crtcs,
 				       &dm_plane_funcs, formats, num_formats,
-				       NULL, plane->type, NULL);
+				       modifiers, plane->type, NULL);
+	kfree(modifiers);
 	if (res)
 		return res;