From 30f90f3c1c2c63c2fa44f61233737d27b72637c2 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 28 Apr 2023 11:23:50 -0400 Subject: drm/amd/display: Skip DPP DTO update if root clock is gated [Why] Hardware implements root clock gating by utilizing the DPP DTO registers with a special case of DTO enabled, phase = 0, modulo = 1. This conflicts with our policy to always update the DPPDTO for cases where it's expected to be disabled. The pipes unexpectedly enter a higher power state than expected because of this programming flow. [How] Guard the upper layers of HWSS against this hardware quirk with programming the register with an internal state flag in DCCG. While technically acting as global state for the DCCG, HWSS shouldn't be expected to understand the hardware quirk for having DTO disabled causing more power than DTO enabled with this specific setting. This also prevents sequencing errors from occuring in the future if we have to program DPP DTO in multiple locations. Acked-by: Stylon Wang Signed-off-by: Nicholas Kazlauskas Reviewed-by: Jun Lei Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c | 5 +++++ drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 1 + 3 files changed, 14 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index 4c2fdfea162f..65c1d754e2d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -47,6 +47,14 @@ void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk) { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + if (dccg->dpp_clock_gated[dpp_inst]) { + /* + * Do not update the DPPCLK DTO if the clock is stopped. + * It is treated the same as if the pipe itself were in PG. + */ + return; + } + if (dccg->ref_dppclk && req_dppclk) { int ref_dppclk = dccg->ref_dppclk; int modulo, phase; diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c index e0e7d32bb1a0..cf23d7bc560a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c @@ -332,6 +332,9 @@ static void dccg314_dpp_root_clock_control( { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + if (dccg->dpp_clock_gated[dpp_inst] == clock_on) + return; + if (clock_on) { /* turn off the DTO and leave phase/modulo at max */ REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0); @@ -345,6 +348,8 @@ static void dccg314_dpp_root_clock_control( DPPCLK0_DTO_PHASE, 0, DPPCLK0_DTO_MODULO, 1); } + + dccg->dpp_clock_gated[dpp_inst] = !clock_on; } static const struct dccg_funcs dccg314_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index 0b700b3d7d97..8dc804bbe98b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -68,6 +68,7 @@ struct dccg { const struct dccg_funcs *funcs; int pipe_dppclk_khz[MAX_PIPES]; int ref_dppclk; + bool dpp_clock_gated[MAX_PIPES]; //int dtbclk_khz[MAX_PIPES];/* TODO needs to be removed */ //int audio_dtbclk_khz;/* TODO needs to be removed */ //int ref_dtbclk_khz;/* TODO needs to be removed */ -- cgit v1.2.3 From c168feed5d0341b35b2f6a744f088e7625cfc1aa Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 9 Jun 2023 09:17:14 +0100 Subject: drm/amd/display/amdgpu_dm/amdgpu_dm_helpers: Move SYNAPTICS_DEVICE_ID into CONFIG_DRM_AMD_DC_DCN ifdef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_helpers.c:48:22: warning: ‘SYNAPTICS_DEVICE_ID’ defined but not used [-Wunused-const-variable=] Cc: Harry Wentland Cc: Leo Li Cc: Rodrigo Siqueira Cc: Alex Deucher Cc: "Christian König" Cc: "Pan, Xinhui" Cc: David Airlie Cc: Daniel Vetter Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Reviewed-by: Harry Wentland Signed-off-by: Lee Jones Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 09e056a64708..cd20cfc04996 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -44,9 +44,6 @@ #include "dm_helpers.h" #include "ddc_service_types.h" -/* MST Dock */ -static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA"; - /* dm_helpers_parse_edid_caps * * Parse edid caps @@ -702,6 +699,9 @@ static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux) DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n"); } +/* MST Dock */ +static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA"; + static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst( struct drm_dp_aux *aux, const struct dc_stream_state *stream, -- cgit v1.2.3 From 41ce6d6d03d5e51420ea7732c83facc8a7f2e5da Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Tue, 23 May 2023 11:55:54 -0400 Subject: drm/amdgpu: Rename DRM schedulers in amdgpu TTM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename mman.entity to mman.high_pr to make the distinction clearer that this is a high priority scheduler. Similarly, rename the recently added mman.delayed to mman.low_pr to make it clear it is a low priority scheduler. No functional change in this patch. Signed-off-by: Mukul Joshi Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 18 +++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 8 ++++---- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index d2d0d27f9053..0534ab716809 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -228,7 +228,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); num_bytes = num_pages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE; - r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity, + r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr, AMDGPU_FENCE_OWNER_UNDEFINED, num_dw * 4 + num_bytes, AMDGPU_IB_POOL_DELAYED, &job); @@ -1456,7 +1456,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, memcpy(adev->mman.sdma_access_ptr, buf, len); num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); - r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity, + r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr, AMDGPU_FENCE_OWNER_UNDEFINED, num_dw * 4, AMDGPU_IB_POOL_DELAYED, &job); @@ -2032,7 +2032,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) ring = adev->mman.buffer_funcs_ring; sched = &ring->sched; - r = drm_sched_entity_init(&adev->mman.entity, + r = drm_sched_entity_init(&adev->mman.high_pr, DRM_SCHED_PRIORITY_KERNEL, &sched, 1, NULL); if (r) { @@ -2041,7 +2041,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) return; } - r = drm_sched_entity_init(&adev->mman.delayed, + r = drm_sched_entity_init(&adev->mman.low_pr, DRM_SCHED_PRIORITY_NORMAL, &sched, 1, NULL); if (r) { @@ -2050,8 +2050,8 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) goto error_free_entity; } } else { - drm_sched_entity_destroy(&adev->mman.entity); - drm_sched_entity_destroy(&adev->mman.delayed); + drm_sched_entity_destroy(&adev->mman.high_pr); + drm_sched_entity_destroy(&adev->mman.low_pr); dma_fence_put(man->move); man->move = NULL; } @@ -2067,7 +2067,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) return; error_free_entity: - drm_sched_entity_destroy(&adev->mman.entity); + drm_sched_entity_destroy(&adev->mman.high_pr); } static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev, @@ -2082,8 +2082,8 @@ static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev, AMDGPU_IB_POOL_DIRECT : AMDGPU_IB_POOL_DELAYED; int r; - struct drm_sched_entity *entity = delayed ? &adev->mman.delayed : - &adev->mman.entity; + struct drm_sched_entity *entity = delayed ? &adev->mman.low_pr : + &adev->mman.high_pr; r = amdgpu_job_alloc_with_ib(adev, entity, AMDGPU_FENCE_OWNER_UNDEFINED, num_dw * 4, pool, job); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index e82b1edee7a4..6d0d66e40db9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -59,10 +59,10 @@ struct amdgpu_mman { bool buffer_funcs_enabled; struct mutex gtt_window_lock; - /* Scheduler entity for buffer moves */ - struct drm_sched_entity entity; - /* Scheduler entity for VRAM clearing */ - struct drm_sched_entity delayed; + /* High priority scheduler entity for buffer moves */ + struct drm_sched_entity high_pr; + /* Low priority scheduler entity for VRAM clearing */ + struct drm_sched_entity low_pr; struct amdgpu_vram_mgr vram_mgr; struct amdgpu_gtt_mgr gtt_mgr; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index b2e42f1b0f12..0c8a47989576 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -382,7 +382,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, * translation. Avoid this by doing the invalidation from the SDMA * itself. */ - r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.entity, + r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.high_pr, AMDGPU_FENCE_OWNER_UNDEFINED, 16 * 4, AMDGPU_IB_POOL_IMMEDIATE, &job); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 58d95fb99595..709ac885ca6d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -64,7 +64,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t npages, num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); num_bytes = npages * 8; - r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity, + r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr, AMDGPU_FENCE_OWNER_UNDEFINED, num_dw * 4 + num_bytes, AMDGPU_IB_POOL_DELAYED, -- cgit v1.2.3 From 17fbdbda9cc87ff5a013898de506212d25323ed7 Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Fri, 19 May 2023 13:02:01 -0400 Subject: drm/amd/display: Enable dcn314 DPP RCO [Why and How] Add back debug bits enabling RCO for dcn314 as underflow associated with this change has been resolved Acked-by: Stylon Wang Signed-off-by: Daniel Miess Reviewed-by: Jun Lei Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 837884c4f03a..7957ad4d6a34 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -904,6 +904,22 @@ static const struct dc_debug_options debug_defaults_drv = { .afmt = true, } }, + + .root_clock_optimization = { + .bits = { + .dpp = true, + .dsc = false, + .hdmistream = false, + .hdmichar = false, + .dpstream = false, + .symclk32_se = false, + .symclk32_le = false, + .symclk_fe = false, + .physymclk = false, + .dpiasymclk = false, + } + }, + .seamless_boot_odm_combine = true }; -- cgit v1.2.3 From e06da81749716ee3f0404fada97882609921d98f Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Fri, 9 Jun 2023 20:35:29 +0530 Subject: drm/amdgpu: Fix kdoc warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following gcc with W=1: drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c:76: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * EEPROM Table structure v1 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c:98: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * EEPROM Table structrue v2.1 Cc: Christian König Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index c2e8f6491ac6..0648dfe559af 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -72,7 +72,7 @@ /* Bad GPU tag ‘BADG’ */ #define RAS_TABLE_HDR_BAD 0x42414447 -/** +/* * EEPROM Table structure v1 * --------------------------------- * | | @@ -94,7 +94,7 @@ #define RAS_MAX_RECORD_COUNT ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE) \ / RAS_TABLE_RECORD_SIZE) -/** +/* * EEPROM Table structrue v2.1 * --------------------------------- * | | -- cgit v1.2.3 From 8020f0f9316b6961fe384031b4780e764eeb9652 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Fri, 9 Jun 2023 11:31:04 -0400 Subject: drm/amd/amdgpu: enable W=1 for amdgpu We have a clean build with W=1 as of commit c168feed5d03 ("drm/amd/display/amdgpu_dm/amdgpu_dm_helpers: Move SYNAPTICS_DEVICE_ID into CONFIG_DRM_AMD_DC_DCN ifdef"). So, let's enable these checks unconditionally for the entire module to catch these errors during development. Cc: Alex Deucher Cc: Nathan Chancellor Tested-by: Nathan Chancellor Reviewed-by: Nathan Chancellor Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 86b833085f19..8d16f280b695 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -40,7 +40,18 @@ ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/amdkfd subdir-ccflags-y := -Wextra -subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable) +subdir-ccflags-y += -Wunused +subdir-ccflags-y += -Wmissing-prototypes +subdir-ccflags-y += -Wmissing-declarations +subdir-ccflags-y += -Wmissing-include-dirs +subdir-ccflags-y += -Wold-style-definition +subdir-ccflags-y += -Wmissing-format-attribute +# Need this to avoid recursive variable evaluation issues +cond-flags := $(call cc-option, -Wunused-but-set-variable) \ + $(call cc-option, -Wunused-const-variable) \ + $(call cc-option, -Wstringop-truncation) \ + $(call cc-option, -Wpacked-not-aligned) +subdir-ccflags-y += $(cond-flags) subdir-ccflags-y += -Wno-unused-parameter subdir-ccflags-y += -Wno-type-limits subdir-ccflags-y += -Wno-sign-compare -- cgit v1.2.3 From c069dbbcba7319c514536820f2782a0af3361811 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 9 Jun 2023 16:03:56 +0200 Subject: drm/radeon: Disable outputs when releasing fbdev client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable the modesetting pipeline before release the radeon's fbdev client. Fixes the following error: [ 17.217408] WARNING: CPU: 5 PID: 1464 at drivers/gpu/drm/ttm/ttm_bo.c:326 ttm_bo_release+0x27e/0x2d0 [ttm] [ 17.217418] Modules linked in: edac_mce_amd radeon(+) drm_ttm_helper ttm video drm_suballoc_helper drm_display_helper kvm irqbypass drm_kms_helper syscopyarea crc32_pclmul sysfillrect sha512_ssse3 sysimgblt sha512_generic cfbfillrect cfbimgblt wmi_bmof aesni_intel cfbcopyarea crypto_simd cryptd k10temp acpi_cpufreq wmi dm_mod [ 17.217432] CPU: 5 PID: 1464 Comm: systemd-udevd Not tainted 6.4.0-rc4+ #1 [ 17.217436] Hardware name: Micro-Star International Co., Ltd. MS-7A38/B450M PRO-VDH MAX (MS-7A38), BIOS B.G0 07/26/2022 [ 17.217438] RIP: 0010:ttm_bo_release+0x27e/0x2d0 [ttm] [ 17.217444] Code: 48 89 43 38 48 89 43 40 48 8b 5c 24 30 48 8b b5 40 08 00 00 48 8b 6c 24 38 48 83 c4 58 e9 7a 49 f7 e0 48 89 ef e9 6c fe ff ff <0f> 0b 48 83 7b 20 00 0f 84 b7 fd ff ff 0f 0b 0f 1f 00 e9 ad fd ff [ 17.217448] RSP: 0018:ffffc9000095fbb0 EFLAGS: 00010202 [ 17.217451] RAX: 0000000000000001 RBX: ffff8881052c8de0 RCX: 0000000000000000 [ 17.217453] RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff8881052c8de0 [ 17.217455] RBP: ffff888104a66e00 R08: ffff8881052c8de0 R09: ffff888104a7cf08 [ 17.217457] R10: ffffc9000095fbe0 R11: ffffc9000095fbe8 R12: ffff8881052c8c78 [ 17.217458] R13: ffff8881052c8c78 R14: dead000000000100 R15: ffff88810528b108 [ 17.217460] FS: 00007f319fcbb8c0(0000) GS:ffff88881a540000(0000) knlGS:0000000000000000 [ 17.217463] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 17.217464] CR2: 000055dc8b0224a0 CR3: 000000010373d000 CR4: 0000000000750ee0 [ 17.217466] PKRU: 55555554 [ 17.217468] Call Trace: [ 17.217470] [ 17.217472] ? __warn+0x97/0x160 [ 17.217476] ? ttm_bo_release+0x27e/0x2d0 [ttm] [ 17.217481] ? report_bug+0x1ec/0x200 [ 17.217487] ? handle_bug+0x3c/0x70 [ 17.217490] ? exc_invalid_op+0x1f/0x90 [ 17.217493] ? preempt_count_sub+0xb5/0x100 [ 17.217496] ? asm_exc_invalid_op+0x16/0x20 [ 17.217500] ? ttm_bo_release+0x27e/0x2d0 [ttm] [ 17.217505] ? ttm_resource_move_to_lru_tail+0x1ab/0x1d0 [ttm] [ 17.217511] radeon_bo_unref+0x1a/0x30 [radeon] [ 17.217547] radeon_gem_object_free+0x20/0x30 [radeon] [ 17.217579] radeon_fbdev_fb_destroy+0x57/0x90 [radeon] [ 17.217616] unregister_framebuffer+0x72/0x110 [ 17.217620] drm_client_dev_unregister+0x6d/0xe0 [ 17.217623] drm_dev_unregister+0x2e/0x90 [ 17.217626] drm_put_dev+0x26/0x90 [ 17.217628] pci_device_remove+0x44/0xc0 [ 17.217631] really_probe+0x257/0x340 [ 17.217635] __driver_probe_device+0x73/0x120 [ 17.217638] driver_probe_device+0x2c/0xb0 [ 17.217641] __driver_attach+0xa0/0x150 [ 17.217643] ? __pfx___driver_attach+0x10/0x10 [ 17.217646] bus_for_each_dev+0x67/0xa0 [ 17.217649] bus_add_driver+0x10e/0x210 [ 17.217651] driver_register+0x5c/0x120 [ 17.217653] ? __pfx_radeon_module_init+0x10/0x10 [radeon] [ 17.217681] do_one_initcall+0x44/0x220 [ 17.217684] ? kmalloc_trace+0x37/0xc0 [ 17.217688] do_init_module+0x64/0x240 [ 17.217691] __do_sys_finit_module+0xb2/0x100 [ 17.217694] do_syscall_64+0x3b/0x90 [ 17.217697] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 17.217700] RIP: 0033:0x7f319feaa5a9 [ 17.217702] Code: 08 89 e8 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 27 08 0d 00 f7 d8 64 89 01 48 [ 17.217706] RSP: 002b:00007ffc6bf3e7f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 17.217709] RAX: ffffffffffffffda RBX: 00005607204f3170 RCX: 00007f319feaa5a9 [ 17.217710] RDX: 0000000000000000 RSI: 00007f31a002eefd RDI: 0000000000000018 [ 17.217712] RBP: 00007f31a002eefd R08: 0000000000000000 R09: 00005607204f1860 [ 17.217714] R10: 0000000000000018 R11: 0000000000000246 R12: 0000000000020000 [ 17.217716] R13: 0000000000000000 R14: 0000560720522450 R15: 0000560720255899 [ 17.217718] [ 17.217719] ---[ end trace 0000000000000000 ]--- The buffer object backing the fbdev emulation got pinned twice: by the fb_probe helper radeon_fbdev_create_pinned_object() and the modesetting code when the framebuffer got displayed. It only got unpinned once by the fbdev helper radeon_fbdev_destroy_pinned_object(). Hence TTM's BO- release function complains about the pin counter. Forcing the outputs off also undoes the modesettings pin increment. Tested-by: Borislav Petkov (AMD) Reported-by: Borislav Petkov Closes: https://lore.kernel.org/dri-devel/20230603174814.GCZHt83pN+wNjf63sC@fat_crate.local/ Signed-off-by: Thomas Zimmermann Fixes: e317a69fe891 ("drm/radeon: Implement client-based fbdev emulation") Cc: Alex Deucher Cc: Thomas Zimmermann Cc: "Christian König" Cc: "Pan, Xinhui" Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_fbdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_fbdev.c b/drivers/gpu/drm/radeon/radeon_fbdev.c index 28212c2d6c98..ab9c1abbac97 100644 --- a/drivers/gpu/drm/radeon/radeon_fbdev.c +++ b/drivers/gpu/drm/radeon/radeon_fbdev.c @@ -304,6 +304,7 @@ static void radeon_fbdev_client_unregister(struct drm_client_dev *client) if (fb_helper->info) { vga_switcheroo_client_fb_set(rdev->pdev, NULL); + drm_helper_force_disable_all(dev); drm_fb_helper_unregister_info(fb_helper); } else { drm_client_release(&fb_helper->client); -- cgit v1.2.3 From 188d3f80fc6d8451ab5e570becd6a7b2d3033023 Mon Sep 17 00:00:00 2001 From: Sonny Jiang Date: Tue, 6 Jun 2023 17:18:52 -0400 Subject: drm/amdgpu: vcn_4_0 set instance 0 init sched score to 1 Only vcn0 can process AV1 codecx. In order to use both vcn0 and vcn1 in h264/265 transcode to AV1 cases, set vcn0 sched score to 1 at initialization time. Signed-off-by: Sonny Jiang Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 8d371faaa2b3..b48bb5212488 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -129,7 +129,11 @@ static int vcn_v4_0_sw_init(void *handle) if (adev->vcn.harvest_config & (1 << i)) continue; - atomic_set(&adev->vcn.inst[i].sched_score, 0); + /* Init instance 0 sched_score to 1, so it's scheduled after other instances */ + if (i == 0) + atomic_set(&adev->vcn.inst[i].sched_score, 1); + else + atomic_set(&adev->vcn.inst[i].sched_score, 0); /* VCN UNIFIED TRAP */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i], -- cgit v1.2.3 From 8d8ffe3740b6de4a8a84817cd85195c533ed52b9 Mon Sep 17 00:00:00 2001 From: Shiwu Zhang Date: Wed, 7 Jun 2023 17:14:08 +0800 Subject: drm/amdgpu: expose num_hops and num_links xgmi info through dev attr Add these two dev attrs for xgmi info details which is helpful for developers checking the xgmi topology by catting the sys file directly. Take 4 cards with xgmi connection as an example, get the num_hops for each device or node through xmig_hive_info dir like, cat /sys/bus/pci/devices/0000:41:00.0/xgmi_hive_info/node1/num_hops will return "00 41 41 41" where "00" stands for the hops to node1 itself and "41" is the hops in hex format to every other node in the same hive. There are node1/node2/node3/node4 representing 4 cards in the hive. The same for num_links dev attr. Signed-off-by: Shiwu Zhang Acked-by: Le Ma Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 85ee1af963dd..03dc59cbe8aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -325,6 +325,36 @@ static ssize_t amdgpu_xgmi_show_device_id(struct device *dev, } +static ssize_t amdgpu_xgmi_show_num_hops(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; + int i; + + for (i = 0; i < top->num_nodes; i++) + sprintf(buf + 3 * i, "%02x ", top->nodes[i].num_hops); + + return sysfs_emit(buf, "%s\n", buf); +} + +static ssize_t amdgpu_xgmi_show_num_links(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; + int i; + + for (i = 0; i < top->num_nodes; i++) + sprintf(buf + 3 * i, "%02x ", top->nodes[i].num_links); + + return sysfs_emit(buf, "%s\n", buf); +} + #define AMDGPU_XGMI_SET_FICAA(o) ((o) | 0x456801) static ssize_t amdgpu_xgmi_show_error(struct device *dev, struct device_attribute *attr, @@ -361,6 +391,8 @@ static ssize_t amdgpu_xgmi_show_error(struct device *dev, static DEVICE_ATTR(xgmi_device_id, S_IRUGO, amdgpu_xgmi_show_device_id, NULL); static DEVICE_ATTR(xgmi_error, S_IRUGO, amdgpu_xgmi_show_error, NULL); +static DEVICE_ATTR(xgmi_num_hops, S_IRUGO, amdgpu_xgmi_show_num_hops, NULL); +static DEVICE_ATTR(xgmi_num_links, S_IRUGO, amdgpu_xgmi_show_num_links, NULL); static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, struct amdgpu_hive_info *hive) @@ -380,6 +412,15 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, if (ret) pr_err("failed to create xgmi_error\n"); + /* Create xgmi num hops file */ + ret = device_create_file(adev->dev, &dev_attr_xgmi_num_hops); + if (ret) + pr_err("failed to create xgmi_num_hops\n"); + + /* Create xgmi num links file */ + ret = device_create_file(adev->dev, &dev_attr_xgmi_num_links); + if (ret) + pr_err("failed to create xgmi_num_links\n"); /* Create sysfs link to hive info folder on the first device */ if (hive->kobj.parent != (&adev->dev->kobj)) { @@ -407,6 +448,9 @@ remove_link: remove_file: device_remove_file(adev->dev, &dev_attr_xgmi_device_id); + device_remove_file(adev->dev, &dev_attr_xgmi_error); + device_remove_file(adev->dev, &dev_attr_xgmi_num_hops); + device_remove_file(adev->dev, &dev_attr_xgmi_num_links); success: return ret; @@ -420,6 +464,8 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev, device_remove_file(adev->dev, &dev_attr_xgmi_device_id); device_remove_file(adev->dev, &dev_attr_xgmi_error); + device_remove_file(adev->dev, &dev_attr_xgmi_num_hops); + device_remove_file(adev->dev, &dev_attr_xgmi_num_links); if (hive->kobj.parent != (&adev->dev->kobj)) sysfs_remove_link(&adev->dev->kobj,"xgmi_hive_info"); -- cgit v1.2.3 From 59eddd4e215afc05f0610ebabfa05d4b099e5c13 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam Date: Fri, 9 Jun 2023 06:18:41 -0700 Subject: Revert "drm/amdgpu: remove TOPDOWN flags when allocating VRAM in large bar system" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c105518679b6e87232874ffc989ec403bee59664. This patch disables the TOPDOWN flag for APU and few dGPU cards which has the VRAM size equal to the BAR size. When we enable the TOPDOWN flag, we get the free blocks at the highest available memory region and we don't split the lower order blocks. This change is required to keep off the fragmentation related issues particularly in ASIC which has VRAM space <= 500MiB Hence, we are reverting this patch. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2270 Signed-off-by: Arunpravin Paneer Selvam Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index f76649e523a0..54cd21c06a44 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -150,7 +150,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) places[c].lpfn = min_not_zero(places[c].lpfn, visible_pfn); - else if (adev->gmc.real_vram_size != adev->gmc.visible_vram_size) + else places[c].flags |= TTM_PL_FLAG_TOPDOWN; if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) -- cgit v1.2.3 From 7a0e005c7957931689a327b2a4e7333a19f13f95 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 25 May 2023 08:37:40 -0400 Subject: drm/amd/display: edp do not add non-edid timings [Why] most edp support only timings from edid. applying non-edid timings, especially those timings out of edp bandwidth, may damage edp. [How] do not add non-edid timings for edp. Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Acked-by: Stylon Wang Signed-off-by: Hersen Wu Reviewed-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 b6bef202b6bb..2f3f579efe30 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7256,7 +7256,13 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) drm_add_modes_noedid(connector, 1920, 1080); } else { amdgpu_dm_connector_ddc_get_modes(connector, edid); - amdgpu_dm_connector_add_common_modes(encoder, connector); + /* most eDP supports only timings from its edid, + * usually only detailed timings are available + * from eDP edid. timings which are not from edid + * may damage eDP + */ + if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) + amdgpu_dm_connector_add_common_modes(encoder, connector); amdgpu_dm_connector_add_freesync_modes(connector, edid); } amdgpu_dm_fbc_init(connector); -- cgit v1.2.3 From ee83c930974d4afb5fec3db638a8341b5d1cd3fa Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 25 May 2023 09:00:29 -0400 Subject: drm/amd/display: add debugfs for allow_edp_hotplug_detection [Why] within dc_link_detect, edp edid is read only for the first time and saved. edid will not be read after the first time read. to run edp edid read test, need read edp edid for each dc_link_detect. dc->config flag allow_edp_hotplug_detection could be used for edp edid test. [How] add debugfs for dc->config.allow_edp_hotplug_detection Acked-by: Stylon Wang Signed-off-by: Hersen Wu Reviewed-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index caf13b2e8cb6..5ea3284b2b77 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2760,6 +2760,32 @@ static int psr_read_residency(void *data, u64 *val) return 0; } +/* read allow_edp_hotplug_detection */ +static int allow_edp_hotplug_detection_get(void *data, u64 *val) +{ + struct amdgpu_dm_connector *aconnector = data; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = drm_to_adev(dev); + + *val = adev->dm.dc->config.allow_edp_hotplug_detection; + + return 0; +} + +/* set allow_edp_hotplug_detection */ +static int allow_edp_hotplug_detection_set(void *data, u64 val) +{ + struct amdgpu_dm_connector *aconnector = data; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = drm_to_adev(dev); + + adev->dm.dc->config.allow_edp_hotplug_detection = (uint32_t) val; + + return 0; +} + /* * Set dmcub trace event IRQ enable or disable. * Usage to enable dmcub trace event IRQ: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en @@ -2798,6 +2824,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n"); DEFINE_DEBUGFS_ATTRIBUTE(psr_residency_fops, psr_read_residency, NULL, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(allow_edp_hotplug_detection_fops, + allow_edp_hotplug_detection_get, + allow_edp_hotplug_detection_set, "%llu\n"); + DEFINE_SHOW_ATTRIBUTE(current_backlight); DEFINE_SHOW_ATTRIBUTE(target_backlight); @@ -2968,6 +2998,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) &target_backlight_fops); debugfs_create_file("ilr_setting", 0644, dir, connector, &edp_ilr_debugfs_fops); + debugfs_create_file("allow_edp_hotplug_detection", 0644, dir, connector, + &allow_edp_hotplug_detection_fops); } for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) { -- cgit v1.2.3 From 3d8de40fd639c8be24e4aa557a98e20e1d09bdc3 Mon Sep 17 00:00:00 2001 From: Austin Zheng Date: Thu, 25 May 2023 14:01:01 -0400 Subject: drm/amd/display: Add DP2 Metrics Why: Log DP2 data to be used for debugging purposes How: Check the reported link rate of the DP connection and translate it to the DP version. Acked-by: Stylon Wang Signed-off-by: Austin Zheng Reviewed-by: Martin Leung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 6 ++++-- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 360dd83b1a7a..7cf3e9510043 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-14 Advanced Micro Devices, Inc. + * Copyright 2012-2023 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -60,7 +60,9 @@ struct dc_versions { }; enum dp_protocol_version { - DP_VERSION_1_4, + DP_VERSION_1_4 = 0, + DP_VERSION_2_1, + DP_VERSION_UNKNOWN, }; enum dc_plane_type { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 4a7f6497dc5a..55139d7bf422 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -61,7 +61,7 @@ enum dc_link_rate { */ LINK_RATE_UHBR10 = 1000, // UHBR10 - 10.0 Gbps/Lane LINK_RATE_UHBR13_5 = 1350, // UHBR13.5 - 13.5 Gbps/Lane - LINK_RATE_UHBR20 = 2000, // UHBR10 - 20.0 Gbps/Lane + LINK_RATE_UHBR20 = 2000, // UHBR20 - 20.0 Gbps/Lane }; enum dc_link_spread { -- cgit v1.2.3 From be3a432a9d382a09e02c3359e4f6fcd991fe7d2a Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Tue, 16 May 2023 15:36:45 -0400 Subject: drm/amd/display: Add Error Code for Dml Validation Failure Any invalid mode from hw perspective should be given corresponding error code, otherwise it leads to confusing warning message "[drm] Mode Validation Warning: Validation OK failed validation." Acked-by: Stylon Wang Signed-off-by: Fangzhi Zuo Reviewed-by: Dmytro Laktyushkin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/dml/dcn314/display_mode_vba_314.c | 59 ++++++++++++++++++++++ .../drm/amd/display/dc/dml/display_mode_enums.h | 8 +++ 2 files changed, 67 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index 1532a7e0ed6c..9010c47476e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -5557,6 +5557,65 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ } } } + for (i = v->soc.num_states; i >= 0; i--) { + for (j = 0; j < 2; j++) { + enum dm_validation_status status = DML_VALIDATION_OK; + + if (!v->ScaleRatioAndTapsSupport) { + status = DML_FAIL_SCALE_RATIO_TAP; + } else if (!v->SourceFormatPixelAndScanSupport) { + status = DML_FAIL_SOURCE_PIXEL_FORMAT; + } else if (!v->ViewportSizeSupport[i][j]) { + status = DML_FAIL_VIEWPORT_SIZE; + } else if (P2IWith420) { + status = DML_FAIL_P2I_WITH_420; + } else if (DSCOnlyIfNecessaryWithBPP) { + status = DML_FAIL_DSC_ONLY_IF_NECESSARY_WITH_BPP; + } else if (DSC422NativeNotSupported) { + status = DML_FAIL_NOT_DSC422_NATIVE; + } else if (!v->ODMCombine4To1SupportCheckOK[i]) { + status = DML_FAIL_ODM_COMBINE4TO1; + } else if (v->NotEnoughDSCUnits[i]) { + status = DML_FAIL_NOT_ENOUGH_DSC; + } else if (!v->ROBSupport[i][j]) { + status = DML_FAIL_REORDERING_BUFFER; + } else if (!v->DISPCLK_DPPCLK_Support[i][j]) { + status = DML_FAIL_DISPCLK_DPPCLK; + } else if (!v->TotalAvailablePipesSupport[i][j]) { + status = DML_FAIL_TOTAL_AVAILABLE_PIPES; + } else if (!EnoughWritebackUnits) { + status = DML_FAIL_ENOUGH_WRITEBACK_UNITS; + } else if (!v->WritebackLatencySupport) { + status = DML_FAIL_WRITEBACK_LATENCY; + } else if (!v->WritebackScaleRatioAndTapsSupport) { + status = DML_FAIL_WRITEBACK_SCALE_RATIO_TAP; + } else if (!v->CursorSupport) { + status = DML_FAIL_CURSOR_SUPPORT; + } else if (!v->PitchSupport) { + status = DML_FAIL_PITCH_SUPPORT; + } else if (ViewportExceedsSurface) { + status = DML_FAIL_VIEWPORT_EXCEEDS_SURFACE; + } else if (!v->PrefetchSupported[i][j]) { + status = DML_FAIL_PREFETCH_SUPPORT; + } else if (!v->DynamicMetadataSupported[i][j]) { + status = DML_FAIL_DYNAMIC_METADATA; + } else if (!v->TotalVerticalActiveBandwidthSupport[i][j]) { + status = DML_FAIL_TOTAL_V_ACTIVE_BW; + } else if (!v->VRatioInPrefetchSupported[i][j]) { + status = DML_FAIL_V_RATIO_PREFETCH; + } else if (!v->PTEBufferSizeNotExceeded[i][j]) { + status = DML_FAIL_PTE_BUFFER_SIZE; + } else if (v->NonsupportedDSCInputBPC) { + status = DML_FAIL_DSC_INPUT_BPC; + } else if ((v->HostVMEnable + && !v->ImmediateFlipSupportedForState[i][j])) { + status = DML_FAIL_HOST_VM_IMMEDIATE_FLIP; + } else if (FMTBufferExceeded) { + status = DML_FAIL_FMT_BUFFER_EXCEEDED; + } + mode_lib->vba.ValidationStatus[i] = status; + } + } { unsigned int MaximumMPCCombine = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index 0bffae95f3a2..d5831a34f5a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -190,6 +190,14 @@ enum dm_validation_status { DML_FAIL_DSC_INPUT_BPC, DML_FAIL_PREFETCH_SUPPORT, DML_FAIL_V_RATIO_PREFETCH, + DML_FAIL_P2I_WITH_420, + DML_FAIL_DSC_ONLY_IF_NECESSARY_WITH_BPP, + DML_FAIL_NOT_DSC422_NATIVE, + DML_FAIL_ODM_COMBINE4TO1, + DML_FAIL_ENOUGH_WRITEBACK_UNITS, + DML_FAIL_VIEWPORT_EXCEEDS_SURFACE, + DML_FAIL_DYNAMIC_METADATA, + DML_FAIL_FMT_BUFFER_EXCEEDED, }; enum writeback_config { -- cgit v1.2.3 From 5b4d93eaf6b44903f4c71b4f404f65317abd8d9c Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 28 May 2023 19:48:27 -0400 Subject: drm/amd/display: Promote DAL to 3.2.238 Acked-by: Stylon Wang Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7cf3e9510043..5c906b007e4d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.237" +#define DC_VER "3.2.238" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From f308116676566b555ec3bab4c3f9eb20c1c9a5cb Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Mon, 29 May 2023 18:00:09 +0800 Subject: drm/amd/display: fix the system hang while disable PSR [Why] When the PSR enabled. If you try to adjust the timing parameters, it may cause system hang. Because the timing mismatch with the DMCUB settings. [How] Disable the PSR before adjusting timing parameters. Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Acked-by: Stylon Wang Signed-off-by: Tom Chung Reviewed-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 2f3f579efe30..c6a1014e0e89 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8279,6 +8279,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (acrtc_state->abm_level != dm_old_crtc_state->abm_level) bundle->stream_update.abm_level = &acrtc_state->abm_level; + mutex_lock(&dm->dc_lock); + if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && + acrtc_state->stream->link->psr_settings.psr_allow_active) + amdgpu_dm_psr_disable(acrtc_state->stream); + mutex_unlock(&dm->dc_lock); + /* * If FreeSync state on the stream has changed then we need to * re-adjust the min/max bounds now that DC doesn't handle this @@ -8292,10 +8298,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } mutex_lock(&dm->dc_lock); - if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && - acrtc_state->stream->link->psr_settings.psr_allow_active) - amdgpu_dm_psr_disable(acrtc_state->stream); - update_planes_and_stream_adapter(dm->dc, acrtc_state->update_type, planes_count, -- cgit v1.2.3 From e8c49e9eead8620c7dd3c64a1f3bb44682325710 Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Mon, 29 May 2023 14:27:11 +0800 Subject: drm/amd/display: Fix disbling PSR slow response issue [Why] dmub_psr_get_state() return an invalid PSR state while disable the PSR because convert_psr_state() doesn't recognize the state that return from DMCUB. [How] Add a PSR state to make the dmub_psr_get_state() return a correct PSR state. Acked-by: Stylon Wang Signed-off-by: Tom Chung Reviewed-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 6b4731b5e975..0ce7728a5a4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -597,6 +597,7 @@ enum dc_psr_state { PSR_STATE4b_FULL_FRAME, PSR_STATE4c_FULL_FRAME, PSR_STATE4_FULL_FRAME_POWERUP, + PSR_STATE4_FULL_FRAME_HW_LOCK, PSR_STATE5, PSR_STATE5a, PSR_STATE5b, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 4000a834592c..0f24b6fbd220 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -87,6 +87,8 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state) state = PSR_STATE4c_FULL_FRAME; else if (raw_state == 0x4E) state = PSR_STATE4_FULL_FRAME_POWERUP; + else if (raw_state == 0x4F) + state = PSR_STATE4_FULL_FRAME_HW_LOCK; else if (raw_state == 0x60) state = PSR_STATE_HWLOCK_MGR; else if (raw_state == 0x61) -- cgit v1.2.3 From 1c982c9ffefd00120f2293bfd15fec5af475dc28 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Tue, 30 May 2023 10:07:39 -0400 Subject: drm/amd/display: SubVP high refresh only if all displays >= 120hz [Description] - SubVP high refresh should only be enabled if all displays are >= 120hz. We do not want to accidentally enables configs such as 60hz[SubVP] + 120hz[SubVP] - Ensure that the SubVP config generation code does not produce configs such as 60hz[SubVP] + 120hz[SubVP] - Also add admissibility checks to ensure these configs do not pass as valid configs Acked-by: Stylon Wang Signed-off-by: Alvin Lee Reviewed-by: Dillon Varone Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn32/dcn32_resource.h | 4 + .../amd/display/dc/dcn32/dcn32_resource_helpers.c | 101 ++++++++++++ .../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 178 +++++++++++++-------- 3 files changed, 217 insertions(+), 66 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h index 2f34f01b3ea1..81e443170829 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -169,6 +169,10 @@ double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *conte bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height); +bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context); + +bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int vlevel); + /* definitions for run time init of reg offsets */ /* CLK SRC */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index 1d13fd797212..578070e7d44b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -660,3 +660,104 @@ bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int widt return is_native_scaling; } + +/** + * ************************************************************************************************ + * dcn32_subvp_drr_admissable: Determine if SubVP + DRR config is admissible + * + * @param [in]: dc: Current DC state + * @param [in]: context: New DC state to be programmed + * + * SubVP + DRR is admissible under the following conditions: + * - Config must have 2 displays (i.e., 2 non-phantom master pipes) + * - One display is SubVP + * - Other display must have Freesync enabled + * + * @return: True if admissible, false otherwise + * + * ************************************************************************************************ + */ +bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context) +{ + bool result = false; + uint32_t i; + uint8_t subvp_count = 0; + uint8_t non_subvp_pipes = 0; + bool drr_pipe_found = false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + + if (pipe->plane_state && !pipe->top_pipe) { + if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) + subvp_count++; + if (pipe->stream->mall_stream_config.type == SUBVP_NONE) { + non_subvp_pipes++; + if (pipe->stream->ignore_msa_timing_param && + (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) { + drr_pipe_found = true; + } + } + } + } + + if (subvp_count == 1 && non_subvp_pipes == 1 && drr_pipe_found) + result = true; + + return result; +} + +/** + * ************************************************************************************************ + * dcn32_subvp_vblank_admissable: Determine if SubVP + Vblank config is admissible + * + * @param [in]: dc: Current DC state + * @param [in]: context: New DC state to be programmed + * + * SubVP + Vblank is admissible under the following conditions: + * - Config must have 2 displays (i.e., 2 non-phantom master pipes) + * - One display is SubVP + * - Other display must not have Freesync capability + * - DML must have output DRAM clock change support as SubVP + Vblank + * + * @return: True if admissible, false otherwise + * + * ************************************************************************************************ + */ +bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int vlevel) +{ + bool result = false; + uint32_t i; + uint8_t subvp_count = 0; + uint8_t non_subvp_pipes = 0; + bool drr_pipe_found = false; + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + + if (pipe->plane_state && !pipe->top_pipe) { + if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) + subvp_count++; + if (pipe->stream->mall_stream_config.type == SUBVP_NONE) { + non_subvp_pipes++; + if (pipe->stream->ignore_msa_timing_param && + (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) { + drr_pipe_found = true; + } + } + } + } + + if (subvp_count == 1 && non_subvp_pipes == 1 && !drr_pipe_found && + vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vblank_w_mall_sub_vp) + result = true; + + return result; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index fa3678342abb..166123be4adc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -679,7 +679,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, unsigned int max_frame_time = 0; bool valid_assignment_found = false; unsigned int free_pipes = dcn32_get_num_free_pipes(dc, context); - bool current_assignment_freesync = false; struct vba_vars_st *vba = &context->bw_ctx.dml.vba; for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { @@ -720,19 +719,10 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, struct dc_stream_state *stream = pipe->stream; unsigned int frame_us = (stream->timing.v_total * stream->timing.h_total / (double)(stream->timing.pix_clk_100hz * 100)) * 1000000; - if (frame_us > max_frame_time && !stream->ignore_msa_timing_param) { + if (frame_us > max_frame_time) { *index = i; max_frame_time = frame_us; valid_assignment_found = true; - current_assignment_freesync = false; - /* For the 2-Freesync display case, still choose the one with the - * longest frame time - */ - } else if (stream->ignore_msa_timing_param && (!valid_assignment_found || - (current_assignment_freesync && frame_us > max_frame_time))) { - *index = i; - valid_assignment_found = true; - current_assignment_freesync = true; } } } @@ -878,11 +868,12 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context) * * Return: True if the SubVP + DRR config is schedulable, false otherwise */ -static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struct pipe_ctx *drr_pipe) +static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context) { bool schedulable = false; uint32_t i; struct pipe_ctx *pipe = NULL; + struct pipe_ctx *drr_pipe = NULL; struct dc_crtc_timing *main_timing = NULL; struct dc_crtc_timing *phantom_timing = NULL; struct dc_crtc_timing *drr_timing = NULL; @@ -908,6 +899,19 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc break; } + // Find the DRR pipe + for (i = 0; i < dc->res_pool->pipe_count; i++) { + drr_pipe = &context->res_ctx.pipe_ctx[i]; + + // We check for master pipe only + if (!drr_pipe->stream || !drr_pipe->plane_state || drr_pipe->top_pipe || drr_pipe->prev_odm_pipe) + continue; + + if (drr_pipe->stream->mall_stream_config.type == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param && + (drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable)) + break; + } + main_timing = &pipe->stream->timing; phantom_timing = &pipe->stream->mall_stream_config.paired_stream->timing; drr_timing = &drr_pipe->stream->timing; @@ -993,13 +997,7 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context) if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN) subvp_pipe = pipe; } - // Use ignore_msa_timing_param and VRR active, or Freesync flag to identify as DRR On - if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param && - (context->res_ctx.pipe_ctx[vblank_index].stream->allow_freesync || - context->res_ctx.pipe_ctx[vblank_index].stream->vrr_active_variable)) { - // SUBVP + DRR case -- only allowed if run through DRR validation path - schedulable = false; - } else if (found) { + if (found) { main_timing = &subvp_pipe->stream->timing; phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing; @@ -1028,6 +1026,56 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context) return schedulable; } +/** + * ************************************************************************************************ + * subvp_subvp_admissable: Determine if subvp + subvp config is admissible + * + * @param [in]: dc: Current DC state + * @param [in]: context: New DC state to be programmed + * + * SubVP + SubVP is admissible under the following conditions: + * - All SubVP pipes are < 120Hz OR + * - All SubVP pipes are >= 120hz + * + * @return: True if admissible, false otherwise + * + * ************************************************************************************************ + */ +static bool subvp_subvp_admissable(struct dc *dc, + struct dc_state *context) +{ + bool result = false; + uint32_t i; + uint8_t subvp_count = 0; + uint32_t min_refresh = subvp_high_refresh_list.min_refresh, max_refresh = 0; + uint32_t refresh_rate = 0; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + + if (pipe->plane_state && !pipe->top_pipe && + pipe->stream->mall_stream_config.type == SUBVP_MAIN) { + refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 + + pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1) + / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total); + if (refresh_rate < min_refresh) + min_refresh = refresh_rate; + if (refresh_rate > max_refresh) + max_refresh = refresh_rate; + subvp_count++; + } + } + + if (subvp_count == 2 && ((min_refresh < 120 && max_refresh < 120) || + (min_refresh >= 120 && max_refresh >= 120))) + result = true; + + return result; +} + /** * subvp_validate_static_schedulability - Check which SubVP case is calculated * and handle static analysis based on the case. @@ -1046,11 +1094,12 @@ static bool subvp_validate_static_schedulability(struct dc *dc, struct dc_state *context, int vlevel) { - bool schedulable = true; // true by default for single display case + bool schedulable = false; struct vba_vars_st *vba = &context->bw_ctx.dml.vba; uint32_t i, pipe_idx; uint8_t subvp_count = 0; uint8_t vactive_count = 0; + uint8_t non_subvp_pipes = 0; for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; @@ -1058,14 +1107,18 @@ static bool subvp_validate_static_schedulability(struct dc *dc, if (!pipe->stream) continue; - if (pipe->plane_state && !pipe->top_pipe && - pipe->stream->mall_stream_config.type == SUBVP_MAIN) - subvp_count++; + if (pipe->plane_state && !pipe->top_pipe) { + if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) + subvp_count++; + if (pipe->stream->mall_stream_config.type == SUBVP_NONE) { + non_subvp_pipes++; + } + } // Count how many planes that aren't SubVP/phantom are capable of VACTIVE // switching (SubVP + VACTIVE unsupported). In situations where we force // SubVP for a VACTIVE plane, we don't want to increment the vactive_count. - if (vba->ActiveDRAMClockChangeLatencyMargin[vba->pipe_plane[pipe_idx]] > 0 && + if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vlevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 && pipe->stream->mall_stream_config.type == SUBVP_NONE) { vactive_count++; } @@ -1074,13 +1127,14 @@ static bool subvp_validate_static_schedulability(struct dc *dc, if (subvp_count == 2) { // Static schedulability check for SubVP + SubVP case - schedulable = subvp_subvp_schedulable(dc, context); - } else if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vblank_w_mall_sub_vp) { - // Static schedulability check for SubVP + VBLANK case. Also handle the case where - // DML outputs SubVP + VBLANK + VACTIVE (DML will report as SubVP + VBLANK) - if (vactive_count > 0) - schedulable = false; - else + schedulable = subvp_subvp_admissable(dc, context) && subvp_subvp_schedulable(dc, context); + } else if (subvp_count == 1 && non_subvp_pipes == 0) { + // Single SubVP configs will be supported by default as long as it's suppported by DML + schedulable = true; + } else if (subvp_count == 1 && non_subvp_pipes == 1) { + if (dcn32_subvp_drr_admissable(dc, context)) + schedulable = subvp_drr_schedulable(dc, context); + else if (dcn32_subvp_vblank_admissable(dc, context, vlevel)) schedulable = subvp_vblank_schedulable(dc, context); } else if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vactive_w_mall_sub_vp && vactive_count > 0) { @@ -1104,10 +1158,6 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, unsigned int dc_pipe_idx = 0; int i = 0; bool found_supported_config = false; - struct pipe_ctx *pipe = NULL; - uint32_t non_subvp_pipes = 0; - bool drr_pipe_found = false; - uint32_t drr_pipe_index = 0; dc_assert_fp_enabled(); @@ -1197,31 +1247,12 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, } } - if (*vlevel < context->bw_ctx.dml.soc.num_states && - vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported - && subvp_validate_static_schedulability(dc, context, *vlevel)) { + if (*vlevel < context->bw_ctx.dml.soc.num_states + && subvp_validate_static_schedulability(dc, context, *vlevel)) found_supported_config = true; - } else if (*vlevel < context->bw_ctx.dml.soc.num_states) { - /* Case where 1 SubVP is added, and DML reports MCLK unsupported or DRR is allowed. - * This handles the case for SubVP + DRR, where the DRR display does not support MCLK - * switch at it's native refresh rate / timing, or DRR is allowed for the non-subvp - * display. - */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - if (pipe->stream && pipe->plane_state && !pipe->top_pipe && - pipe->stream->mall_stream_config.type == SUBVP_NONE) { - non_subvp_pipes++; - // Use ignore_msa_timing_param flag to identify as DRR - if (pipe->stream->ignore_msa_timing_param && pipe->stream->allow_freesync) { - drr_pipe_found = true; - drr_pipe_index = i; - } - } - } - // If there is only 1 remaining non SubVP pipe that is DRR, check static - // schedulability for SubVP + DRR. - if (non_subvp_pipes == 1 && drr_pipe_found) { + if (found_supported_config) { + // For SubVP + DRR cases, we can force the lowest vlevel that supports the mode + if (dcn32_subvp_drr_admissable(dc, context) && subvp_drr_schedulable(dc, context)) { /* find lowest vlevel that supports the config */ for (i = *vlevel; i >= 0; i--) { if (vba->ModeSupport[i][vba->maxMpcComb]) { @@ -1230,9 +1261,6 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, break; } } - - found_supported_config = subvp_drr_schedulable(dc, context, - &context->res_ctx.pipe_ctx[drr_pipe_index]); } } } @@ -2882,16 +2910,34 @@ bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context { bool allow = false; uint32_t refresh_rate = 0; - uint32_t min_refresh = subvp_high_refresh_list.min_refresh; - uint32_t max_refresh = subvp_high_refresh_list.max_refresh; + uint32_t subvp_min_refresh = subvp_high_refresh_list.min_refresh; + uint32_t subvp_max_refresh = subvp_high_refresh_list.max_refresh; + uint32_t min_refresh = subvp_max_refresh; uint32_t i; - if (!dc->debug.disable_subvp_high_refresh && pipe->stream && + /* Only allow SubVP on high refresh displays if all connected displays + * are considered "high refresh" (i.e. >= 120hz). We do not want to + * allow combinations such as 120hz (SubVP) + 60hz (SubVP). + */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->stream) + continue; + refresh_rate = (pipe_ctx->stream->timing.pix_clk_100hz * 100 + + pipe_ctx->stream->timing.v_total * pipe_ctx->stream->timing.h_total - 1) + / (double)(pipe_ctx->stream->timing.v_total * pipe_ctx->stream->timing.h_total); + + if (refresh_rate < min_refresh) + min_refresh = refresh_rate; + } + + if (!dc->debug.disable_subvp_high_refresh && min_refresh >= subvp_min_refr