From f0c746ce07c8df0d5b5582a87b0baf238ab49d27 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 17 Jul 2020 16:28:46 +0800 Subject: drm/amd/display: add S/G support for Renoir S/G (scatter/gather) display support for display buffers in system memory. Signed-off-by: Yifan Zhang Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 7cc7af2a6822..21da253d8edf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -528,6 +528,10 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev, (adev->apu_flags & AMD_APU_IS_PICASSO)) domain |= AMDGPU_GEM_DOMAIN_GTT; break; + case CHIP_RENOIR: + domain |= AMDGPU_GEM_DOMAIN_GTT; + break; + default: break; } -- cgit v1.2.3 From 6eed95b00b45ca241dbec6f684967925bfdfb0e5 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 2 Sep 2020 14:22:38 +0200 Subject: drm/amd/display: Store tiling_flags in the framebuffer. This moves the tiling_flags to the framebuffer creation. This way the time of the "tiling" decision is the same as it would be with modifiers. Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Alex Deucher Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 48 +++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 3 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 73 ++++------------------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 - 4 files changed, 59 insertions(+), 67 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 21da253d8edf..695f81fd93bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -541,6 +541,39 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev, return domain; } +static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, bool *tmz_surface) +{ + struct amdgpu_bo *rbo; + int r; + + if (!amdgpu_fb) { + *tiling_flags = 0; + *tmz_surface = false; + return 0; + } + + rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]); + r = amdgpu_bo_reserve(rbo, false); + + if (unlikely(r)) { + /* Don't show error message when returning -ERESTARTSYS */ + if (r != -ERESTARTSYS) + DRM_ERROR("Unable to reserve buffer: %d\n", r); + return r; + } + + if (tiling_flags) + amdgpu_bo_get_tiling_flags(rbo, tiling_flags); + + if (tmz_surface) + *tmz_surface = amdgpu_bo_encrypted(rbo); + + amdgpu_bo_unreserve(rbo); + + return r; +} + int amdgpu_display_framebuffer_init(struct drm_device *dev, struct amdgpu_framebuffer *rfb, const struct drm_mode_fb_cmd2 *mode_cmd, @@ -550,11 +583,18 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev, rfb->base.obj[0] = obj; drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd); ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs); - if (ret) { - rfb->base.obj[0] = NULL; - return ret; - } + if (ret) + goto fail; + + ret = amdgpu_display_get_fb_info(rfb, &rfb->tiling_flags, &rfb->tmz_surface); + if (ret) + goto fail; + return 0; + +fail: + rfb->base.obj[0] = NULL; + return ret; } struct drm_framebuffer * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index a04decb934b0..319cb19e1b99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -302,6 +302,9 @@ struct amdgpu_display_funcs { struct amdgpu_framebuffer { struct drm_framebuffer base; + uint64_t tiling_flags; + bool tmz_surface; + /* caching for later use */ uint64_t address; }; 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 b10af51b0a0c..203a4e098f39 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3760,39 +3760,6 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state, return 0; } -static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, bool *tmz_surface) -{ - struct amdgpu_bo *rbo; - int r; - - if (!amdgpu_fb) { - *tiling_flags = 0; - *tmz_surface = false; - return 0; - } - - rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]); - r = amdgpu_bo_reserve(rbo, false); - - if (unlikely(r)) { - /* Don't show error message when returning -ERESTARTSYS */ - if (r != -ERESTARTSYS) - DRM_ERROR("Unable to reserve buffer: %d\n", r); - return r; - } - - if (tiling_flags) - amdgpu_bo_get_tiling_flags(rbo, tiling_flags); - - if (tmz_surface) - *tmz_surface = amdgpu_bo_encrypted(rbo); - - amdgpu_bo_unreserve(rbo); - - return r; -} - static inline uint64_t get_dcc_address(uint64_t address, uint64_t tiling_flags) { uint32_t offset = AMDGPU_TILING_GET(tiling_flags, DCC_OFFSET_256B); @@ -4208,7 +4175,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, struct drm_crtc_state *crtc_state) { struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state); - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + struct amdgpu_framebuffer *afb = (struct amdgpu_framebuffer *)plane_state->fb; struct dc_scaling_info scaling_info; struct dc_plane_info plane_info; int ret; @@ -4225,10 +4192,10 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend; ret = fill_dc_plane_info_and_addr(adev, plane_state, - dm_plane_state->tiling_flags, + afb->tiling_flags, &plane_info, &dc_plane_state->address, - dm_plane_state->tmz_surface, + afb->tmz_surface, force_disable_dcc); if (ret) return ret; @@ -5828,10 +5795,6 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) dc_plane_state_retain(dm_plane_state->dc_state); } - /* Framebuffer hasn't been updated yet, so retain old flags. */ - dm_plane_state->tiling_flags = old_dm_plane_state->tiling_flags; - dm_plane_state->tmz_surface = old_dm_plane_state->tmz_surface; - return &dm_plane_state->base; } @@ -5936,10 +5899,10 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, fill_plane_buffer_attributes( adev, afb, plane_state->format, plane_state->rotation, - dm_plane_state_new->tiling_flags, + afb->tiling_flags, &plane_state->tiling_info, &plane_state->plane_size, &plane_state->dcc, &plane_state->address, - dm_plane_state_new->tmz_surface, force_disable_dcc); + afb->tmz_surface, force_disable_dcc); } return 0; @@ -7202,6 +7165,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_crtc *crtc = new_plane_state->crtc; struct drm_crtc_state *new_crtc_state; struct drm_framebuffer *fb = new_plane_state->fb; + struct amdgpu_framebuffer *afb = (struct amdgpu_framebuffer *)fb; bool plane_needs_flip; struct dc_plane_state *dc_plane; struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); @@ -7256,10 +7220,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, fill_dc_plane_info_and_addr( dm->adev, new_plane_state, - dm_new_plane_state->tiling_flags, + afb->tiling_flags, &bundle->plane_infos[planes_count], &bundle->flip_addrs[planes_count].address, - dm_new_plane_state->tmz_surface, false); + afb->tmz_surface, false); DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n", new_plane_state->plane->index, @@ -8400,8 +8364,7 @@ static bool should_reset_plane(struct drm_atomic_state *state, * TODO: Come up with a more elegant solution for this. */ for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) { - struct dm_plane_state *old_dm_plane_state, *new_dm_plane_state; - + struct amdgpu_framebuffer *old_afb, *new_afb; if (other->type == DRM_PLANE_TYPE_CURSOR) continue; @@ -8445,12 +8408,11 @@ static bool should_reset_plane(struct drm_atomic_state *state, if (old_other_state->fb->format != new_other_state->fb->format) return true; - old_dm_plane_state = to_dm_plane_state(old_other_state); - new_dm_plane_state = to_dm_plane_state(new_other_state); + old_afb = (struct amdgpu_framebuffer *)old_other_state->fb; + new_afb = (struct amdgpu_framebuffer *)new_other_state->fb; /* Tiling and DCC changes also require bandwidth updates. */ - if (old_dm_plane_state->tiling_flags != - new_dm_plane_state->tiling_flags) + if (old_afb->tiling_flags != new_afb->tiling_flags) return true; } @@ -8776,17 +8738,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } - /* Prepass for updating tiling flags on new planes. */ - for_each_new_plane_in_state(state, plane, new_plane_state, i) { - struct dm_plane_state *new_dm_plane_state = to_dm_plane_state(new_plane_state); - struct amdgpu_framebuffer *new_afb = to_amdgpu_framebuffer(new_plane_state->fb); - - ret = get_fb_info(new_afb, &new_dm_plane_state->tiling_flags, - &new_dm_plane_state->tmz_surface); - if (ret) - goto fail; - } - /* Remove exiting planes if they are modified */ for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { ret = dm_update_plane_state(dc, state, plane, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a8a0e8cb1a11..03e7e4f23178 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -420,8 +420,6 @@ struct dc_plane_state; struct dm_plane_state { struct drm_plane_state base; struct dc_plane_state *dc_state; - uint64_t tiling_flags; - bool tmz_surface; }; struct dm_crtc_state { -- cgit v1.2.3 From 08d769151dc9690a418e974312e761989a095371 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 2 Sep 2020 18:57:45 +0200 Subject: 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: Bas Nieuwenhuizen Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 123 ++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 695f81fd93bb..8affe50824c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -38,6 +38,7 @@ #include #include #include +#include #include static void amdgpu_display_flip_callback(struct dma_fence *f, @@ -541,6 +542,121 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev, 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, uint64_t *tiling_flags, bool *tmz_surface) { @@ -590,6 +706,13 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev, if (ret) 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; fail: -- cgit v1.2.3