From 83edf00d8972eecd849865a34bd4fada09444ec4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Jun 2024 13:48:26 -0400 Subject: [PATCH 01/87] drm/amdgpu/atomfirmware: fix parsing of vram_info v3.x changed the how vram width was encoded. The previous implementation actually worked correctly for most boards. Fix the implementation to work correctly everywhere. This fixes the vram width reported in the kernel log on some boards. Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index f932bec6e534..f873dd3cae16 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -433,7 +433,7 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev, mem_channel_number = vram_info->v30.channel_num; mem_channel_width = vram_info->v30.channel_width; if (vram_width) - *vram_width = mem_channel_number * (1 << mem_channel_width); + *vram_width = mem_channel_number * 16; break; default: return -EINVAL; From ed3165d660d8c4e4ba540bfaa461594e01b3815b Mon Sep 17 00:00:00 2001 From: Sonny Jiang Date: Tue, 18 Jun 2024 11:11:11 -0400 Subject: [PATCH 02/87] drm/amdgpu/jpeg5: reprogram doorbell setting after power up for each playback Doorbell needs to be configured after power up during each playback Signed-off-by: Sonny Jiang Reviewed-by: Kenneth Feng Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c index 68ef29bc70e2..e766b9463759 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c @@ -137,10 +137,6 @@ static int jpeg_v5_0_0_hw_init(void *handle) adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0); - WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL, - ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT | - VCN_JPEG_DB_CTRL__EN_MASK); - r = amdgpu_ring_test_helper(ring); if (r) return r; @@ -314,6 +310,10 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev) JPEG_SYS_INT_EN__DJRBC0_MASK, ~JPEG_SYS_INT_EN__DJRBC0_MASK); + WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL, + ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT | + VCN_JPEG_DB_CTRL__EN_MASK); + WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0); WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L)); WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, From dab70d9f653665aec5cdffd2d512aa98b1b38bdb Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Fri, 31 May 2024 14:04:01 +0800 Subject: [PATCH 03/87] drm/amdgpu: refine gfx11 firmware loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refine gfx11 firmware loading Signed-off-by: Yang Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 2a510351dfce..b4575765d7a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -611,10 +611,9 @@ static int gfx_v11_0_init_toc_microcode(struct amdgpu_device *adev, const char * { const struct psp_firmware_header_v1_0 *toc_hdr; int err = 0; - char fw_name[40]; - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, + "amdgpu/%s_toc.bin", ucode_prefix); if (err) goto out; @@ -653,7 +652,6 @@ static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev) static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) { - char fw_name[40]; char ucode_prefix[25]; int err; const struct rlc_firmware_header_v2_0 *rlc_hdr; @@ -663,9 +661,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) DRM_DEBUG("\n"); amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); - - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, + "amdgpu/%s_pfp.bin", ucode_prefix); if (err) goto out; /* check pfp fw hdr version to decide if enable rs64 for gfx11.*/ @@ -681,8 +678,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP); } - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, + "amdgpu/%s_me.bin", ucode_prefix); if (err) goto out; if (adev->gfx.rs64_enable) { @@ -696,10 +693,11 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) if (!amdgpu_sriov_vf(adev)) { if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 0) && adev->pdev->revision == 0xCE) - snprintf(fw_name, sizeof(fw_name), "amdgpu/gc_11_0_0_rlc_1.bin"); + err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, + "amdgpu/gc_11_0_0_rlc_1.bin"); else - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, + "amdgpu/%s_rlc.bin", ucode_prefix); if (err) goto out; rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data; @@ -710,8 +708,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) goto out; } - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, + "amdgpu/%s_mec.bin", ucode_prefix); if (err) goto out; if (adev->gfx.rs64_enable) { From e779af8e8b51b4b3d403fa002e579b56b1931296 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Tue, 18 Jun 2024 14:04:38 +0530 Subject: [PATCH 04/87] drm/amdgpu: Fix pci state save during mode-1 reset Cache the PCI state before bus master is disabled. The saved state is later used for other cases like restoring config space after mode-2 reset. Fixes: 5c03e5843e6b ("drm/amdgpu:add smu mode1/2 support for aldebaran") Signed-off-by: Lijo Lazar Reviewed-by: Feifei Xu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2de36883fc9f..183e219b6a85 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5224,11 +5224,14 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev) dev_info(adev->dev, "GPU mode1 reset\n"); + /* Cache the state before bus master disable. The saved config space + * values are used in other cases like restore after mode-2 reset. + */ + amdgpu_device_cache_pci_state(adev->pdev); + /* disable BM */ pci_clear_master(adev->pdev); - amdgpu_device_cache_pci_state(adev->pdev); - if (amdgpu_dpm_is_mode1_reset_supported(adev)) { dev_info(adev->dev, "GPU smu mode1 reset\n"); ret = amdgpu_dpm_mode1_reset(adev); From c71c9aafd5faa579e6ffe32018071c7af97d5a2e Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Mon, 3 Jun 2024 10:46:10 +0200 Subject: [PATCH 05/87] amdgpu: don't dereference a NULL resource in sysfs code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_resv_trylock being successful doesn't guarantee that bo->tbo.base.resv is not NULL, so check its validity before using it. Signed-off-by: Pierre-Eric Pelloux-Prayer Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 63 +++++++++++----------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index fa5227a4aac2..08e53dacdad9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1601,36 +1601,39 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) u64 size; if (dma_resv_trylock(bo->tbo.base.resv)) { - - switch (bo->tbo.resource->mem_type) { - case TTM_PL_VRAM: - if (amdgpu_res_cpu_visible(adev, bo->tbo.resource)) - placement = "VRAM VISIBLE"; - else - placement = "VRAM"; - break; - case TTM_PL_TT: - placement = "GTT"; - break; - case AMDGPU_PL_GDS: - placement = "GDS"; - break; - case AMDGPU_PL_GWS: - placement = "GWS"; - break; - case AMDGPU_PL_OA: - placement = "OA"; - break; - case AMDGPU_PL_PREEMPT: - placement = "PREEMPTIBLE"; - break; - case AMDGPU_PL_DOORBELL: - placement = "DOORBELL"; - break; - case TTM_PL_SYSTEM: - default: - placement = "CPU"; - break; + if (!bo->tbo.resource) { + placement = "NONE"; + } else { + switch (bo->tbo.resource->mem_type) { + case TTM_PL_VRAM: + if (amdgpu_res_cpu_visible(adev, bo->tbo.resource)) + placement = "VRAM VISIBLE"; + else + placement = "VRAM"; + break; + case TTM_PL_TT: + placement = "GTT"; + break; + case AMDGPU_PL_GDS: + placement = "GDS"; + break; + case AMDGPU_PL_GWS: + placement = "GWS"; + break; + case AMDGPU_PL_OA: + placement = "OA"; + break; + case AMDGPU_PL_PREEMPT: + placement = "PREEMPTIBLE"; + break; + case AMDGPU_PL_DOORBELL: + placement = "DOORBELL"; + break; + case TTM_PL_SYSTEM: + default: + placement = "CPU"; + break; + } } dma_resv_unlock(bo->tbo.base.resv); } else { From 1a0c9c218250fe53f530fcdfa1ac16c59f2762e4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 20 Jun 2024 11:49:43 +0300 Subject: [PATCH 06/87] drm/amd/display: Clean up indenting in dm_dp_mst_is_port_support_mode() This code works, but it's not aligned correctly. Add a couple missing tabs. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 48118447c8d9..5d4f831b1e55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1691,7 +1691,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( if (aconnector->mst_output_port->passthrough_aux) { if (bw_range.min_kbps > end_to_end_bw_in_kbps) { DRM_DEBUG_DRIVER("DSC passthrough. Max dsc compression can't fit into end-to-end bw\n"); - return DC_FAIL_BANDWIDTH_VALIDATE; + return DC_FAIL_BANDWIDTH_VALIDATE; } } else { /*dsc bitstream decoded at the dp last link*/ @@ -1756,7 +1756,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( if (branch_max_throughput_mps != 0 && ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) { DRM_DEBUG_DRIVER("DSC is required but max throughput mps fails"); - return DC_FAIL_BANDWIDTH_VALIDATE; + return DC_FAIL_BANDWIDTH_VALIDATE; } } else { DRM_DEBUG_DRIVER("DSC is required but can't find common dsc config."); From 35665ca2cdef314bf0bde0c568a0ad38db3020ce Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Thu, 20 Jun 2024 16:10:52 +0800 Subject: [PATCH 07/87] drm/amd/display: Remove redundant code and semicolons No functional modification involved. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c:3171:2-3: Unneeded semicolon. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c:3185:2-3: Unneeded semicolon. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c:3200:2-3: Unneeded semicolon. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9365 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- .../dml21/src/dml2_core/dml2_core_shared.c | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c index 0099e58e0b1a..81f0a6f19f87 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c @@ -3142,62 +3142,62 @@ static unsigned int dml_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode { switch (sw_mode) { case (dml2_sw_linear): - return 256; break; + return 256; case (dml2_sw_256b_2d): - return 256; break; + return 256; case (dml2_sw_4kb_2d): - return 4096; break; + return 4096; case (dml2_sw_64kb_2d): - return 65536; break; + return 65536; case (dml2_sw_256kb_2d): - return 262144; break; + return 262144; case (dml2_gfx11_sw_linear): - return 256; break; + return 256; case (dml2_gfx11_sw_64kb_d): - return 65536; break; + return 65536; case (dml2_gfx11_sw_64kb_d_t): - return 65536; break; + return 65536; case (dml2_gfx11_sw_64kb_d_x): - return 65536; break; + return 65536; case (dml2_gfx11_sw_64kb_r_x): - return 65536; break; + return 65536; case (dml2_gfx11_sw_256kb_d_x): - return 262144; break; + return 262144; case (dml2_gfx11_sw_256kb_r_x): - return 262144; break; + return 262144; default: DML2_ASSERT(0); return 256; - }; + } } const char *dml2_core_internal_bw_type_str(enum dml2_core_internal_bw_type bw_type) { switch (bw_type) { case (dml2_core_internal_bw_sdp): - return("dml2_core_internal_bw_sdp"); break; + return("dml2_core_internal_bw_sdp"); case (dml2_core_internal_bw_dram): - return("dml2_core_internal_bw_dram"); break; + return("dml2_core_internal_bw_dram"); case (dml2_core_internal_bw_max): - return("dml2_core_internal_bw_max"); break; + return("dml2_core_internal_bw_max"); default: - return("dml2_core_internal_bw_unknown"); break; - }; + return("dml2_core_internal_bw_unknown"); + } } const char *dml2_core_internal_soc_state_type_str(enum dml2_core_internal_soc_state_type dml2_core_internal_soc_state_type) { switch (dml2_core_internal_soc_state_type) { case (dml2_core_internal_soc_state_sys_idle): - return("dml2_core_internal_soc_state_sys_idle"); break; + return("dml2_core_internal_soc_state_sys_idle"); case (dml2_core_internal_soc_state_sys_active): - return("dml2_core_internal_soc_state_sys_active"); break; + return("dml2_core_internal_soc_state_sys_active"); case (dml2_core_internal_soc_state_svp_prefetch): - return("dml2_core_internal_soc_state_svp_prefetch"); break; + return("dml2_core_internal_soc_state_svp_prefetch"); case dml2_core_internal_soc_state_max: default: - return("dml2_core_internal_soc_state_unknown"); break; - }; + return("dml2_core_internal_soc_state_unknown"); + } } static bool dml_is_vertical_rotation(enum dml2_rotation_angle Scan) From 39de69c4f935aa66fd4675c1d000643e46083842 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 20 Jun 2024 11:49:30 +0300 Subject: [PATCH 08/87] drm/amdgpu/kfd: Add unlock() on error path to add_queue_mes() We recently added locking to add_queue_mes() but this error path was overlooked. Add an unlock to the error path. Fixes: 1802b042a343 ("drm/amdgpu/kfd: remove is_hws_hang and is_resetting") Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index d2fceb6f9802..4f48507418d2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -230,6 +230,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, if (queue_type < 0) { dev_err(adev->dev, "Queue type not supported with MES, queue:%d\n", q->properties.type); + up_read(&adev->reset_domain->sem); return -EINVAL; } queue_input.queue_type = (uint32_t)queue_type; From 541fe90ee699658134c26539fdc0ea31c8f47fa9 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Tue, 18 Jun 2024 14:34:24 +0800 Subject: [PATCH 09/87] drm/amdgpu: update MTYPE mapping for gfx12 gfx12 only support MTYPE UC and NC, so update it accordingly. Signed-off-by: Frank Min Reviewed-by: Hawking Zhang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index be78507ec0d8..fd3ac483760e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -464,10 +464,6 @@ static uint64_t gmc_v12_0_map_mtype(struct amdgpu_device *adev, uint32_t flags) return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_NC); case AMDGPU_VM_MTYPE_NC: return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_NC); - case AMDGPU_VM_MTYPE_WC: - return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_WC); - case AMDGPU_VM_MTYPE_CC: - return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_CC); case AMDGPU_VM_MTYPE_UC: return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_UC); default: From 78beaba9796365dfe264a93e0f33e0793c551367 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 19 Jun 2024 13:58:33 +0800 Subject: [PATCH 10/87] Revert "drm/amd/pm: workaround to pass jpeg unit test" This reverts commit 6b18376ef37c3dd2bbf34ed4b42fefaa1f348a3d. Revert this due to a final solution: commit ed3165d660d8 ("drm/amdgpu/jpeg5: reprogram doorbell setting after power up for each playback") Signed-off-by: Kenneth Feng Reviewed-by: Sonny Jiang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 3 +- .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 30 +------------------ 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8e694b576d1c..00384b381289 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -237,7 +237,6 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu, { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; - struct amdgpu_device *adev = smu->adev; int ret = 0; /* @@ -253,7 +252,7 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu, return 0; ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); - if (!ret && !adev->enable_jpeg_test) + if (!ret) atomic_set(&power_gate->vcn_gated, !enable); return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index 7179cdacf156..98ea58d792ca 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -1869,34 +1869,6 @@ static ssize_t smu_v14_0_2_get_ecc_info(struct smu_context *smu, return ret; } -static int smu_v14_0_2_set_vcn_enable(struct smu_context *smu, - bool enable) -{ - struct amdgpu_device *adev = smu->adev; - struct smu_power_gate *power_gate = &smu->smu_power.power_gate; - int i, ret = 0; - - if (!adev->enable_jpeg_test) - return smu_v14_0_set_vcn_enable(smu, enable); - - if (!atomic_read(&power_gate->vcn_gated) || !enable) - return 0; - - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - if (adev->vcn.harvest_config & (1 << i)) - continue; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, - i << 16U, NULL); - if (ret) - return ret; - } - - atomic_set(&power_gate->vcn_gated, 0); - - return ret; -} - static const struct pptable_funcs smu_v14_0_2_ppt_funcs = { .get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask, .set_default_dpm_table = smu_v14_0_2_set_default_dpm_table, @@ -1919,7 +1891,7 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = { .system_features_control = smu_v14_0_system_features_control, .set_allowed_mask = smu_v14_0_set_allowed_mask, .get_enabled_mask = smu_cmn_get_enabled_mask, - .dpm_set_vcn_enable = smu_v14_0_2_set_vcn_enable, + .dpm_set_vcn_enable = smu_v14_0_set_vcn_enable, .dpm_set_jpeg_enable = smu_v14_0_set_jpeg_enable, .get_dpm_ultimate_freq = smu_v14_0_2_get_dpm_ultimate_freq, .get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values, From 6bab222b8b767aa773a8aeac7a3a43b958fcd694 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Fri, 31 May 2024 14:05:37 +0800 Subject: [PATCH 11/87] drm/amdgpu: refine gfx12 firmware loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refine gfx12 firmware loading Signed-off-by: Yang Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index 460bf33a22b1..e9559bdd8264 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -386,10 +386,9 @@ static int gfx_v12_0_init_toc_microcode(struct amdgpu_device *adev, const char * { const struct psp_firmware_header_v1_0 *toc_hdr; int err = 0; - char fw_name[40]; - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, + "amdgpu/%s_toc.bin", ucode_prefix); if (err) goto out; @@ -407,7 +406,6 @@ out: static int gfx_v12_0_init_microcode(struct amdgpu_device *adev) { - char fw_name[40]; char ucode_prefix[15]; int err; const struct rlc_firmware_header_v2_0 *rlc_hdr; @@ -418,23 +416,23 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev) amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, + "amdgpu/%s_pfp.bin", ucode_prefix); if (err) goto out; amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP); amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK); - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, + "amdgpu/%s_me.bin", ucode_prefix); if (err) goto out; amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME); amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK); if (!amdgpu_sriov_vf(adev)) { - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, + "amdgpu/%s_rlc.bin", ucode_prefix); if (err) goto out; rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data; @@ -445,8 +443,8 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev) goto out; } - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix); - err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name); + err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, + "amdgpu/%s_mec.bin", ucode_prefix); if (err) goto out; amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC); From 748bd8ebae91fc0aee76d13026427d0de02e9e1e Mon Sep 17 00:00:00 2001 From: Frank Min Date: Wed, 19 Jun 2024 15:54:38 +0800 Subject: [PATCH 12/87] drm/amdgpu: access ltr through pci cfg space Access ltr through pci cfg space instead of mmio while programing aspm on gfx12 Signed-off-by: Frank Min Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c index 5a20bb229788..39919e0892c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c @@ -345,6 +345,7 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev) { #ifdef CONFIG_PCIEASPM uint32_t def, data; + u16 devctl2, ltr; def = data = RREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL); data &= ~PCIE_LC_CNTL__LC_L1_INACTIVITY_MASK; @@ -374,12 +375,17 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev) if (def != data) WREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_BIF_STRAP5, data); - def = data = RREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_DEVICE_CNTL2); - data &= ~BIF_CFG_DEV0_EPF0_DEVICE_CNTL2__LTR_EN_MASK; + pcie_capability_read_word(adev->pdev, PCI_EXP_DEVCTL2, &devctl2); + data = def = devctl2; + data &= ~PCI_EXP_DEVCTL2_LTR_EN; if (def != data) - WREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_DEVICE_CNTL2, data); + pcie_capability_set_word(adev->pdev, PCI_EXP_DEVCTL2, (u16)data); - WREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_PCIE_LTR_CAP, 0x10011001); + ltr = pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_LTR); + + if (ltr) { + pci_write_config_dword(adev->pdev, ltr + PCI_LTR_MAX_SNOOP_LAT, 0x10011001); + } #if 0 /* regPSWUSP0_PCIE_LC_CNTL2 should be replace by PCIE_LC_CNTL2 or someone else ? */ From 6e3eb2766731c6bd2bfae5a0fbb538ec85e7e822 Mon Sep 17 00:00:00 2001 From: Nicholas Susanto Date: Fri, 7 Jun 2024 14:39:01 -0400 Subject: [PATCH 13/87] drm/amd/display: Temporarily disable HPO PG on DCN35 [WHY] On hotpluggin a 4k144 HDMI FRL setup, display fails FRL link training and falls back to TMDS which is caused by driver not ungating HPO before doing FRL link training. [HOW] Enable debug flag to disable HPO power gate in DCN35 Reviewed-by: Nicholas Kazlauskas Reviewed-by: Charlene Liu Signed-off-by: Alex Hung Signed-off-by: Nicholas Susanto Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 0094ef223c5d..67ab8c1962ff 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -721,7 +721,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_dpp_power_gate = true, .disable_hubp_power_gate = true, .disable_optc_power_gate = true, /*should the same as above two*/ - .disable_hpo_power_gate = false, /*dmubfw force domain25 on*/ + .disable_hpo_power_gate = true, /*dmubfw force domain25 on*/ .disable_clock_gate = false, .disable_dsc_power_gate = true, .vsr_support = true, From 8aa5aff2bf2d5cf793946f1415dfbeea9f936ad5 Mon Sep 17 00:00:00 2001 From: Relja Vojvodic Date: Mon, 10 Jun 2024 14:37:06 -0400 Subject: [PATCH 14/87] drm/amd/display: Refactor dccg401_get_other_enable_symclk_fe [WHY] Function was used to check the number of FEs connected to the current BE. This was then used to determine if the symclk could be disabled, if all FEs were disconnected. However, the function would skip over the primary FE and return 0 when the primary FE was still connected. This caused black screens on driver disable with an MST daisy chain hooked up. [HOW] Refactored the function to correctly return the number of FEs connected to the input BE. Also renamed it for clarity. Reviewed-by: Wenjing Liu Signed-off-by: Alex Hung Signed-off-by: Relja Vojvodic Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dccg/dcn401/dcn401_dccg.c | 57 +++++++------------ 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c index 6a467c49b4a4..07f1f396ba52 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c @@ -853,43 +853,30 @@ static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst } /*get other front end connected to this backend*/ -static uint8_t dccg401_get_other_enabled_symclk_fe(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) +static uint8_t dccg401_get_number_enabled_symclk_fe_connected_to_be(struct dccg *dccg, uint32_t link_enc_inst) { uint8_t num_enabled_symclk_fe = 0; - uint32_t be_clk_en = 0, fe_clk_en[4] = {0}, be_clk_sel[4] = {0}; + uint32_t fe_clk_en[4] = {0}, be_clk_sel[4] = {0}; struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + uint8_t i; - switch (link_enc_inst) { - case 0: - REG_GET_3(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, &be_clk_en, - SYMCLKA_FE_EN, &fe_clk_en[0], - SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]); - break; - case 1: - REG_GET_3(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, &be_clk_en, - SYMCLKB_FE_EN, &fe_clk_en[1], - SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]); - break; - case 2: - REG_GET_3(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, &be_clk_en, - SYMCLKC_FE_EN, &fe_clk_en[2], - SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]); - break; - case 3: - REG_GET_3(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, &be_clk_en, - SYMCLKD_FE_EN, &fe_clk_en[3], - SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]); - break; - } - if (be_clk_en) { - /* for DPMST, this backend could be used by multiple front end. - only disable the backend if this stream_enc_ins is the last active stream enc connected to this back_end*/ - uint8_t i; - for (i = 0; i != link_enc_inst && i < ARRAY_SIZE(fe_clk_en); i++) { - if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst) - num_enabled_symclk_fe++; - } + REG_GET_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, &fe_clk_en[0], + SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]); + + REG_GET_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, &fe_clk_en[1], + SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]); + + REG_GET_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, &fe_clk_en[2], + SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]); + + REG_GET_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, &fe_clk_en[3], + SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]); + + for (i = 0; i < ARRAY_SIZE(fe_clk_en); i++) { + if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst) + num_enabled_symclk_fe++; } + return num_enabled_symclk_fe; } @@ -921,9 +908,9 @@ static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_ins break; } - /*check other enabled symclk fe */ - num_enabled_symclk_fe = dccg401_get_other_enabled_symclk_fe(dccg, stream_enc_inst, link_enc_inst); - /*only turn off backend clk if other front end attachecd to this backend are all off, + /*check other enabled symclk fe connected to this be */ + num_enabled_symclk_fe = dccg401_get_number_enabled_symclk_fe_connected_to_be(dccg, link_enc_inst); + /*only turn off backend clk if other front ends attached to this backend are all off, for mst, only turn off the backend if this is the last front end*/ if (num_enabled_symclk_fe == 0) { switch (link_enc_inst) { From 4fa0046f11d998c39689ece909b912527081e558 Mon Sep 17 00:00:00 2001 From: Ivan Lipski Date: Fri, 7 Jun 2024 10:10:38 -0400 Subject: [PATCH 15/87] drm/amd/display: Remove redundant var from display_rq_dig_calc in dml [WHY] Coverity analysis flagged these files as containing DEADCODE, i. e. redundant or unreachabale. In these files, variable 'mode_422' is always the same file (0 or false), so any code logic with it is redundant. [HOW] Removed 'mode_422' variable and all code with it from 'display_rq_dlg_calc_' functions in dml. Reviewed-by: Alex Hung Signed-off-by: Alex Hung Signed-off-by: Ivan Lipski Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/dml/dcn20/display_rq_dlg_calc_20.c | 14 +++----------- .../dc/dml/dcn20/display_rq_dlg_calc_20v2.c | 14 +++----------- .../display/dc/dml/dcn21/display_rq_dlg_calc_21.c | 14 +++----------- .../display/dc/dml/dcn30/display_rq_dlg_calc_30.c | 14 +++----------- .../display/dc/dml/dcn31/display_rq_dlg_calc_31.c | 14 +++----------- .../dc/dml/dcn314/display_rq_dlg_calc_314.c | 14 +++----------- 6 files changed, 18 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 07146569e335..7c56ad0f8812 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -688,12 +688,11 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, const display_pipe_source_params_st *pipe_src_param, bool is_chroma) { - bool mode_422 = false; unsigned int vp_width = 0; unsigned int vp_height = 0; unsigned int data_pitch = 0; unsigned int meta_pitch = 0; - unsigned int ppe = mode_422 ? 2 : 1; + unsigned int ppe = 1; // TODO check if ppe apply for both luma and chroma in 422 case if (is_chroma) { @@ -825,7 +824,6 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, double min_dst_y_ttu_vblank; unsigned int dlg_vblank_start; bool dual_plane; - bool mode_422; unsigned int access_dir; unsigned int vp_height_l; unsigned int vp_width_l; @@ -971,7 +969,6 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, // Source // dcc_en = src.dcc; dual_plane = is_dual_plane((enum source_format_class)(src->source_format)); - mode_422 = false; // TODO access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed // bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0); // bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1); @@ -1148,13 +1145,8 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element - swath_width_pixels_ub_c = swath_width_ub_c * 2; - } else { - swath_width_pixels_ub_l = swath_width_ub_l * 1; - swath_width_pixels_ub_c = swath_width_ub_c * 1; - } + swath_width_pixels_ub_l = swath_width_ub_l; + swath_width_pixels_ub_c = swath_width_ub_c; if (htaps_l <= 1) min_hratio_fact_l = 2.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index f4bba1f2aeb6..3d95bfa5aca2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -688,12 +688,11 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, const display_pipe_source_params_st *pipe_src_param, bool is_chroma) { - bool mode_422 = false; unsigned int vp_width = 0; unsigned int vp_height = 0; unsigned int data_pitch = 0; unsigned int meta_pitch = 0; - unsigned int ppe = mode_422 ? 2 : 1; + unsigned int ppe = 1; // TODO check if ppe apply for both luma and chroma in 422 case if (is_chroma) { @@ -825,7 +824,6 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, double min_dst_y_ttu_vblank; unsigned int dlg_vblank_start; bool dual_plane; - bool mode_422; unsigned int access_dir; unsigned int vp_height_l; unsigned int vp_width_l; @@ -972,7 +970,6 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, // Source // dcc_en = src.dcc; dual_plane = is_dual_plane((enum source_format_class)(src->source_format)); - mode_422 = false; // TODO access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed // bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0); // bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1); @@ -1149,13 +1146,8 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element - swath_width_pixels_ub_c = swath_width_ub_c * 2; - } else { - swath_width_pixels_ub_l = swath_width_ub_l * 1; - swath_width_pixels_ub_c = swath_width_ub_c * 1; - } + swath_width_pixels_ub_l = swath_width_ub_l; + swath_width_pixels_ub_c = swath_width_ub_c; if (htaps_l <= 1) min_hratio_fact_l = 2.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index c229a9edf82a..98502a4f0567 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -694,12 +694,11 @@ static void get_surf_rq_param( const display_pipe_params_st *pipe_param, bool is_chroma) { - bool mode_422 = false; unsigned int vp_width = 0; unsigned int vp_height = 0; unsigned int data_pitch = 0; unsigned int meta_pitch = 0; - unsigned int ppe = mode_422 ? 2 : 1; + unsigned int ppe = 1; // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma) { @@ -868,7 +867,6 @@ static void dml_rq_dlg_get_dlg_params( double min_dst_y_ttu_vblank; unsigned int dlg_vblank_start; bool dual_plane; - bool mode_422; unsigned int access_dir; unsigned int vp_height_l; unsigned int vp_width_l; @@ -1020,7 +1018,6 @@ static void dml_rq_dlg_get_dlg_params( // Source // dcc_en = src.dcc; dual_plane = is_dual_plane((enum source_format_class) (src->source_format)); - mode_422 = false; // FIXME access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed // bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0); // bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1); @@ -1197,13 +1194,8 @@ static void dml_rq_dlg_get_dlg_params( dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element - swath_width_pixels_ub_c = swath_width_ub_c * 2; - } else { - swath_width_pixels_ub_l = swath_width_ub_l * 1; - swath_width_pixels_ub_c = swath_width_ub_c * 1; - } + swath_width_pixels_ub_l = swath_width_ub_l; + swath_width_pixels_ub_c = swath_width_ub_c; if (hratio_l <= 1) min_hratio_fact_l = 2.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index f3ee7baac786..b28fcc8608ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -660,13 +660,12 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, bool is_chroma, bool is_alpha) { - bool mode_422 = 0; unsigned int vp_width = 0; unsigned int vp_height = 0; unsigned int data_pitch = 0; unsigned int meta_pitch = 0; unsigned int surface_height = 0; - unsigned int ppe = mode_422 ? 2 : 1; + unsigned int ppe = 1; // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma | is_alpha) { @@ -934,7 +933,6 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, double min_dst_y_ttu_vblank = 0; unsigned int dlg_vblank_start = 0; bool dual_plane = false; - bool mode_422 = false; unsigned int access_dir = 0; unsigned int vp_height_l = 0; unsigned int vp_width_l = 0; @@ -1083,7 +1081,6 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, // Source // dcc_en = src.dcc; dual_plane = is_dual_plane((enum source_format_class)(src->source_format)); - mode_422 = false; // TODO access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed vp_height_l = src->viewport_height; vp_width_l = src->viewport_width; @@ -1301,13 +1298,8 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element - swath_width_pixels_ub_c = swath_width_ub_c * 2; - } else { - swath_width_pixels_ub_l = swath_width_ub_l * 1; - swath_width_pixels_ub_c = swath_width_ub_c * 1; - } + swath_width_pixels_ub_l = swath_width_ub_l; + swath_width_pixels_ub_c = swath_width_ub_c; if (hratio_l <= 1) min_hratio_fact_l = 2.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c index b6d954d9aa00..b57b095cd4a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c @@ -655,13 +655,12 @@ static void get_surf_rq_param( bool is_chroma, bool is_alpha) { - bool mode_422 = 0; unsigned int vp_width = 0; unsigned int vp_height = 0; unsigned int data_pitch = 0; unsigned int meta_pitch = 0; unsigned int surface_height = 0; - unsigned int ppe = mode_422 ? 2 : 1; + unsigned int ppe = 1; // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma | is_alpha) { @@ -888,7 +887,6 @@ static void dml_rq_dlg_get_dlg_params( double min_ttu_vblank; unsigned int dlg_vblank_start; bool dual_plane; - bool mode_422; unsigned int access_dir; unsigned int vp_height_l; unsigned int vp_width_l; @@ -1004,7 +1002,6 @@ static void dml_rq_dlg_get_dlg_params( // Prefetch Calc // Source dual_plane = is_dual_plane((enum source_format_class) (src->source_format)); - mode_422 = 0; access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed vp_height_l = src->viewport_height; vp_width_l = src->viewport_width; @@ -1142,13 +1139,8 @@ static void dml_rq_dlg_get_dlg_params( dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element - swath_width_pixels_ub_c = swath_width_ub_c * 2; - } else { - swath_width_pixels_ub_l = swath_width_ub_l * 1; - swath_width_pixels_ub_c = swath_width_ub_c * 1; - } + swath_width_pixels_ub_l = swath_width_ub_l; + swath_width_pixels_ub_c = swath_width_ub_c; if (hratio_l <= 1) min_hratio_fact_l = 2.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c index 94975b0fa398..61b3bebf24c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c @@ -743,13 +743,12 @@ static void get_surf_rq_param( bool is_chroma, bool is_alpha) { - bool mode_422 = 0; unsigned int vp_width = 0; unsigned int vp_height = 0; unsigned int data_pitch = 0; unsigned int meta_pitch = 0; unsigned int surface_height = 0; - unsigned int ppe = mode_422 ? 2 : 1; + unsigned int ppe = 1; // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma | is_alpha) { @@ -973,7 +972,6 @@ static void dml_rq_dlg_get_dlg_params( double min_ttu_vblank; unsigned int dlg_vblank_start; bool dual_plane; - bool mode_422; unsigned int access_dir; unsigned int vp_height_l; unsigned int vp_width_l; @@ -1091,7 +1089,6 @@ static void dml_rq_dlg_get_dlg_params( // Prefetch Calc // Source dual_plane = is_dual_plane((enum source_format_class) (src->source_format)); - mode_422 = 0; access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed vp_height_l = src->viewport_height; vp_width_l = src->viewport_width; @@ -1230,13 +1227,8 @@ static void dml_rq_dlg_get_dlg_params( dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element - swath_width_pixels_ub_c = swath_width_ub_c * 2; - } else { - swath_width_pixels_ub_l = swath_width_ub_l * 1; - swath_width_pixels_ub_c = swath_width_ub_c * 1; - } + swath_width_pixels_ub_l = swath_width_ub_l; + swath_width_pixels_ub_c = swath_width_ub_c; if (hratio_l <= 1) min_hratio_fact_l = 2.0; From 9da0f7736763aa0fbf63bb15060c6827135f3f67 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Fri, 21 Jun 2024 11:25:30 +0800 Subject: [PATCH 16/87] drm/amdgpu: Fix register access violation fault_status is read only register. fault_cntl is not accessible from guest environment. Signed-off-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c | 8 +++++--- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 8 +++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c index e14acab5cceb..72109abe7c86 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c @@ -629,9 +629,11 @@ static bool gfxhub_v1_2_query_utcl2_poison_status(struct amdgpu_device *adev, status = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVM_L2_PROTECTION_FAULT_STATUS); fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); - /* reset page fault status */ - WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), - regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1); + if (!amdgpu_sriov_vf(adev)) { + /* clear page fault status and address */ + WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), + regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1); + } return fed; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 88b4644f8e96..b73136d390cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -672,7 +672,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2))) return 0; - WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); + if (!amdgpu_sriov_vf(adev)) + WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status, vmhub); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c index 7a1ff298417a..8d7267a013d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c @@ -566,9 +566,11 @@ static bool mmhub_v1_8_query_utcl2_poison_status(struct amdgpu_device *adev, status = RREG32_SOC15(MMHUB, hub_inst, regVM_L2_PROTECTION_FAULT_STATUS); fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); - /* reset page fault status */ - WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst, - regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1); + if (!amdgpu_sriov_vf(adev)) { + /* clear page fault status and address */ + WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst, + regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1); + } return fed; } From c6dfe8f20b00d0ac6addc0024d4c70693e78e7cd Mon Sep 17 00:00:00 2001 From: Ivan Lipski Date: Fri, 31 May 2024 16:54:24 -0400 Subject: [PATCH 17/87] drm/amd/display: Remove unnecessary variable [WHY] Coverity analysis flagged this code as DEADCODE because the condition '(!need_recovery)' is never true. The variable 'need_recovery' is initialized as 'true', is not assigned to 'false' anywhere before the conditional statement. Since the variable is only used for the conditional check, but the check can never be true, the variable itself is redundant. [HOW] Removed the variable 'need_recovery'. Reviewed-by: Alex Hung Signed-off-by: Alex Hung Signed-off-by: Ivan Lipski Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 35151dd056cb..4ef329a4d764 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -1134,26 +1134,9 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc) { struct hubp *hubp ; unsigned int i; - bool need_recover = true; if (!dc->debug.recovery_enabled) return false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = - &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx != NULL) { - hubp = pipe_ctx->plane_res.hubp; - if (hubp != NULL && hubp->funcs->hubp_get_underflow_status) { - if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) { - /* one pipe underflow, we will reset all the pipes*/ - need_recover = true; - } - } - } - } - if (!need_recover) - return false; /* DCHUBP_CNTL:HUBP_BLANK_EN=1 DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1 From ee8287e068a3995b0f8001dd6931e221dfb7c530 Mon Sep 17 00:00:00 2001 From: Nevenko Stupar Date: Mon, 10 Jun 2024 15:32:05 -0400 Subject: [PATCH 18/87] drm/amd/display: Fix cursor issues with ODMs and HW rotations [WHY & HOW] Current code for cursor positions does not work properly with different ODM options and HW rotations like ODM 2to1, 3to1 and 4to1, and has different issues depending on angle of HW rotations. [HOW] Fixed these issues so to work properly when ODM is used with HW rotations. Reviewed-by: Sridevi Arvindekar Signed-off-by: Alex Hung Signed-off-by: Nevenko Stupar Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c | 50 ------- .../amd/display/dc/hubp/dcn401/dcn401_hubp.c | 38 ----- .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 135 +++--------------- 3 files changed, 19 insertions(+), 204 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c index aef73bd1221a..d0f8c9ff5232 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c @@ -153,58 +153,8 @@ void dpp401_set_cursor_position( uint32_t height) { struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); - int x_pos = pos->x - param->recout.x; - int y_pos = pos->y - param->recout.y; - int x_hotspot = pos->x_hotspot; - int y_hotspot = pos->y_hotspot; - int rec_x_offset = x_pos - pos->x_hotspot; - int rec_y_offset = y_pos - pos->y_hotspot; - int cursor_height = (int)height; - int cursor_width = (int)width; uint32_t cur_en = pos->enable ? 1 : 0; - // Transform cursor width / height and hotspots for offset calculations - if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { - swap(cursor_height, cursor_width); - swap(x_hotspot, y_hotspot); - - if (param->rotation == ROTATION_ANGLE_90) { - // hotspot = (-y, x) - rec_x_offset = x_pos - (cursor_width - x_hotspot); - rec_y_offset = y_pos - y_hotspot; - } else if (param->rotation == ROTATION_ANGLE_270) { - // hotspot = (y, -x) - rec_x_offset = x_pos - x_hotspot; - rec_y_offset = y_pos - (cursor_height - y_hotspot); - } - } else if (param->rotation == ROTATION_ANGLE_180) { - // hotspot = (-x, -y) - if (!param->mirror) - rec_x_offset = x_pos - (cursor_width - x_hotspot); - - rec_y_offset = y_pos - (cursor_height - y_hotspot); - } - - if (param->rotation == ROTATION_ANGLE_0 && !param->mirror) { - if (rec_x_offset >= (int)param->recout.width) - cur_en = 0; /* not visible beyond right edge*/ - - if (rec_y_offset >= (int)param->recout.height) - cur_en = 0; /* not visible beyond bottom edge*/ - } else { - if (rec_x_offset > (int)param->recout.width) - cur_en = 0; /* not visible beyond right edge*/ - - if (rec_y_offset > (int)param->recout.height) - cur_en = 0; /* not visible beyond bottom edge*/ - } - - if (rec_x_offset + cursor_width <= 0) - cur_en = 0; /* not visible beyond left edge*/ - - if (rec_y_offset + cursor_height <= 0) - cur_en = 0; /* not visible beyond top edge*/ - REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, cur_en); dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en; diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c index 6692d57d5cce..a893160ae775 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c @@ -654,12 +654,8 @@ void hubp401_cursor_set_position( struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); int x_pos = pos->x - param->recout.x; int y_pos = pos->y - param->recout.y; - int x_hotspot = pos->x_hotspot; - int y_hotspot = pos->y_hotspot; int rec_x_offset = x_pos - pos->x_hotspot; int rec_y_offset = y_pos - pos->y_hotspot; - int cursor_height = (int)hubp->curs_attr.height; - int cursor_width = (int)hubp->curs_attr.width; uint32_t dst_x_offset; uint32_t cur_en = pos->enable ? 1 : 0; @@ -672,28 +668,6 @@ void hubp401_cursor_set_position( if (hubp->curs_attr.address.quad_part == 0) return; - // Transform cursor width / height and hotspots for offset calculations - if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { - swap(cursor_height, cursor_width); - swap(x_hotspot, y_hotspot); - - if (param->rotation == ROTATION_ANGLE_90) { - // hotspot = (-y, x) - rec_x_offset = x_pos - (cursor_width - x_hotspot); - rec_y_offset = y_pos - y_hotspot; - } else if (param->rotation == ROTATION_ANGLE_270) { - // hotspot = (y, -x) - rec_x_offset = x_pos - x_hotspot; - rec_y_offset = y_pos - (cursor_height - y_hotspot); - } - } else if (param->rotation == ROTATION_ANGLE_180) { - // hotspot = (-x, -y) - if (!param->mirror) - rec_x_offset = x_pos - (cursor_width - x_hotspot); - - rec_y_offset = y_pos - (cursor_height - y_hotspot); - } - dst_x_offset = (rec_x_offset >= 0) ? rec_x_offset : 0; dst_x_offset *= param->ref_clk_khz; dst_x_offset /= param->pixel_clk_khz; @@ -705,18 +679,6 @@ void hubp401_cursor_set_position( dc_fixpt_from_int(dst_x_offset), param->h_scale_ratio)); - if (rec_x_offset >= (int)param->recout.width) - cur_en = 0; /* not visible beyond right edge*/ - - if (rec_x_offset + cursor_width <= 0) - cur_en = 0; /* not visible beyond left edge*/ - - if (rec_y_offset >= (int)param->recout.height) - cur_en = 0; /* not visible beyond bottom edge*/ - - if (rec_y_offset + cursor_height <= 0) - cur_en = 0; /* not visible beyond top edge*/ - if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 7a456618f313..8d0da56e4cc5 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1099,31 +1099,21 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert, .rotation = pipe_ctx->plane_state->rotation, - .mirror = pipe_ctx->plane_state->horizontal_mirror + .mirror = pipe_ctx->plane_state->horizontal_mirror, + .stream = pipe_ctx->stream }; - bool pipe_split_on = false; bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) || (pipe_ctx->prev_odm_pipe != NULL); int prev_odm_width = 0; int prev_odm_offset = 0; - int next_odm_width = 0; - int next_odm_offset = 0; - struct pipe_ctx *next_odm_pipe = NULL; struct pipe_ctx *prev_odm_pipe = NULL; int x_pos = pos_cpy.x; int y_pos = pos_cpy.y; + int recout_x_pos = 0; + int recout_y_pos = 0; - if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) { - if ((pipe_ctx->plane_state->src_rect.width != pipe_ctx->plane_res.scl_data.viewport.width) || - (pipe_ctx->plane_state->src_rect.height != pipe_ctx->plane_res.scl_data.viewport.height)) { - pipe_split_on = true; - } - } - - - /** - * DCN4 moved cursor composition after Scaler, so in HW it is in + /* DCN4 moved cursor composition after Scaler, so in HW it is in * recout space and for HW Cursor position programming need to * translate to recout space. * @@ -1148,8 +1138,7 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) y_pos = pipe_ctx->stream->dst.y + y_pos * pipe_ctx->stream->dst.height / pipe_ctx->stream->src.height; - /** - * If the cursor's source viewport is clipped then we need to + /* If the cursor's source viewport is clipped then we need to * translate the cursor to appear in the correct position on * the screen. * @@ -1169,38 +1158,15 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) * next/prev_odm_offset is to account for scaled modes that have underscan */ if (odm_combine_on) { - next_odm_pipe = pipe_ctx->next_odm_pipe; prev_odm_pipe = pipe_ctx->prev_odm_pipe; - while (next_odm_pipe != NULL) { - next_odm_width += next_odm_pipe->plane_res.scl_data.recout.width; - next_odm_offset += next_odm_pipe->plane_res.scl_data.recout.x; - next_odm_pipe = next_odm_pipe->next_odm_pipe; - } while (prev_odm_pipe != NULL) { prev_odm_width += prev_odm_pipe->plane_res.scl_data.recout.width; prev_odm_offset += prev_odm_pipe->plane_res.scl_data.recout.x; prev_odm_pipe = prev_odm_pipe->prev_odm_pipe; } - if (param.rotation == ROTATION_ANGLE_0) { - x_pos -= (prev_odm_width + prev_odm_offset); - } - } - - /** - * If the position is negative then we need to add to the hotspot - * to shift the cursor outside the plane. - */ - - if (x_pos < 0) { - pos_cpy.x_hotspot -= x_pos; - x_pos = 0; - } - - if (y_pos < 0) { - pos_cpy.y_hotspot -= y_pos; - y_pos = 0; + x_pos -= (prev_odm_width + prev_odm_offset); } pos_cpy.x = (uint32_t)x_pos; @@ -1209,86 +1175,23 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) if (pos_cpy.enable && dcn401_can_pipe_disable_cursor(pipe_ctx)) pos_cpy.enable = false; - if (param.rotation == ROTATION_ANGLE_270) { - // Swap axis and mirror vertically - uint32_t temp_x = pos_cpy.x; + x_pos = pos_cpy.x - param.recout.x; + y_pos = pos_cpy.y - param.recout.y; - int recout_height = - pipe_ctx->plane_res.scl_data.recout.height; - int recout_y = - pipe_ctx->plane_res.scl_data.recout.y; + recout_x_pos = x_pos - pos_cpy.x_hotspot; + recout_y_pos = y_pos - pos_cpy.y_hotspot; - /** - * Display groups that are 1xnY, have pos_cpy.x > 2 * recout.height - * For pipe split cases: - * - apply offset of recout.y to normalize pos_cpy.x - * - calculate the pos_cpy.y as before - * - shift pos_cpy.y back by same offset to get final value - * - since we iterate through both pipes, use the lower - * recout.y for offset - * For non pipe split cases, use the same calculation for - * pos_cpy.y as the 180 degree rotation case below, - * but use pos_cpy.x as our input because we are rotating - * 270 degrees - */ - if (pipe_split_on || odm_combine_on) { - int pos_cpy_x_offset; - int other_pipe_recout_y; + if (recout_x_pos >= (int)param.recout.width) + pos_cpy.enable = false; /* not visible beyond right edge*/ - if (pipe_split_on) { - if (pipe_ctx->bottom_pipe) { - other_pipe_recout_y = - pipe_ctx->bottom_pipe->plane_res.scl_data.recout.y; - } else { - other_pipe_recout_y = - pipe_ctx->top_pipe->plane_res.scl_data.recout.y; - } - pos_cpy_x_offset = (recout_y > other_pipe_recout_y) ? - other_pipe_recout_y : recout_y; - pos_cpy.x -= pos_cpy_x_offset; - if (pos_cpy.x > recout_height) { - pos_cpy.x = pos_cpy.x - recout_height; - pos_cpy.y = recout_height - pos_cpy.x; - } else { - pos_cpy.y = 2 * recout_height - pos_cpy.x; - } - pos_cpy.y += pos_cpy_x_offset; + if (recout_y_pos >= (int)param.recout.height) + pos_cpy.enable = false; /* not visible beyond bottom edge*/ - } else { - pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width + next_odm_width + next_odm_offset - pos_cpy.y; - pos_cpy.y = temp_x; - } - } - } else if (param.rotation == ROTATION_ANGLE_180) { - // Mirror horizontally and vertically - int recout_width = - pipe_ctx->plane_res.scl_data.recout.width; - int recout_x = - pipe_ctx->plane_res.scl_data.recout.x; + if (recout_x_pos + (int)hubp->curs_attr.width <= 0) + pos_cpy.enable = false; /* not visible beyond left edge*/ - if (!param.mirror) { - if (odm_combine_on) { - pos_cpy.x = pipe_ctx->plane_res.scl_data.recout.width + next_odm_width - pos_cpy.x; - } else if (pipe_split_on) { - if (pos_cpy.x >= recout_width + recout_x) { - pos_cpy.x = 2 * recout_width - - pos_cpy.x + 2 * recout_x; - } else { - uint32_t temp_x = pos_cpy.x; - - pos_cpy.x = 2 * recout_x - pos_cpy.x; - if (temp_x >= recout_x + - (int)hubp->curs_attr.width || pos_cpy.x - <= (int)hubp->curs_attr.width + - pipe_ctx->plane_state->src_rect.x) { - pos_cpy.x = temp_x + recout_width; - } - } - } - - } - - } + if (recout_y_pos + (int)hubp->curs_attr.height <= 0) + pos_cpy.enable = false; /* not visible beyond top edge*/ hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height); From d03415f60b3401914fabd27a20017f8056fd5e40 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Tue, 28 Nov 2023 10:31:12 -0500 Subject: [PATCH 19/87] drm/amd/display: Send DP_TOTAL_LTTPR_CNT during detection if LTTPR is present [WHY] New register field added in DP2.1 SCR, needed for auxless ALPM [HOW] Echo value read from 0xF0007 back to sink Reviewed-by: Wenjing Liu Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/link/protocols/link_dp_capability.c | 10 +++++++++- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 00974c50e11f..f1cac74dd7f7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -1605,9 +1605,17 @@ static bool retrieve_link_cap(struct dc_link *link) return false; } - if (dp_is_lttpr_present(link)) + if (dp_is_lttpr_present(link)) { configure_lttpr_mode_transparent(link); + // Echo TOTAL_LTTPR_CNT back downstream + core_link_write_dpcd( + link, + DP_TOTAL_LTTPR_CNT, + &link->dpcd_caps.lttpr_caps.phy_repeater_cnt, + sizeof(link->dpcd_caps.lttpr_caps.phy_repeater_cnt)); + } + /* Read DP tunneling information. */ status = dpcd_get_tunneling_device_data(link); diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index 914f28e9f224..aee5170f5fb2 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -177,4 +177,9 @@ enum dpcd_psr_sink_states { #define DP_SINK_PR_PIXEL_DEVIATION_PER_LINE 0x379 #define DP_SINK_PR_MAX_NUMBER_OF_DEVIATION_LINE 0x37A +/* Remove once drm_dp_helper.h is updated upstream */ +#ifndef DP_TOTAL_LTTPR_CNT +#define DP_TOTAL_LTTPR_CNT 0xF000A /* 2.1 */ +#endif + #endif /* __DAL_DPCD_DEFS_H__ */ From cd80e7ee47d2fd5c97563c003ff31ce8240ca2d8 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 6 Jun 2024 14:43:36 -0600 Subject: [PATCH 20/87] drm/amd/display: Remove redundant checks for pipe_ctx->stream [WHAT & HOW] The null checks for pipe_ctx->stream and pipe_ctx->stream_res.tg are redundant as they were already dereferenced previously, as reported by Coverity; therefore the null checks are removed. This fixes 6 REVERSE_INULL issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 7 +++---- drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 4 ++-- .../gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 82d1ded09561..4d359bb9b1ec 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -974,8 +974,8 @@ enum dc_status dcn20_enable_stream_timing( /* TODO enable stream if timing changed */ /* TODO unblank stream if DP */ - if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { - if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable) + if (dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { + if (pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable) pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg); } @@ -1827,8 +1827,7 @@ static void dcn20_update_dchubp_dpp( if (pipe_ctx->update_flags.bits.enable) hubp->funcs->set_blank(hubp, false); /* If the stream paired with this plane is phantom, the plane is also phantom */ - if (pipe_ctx->stream && pipe_mall_type == SUBVP_PHANTOM - && hubp->funcs->phantom_hubp_post_enable) + if (pipe_mall_type == SUBVP_PHANTOM && hubp->funcs->phantom_hubp_post_enable) hubp->funcs->phantom_hubp_post_enable(hubp); } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 8d0da56e4cc5..0cf55f557c3c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -916,8 +916,8 @@ enum dc_status dcn401_enable_stream_timing( /* TODO enable stream if timing changed */ /* TODO unblank stream if DP */ - if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { - if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable) + if (dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { + if (pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable) pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg); } diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 8d1a1cc94a8b..555c1c484cfd 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -853,7 +853,7 @@ bool dp_set_test_pattern( CRTC_STATE_VACTIVE); if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) { - if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) { + if (should_use_dmub_lock(pipe_ctx->stream->link)) { union dmub_hw_lock_flags hw_locks = { 0 }; struct dmub_hw_lock_inst_flags inst_flags = { 0 }; From 3a82f62b0d9d7687eac47603bb6cd14a50fa718b Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 7 Jun 2024 09:21:30 -0600 Subject: [PATCH 21/87] drm/amd/display: Run DC_LOG_DC after checking link->link_enc [WHAT] The DC_LOG_DC should be run after link->link_enc is checked, not before. This fixes 1 REVERSE_INULL issue reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/link/link_factory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index 8073fdae9cb1..8246006857b3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -610,14 +610,14 @@ static bool construct_phy(struct dc_link *link, link->link_enc = link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data); - DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); - DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE); - if (!link->link_enc) { DC_ERROR("Failed to create link encoder!\n"); goto link_enc_create_fail; } + DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); + DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE); + /* Update link encoder tracking variables. These are used for the dynamic * assignment of link encoders to streams. */ From 51dbe0239b1fc7c435867ce28e5eb4394b6641e1 Mon Sep 17 00:00:00 2001 From: Nevenko Stupar Date: Tue, 11 Jun 2024 12:31:38 -0400 Subject: [PATCH 22/87] drm/amd/display: Fix cursor size issues [WHY & HOW] Fix the cursor size between ODM slices. Reviewed-by: Sridevi Arvindekar Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Nevenko Stupar Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 0cf55f557c3c..42753f56d31d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1169,6 +1169,20 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) x_pos -= (prev_odm_width + prev_odm_offset); } + /* If the position is negative then we need to add to the hotspot + * to fix cursor size between ODM slices + */ + + if (x_pos < 0) { + pos_cpy.x_hotspot -= x_pos; + x_pos = 0; + } + + if (y_pos < 0) { + pos_cpy.y_hotspot -= y_pos; + y_pos = 0; + } + pos_cpy.x = (uint32_t)x_pos; pos_cpy.y = (uint32_t)y_pos; From 3bc73bc096e64752961060cdf9d460e0a6bb0e6b Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 7 Jun 2024 20:03:31 -0600 Subject: [PATCH 23/87] drm/amd/display: Fix uninitialized variables in dcn401 [WHAT & HOW] surf_linear_128_l/c are used in CalculateBytePerPixelAndBlockSizes before they are assigned, so initializing them before passing them into the function. This fixes 2 UNINIT issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c index be73784e21eb..6f4026e396e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c @@ -11521,8 +11521,8 @@ void dml2_core_calcs_get_dpte_row_height( unsigned int MacroTileWidthC; unsigned int MacroTileHeightY; unsigned int MacroTileHeightC; - bool surf_linear_128_l; - bool surf_linear_128_c; + bool surf_linear_128_l = false; + bool surf_linear_128_c = false; CalculateBytePerPixelAndBlockSizes( SourcePixelFormat, From e094992bd1caa1fbd42221c7c305fc3b54172b5c Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Jun 2024 10:47:35 -0600 Subject: [PATCH 24/87] drm/amd/display: Remove useless function call [WHAT & HOW] clk_mgr_helper_get_active_display_cnt returns display count and itself alone has no use. This fixes 1 CHECKED_RETURN issue reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c index f77840dd051e..7920f6f1aa62 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c @@ -113,8 +113,6 @@ static void dcn201_update_clocks(struct clk_mgr *clk_mgr_base, dcn2_read_clocks_from_hw_dentist(clk_mgr_base); } - clk_mgr_helper_get_active_display_cnt(dc, context); - if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz)) clk_mgr_base->clks.phyclk_khz = new_clocks->phyclk_khz; From a171cce57792b0a6206d532050179a381ad74f8f Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Jun 2024 11:41:32 -0600 Subject: [PATCH 25/87] drm/amd/display: Check and log for function error codes [WHAT & HOW] BIOS_CMD_TABLE_REVISION and link_transmitter_control can return error codes and errors should be reported. This fixes 3 CHECKED_RETURN issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 8 +++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index cc000833d300..4254bdfefe38 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -227,7 +227,8 @@ static void init_transmitter_control(struct bios_parser *bp) uint8_t frev; uint8_t crev = 0; - BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev); + if (!BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev)) + BREAK_TO_DEBUGGER(); switch (crev) { case 6: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 136bd93c3b65..4a9d07c31bc5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1361,7 +1361,10 @@ void dce110_link_encoder_dp_set_lane_settings( cntl.lane_settings = training_lane_set.raw; /* call VBIOS table to set voltage swing and pre-emphasis */ - link_transmitter_control(enc110, &cntl); + if (link_transmitter_control(enc110, &cntl) != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__); + BREAK_TO_DEBUGGER(); + } } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index 4d0eed7598b2..e0558a78b11c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -1104,6 +1104,7 @@ void dcn10_link_encoder_dp_set_lane_settings( union dpcd_training_lane_set training_lane_set = { { 0 } }; int32_t lane = 0; struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; if (!link_settings) { BREAK_TO_DEBUGGER(); @@ -1138,7 +1139,12 @@ void dcn10_link_encoder_dp_set_lane_settings( cntl.lane_settings = training_lane_set.raw; /* call VBIOS table to set voltage swing and pre-emphasis */ - link_transmitter_control(enc10, &cntl); + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__); + BREAK_TO_DEBUGGER(); + } } } From 2c2ee1d1329881d8e6bb23c3b9f3b41df8a8055c Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Jun 2024 10:51:31 -0600 Subject: [PATCH 26/87] drm/amd/display: Check and log for function error codes [WHAT & HOW] dm_dmub_hw_init and drm_dp_mst_topology_mgr_set_mst can return error codes and errors should be reported. This fixes 2 CHECKED_RETURN issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) 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 c96407379224..cefc2569a50f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1302,6 +1302,7 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev) struct dmub_srv *dmub_srv = adev->dm.dmub_srv; enum dmub_status status; bool init; + int r; if (!dmub_srv) { /* DMUB isn't supported on the ASIC. */ @@ -1319,7 +1320,9 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev) DRM_WARN("Wait for DMUB auto-load failed: %d\n", status); } else { /* Perform the full hardware initialization. */ - dm_dmub_hw_init(adev); + r = dm_dmub_hw_init(adev); + if (r) + DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); } } 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 717d97191dda..62cb59f00929 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 @@ -3795,6 +3795,7 @@ static int trigger_hpd_mst_set(void *data, u64 val) struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct dc_link *link = NULL; + int ret; if (val == 1) { drm_connector_list_iter_begin(dev, &iter); @@ -3806,7 +3807,9 @@ static int trigger_hpd_mst_set(void *data, u64 val) dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); mutex_unlock(&adev->dm.dc_lock); - drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); + ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); + if (ret < 0) + DRM_ERROR("DM_MST: Failed to set the device into MST mode!"); } } } else if (val == 0) { From 5d93060d430b359e16e7c555c8f151ead1ac614b Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Jun 2024 10:36:49 -0600 Subject: [PATCH 27/87] drm/amd/display: Check HDCP returned status [WHAT & HOW] Check mod_hdcp_execute_and_set() return values in authenticated_dp. This fixes 3 CHECKED_RETURN issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/modules/hdcp/hdcp1_execution.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index 182e7532dda8..d77836cef563 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -433,17 +433,20 @@ static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp, } if (status == MOD_HDCP_STATUS_SUCCESS) - mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, &input->bstatus_read, &status, - hdcp, "bstatus_read"); + hdcp, "bstatus_read")) + goto out; if (status == MOD_HDCP_STATUS_SUCCESS) - mod_hdcp_execute_and_set(check_link_integrity_dp, + if (!mod_hdcp_execute_and_set(check_link_integrity_dp, &input->link_integrity_check, &status, - hdcp, "link_integrity_check"); + hdcp, "link_integrity_check")) + goto out; if (status == MOD_HDCP_STATUS_SUCCESS) - mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, + if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, &input->reauth_request_check, &status, - hdcp, "reauth_request_check"); + hdcp, "reauth_request_check")) + goto out; out: return status; } From e5a290fa5df4efdc026ff36fe86d53c58d944fe6 Mon Sep 17 00:00:00 2001 From: Joan Lee Date: Wed, 12 Jun 2024 10:12:52 +0800 Subject: [PATCH 28/87] drm/amd/display: Add Replay general cmd [WHY & HOW] Driver side adding replay general cmd interface. Replay general command will config at most two uint_32 parameters, with a replay general command subtype to set relative configurations. Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Hung Signed-off-by: Joan Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + .../gpu/drm/amd/display/dc/dce/dmub_replay.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 21f4af9ab096..c550e8997033 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1036,6 +1036,7 @@ enum replay_FW_Message_type { Replay_Set_Residency_Frameupdate_Timer, Replay_Set_Pseudo_VTotal, Replay_Disabled_Adaptive_Sync_SDP, + Replay_Set_General_Cmd, }; union replay_error_status { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index 5437ebd8bc21..2a21bcf5224f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -346,13 +346,29 @@ static void dmub_replay_send_cmd(struct dmub_replay *dmub, cmd.replay_disabled_adaptive_sync_sdp.header.sub_type = DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP; cmd.replay_disabled_adaptive_sync_sdp.header.payload_bytes = - sizeof(struct dmub_rb_cmd_replay_set_pseudo_vtotal); + sizeof(struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp); //Cmd Body cmd.replay_disabled_adaptive_sync_sdp.data.panel_inst = cmd_element->disabled_adaptive_sync_sdp_data.panel_inst; cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled = cmd_element->disabled_adaptive_sync_sdp_data.force_disabled; break; + case Replay_Set_General_Cmd: + //Header + cmd.replay_set_general_cmd.header.sub_type = + DMUB_CMD__REPLAY_SET_GENERAL_CMD; + cmd.replay_set_general_cmd.header.payload_bytes = + sizeof(struct dmub_rb_cmd_replay_set_general_cmd); + //Cmd Body + cmd.replay_set_general_cmd.data.panel_inst = + cmd_element->set_general_cmd_data.panel_inst; + cmd.replay_set_general_cmd.data.subtype = + cmd_element->set_general_cmd_data.subtype; + cmd.replay_set_general_cmd.data.param1 = + cmd_element->set_general_cmd_data.param1; + cmd.replay_set_general_cmd.data.param2 = + cmd_element->set_general_cmd_data.param2; + break; case Replay_Msg_Not_Support: default: return; From 2ffa97c50a8b0598975e47c890032e71958425a0 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Mon, 10 Jun 2024 18:22:59 +0000 Subject: [PATCH 29/87] drm/amd/display: Use sw cursor for DCN401 with rotation [WHAT & HOW] On DCN401, the cursor composition to the plane happens after scaler. So the cursor isn't stretched with the rest of the surface. Temporarily disable hardware cursor in case when hardware rotation is enabled such that userspace falls back to software cursor. Reviewed-by: Sun peng Li Reviewed-by: Rodrigo Siqueira Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) 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 cefc2569a50f..6e757ee2d74b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -11093,8 +11093,12 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev, int cursor_scale_w, cursor_scale_h; int i; - /* Overlay cursor not supported on HW before DCN */ - if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) { + /* Overlay cursor not supported on HW before DCN + * DCN401 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions + * as previous DCN generations, so enable native mode on DCN401 in addition to DCE + */ + if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0 || + amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) { *cursor_mode = DM_CURSOR_NATIVE_MODE; return 0; } @@ -11237,7 +11241,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; - struct drm_plane_state *old_plane_state, *new_plane_state; + struct drm_plane_state *old_plane_state, *new_plane_state, *new_cursor_state; enum dc_status status; int ret, i; bool lock_and_validation_needed = false; @@ -11465,19 +11469,39 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, drm_dbg_atomic(dev, "MPO enablement requested on crtc:[%p]\n", crtc); } - /* Check cursor planes restrictions */ + /* Check cursor restrictions */ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { enum amdgpu_dm_cursor_mode required_cursor_mode; + int is_rotated, is_scaled; /* Overlay cusor not subject to native cursor restrictions */ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE) continue; + /* Check if rotation or scaling is enabled on DCN401 */ + if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) && + amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) { + new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor); + + is_rotated = new_cursor_state && + ((new_cursor_state->rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0); + is_scaled = new_cursor_state && ((new_cursor_state->src_w >> 16 != new_cursor_state->crtc_w) || + (new_cursor_state->src_h >> 16 != new_cursor_state->crtc_h)); + + if (is_rotated || is_scaled) { + drm_dbg_driver( + crtc->dev, + "[CRTC:%d:%s] cannot enable hardware cursor due to rotation/scaling\n", + crtc->base.id, crtc->name); + ret = -EINVAL; + goto fail; + } + } + /* If HW can only do native cursor, check restrictions again */ ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state, &required_cursor_mode); - if (ret) { drm_dbg_driver(crtc->dev, "[CRTC:%d:%s] Checking cursor mode failed\n", From a4758aa3d1d9ff1c7a05da58387d217c2cd0c38b Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" Date: Tue, 11 Jun 2024 14:12:43 -0400 Subject: [PATCH 30/87] drm/amd/display: Always enable HPO for DCN4 dGPU [WHY && HOW] Some DP EDID CTS tests fail due to HPO disable, and we should keep it enable on DCN4 dGPU. Reviewed-by: Wenjing Liu Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Leo (Hanghong) Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 2 ++ drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 42753f56d31d..79a911e1a09a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -408,6 +408,8 @@ void dcn401_init_hw(struct dc *dc) REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); } + dcn401_setup_hpo_hw_control(hws, true); + if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks) dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c index 1cf0608e1980..8159fd838dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c @@ -137,7 +137,6 @@ static const struct hwseq_private_funcs dcn401_private_funcs = { .program_mall_pipe_config = dcn32_program_mall_pipe_config, .update_force_pstate = dcn32_update_force_pstate, .update_mall_sel = dcn32_update_mall_sel, - .setup_hpo_hw_control = dcn401_setup_hpo_hw_control, .calculate_dccg_k1_k2_values = NULL, .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw, .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe, From f86b47bee6343c9f74630d7fc2fb8f5e41db0440 Mon Sep 17 00:00:00 2001 From: TungYu Lu Date: Wed, 12 Jun 2024 22:34:33 +0800 Subject: [PATCH 31/87] drm/amd/display: resync OTG after DIO FIFO resync [WHY] Tiled displays showed not aligned on 8K60hz when system resumed from S3/S4. [HOW] Do dc_trigger_sync to re-sync pipes to ensure OTG become synced. Reviewed-by: Alvin Lee Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: TungYu Lu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index bdbb4a71651f..fe62478fbcde 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -1254,6 +1254,8 @@ void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); } } + + dc_trigger_sync(dc, dc->current_state); } void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, From a42e74391783603b28f266fc7bbfc1011eb0a151 Mon Sep 17 00:00:00 2001 From: George Shen Date: Tue, 4 Jun 2024 10:11:23 -0400 Subject: [PATCH 32/87] drm/amd/display: Call dpmm when checking mode support [WHY] In check_mode_supported, we should validate that the required clocks can be successfully mapped to DPM levels. This ensures we only apply dynamic ODM optimizations to modes that are supported without dynamic ODM optimizations to begin with. [HOW] Call dpmm to check that the display config can successfully be mapped to a DPM level. Reviewed-by: Chaitanya Dhere Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dml2/dml21/dml21_wrapper.c | 1 + .../dc/dml2/dml21/src/dml2_top/dml_top.c | 17 +++++++++++++++++ .../dml21/src/inc/dml2_internal_shared_types.h | 1 + 3 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index b442e1f9f204..9c28304568d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -257,6 +257,7 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co mode_support->dml2_instance = dml_init->dml2_instance; dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); + dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming; is_supported = dml2_check_mode_supported(mode_support); if (!is_supported) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c index 6f334fdc6eb8..2fb3e2f45e07 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml_top.c @@ -96,10 +96,15 @@ bool dml2_check_mode_supported(struct dml2_check_mode_supported_in_out *in_out) { struct dml2_instance *dml = (struct dml2_instance *)in_out->dml2_instance; struct dml2_check_mode_supported_locals *l = &dml->scratch.check_mode_supported_locals; + /* Borrow the build_mode_programming_locals programming struct for DPMM call. */ + struct dml2_display_cfg_programming *dpmm_programming = dml->scratch.build_mode_programming_locals.mode_programming_params.programming; bool result = false; bool mcache_success = false; + if (dpmm_programming) + memset(dpmm_programming, 0, sizeof(struct dml2_display_cfg_programming)); + setup_unoptimized_display_config_with_meta(dml, &l->base_display_config_with_meta, in_out->display_config); l->mode_support_params.instance = &dml->core_instance; @@ -122,6 +127,18 @@ bool dml2_check_mode_supported(struct dml2_check_mode_supported_in_out *in_out) mcache_success = dml2_top_optimization_perform_optimization_phase(&l->optimization_phase_locals, &mcache_phase); } + /* + * Call DPMM to map all requirements to minimum clock state + */ + if (result && dpmm_programming) { + l->dppm_map_mode_params.min_clk_table = &dml->min_clk_table; + l->dppm_map_mode_params.display_cfg = &l->base_display_config_with_meta; + l->dppm_map_mode_params.programming = dpmm_programming; + l->dppm_map_mode_params.soc_bb = &dml->soc_bbox; + l->dppm_map_mode_params.ip = &dml->core_instance.clean_me_up.mode_lib.ip; + result = dml->dpmm_instance.map_mode_to_soc_dpm(&l->dppm_map_mode_params); + } + in_out->is_supported = mcache_success; result = result && in_out->is_supported; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h index dd90c5df5a5a..5632cdacb7f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/inc/dml2_internal_shared_types.h @@ -870,6 +870,7 @@ struct dml2_check_mode_supported_locals { struct dml2_optimization_phase_locals optimization_phase_locals; struct display_configuation_with_meta base_display_config_with_meta; struct display_configuation_with_meta optimized_display_config_with_meta; + struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out dppm_map_mode_params; }; struct optimization_init_function_params { From 871512e36f9c1c2cb4e62eb860ca0438800e4d63 Mon Sep 17 00:00:00 2001 From: Sung-huai Wang Date: Thu, 13 Jun 2024 15:22:17 +0800 Subject: [PATCH 33/87] drm/amd/display: Add workaround to restrict max frac urgent for DPM0 [WHY] Underflow occurs on some platforms when urgent BW is close to the maximum in DPM0. [HOW] It does not occur at DPM1, so as a workaround restrict the maximum amount and increase the lowest state index for clock states until we're out of DPM0. Adds DML2 config options to specify this pe platform as required. Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Hung Signed-off-by: Sung-huai Wang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml2/dml2_wrapper.c | 15 +++++++++++++++ .../gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 2 ++ .../display/dc/resource/dcn35/dcn35_resource.c | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index f6310408dbba..f4038ac2e476 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -628,6 +628,21 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s if (result) { unsigned int lowest_state_idx = s->mode_support_params.out_lowest_state_idx; + double min_fclk_mhz_for_urgent_workaround = (double)dml2->config.min_fclk_for_urgent_workaround_khz / 1000.0; + double max_frac_urgent = (double)dml2->config.max_frac_urgent_for_min_fclk_x1000 / 1000.0; + + if (min_fclk_mhz_for_urgent_workaround > 0.0 && max_frac_urgent > 0.0 && + (dml2->v20.dml_core_ctx.mp.FractionOfUrgentBandwidth > max_frac_urgent || + dml2->v20.dml_core_ctx.mp.FractionOfUrgentBandwidthImmediateFlip > max_frac_urgent)) { + unsigned int forced_lowest_state_idx = lowest_state_idx; + + while (forced_lowest_state_idx < dml2->v20.dml_core_ctx.states.num_states && + dml2->v20.dml_core_ctx.states.state_array[forced_lowest_state_idx].fabricclk_mhz <= min_fclk_mhz_for_urgent_workaround) { + forced_lowest_state_idx += 1; + } + lowest_state_idx = forced_lowest_state_idx; + } + out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.mp.Dispclk_calculated * 1000; out_clks.p_state_supported = s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported; if (in_dc->config.use_default_clock_table && diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 20b3970c0857..79bf2d757804 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -237,6 +237,8 @@ struct dml2_configuration_options { bool use_clock_dc_limits; bool gpuvm_enable; struct dml2_soc_bb *bb_from_dmub; + int max_frac_urgent_for_min_fclk_x1000; + int min_fclk_for_urgent_workaround_khz; }; /* diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 67ab8c1962ff..1ce0f9ecff9c 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -2152,8 +2152,9 @@ static bool dcn35_resource_construct( dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; dc->dml2_options.max_segments_per_hubp = 24; - dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ + dc->dml2_options.max_frac_urgent_for_min_fclk_x1000 = 900; + dc->dml2_options.min_fclk_for_urgent_workaround_khz = 400 * 1000; if (dc->config.sdpif_request_limit_words_per_umc == 0) dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/ From 020fccbe8fe7552e57804bba0c7578d227f561c2 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 13 Jun 2024 12:08:16 -0400 Subject: [PATCH 34/87] drm/amd/display: Make DML2.1 P-State method force per stream [WHY & HOW] Currently the force only works for a single display, make it so it can be forced per stream. Reviewed-by: Alvin Lee Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Dillon Varone Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- .../drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c | 2 +- drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 3 ++- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d0d1af451b64..e0334b573f2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1038,7 +1038,7 @@ struct dc_debug_options { bool force_chroma_subsampling_1tap; bool disable_422_left_edge_pixel; bool dml21_force_pstate_method; - uint32_t dml21_force_pstate_method_value; + uint32_t dml21_force_pstate_method_values[MAX_PIPES]; uint32_t dml21_disable_pstate_method_mask; union dmub_fams2_global_feature_config fams2_config; bool enable_legacy_clock_update; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c index d5ead0205053..06387b8b0aee 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c @@ -1000,7 +1000,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s /* apply forced pstate policy */ if (dml_ctx->config.pmo.force_pstate_method_enable) { dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy = - dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_value); + dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index 9c28304568d2..c310354cd5fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -47,7 +47,8 @@ static void dml21_apply_debug_options(const struct dc *in_dc, struct dml2_contex /* UCLK P-State options */ if (in_dc->debug.dml21_force_pstate_method) { dml_ctx->config.pmo.force_pstate_method_enable = true; - dml_ctx->config.pmo.force_pstate_method_value = in_dc->debug.dml21_force_pstate_method_value; + for (int i = 0; i < MAX_PIPES; i++) + dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i]; } else { dml_ctx->config.pmo.force_pstate_method_enable = false; } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 79bf2d757804..1e891a3297c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -230,7 +230,7 @@ struct dml2_configuration_options { struct socbb_ip_params_external *external_socbb_ip_params; struct { bool force_pstate_method_enable; - enum dml2_force_pstate_methods force_pstate_method_value; + enum dml2_force_pstate_methods force_pstate_method_values[MAX_PIPES]; } pmo; bool map_dc_pipes_with_callbacks; From 0dd1190faff7f7b389291266e118deb381b6c8d9 Mon Sep 17 00:00:00 2001 From: Daniel Sa Date: Thu, 13 Jun 2024 15:38:06 -0400 Subject: [PATCH 35/87] drm/amd/display: Fix reduced resolution and refresh rate [WHY] Some monitors are forced to a lower resolution and refresh rate after system restarts. [HOW] Some monitors may give invalid LTTPR information when queried such as indicating they have one DP lane instead of 4. If given an invalid DPCD version, skip over getting lttpr link rate and lane counts. Reviewed-by: Wenjing Liu Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Daniel Sa Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../dc/link/protocols/link_dp_capability.c | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index f1cac74dd7f7..46bb7a855bc2 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -409,9 +409,6 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) case LINK_RATE_HIGH3: lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; break; - default: - // Assume all LTTPRs support up to HBR3 to improve misbehaving sink interop - lttpr_max_link_rate = LINK_RATE_HIGH3; } if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20) @@ -2137,15 +2134,19 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). */ if (dp_is_lttpr_present(link)) { - if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) - max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; - lttpr_max_link_rate = get_lttpr_max_link_rate(link); - if (lttpr_max_link_rate < max_link_cap.link_rate) - max_link_cap.link_rate = lttpr_max_link_rate; + /* Some LTTPR devices do not report valid DPCD revisions, if so, do not take it's link cap into consideration. */ + if (link->dpcd_caps.lttpr_caps.revision.raw >= DPCD_REV_14) { + if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) + max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; + lttpr_max_link_rate = get_lttpr_max_link_rate(link); - if (!link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5) - is_uhbr13_5_supported = false; + if (lttpr_max_link_rate < max_link_cap.link_rate) + max_link_cap.link_rate = lttpr_max_link_rate; + + if (!link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5) + is_uhbr13_5_supported = false; + } DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n", __func__, From e1f4805bcc6b39e1c249777c237e419705266234 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 6 Jun 2024 15:42:36 -0600 Subject: [PATCH 36/87] drm/amd/display: Add null checks before accessing struct elements [WHAT] 1. is_pwrseq0 needs to check link before accessing link->link_index. 2. context is checked before accessing its bw_ctx.dml2 3. clk_mgr_base->bw_params is checked before clk_table.num_entries_per_cl This fixes 4 REVERSE_INULL issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 10 ++++++---- .../drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 10 ++++++---- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 2 +- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c | 4 +++- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 06f0c41ad6f1..3b10b24f5e23 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -163,9 +163,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); unsigned int num_levels; - struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; + struct clk_limit_num_entries *num_entries_per_clk; unsigned int i; + if (!clk_mgr_base->bw_params) + return; + + num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; + memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); clk_mgr_base->clks.p_state_change_support = true; clk_mgr_base->clks.prev_p_state_change_support = true; @@ -173,9 +178,6 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) clk_mgr->smu_present = false; clk_mgr->dpm_present = false; - if (!clk_mgr_base->bw_params) - return; - if (!clk_mgr_base->force_smu_not_present && dcn30_smu_get_smu_version(clk_mgr, &clk_mgr->smu_ver)) clk_mgr->smu_present = true; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index 70f06a7c882e..606b2411eee9 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -207,9 +207,14 @@ static void dcn401_build_wm_range_table(struct clk_mgr *clk_mgr) void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; + struct clk_limit_num_entries *num_entries_per_clk; unsigned int i; + if (!clk_mgr_base->bw_params) + return; + + num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; + memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); clk_mgr_base->clks.p_state_change_support = true; clk_mgr_base->clks.prev_p_state_change_support = true; @@ -217,9 +222,6 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) clk_mgr->smu_present = false; clk_mgr->dpm_present = false; - if (!clk_mgr_base->bw_params) - return; - if (!clk_mgr_base->force_smu_not_present && dcn30_smu_get_smu_version(clk_mgr, &clk_mgr->smu_ver)) clk_mgr->smu_present = true; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 54dd7e164635..8a8efe408a9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1084,7 +1084,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc struct dc_stream_status *stream_status = &context->stream_status[0]; int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000; bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency; - bool is_pwrseq0 = link->link_index == 0; + bool is_pwrseq0 = (link && link->link_index == 0); bool is_psr = (link && (link->psr_settings.psr_version == DC_PSR_VERSION_1 || link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) && !link->panel_config.psr.disable_psr); bool is_replay = link && link->replay_settings.replay_feature_enabled; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index f4038ac2e476..90bb6e718301 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -687,12 +687,14 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s static bool dml2_validate_only(struct dc_state *context) { - struct dml2_context *dml2 = context->bw_ctx.dml2; + struct dml2_context *dml2; unsigned int result = 0; if (!context || context->stream_count == 0) return true; + dml2 = context->bw_ctx.dml2; + /* Zero out before each call before proceeding */ memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch)); memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st)); From e1e75cf7334c0e31f4c37d715b964784d45685fa Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 13 Jun 2024 16:10:16 -0400 Subject: [PATCH 37/87] drm/amd/display: Program CURSOR_DST_X_OFFSET in viewport space [WHAT & HOW] According to register specifications, the CURSOR_DST_X_OFFSET is relative to the start of the data viewport, not RECOUT space. In this case we must transform the cursor coordinates passed to hubp401_cursor_set_position into viewport space to program this register. This fixes an underflow issue that occurs in scaled mode with low refresh rate. Reviewed-by: Nevenko Stupar Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c index a893160ae775..3f9ca9b40949 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c @@ -656,7 +656,9 @@ void hubp401_cursor_set_position( int y_pos = pos->y - param->recout.y; int rec_x_offset = x_pos - pos->x_hotspot; int rec_y_offset = y_pos - pos->y_hotspot; - uint32_t dst_x_offset; + int dst_x_offset; + int x_pos_viewport = x_pos * param->viewport.width / param->recout.width; + int x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width; uint32_t cur_en = pos->enable ? 1 : 0; hubp->curs_pos = *pos; @@ -668,7 +670,13 @@ void hubp401_cursor_set_position( if (hubp->curs_attr.address.quad_part == 0) return; - dst_x_offset = (rec_x_offset >= 0) ? rec_x_offset : 0; + /* Translate the x position of the cursor from rect + * space into viewport space. CURSOR_DST_X_OFFSET + * is the offset relative to viewport start position. + */ + dst_x_offset = x_pos_viewport - x_hot_viewport * + (1 + hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION); + dst_x_offset = (dst_x_offset >= 0) ? dst_x_offset : 0; dst_x_offset *= param->ref_clk_khz; dst_x_offset /= param->pixel_clk_khz; From 7210195f1bc51ba02cffa45b27ddb5c962faa606 Mon Sep 17 00:00:00 2001 From: Duncan Ma Date: Mon, 27 May 2024 16:59:59 -0400 Subject: [PATCH 38/87] drm/amd/display: Reset DSC memory status [WHY] When system exits idle state followed by enabling the display, DSC memory may still be forced in a deep sleep or shutdown state. Intermittent DSC corruption is seen when display is visible. [HOW] When DSC is enabled, reset dsc memory to force and disable status. Reviewed-by: Nicholas Kazlauskas Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Duncan Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c | 24 +++----- .../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h | 9 +++ .../drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c | 58 ++++++++++++++++++- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c index d6b2334d5364..75128fd34306 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c @@ -32,16 +32,6 @@ static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals); -/* Object I/F functions */ -static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); -static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); -static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, - struct dsc_optc_config *dsc_optc_cfg); -static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe); -static void dsc2_disable(struct display_stream_compressor *dsc); -static void dsc2_disconnect(struct display_stream_compressor *dsc); -static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc); - static const struct dsc_funcs dcn20_dsc_funcs = { .dsc_get_enc_caps = dsc2_get_enc_caps, .dsc_read_state = dsc2_read_state, @@ -156,7 +146,7 @@ void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz) /* this function read dsc related register fields to be logged later in dcn10_log_hw_state * into a dcn_dsc_state struct. */ -static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s) +void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s) { struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); @@ -173,7 +163,7 @@ static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_ds } -static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg) +bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg) { struct dsc_optc_config dsc_optc_cfg; struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); @@ -196,7 +186,7 @@ void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_conf DC_LOG_DSC("\tcolor_depth %d", config->color_depth); } -static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, +void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, struct dsc_optc_config *dsc_optc_cfg) { bool is_config_ok; @@ -233,7 +223,7 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc } -static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe) +void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe) { struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); int dsc_clock_en; @@ -258,7 +248,7 @@ static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe) } -static void dsc2_disable(struct display_stream_compressor *dsc) +void dsc2_disable(struct display_stream_compressor *dsc) { struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); int dsc_clock_en; @@ -277,14 +267,14 @@ static void dsc2_disable(struct display_stream_compressor *dsc) DSC_CLOCK_EN, 0); } -static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc) +void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc) { struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000); } -static void dsc2_disconnect(struct display_stream_compressor *dsc) +void dsc2_disconnect(struct display_stream_compressor *dsc) { struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h index a136b26c914c..a23308a785bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h @@ -597,5 +597,14 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps); +void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); +bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); +void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, + struct dsc_optc_config *dsc_optc_cfg); +void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe); +void dsc2_disable(struct display_stream_compressor *dsc); +void dsc2_disconnect(struct display_stream_compressor *dsc); +void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c index 71d2dff9986d..6f4f5a3c4861 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c @@ -27,6 +27,20 @@ #include "dcn35_dsc.h" #include "reg_helper.h" +static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe); + +static const struct dsc_funcs dcn35_dsc_funcs = { + .dsc_get_enc_caps = dsc2_get_enc_caps, + .dsc_read_state = dsc2_read_state, + .dsc_validate_stream = dsc2_validate_stream, + .dsc_set_config = dsc2_set_config, + .dsc_get_packed_pps = dsc2_get_packed_pps, + .dsc_enable = dsc35_enable, + .dsc_disable = dsc2_disable, + .dsc_disconnect = dsc2_disconnect, + .dsc_wait_disconnect_pending_clear = dsc2_wait_disconnect_pending_clear, +}; + /* Macro definitios for REG_SET macros*/ #define CTX \ dsc20->base.ctx @@ -49,9 +63,47 @@ void dsc35_construct(struct dcn20_dsc *dsc, const struct dcn35_dsc_shift *dsc_shift, const struct dcn35_dsc_mask *dsc_mask) { - dsc2_construct(dsc, ctx, inst, dsc_regs, - (const struct dcn20_dsc_shift *)(dsc_shift), - (const struct dcn20_dsc_mask *)(dsc_mask)); + dsc->base.ctx = ctx; + dsc->base.inst = inst; + dsc->base.funcs = &dcn35_dsc_funcs; + + dsc->dsc_regs = dsc_regs; + dsc->dsc_shift = (const struct dcn20_dsc_shift *)(dsc_shift); + dsc->dsc_mask = (const struct dcn20_dsc_mask *)(dsc_mask); + + dsc->max_image_width = 5184; +} + +static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe) +{ + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + int dsc_clock_en; + int dsc_fw_config; + int enabled_opp_pipe; + + DC_LOG_DSC("enable DSC %d at opp pipe %d", dsc->inst, opp_pipe); + + // TODO: After an idle exit, the HW default values for power control + // are changed intermittently due to unknown reasons. There are cases + // when dscc memory are still in shutdown state during enablement. + // Reset power control to hw default values. + REG_UPDATE_2(DSCC_MEM_POWER_CONTROL, + DSCC_MEM_PWR_FORCE, 0, + DSCC_MEM_PWR_DIS, 0); + + REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en); + REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe); + if ((dsc_clock_en || dsc_fw_config) && enabled_opp_pipe != opp_pipe) { + DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already enabled!", dsc->inst, enabled_opp_pipe); + ASSERT(0); + } + + REG_UPDATE(DSC_TOP_CONTROL, + DSC_CLOCK_EN, 1); + + REG_UPDATE_2(DSCRM_DSC_FORWARD_CONFIG, + DSCRM_DSC_FORWARD_EN, 1, + DSCRM_DSC_OPP_PIPE_SOURCE, opp_pipe); } void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable) From 4228900a64592f9c5d4f3b3d48d158948b08ec98 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Mon, 10 Jun 2024 12:34:25 -0400 Subject: [PATCH 39/87] drm/amd/display: Wait for double buffer update on ODM changes [WHAT & HOW] We must wait for ODM double buffer updates to complete before exiting the pipe update sequence or we may reduce DISPCLK and hit some transient underflow (pixel rate is reduced before the pipes have ODM enabled). Reviewed-by: Samson Tam Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 23 +++++++++++++++++++ .../amd/display/dc/inc/hw/timing_generator.h | 1 + .../amd/display/dc/optc/dcn10/dcn10_optc.h | 3 ++- .../amd/display/dc/optc/dcn32/dcn32_optc.c | 13 +++++++++++ .../amd/display/dc/optc/dcn32/dcn32_optc.h | 2 ++ .../amd/display/dc/optc/dcn401/dcn401_optc.c | 1 + .../amd/display/dc/optc/dcn401/dcn401_optc.h | 1 + 7 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 4d359bb9b1ec..36797ed7ad8c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -2227,6 +2227,29 @@ void dcn20_post_unlock_program_front_end( } } + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + /* When going from a smaller ODM slice count to larger, we must ensure double + * buffer update completes before we return to ensure we don't reduce DISPCLK + * before we've transitioned to 2:1 or 4:1 + */ + if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) && + resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) && + dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) { + int j = 0; + struct timing_generator *tg = pipe->stream_res.tg; + + + if (tg->funcs->get_double_buffer_pending) { + for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us + && tg->funcs->get_double_buffer_pending(tg); j++) + udelay(polling_interval_us); + } + } + } + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) dc->res_pool->hubbub->funcs->force_pstate_change_control( dc->res_pool->hubbub, false, false); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index cd4826f329c1..0f453452234c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -340,6 +340,7 @@ struct timing_generator_funcs { void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator *tg); void (*set_long_vtotal)(struct timing_generator *optc, const struct long_vtotal_params *params); void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator *tg); + bool (*get_double_buffer_pending)(struct timing_generator *tg); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h index e3e70c1db040..369a13244e5e 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h @@ -562,7 +562,8 @@ struct dcn_optc_registers { type OTG_CRC_DATA_FORMAT;\ type OTG_V_TOTAL_LAST_USED_BY_DRR;\ type OTG_DRR_TIMING_DBUF_UPDATE_PENDING;\ - type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING; + type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING;\ + type OPTC_DOUBLE_BUFFER_PENDING;\ #define TG_REG_FIELD_LIST_DCN3_2(type) \ type OTG_H_TIMING_DIV_MODE_MANUAL; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index 6c837409df42..00094f0e8470 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -297,6 +297,18 @@ static void optc32_set_drr( optc32_setup_manual_trigger(optc); } +bool optc32_get_double_buffer_pending(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t update_pending = 0; + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_DOUBLE_BUFFER_PENDING, + &update_pending); + + return (update_pending == 1); +} + static struct timing_generator_funcs dcn32_tg_funcs = { .validate_timing = optc1_validate_timing, .program_timing = optc1_program_timing, @@ -361,6 +373,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .is_two_pixels_per_container = optc1_is_two_pixels_per_container, + .get_double_buffer_pending = optc32_get_double_buffer_pending, }; void dcn32_timing_generator_init(struct optc *optc1) diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h index 0c2c14695561..665d7c52f67c 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h @@ -116,6 +116,7 @@ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ @@ -184,5 +185,6 @@ void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combi void optc32_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing); void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *tg); +bool optc32_get_double_buffer_pending(struct timing_generator *optc); #endif /* __DC_OPTC_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c index fd1c8b45c40e..9f5c2efa7560 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c @@ -459,6 +459,7 @@ static struct timing_generator_funcs dcn401_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .is_two_pixels_per_container = optc1_is_two_pixels_per_container, + .get_double_buffer_pending = optc32_get_double_buffer_pending, }; void dcn401_timing_generator_init(struct optc *optc1) diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h index 1671fdd5061c..3114ecef332a 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h @@ -94,6 +94,7 @@ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ From adcd67e0bbea5fb504d6de50e5ccf74ebf96bc29 Mon Sep 17 00:00:00 2001 From: Nevenko Stupar Date: Thu, 13 Jun 2024 17:19:42 -0400 Subject: [PATCH 40/87] drm/amd/display: Fix cursor issues with ODMs and magnification [WHY & HOW] Adjust hot spot positions between ODM slices when cursor magnification is used. Reviewed-by: Sridevi Arvindekar Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Nevenko Stupar Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 79a911e1a09a..5306c8c170c5 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1177,6 +1177,15 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) if (x_pos < 0) { pos_cpy.x_hotspot -= x_pos; + if ((odm_combine_on) && (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION)) { + if (hubp->curs_attr.width <= 128) { + pos_cpy.x_hotspot /= 2; + pos_cpy.x_hotspot += 1; + } else { + pos_cpy.x_hotspot /= 2; + pos_cpy.x_hotspot += 2; + } + } x_pos = 0; } From 0b8de7a04f7c14abd28bd8b9f3e1e5737a3702e2 Mon Sep 17 00:00:00 2001 From: Ryan Seto Date: Fri, 14 Jun 2024 14:23:41 -0400 Subject: [PATCH 41/87] drm/amd/display: Add HW cursor visual confirm [WHY] Added HW cursor visual confirm [HOW] Added visual confirm logic when programming cursor positions. HW is programmed on cursor updates since cursor can change without flips. Reviewed-by: Alvin Lee Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Ryan Seto Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 29 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 9b24f448ce50..de0633f98158 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -416,6 +416,35 @@ bool dc_stream_program_cursor_position( if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle) dc_allow_idle_optimizations(dc, true); + /* apply/update visual confirm */ + if (dc->debug.visual_confirm == VISUAL_CONFIRM_HW_CURSOR) { + /* update software state */ + uint32_t color_value = MAX_TG_COLOR_VALUE; + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + + /* adjust visual confirm color for all pipes with current stream */ + if (stream == pipe_ctx->stream) { + if (stream->cursor_position.enable) { + pipe_ctx->visual_confirm_color.color_r_cr = color_value; + pipe_ctx->visual_confirm_color.color_g_y = 0; + pipe_ctx->visual_confirm_color.color_b_cb = 0; + } else { + pipe_ctx->visual_confirm_color.color_r_cr = 0; + pipe_ctx->visual_confirm_color.color_g_y = 0; + pipe_ctx->visual_confirm_color.color_b_cb = color_value; + } + + /* programming hardware */ + if (pipe_ctx->plane_state) + dc->hwss.update_visual_confirm_color(dc, pipe_ctx, + pipe_ctx->plane_res.hubp->mpcc_id); + } + } + } + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e0334b573f2d..64241de70f15 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -476,6 +476,7 @@ enum visual_confirm { VISUAL_CONFIRM_SUBVP = 14, VISUAL_CONFIRM_MCLK_SWITCH = 16, VISUAL_CONFIRM_FAMS2 = 19, + VISUAL_CONFIRM_HW_CURSOR = 20, }; enum dc_psr_power_opts { From 4b22869f76563ce1e10858d2ae3305affa8d4a6a Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 14 Jun 2024 11:01:59 -0400 Subject: [PATCH 42/87] drm/amd/display: Remove a redundant check in authenticated_dp [WHY] mod_hdcp_execute_and_set returns (*status == MOD_HDCP_STATUS_SUCCESS). When it return 0, it is guaranteed that status == MOD_HDCP_STATUS_SUCCESS will be evaluated as false. Since now we are using goto out already, all 3 if (status == MOD_HDCP_STATUS_SUCCESS) clauses are guaranteed to enter. Therefore we are removing the if statements due to redundancy. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/modules/hdcp/hdcp1_execution.c | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index d77836cef563..1e495e884484 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -432,21 +432,18 @@ static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp, goto out; } - if (status == MOD_HDCP_STATUS_SUCCESS) - if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, - &input->bstatus_read, &status, - hdcp, "bstatus_read")) - goto out; - if (status == MOD_HDCP_STATUS_SUCCESS) - if (!mod_hdcp_execute_and_set(check_link_integrity_dp, - &input->link_integrity_check, &status, - hdcp, "link_integrity_check")) - goto out; - if (status == MOD_HDCP_STATUS_SUCCESS) - if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, - &input->reauth_request_check, &status, - hdcp, "reauth_request_check")) - goto out; + if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, + &input->bstatus_read, &status, + hdcp, "bstatus_read")) + goto out; + if (!mod_hdcp_execute_and_set(check_link_integrity_dp, + &input->link_integrity_check, &status, + hdcp, "link_integrity_check")) + goto out; + if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, + &input->reauth_request_check, &status, + hdcp, "reauth_request_check")) + goto out; out: return status; } From 569d7db70e5dcf13fbf072f10e9096577ac1e565 Mon Sep 17 00:00:00 2001 From: Ryan Seto Date: Fri, 14 Jun 2024 14:56:15 -0400 Subject: [PATCH 43/87] drm/amd/display: Adjust reg field for DSC wait for disconnect [WHY] DSC was waiting for the wrong field to disconnect cleanly. [HOW] Changed field the DSC disconnect was waiting on. Reviewed-by: Wenjing Liu Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Ryan Seto Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h | 4 +++- drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c | 2 +- drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h index a23308a785bc..1fb90b52b814 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h @@ -454,7 +454,9 @@ type DSCCIF_UPDATE_TAKEN_ACK; \ type DSCRM_DSC_FORWARD_EN; \ type DSCRM_DSC_OPP_PIPE_SOURCE; \ - type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING + type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING; \ + type DSCRM_DSC_FORWARD_EN_STATUS + struct dcn20_dsc_registers { uint32_t DSC_TOP_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c index 52f23bb554af..6acb6699f146 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c @@ -208,7 +208,7 @@ static void dsc401_wait_disconnect_pending_clear(struct display_stream_compresso { struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc); - REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000); + REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN_STATUS, 0, 2, 50000); } static void dsc401_disconnect(struct display_stream_compressor *dsc) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h index 2143e81ca22a..3c9fa8988974 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h @@ -196,7 +196,8 @@ DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \ DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \ DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \ - DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh) + DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh), \ + DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN_STATUS, mask_sh) struct dcn401_dsc_registers { uint32_t DSC_TOP_CONTROL; From 58acedd7849a238d2d06430b030b365cf069cca8 Mon Sep 17 00:00:00 2001 From: Relja Vojvodic Date: Fri, 14 Jun 2024 16:49:44 -0400 Subject: [PATCH 44/87] drm/amd/display: Fix 1DLUT setting for NL SDR blending [WHY] Enabling NL SDR blending caused the 1D LUTs to be set/populated in two different functions. This caused flickering as the LUT was set differently by the two functions, one of which should only have been modifying the 1D LUT if 3D LUT was enabled. [HOW] Added check to only modify the 1D LUT in populate_mcm if 3D LUT was enabled. Added blend_tf function update for non-main planes if the 3D LUT path was taken. Reviewed-by: Ilya Bakoulin Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Relja Vojvodic Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 5306c8c170c5..b5a02a8fc9d8 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -502,7 +502,7 @@ void dcn401_populate_mcm_luts(struct dc *dc, dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); /* 1D LUT */ - if (mcm_luts.lut1d_func) { + if (mcm_luts.lut1d_func && lut3d_xable != MCM_LUT_DISABLE) { memset(&m_lut_params, 0, sizeof(m_lut_params)); if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL) m_lut_params.pwl = &mcm_luts.lut1d_func->pwl; @@ -674,7 +674,7 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx, mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE; // 1D LUT - if (!plane_state->mcm_lut1d_enable) { + if (plane_state->mcm_shaper_3dlut_setting == DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL) { if (plane_state->blend_tf.type == TF_TYPE_HWPWL) lut_params = &plane_state->blend_tf.pwl; else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { From 9862ef7bae47b9292a38a0a1b30bff7f56d7815b Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 13 Jun 2024 10:41:51 -0400 Subject: [PATCH 45/87] drm/amd/display: Use periodic detection for ipx/headless [WHY] Hotplug is not detected in headless (no eDP) mode on dcn35x. With no display dcn35x goes to IPS2 powersaving state where HPD interrupt is not handled. [HOW] Use idle worker thread for periodic detection of HPD in headless mode. Reviewed-by: Aurabindo Pillai Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Hung Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 ++ .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 50 +++++++++++++++---- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 5 +- 3 files changed, 47 insertions(+), 11 deletions(-) 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 dfcbc1970fe6..5fd1b6b44577 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -989,4 +989,7 @@ void *dm_allocate_gpu_mem(struct amdgpu_device *adev, enum dc_gpu_mem_alloc_type type, size_t size, long long *addr); + +bool amdgpu_dm_is_headless(struct amdgpu_device *adev); + #endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index e16eecb146fd..99014339aaa3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -162,33 +162,63 @@ static void amdgpu_dm_crtc_set_panel_sr_feature( } } +bool amdgpu_dm_is_headless(struct amdgpu_device *adev) +{ + struct drm_connector *connector; + struct drm_connector_list_iter iter; + struct drm_device *dev; + bool is_headless = true; + + if (adev == NULL) + return true; + + dev = adev->dm.ddev; + + drm_connector_list_iter_begin(dev, &iter); + drm_for_each_connector_iter(connector, &iter) { + + if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + continue; + + if (connector->status == connector_status_connected) { + is_headless = false; + break; + } + } + drm_connector_list_iter_end(&iter); + return is_headless; +} + static void amdgpu_dm_idle_worker(struct work_struct *work) { struct idle_workqueue *idle_work; idle_work = container_of(work, struct idle_workqueue, work); idle_work->dm->idle_workqueue->running = true; - fsleep(HPD_DETECTION_PERIOD_uS); - mutex_lock(&idle_work->dm->dc_lock); - while (idle_work->enable) { - if (!idle_work->dm->dc->idle_optimizations_allowed) - break; + while (idle_work->enable) { + fsleep(HPD_DETECTION_PERIOD_uS); + mutex_lock(&idle_work->dm->dc_lock); + if (!idle_work->dm->dc->idle_optimizations_allowed) { + mutex_unlock(&idle_work->dm->dc_lock); + break; + } dc_allow_idle_optimizations(idle_work->dm->dc, false); mutex_unlock(&idle_work->dm->dc_lock); fsleep(HPD_DETECTION_TIME_uS); mutex_lock(&idle_work->dm->dc_lock); - if (!amdgpu_dm_psr_is_active_allowed(idle_work->dm)) + if (!amdgpu_dm_is_headless(idle_work->dm->adev) && + !amdgpu_dm_psr_is_active_allowed(idle_work->dm)) { + mutex_unlock(&idle_work->dm->dc_lock); break; + } - dc_allow_idle_optimizations(idle_work->dm->dc, true); + if (idle_work->enable) + dc_allow_idle_optimizations(idle_work->dm->dc, true); mutex_unlock(&idle_work->dm->dc_lock); - fsleep(HPD_DETECTION_PERIOD_uS); - mutex_lock(&idle_work->dm->dc_lock); } - mutex_unlock(&idle_work->dm->dc_lock); idle_work->dm->idle_workqueue->running = false; } 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 adbf560d6a74..97614947d75b 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 @@ -1239,8 +1239,11 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) { struct amdgpu_device *adev = ctx->driver_context; - if (adev->dm.idle_workqueue) + if (adev->dm.idle_workqueue) { adev->dm.idle_workqueue->enable = enable; + if (enable && !adev->dm.idle_workqueue->running && amdgpu_dm_is_headless(adev)) + schedule_work(&adev->dm.idle_workqueue->work); + } } void dm_helpers_dp_mst_update_branch_bandwidth( From c53bb80f49a7cea933ccb4b7a458e6983820e9a5 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Jun 2024 10:43:12 -0600 Subject: [PATCH 46/87] drm/amd/display: Ensure curve to hw translation succeed [WHAT & HOW] Check cm3_helper_translate_curve_to_hw_format runs successfully so the regamma_params is valid and can be used. Also revmoed two result assignments. This fixes 2 CHECKED_RETURN UNUSED_VALUE issues reported by Coverity. Reviewed-by: Harry Wentland Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 5 ++++- drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c index bcacfd893cf7..eaeeade31ed7 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c @@ -228,8 +228,11 @@ bool dcn30_set_blend_lut( if (plane_state->blend_tf.type == TF_TYPE_HWPWL) blend_lut = &plane_state->blend_tf.pwl; else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { - cm3_helper_translate_curve_to_hw_format( + result = cm3_helper_translate_curve_to_hw_format( &plane_state->blend_tf, &dpp_base->regamma_params, false); + if (!result) + return result; + blend_lut = &dpp_base->regamma_params; } result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index fe62478fbcde..05d8f81daa06 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -483,11 +483,14 @@ bool dcn32_set_mcm_luts( if (plane_state->blend_tf.type == TF_TYPE_HWPWL) lut_params = &plane_state->blend_tf.pwl; else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { - cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf, + result = cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf, &dpp_base->regamma_params, false); + if (!result) + return result; + lut_params = &dpp_base->regamma_params; } - result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id); + mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id); lut_params = NULL; // Shaper @@ -501,7 +504,7 @@ bool dcn32_set_mcm_luts( lut_params = &dpp_base->shaper_params; } - result = mpc->funcs->program_shaper(mpc, lut_params, mpcc_id); + mpc->funcs->program_shaper(mpc, lut_params, mpcc_id); // 3D if (plane_state->lut3d_func.state.bits.initialized == 1) From 673f816b9e1e92d1f70e1bf5f21b531e0ff9ad6c Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Tue, 11 Jun 2024 11:45:42 -0600 Subject: [PATCH 47/87] drm/amd/display: Validate function returns [WHAT & HOW] Function return values must be checked before data can be used in subsequent functions. This fixes 4 CHECKED_RETURN issues reported by Coverity. Reviewed-by: Harry Wentland Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 7 +++++-- drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c | 3 ++- .../drm/amd/display/dc/link/protocols/link_dp_training.c | 3 +-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index b2051c4dd7b6..ded13026c8ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -245,7 +245,9 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun if (status == DMUB_STATUS_POWER_STATE_D3) return false; - dmub_srv_wait_for_idle(dmub, 100000); + status = dmub_srv_wait_for_idle(dmub, 100000); + if (status != DMUB_STATUS_OK) + return false; /* Requeue the command. */ status = dmub_srv_cmd_queue(dmub, &cmd_list[i]); @@ -517,7 +519,8 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi union dmub_rb_cmd cmd = { 0 }; unsigned int panel_inst = 0; - dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst); + if (!dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst)) + return; memset(&cmd, 0, sizeof(cmd)); diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c index 8901bd80f7d1..5c6f7ddafd6b 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c @@ -616,7 +616,8 @@ static bool hubbub2_program_watermarks( hubbub1->base.ctx->dc->clk_mgr->clks.p_state_change_support == false) safe_to_lower = true; - hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); + if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 5a0f574056d4..988999c44475 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -1663,8 +1663,7 @@ bool perform_link_training_with_retries( if (status == LINK_TRAINING_ABORT) { enum dc_connection_type type = dc_connection_none; - link_detect_connection_type(link, &type); - if (type == dc_connection_none) { + if (link_detect_connection_type(link, &type) && type == dc_connection_none) { DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__); break; } From 4de670dcdef04feee864a110dd6c1737f29f6dd0 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 14 Jun 2024 19:10:40 -0600 Subject: [PATCH 48/87] drm/amd/display: Remove always true condition [WHAT & HOW] advanced_pstate_switching was initialized to false and never assigned to another value; as a result !advanced_pstate_switching is always true and should be removed. This fixes 2 DEADCODE issues reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 90bb6e718301..60e2bf4ae6de 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -442,7 +442,6 @@ static bool optimize_pstate_with_svp_and_drr(struct dml2_context *dml2, struct d bool result = false; int drr_display_index = 0, non_svp_streams = 0; bool force_svp = dml2->config.svp_pstate.force_enable_subvp; - bool advanced_pstate_switching = false; display_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false; display_state->bw_ctx.bw.dcn.legacy_svp_drr_stream_index_valid = false; @@ -451,8 +450,7 @@ static bool optimize_pstate_with_svp_and_drr(struct dml2_context *dml2, struct d if (!result) { pstate_optimization_done = true; - } else if (!advanced_pstate_switching || - (s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported && !force_svp)) { + } else if (s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported && !force_svp) { pstate_optimization_success = true; pstate_optimization_done = true; } From bc180e26837ec238d05d7c7ac05d73ee35dc1076 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 14 Jun 2024 19:06:59 -0600 Subject: [PATCH 49/87] drm/amd/display: Remove duplicate null check [WHAT & HOW] The same display null check was a few lines above. This fixes 1 DEADCODE issue reported by Coverity. Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index 7c9805705fd3..8c137d7c032e 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -513,9 +513,6 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp) hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); - if (!display) - return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; - hdcp_cmd->in_msg.hdcp2_create_session_v2.display_handle = display->index; if (hdcp->connection.link.adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0) From 2d072b445622b90f8a961c0376887120da75221f Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 14 Jun 2024 15:42:55 -0400 Subject: [PATCH 50/87] drm/amd: Add reg definitions for DCN401 DCC [WHAT] Add the necessary register definitions to enable DCC on DCN4x Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../include/asic_reg/dcn/dcn_4_1_0_sh_mask.h | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h index 0c68f5d818bb..f42a276499cd 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h @@ -6430,6 +6430,28 @@ //DCHUBBUB_SDPIF_MEM_PWR_STATUS #define DCHUBBUB_SDPIF_MEM_PWR_STATUS__DCHUBBUB_SDPIF_MEM_PWR_STATE__SHIFT 0x0 #define DCHUBBUB_SDPIF_MEM_PWR_STATUS__DCHUBBUB_SDPIF_MEM_PWR_STATE_MASK 0x00000003L +//DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE0__SHIFT 0x0 +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE1__SHIFT 0x1 +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE2__SHIFT 0x2 +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE3__SHIFT 0x3 +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE0__SHIFT 0xc +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE1__SHIFT 0xd +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE2__SHIFT 0xe +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE3__SHIFT 0xf +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_ENABLE__SHIFT 0x1c +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_VREADY_MODE__SHIFT 0x1f +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE0_MASK 0x00000001L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE1_MASK 0x00000002L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE2_MASK 0x00000004L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_FLIP_AWAY_MISSING_PIPE3_MASK 0x00000008L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE0_MASK 0x00001000L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE1_MASK 0x00002000L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE2_MASK 0x00004000L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_CLEAR_PIPE3_MASK 0x00008000L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_ERR_ENABLE_MASK 0x10000000L +#define DCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL__DCHUBBUB_SDPIF_MCACHEID_INV_VREADY_MODE_MASK 0x80000000L + // addressBlock: dcn_dcec_dchubbubl_hubbub_ret_path_dispdec @@ -7084,6 +7106,11 @@ #define HUBP0_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10 #define HUBP0_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL #define HUBP0_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L +//HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE +#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0 +#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10 +#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL +#define HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L //HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0 #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10 @@ -7244,6 +7271,23 @@ #define HUBP0_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc #define HUBP0_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL #define HUBP0_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L +//HUBP0_DCHUBP_MCACHEID_CONFIG +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0 +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4 +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8 +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10 +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14 +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18 +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L +#define HUBP0_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L //HUBP0_HUBP_MEASURE_WIN_CTRL_DCFCLK #define HUBP0_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0 #define HUBP0_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4 @@ -8013,6 +8057,11 @@ #define HUBP1_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10 #define HUBP1_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL #define HUBP1_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L +//HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE +#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0 +#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10 +#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL +#define HUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L //HUBP1_DCSURF_PRI_VIEWPORT_DIMENSION #define HUBP1_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0 #define HUBP1_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10 @@ -8173,6 +8222,23 @@ #define HUBP1_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc #define HUBP1_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL #define HUBP1_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L +//HUBP1_DCHUBP_MCACHEID_CONFIG +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0 +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4 +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8 +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10 +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14 +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18 +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L +#define HUBP1_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L //HUBP1_HUBP_MEASURE_WIN_CTRL_DCFCLK #define HUBP1_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0 #define HUBP1_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4 @@ -8942,6 +9008,11 @@ #define HUBP2_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10 #define HUBP2_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL #define HUBP2_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L +//HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE +#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0 +#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10 +#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL +#define HUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L //HUBP2_DCSURF_PRI_VIEWPORT_DIMENSION #define HUBP2_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0 #define HUBP2_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10 @@ -9102,6 +9173,23 @@ #define HUBP2_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc #define HUBP2_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL #define HUBP2_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L +//HUBP2_DCHUBP_MCACHEID_CONFIG +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0 +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4 +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8 +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10 +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14 +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18 +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L +#define HUBP2_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L //HUBP2_HUBP_MEASURE_WIN_CTRL_DCFCLK #define HUBP2_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0 #define HUBP2_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4 @@ -9871,6 +9959,11 @@ #define HUBP3_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START__SHIFT 0x10 #define HUBP3_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_X_START_MASK 0x0000FFFFL #define HUBP3_DCSURF_PRI_VIEWPORT_START__PRI_VIEWPORT_Y_START_MASK 0xFFFF0000L +//HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE +#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE__SHIFT 0x0 +#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C__SHIFT 0x10 +#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_MASK 0x0000FFFFL +#define HUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE__VIEWPORT_MCACHE_SPLIT_COORDINATE_C_MASK 0xFFFF0000L //HUBP3_DCSURF_PRI_VIEWPORT_DIMENSION #define HUBP3_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT 0x0 #define HUBP3_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10 @@ -10031,6 +10124,23 @@ #define HUBP3_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1__SHIFT 0xc #define HUBP3_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_CURR_S1_MASK 0x00000FFFL #define HUBP3_DCHUBP_MALL_SUB_VP2__SUB_VP_HEIGHT_NEXT_S1_MASK 0x00FFF000L +//HUBP3_DCHUBP_MCACHEID_CONFIG +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0__SHIFT 0x0 +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0__SHIFT 0x4 +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1__SHIFT 0x8 +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1__SHIFT 0xc +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0__SHIFT 0x10 +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0__SHIFT 0x14 +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1__SHIFT 0x18 +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1__SHIFT 0x1c +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P0_MASK 0x0000000FL +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P0_MASK 0x000000F0L +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_1H_P1_MASK 0x00000F00L +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_REG_READ_2H_P1_MASK 0x0000F000L +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P0_MASK 0x000F0000L +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P0_MASK 0x00F00000L +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_1H_P1_MASK 0x0F000000L +#define HUBP3_DCHUBP_MCACHEID_CONFIG__MCACHEID_MALL_PREF_2H_P1_MASK 0xF0000000L //HUBP3_HUBP_MEASURE_WIN_CTRL_DCFCLK #define HUBP3_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_EN_DCFCLK__SHIFT 0x0 #define HUBP3_HUBP_MEASURE_WIN_CTRL_DCFCLK__HUBP_MEASURE_WIN_PERIOD_M1_DCFCLK__SHIFT 0x4 From 78f608d7aff05c245bf0aab00ce7273a7d9f04b9 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 14 Jun 2024 15:44:12 -0400 Subject: [PATCH 51/87] drm/amd/display: Enable DCC on DCN401 [WHAT] Add registers and entry points to enable DCC on DCN4x Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Hung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 + .../drm/amd/display/dc/core/dc_hw_sequencer.c | 11 + drivers/gpu/drm/amd/display/dc/dc.h | 4 + .../drm/amd/display/dc/dml2/dml2_wrapper.c | 6 + .../drm/amd/display/dc/dml2/dml2_wrapper.h | 2 +- .../display/dc/hubbub/dcn30/dcn30_hubbub.c | 3 + .../display/dc/hubbub/dcn31/dcn31_hubbub.c | 3 + .../display/dc/hubbub/dcn401/dcn401_hubbub.c | 280 ++++++++++++++++++ .../display/dc/hubbub/dcn401/dcn401_hubbub.h | 5 + .../amd/display/dc/hubp/dcn20/dcn20_hubp.h | 14 + .../amd/display/dc/hubp/dcn401/dcn401_hubp.c | 21 ++ .../amd/display/dc/hubp/dcn401/dcn401_hubp.h | 14 +- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 4 + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 25 ++ .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 2 + .../amd/display/dc/hwss/dcn401/dcn401_init.c | 1 + .../drm/amd/display/dc/hwss/hw_sequencer.h | 9 + .../gpu/drm/amd/display/dc/inc/core_types.h | 3 + .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 1 + .../dc/resource/dcn401/dcn401_resource.c | 9 + .../dc/resource/dcn401/dcn401_resource.h | 2 + 22 files changed, 433 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a4ba6f99cd34..85a2ef82afa5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1264,6 +1264,9 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false); dc->hwss.post_unlock_program_front_end(dc, dangling_context); } + + if (dc->res_pool->funcs->prepare_mcache_programming) + dc->res_pool->funcs->prepare_mcache_programming(dc, dangling_context); if (dc->hwss.program_front_end_for_ctx) { dc->hwss.interdependent_update_lock(dc, dc->current_state, true); dc->hwss.program_front_end_for_ctx(dc, dangling_context); @@ -2037,6 +2040,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c } /* Program all planes within new context*/ + if (dc->res_pool->funcs->prepare_mcache_programming) + dc->res_pool->funcs->prepare_mcache_programming(dc, context); if (dc->hwss.program_front_end_for_ctx) { dc->hwss.interdependent_update_lock(dc, context, true); dc->hwss.program_front_end_for_ctx(dc, context); @@ -3884,6 +3889,9 @@ static void commit_planes_for_stream(struct dc *dc, odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU; } + if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming) + dc->res_pool->funcs->prepare_mcache_programming(dc, context); + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program && top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { @@ -3903,6 +3911,10 @@ static void commit_planes_for_stream(struct dc *dc, top_pipe_to_program->stream_res.tg); } + if (dc->hwss.wait_for_dcc_meta_propagation) { + dc->hwss.wait_for_dcc_meta_propagation(dc, top_pipe_to_program); + } + if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 5037474bf95c..87e36d51c56d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -595,6 +595,12 @@ void hwss_build_fast_sequence(struct dc *dc, if (!plane || !stream) return; + if (dc->hwss.wait_for_dcc_meta_propagation) { + block_sequence[*num_steps].params.wait_for_dcc_meta_propagation_params.dc = dc; + block_sequence[*num_steps].params.wait_for_dcc_meta_propagation_params.top_pipe_to_program = pipe_ctx; + block_sequence[*num_steps].func = HUBP_WAIT_FOR_DCC_META_PROP; + (*num_steps)++; + } if (dc->hwss.subvp_pipe_control_lock_fast) { block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc; block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true; @@ -835,6 +841,11 @@ void hwss_execute_sequence(struct dc *dc, case DMUB_SUBVP_SAVE_SURF_ADDR: hwss_subvp_save_surf_addr(params); break; + case HUBP_WAIT_FOR_DCC_META_PROP: + dc->hwss.wait_for_dcc_meta_propagation( + params->wait_for_dcc_meta_propagation_params.dc, + params->wait_for_dcc_meta_propagation_params.top_pipe_to_program); + break; case DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST: dc->hwss.fams2_global_control_lock_fast(params); break; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 64241de70f15..40f183816e31 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -333,6 +333,9 @@ struct dc_dcc_setting { uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN 3.0 uint32_t dcc_256_128_128 : 1; //available starting with DCN 3.0 uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN 3.0 (the best compression case) + uint32_t dcc_256_256 : 1; //available in ASICs starting with DCN 4.0x (the best compression case) + uint32_t dcc_256_128 : 1; //available in ASICs starting with DCN 4.0x + uint32_t dcc_256_64 : 1; //available in ASICs starting with DCN 4.0x (the worst compression case) } dcc_controls; }; @@ -1037,6 +1040,7 @@ struct dc_debug_options { unsigned int static_screen_wait_frames; uint32_t pwm_freq; bool force_chroma_subsampling_1tap; + unsigned int dcc_meta_propagation_delay_us; bool disable_422_left_edge_pixel; bool dml21_force_pstate_method; uint32_t dml21_force_pstate_method_values[MAX_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 60e2bf4ae6de..c58235121474 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -821,6 +821,12 @@ void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2, *dram_clk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.DRAMClockChangeSupport[0]; } +void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2) +{ + if (dml2->architecture == dml2_architecture_21) + dml21_prepare_mcache_programming(in_dc, context, dml2); +} + void dml2_copy(struct dml2_context *dst_dml2, struct dml2_context *src_dml2) { diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 1e891a3297c2..6e3d52eb45c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -303,5 +303,5 @@ bool dml2_validate(const struct dc *in_dc, */ void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2, unsigned int *fclk_change_support, unsigned int *dram_clk_change_support); - +void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2); #endif //_DML2_WRAPPER_H_ diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c index 6a5af3da4b45..fe741100c0f8 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c @@ -339,6 +339,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub, return false; switch (dcc_control) { + case dcc_control__256_256: case dcc_control__256_256_xxx: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 256; @@ -346,6 +347,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub, output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1; output->grph.rgb.dcc_controls.dcc_256_128_128 = 1; break; + case dcc_control__256_128: case dcc_control__128_128_xxx: output->grph.rgb.max_uncompressed_blk_size = 128; output->grph.rgb.max_compressed_blk_size = 128; @@ -353,6 +355,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub, output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1; output->grph.rgb.dcc_controls.dcc_256_128_128 = 1; break; + case dcc_control__256_64: case dcc_control__256_64_64: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 64; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c index b906db6e7355..7fb5523f9722 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c @@ -866,6 +866,7 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub, return false; switch (dcc_control) { + case dcc_control__256_256: case dcc_control__256_256_xxx: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 256; @@ -881,12 +882,14 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub, output->grph.rgb.dcc_controls.dcc_256_128_128 = 1; break; case dcc_control__256_64_64: + case dcc_control__256_64: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 64; output->grph.rgb.independent_64b_blks = true; output->grph.rgb.dcc_controls.dcc_256_64_64 = 1; break; case dcc_control__256_128_128: + case dcc_control__256_128: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 128; output->grph.rgb.independent_64b_blks = false; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c index 054607c944a3..5126d603f0b1 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c @@ -824,6 +824,285 @@ void hubbub401_det_request_size( } } } +bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + struct dc *dc = hubbub->ctx->dc; + /* DCN4_Programming_Guide_DCHUB.docx, Section 5.11.2.2 */ + enum dcc_control dcc_control; + unsigned int plane0_bpe, plane1_bpe; + enum segment_order segment_order_horz, segment_order_vert; + enum segment_order p1_segment_order_horz, p1_segment_order_vert; + bool req128_horz_wc, req128_vert_wc; + unsigned int plane0_width = 0, plane0_height = 0, plane1_width = 0, plane1_height = 0; + bool p1_req128_horz_wc, p1_req128_vert_wc, is_dual_plane; + + memset(output, 0, sizeof(*output)); + + if (dc->debug.disable_dcc == DCC_DISABLE) + return false; + + switch (input->format) { + default: + is_dual_plane = false; + + plane1_width = 0; + plane1_height = 0; + + if (input->surface_size.width > 6144 + 16) + plane0_width = 6160; + else + plane0_width = input->surface_size.width; + + if (input->surface_size.height > 6144 + 16) + plane0_height = 6160; + else + plane0_height = input->surface_size.height; + + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + is_dual_plane = true; + + if (input->surface_size.width > 7680 + 16) + plane0_width = 7696; + else + plane0_width = input->surface_size.width; + + if (input->surface_size.height > 4320 + 16) + plane0_height = 4336; + else + plane0_height = input->surface_size.height; + + if (input->plane1_size.width > 7680 + 16) + plane1_width = 7696 / 2; + else + plane1_width = input->plane1_size.width; + + if (input->plane1_size.height > 4320 + 16) + plane1_height = 4336 / 2; + else + plane1_height = input->plane1_size.height; + + break; + + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: + is_dual_plane = true; + + if (input->surface_size.width > 5120 + 16) + plane0_width = 5136; + else + plane0_width = input->surface_size.width; + + if (input->surface_size.height > 5120 + 16) + plane0_height = 5136; + else + plane0_height = input->surface_size.height; + + if (input->plane1_size.width > 5120 + 16) + plane1_width = 5136; + else + plane1_width = input->plane1_size.width; + + if (input->plane1_size.height > 5120 + 16) + plane1_height = 5136; + else + plane1_height = input->plane1_size.height; + + break; + } + + if (!hubbub->funcs->dcc_support_pixel_format_plane0_plane1(input->format, + &plane0_bpe, &plane1_bpe)) + return false; + + /* Find plane0 DCC Controls */ + if (!is_dual_plane) { + + if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3, + input->plane0_pitch, plane0_bpe, + &segment_order_horz, &segment_order_vert)) + return false; + + hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format, + plane0_height, plane0_width, plane0_bpe, + plane1_height, plane1_width, plane1_bpe, + &req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc); + + if (!req128_horz_wc && !req128_vert_wc) { + dcc_control = dcc_control__256_256; + } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { + if (!req128_horz_wc) + dcc_control = dcc_control__256_256; + else if (segment_order_horz == segment_order__contiguous) + dcc_control = dcc_control__256_128; + else + dcc_control = dcc_control__256_64; + } else if (input->scan == SCAN_DIRECTION_VERTICAL) { + if (!req128_vert_wc) + dcc_control = dcc_control__256_256; + else if (segment_order_vert == segment_order__contiguous) + dcc_control = dcc_control__256_128; + else + dcc_control = dcc_control__256_64; + } else { + if ((req128_horz_wc && + segment_order_horz == segment_order__non_contiguous) || + (req128_vert_wc && + segment_order_vert == segment_order__non_contiguous)) + /* access_dir not known, must use most constraining */ + dcc_control = dcc_control__256_64; + else + /* req128 is true for either horz and vert + * but segment_order is contiguous + */ + dcc_control = dcc_control__256_128; + } + + if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && + dcc_control != dcc_control__256_256) + return false; + + switch (dcc_control) { + case dcc_control__256_256: + output->grph.rgb.dcc_controls.dcc_256_256 = 1; + output->grph.rgb.dcc_controls.dcc_256_128 = 1; + output->grph.rgb.dcc_controls.dcc_256_64 = 1; + break; + case dcc_control__256_128: + output->grph.rgb.dcc_controls.dcc_256_128 = 1; + output->grph.rgb.dcc_controls.dcc_256_64 = 1; + break; + case dcc_control__256_64: + output->grph.rgb.dcc_controls.dcc_256_64 = 1; + break; + default: + /* Shouldn't get here */ + ASSERT(0); + break; + } + } else { + /* For dual plane cases, need to examine both planes together */ + if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3, + input->plane0_pitch, plane0_bpe, + &segment_order_horz, &segment_order_vert)) + return false; + + if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3, + input->plane1_pitch, plane1_bpe, + &p1_segment_order_horz, &p1_segment_order_vert)) + return false; + + hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format, + plane0_height, plane0_width, plane0_bpe, + plane1_height, plane1_width, plane1_bpe, + &req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc); + + /* Determine Plane 0 DCC Controls */ + if (!req128_horz_wc && !req128_vert_wc) { + dcc_control = dcc_control__256_256; + } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { + if (!req128_horz_wc) + dcc_control = dcc_control__256_256; + else if (segment_order_horz == segment_order__contiguous) + dcc_control = dcc_control__256_128; + else + dcc_control = dcc_control__256_64; + } else if (input->scan == SCAN_DIRECTION_VERTICAL) { + if (!req128_vert_wc) + dcc_control = dcc_control__256_256; + else if (segment_order_vert == segment_order__contiguous) + dcc_control = dcc_control__256_128; + else + dcc_control = dcc_control__256_64; + } else { + if ((req128_horz_wc && + segment_order_horz == segment_order__non_contiguous) || + (req128_vert_wc && + segment_order_vert == segment_order__non_contiguous)) + /* access_dir not known, must use most constraining */ + dcc_control = dcc_control__256_64; + else + /* req128 is true for either horz and vert + * but segment_order is contiguous + */ + dcc_control = dcc_control__256_128; + } + + switch (dcc_control) { + case dcc_control__256_256: + output->video.luma.dcc_controls.dcc_256_256 = 1; + output->video.luma.dcc_controls.dcc_256_128 = 1; + output->video.luma.dcc_controls.dcc_256_64 = 1; + break; + case dcc_control__256_128: + output->video.luma.dcc_controls.dcc_256_128 = 1; + output->video.luma.dcc_controls.dcc_256_64 = 1; + break; + case dcc_control__256_64: + output->video.luma.dcc_controls.dcc_256_64 = 1; + break; + default: + ASSERT(0); + break; + } + + /* Determine Plane 1 DCC Controls */ + if (!p1_req128_horz_wc && !p1_req128_vert_wc) { + dcc_control = dcc_control__256_256; + } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { + if (!p1_req128_horz_wc) + dcc_control = dcc_control__256_256; + else if (p1_segment_order_horz == segment_order__contiguous) + dcc_control = dcc_control__256_128; + else + dcc_control = dcc_control__256_64; + } else if (input->scan == SCAN_DIRECTION_VERTICAL) { + if (!p1_req128_vert_wc) + dcc_control = dcc_control__256_256; + else if (p1_segment_order_vert == segment_order__contiguous) + dcc_control = dcc_control__256_128; + else + dcc_control = dcc_control__256_64; + } else { + if ((p1_req128_horz_wc && + p1_segment_order_horz == segment_order__non_contiguous) || + (p1_req128_vert_wc && + p1_segment_order_vert == segment_order__non_contiguous)) + /* access_dir not known, must use most constraining */ + dcc_control = dcc_control__256_64; + else + /* req128 is true for either horz and vert + * but segment_order is contiguous + */ + dcc_control = dcc_control__256_128; + } + + switch (dcc_control) { + case dcc_control__256_256: + output->video.chroma.dcc_controls.dcc_256_256 = 1; + output->video.chroma.dcc_controls.dcc_256_128 = 1; + output->video.chroma.dcc_controls.dcc_256_64 = 1; + break; + case dcc_control__256_128: + output->video.chroma.dcc_controls.dcc_256_128 = 1; + output->video.chroma.dcc_controls.dcc_256_64 = 1; + break; + case dcc_control__256_64: + output->video.chroma.dcc_controls.dcc_256_64 = 1; + break; + default: + ASSERT(0); + break; + } + } + + output->capable = true; + return true; +} static void dcn401_program_det_segments(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg) { @@ -891,6 +1170,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = { .init_vm_ctx = hubbub2_init_vm_ctx, .dcc_support_swizzle_addr3 = hubbub401_dcc_support_swizzle, .dcc_support_pixel_format_plane0_plane1 = hubbub401_dcc_support_pixel_format, + .get_dcc_compression_cap = hubbub401_get_dcc_compression_cap, .wm_read_state = hubbub401_wm_read_state, .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, .program_watermarks = hubbub401_program_watermarks, diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h index d8a57f64a70c..f35f19ba3e18 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h @@ -180,6 +180,11 @@ void hubbub401_det_request_size( bool *p0_req128_vert_wc, bool *p1_req128_horz_wc, bool *p1_req128_vert_wc); +bool hubbub401_get_dcc_compression_cap( + struct hubbub *hubbub, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output); + void hubbub401_construct(struct dcn20_hubbub *hubbub2, struct dc_context *ctx, const struct dcn_hubbub_registers *hubbub_regs, diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h index ecc0a2f37938..18e194507e36 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h @@ -175,6 +175,8 @@ uint32_t HUBP_3DLUT_ADDRESS_LOW;\ uint32_t HUBP_3DLUT_CONTROL;\ uint32_t HUBP_3DLUT_DLG_PARAM;\ + uint32_t DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE;\ + uint32_t DCHUBP_MCACHEID_CONFIG #define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \ DCN_HUBP_REG_FIELD_BASE_LIST(type); \ @@ -269,6 +271,18 @@ type HUBP_3DLUT_ADDRESS_HIGH;\ type HUBP_3DLUT_ADDRESS_LOW;\ type REFCYC_PER_3DLUT_GROUP;\ + type VIEWPORT_MCACHE_SPLIT_COORDINATE;\ + type VIEWPORT_MCACHE_SPLIT_COORDINATE_C;\ + type MCACHEID_REG_READ_1H_P0;\ + type MCACHEID_REG_READ_2H_P0;\ + type MCACHEID_REG_READ_1H_P1;\ + type MCACHEID_REG_READ_2H_P1;\ + type MCACHEID_MALL_PREF_1H_P0;\ + type MCACHEID_MALL_PREF_2H_P0;\ + type MCACHEID_MALL_PREF_1H_P1;\ + type MCACHEID_MALL_PREF_2H_P1 + + struct dcn_hubp2_registers { DCN401_HUBP_REG_COMMON_VARIABLE_LIST; diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c index 3f9ca9b40949..f0c45a74c2e5 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c @@ -626,6 +626,26 @@ void hubp401_set_viewport( SEC_VIEWPORT_Y_START_C, viewport_c->y); } +void hubp401_program_mcache_id_and_split_coordinate( + struct hubp *hubp, + struct dml2_hubp_pipe_mcache_regs *mcache_regs) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_SET_8(DCHUBP_MCACHEID_CONFIG, 0, + MCACHEID_REG_READ_1H_P0, mcache_regs->main.p0.mcache_id_first, + MCACHEID_REG_READ_2H_P0, mcache_regs->main.p0.mcache_id_second, + MCACHEID_REG_READ_1H_P1, mcache_regs->main.p1.mcache_id_first, + MCACHEID_REG_READ_2H_P1, mcache_regs->main.p1.mcache_id_second, + MCACHEID_MALL_PREF_1H_P0, mcache_regs->mall.p0.mcache_id_first, + MCACHEID_MALL_PREF_2H_P0, mcache_regs->mall.p0.mcache_id_second, + MCACHEID_MALL_PREF_1H_P1, mcache_regs->mall.p1.mcache_id_first, + MCACHEID_MALL_PREF_2H_P1, mcache_regs->mall.p1.mcache_id_second); + + REG_SET_2(DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, 0, + VIEWPORT_MCACHE_SPLIT_COORDINATE, mcache_regs->main.p0.split_location, + VIEWPORT_MCACHE_SPLIT_COORDINATE_C, mcache_regs->main.p1.split_location); +} void hubp401_set_flip_int(struct hubp *hubp) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); @@ -963,6 +983,7 @@ static struct hubp_funcs dcn401_hubp_funcs = { .phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable, .hubp_update_mall_sel = hubp401_update_mall_sel, .hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering, + .hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate, .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale, .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode, .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format, diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h index e0cec898a2c0..e52fdb5b0cd0 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h @@ -243,6 +243,16 @@ HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, mask_sh),\ HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_LOW, HUBP_3DLUT_ADDRESS_LOW, mask_sh),\ HUBP_SF(CURSOR0_0_HUBP_3DLUT_DLG_PARAM, REFCYC_PER_3DLUT_GROUP, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, VIEWPORT_MCACHE_SPLIT_COORDINATE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, VIEWPORT_MCACHE_SPLIT_COORDINATE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_1H_P0, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_2H_P0, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_1H_P1, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_REG_READ_2H_P1, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_1H_P0, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_2H_P0, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_1H_P1, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_MCACHEID_CONFIG, MCACHEID_MALL_PREF_2H_P1, mask_sh) void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor); @@ -302,7 +312,9 @@ void hubp401_program_surface_config( void hubp401_set_viewport(struct hubp *hubp, const struct rect *viewport, const struct rect *viewport_c); - +void hubp401_program_mcache_id_and_split_coordinate( + struct hubp *hubp, + struct dml2_hubp_pipe_mcache_regs *mcache_regs); void hubp401_set_flip_int(struct hubp *hubp); bool hubp401_in_blank(struct hubp *hubp); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 36797ed7ad8c..2532ad410cb5 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -1753,6 +1753,10 @@ static void dcn20_update_dchubp_dpp( &pipe_ctx->plane_res.scl_data.viewport_c); viewport_changed = true; } + if (hubp->funcs->hubp_program_mcache_id_and_split_coordinate) + hubp->funcs->hubp_program_mcache_id_and_split_coordinate( + hubp, + &pipe_ctx->mcache_regs); /* Any updates are handled in dc interface, just need to apply existing for plane enable */ if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed || diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index b5a02a8fc9d8..11570ef06086 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1336,6 +1336,31 @@ bool dcn401_apply_idle_power_optimizations(struct dc *dc, bool enable) return true; } +void dcn401_wait_for_dcc_meta_propagation(const struct dc *dc, + const struct pipe_ctx *top_pipe) +{ + bool is_wait_needed = false; + const struct pipe_ctx *pipe_ctx = top_pipe; + + /* check if any surfaces are updating address while using flip immediate and dcc */ + while (pipe_ctx != NULL) { + if (pipe_ctx->plane_state && + pipe_ctx->plane_state->dcc.enable && + pipe_ctx->plane_state->flip_immediate && + pipe_ctx->plane_state->update_flags.bits.addr_update) { + is_wait_needed = true; + break; + } + + /* check next pipe */ + pipe_ctx = pipe_ctx->bottom_pipe; + } + + if (is_wait_needed && dc->debug.dcc_meta_propagation_delay_us > 0) { + udelay(dc->debug.dcc_meta_propagation_delay_us); + } +} + void dcn401_prepare_bandwidth(struct dc *dc, struct dc_state *context) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h index bada43d4b2eb..c1d4287d5a0d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h @@ -61,6 +61,8 @@ bool dcn401_apply_idle_power_optimizations(struct dc *dc, bool enable); struct ips_ono_region_state dcn401_read_ono_state(struct dc *dc, uint8_t region); +void dcn401_wait_for_dcc_meta_propagation(const struct dc *dc, + const struct pipe_ctx *top_pipe_to_program); void dcn401_prepare_bandwidth(struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c index 8159fd838dc3..6a768702c7bd 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c @@ -94,6 +94,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = { .update_dsc_pg = dcn32_update_dsc_pg, .apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom, .blank_phantom = dcn32_blank_phantom, + .wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation, .is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless, .fams2_global_control_lock = dcn401_fams2_global_control_lock, .fams2_update_config = dcn401_fams2_update_config, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index e9b85884edce..d05be65a2256 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -141,6 +141,11 @@ struct subvp_save_surf_addr { uint8_t subvp_index; }; +struct wait_for_dcc_meta_propagation_params { + const struct dc *dc; + const struct pipe_ctx *top_pipe_to_program; +}; + struct fams2_global_control_lock_fast_params { struct dc *dc; bool is_required; @@ -165,6 +170,7 @@ union block_sequence_params { struct set_output_csc_params set_output_csc_params; struct set_ocsc_default_params set_ocsc_default_params; struct subvp_save_surf_addr subvp_save_surf_addr; + struct wait_for_dcc_meta_propagation_params wait_for_dcc_meta_propagation_params; struct fams2_global_control_lock_fast_params fams2_global_control_lock_fast_params; }; @@ -186,6 +192,7 @@ enum block_sequence_func { MPC_SET_OUTPUT_CSC, MPC_SET_OCSC_DEFAULT, DMUB_SUBVP_SAVE_SURF_ADDR, + HUBP_WAIT_FOR_DCC_META_PROP, DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST, }; @@ -443,6 +450,8 @@ struct hw_sequencer_funcs { bool (*is_pipe_topology_transition_seamless)(struct dc *dc, const struct dc_state *cur_ctx, const struct dc_state *new_ctx); + void (*wait_for_dcc_meta_propagation)(const struct dc *dc, + const struct pipe_ctx *top_pipe_to_program); void (*fams2_global_control_lock)(struct dc *dc, struct dc_state *context, bool lock); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f58c27ad8b3e..4c8e6436c7e1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -97,6 +97,9 @@ struct resource_funcs { unsigned int (*calculate_mall_ways_from_bytes)( const struct dc *dc, unsigned int total_size_in_mall_bytes); + void (*prepare_mcache_programming)( + struct dc *dc, + struct dc_state *context); /** * @populate_dml_pipes - Populate pipe data struct * diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index a73cb8f731b3..dd2b2864876c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -40,6 +40,10 @@ enum dcc_control { dcc_control__128_128_xxx, dcc_control__256_64_64, dcc_control__256_128_128, + dcc_control__256_256, + dcc_control__256_128, + dcc_control__256_64, + }; enum segment_order { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index bcd7b22a1627..16580d624278 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -257,6 +257,7 @@ struct hubp_funcs { unsigned int min_dst_y_next_start_optimized); void (*hubp_wait_pipe_read_start)(struct hubp *hubp); + void (*hubp_program_mcache_id_and_split_coordinate)(struct hubp *hubp, struct dml2_hubp_pipe_mcache_regs *mcache_regs); void (*hubp_update_3dlut_fl_bias_scale)(struct hubp *hubp, uint16_t bias, uint16_t scale); void (*hubp_program_3dlut_fl_mode)(struct hubp *hubp, enum hubp_3dlut_fl_mode mode); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index 74fb21b88f12..4e27d2cee9fb 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1617,6 +1617,14 @@ bool dcn401_validate_bandwidth(struct dc *dc, return out; } +void dcn401_prepare_mcache_programming(struct dc *dc, + struct dc_state *context) +{ + if (dc->debug.using_dml21) + dml2_prepare_mcache_programming(dc, context, + context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2); +} + static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) { const struct dc_stream_state *stream = pipe_ctx->stream; @@ -1699,6 +1707,7 @@ static struct resource_funcs dcn401_res_pool_funcs = { .patch_unknown_plane_state = dcn401_patch_unknown_plane_state, .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, + .prepare_mcache_programming = dcn401_prepare_mcache_programming, .build_pipe_pix_clk_params = dcn401_build_pipe_pix_clk_params, .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, }; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h index c04c8b8f2114..26efeada4f41 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h @@ -26,6 +26,8 @@ bool dcn401_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); +void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context); + /* Following are definitions for run time init of reg offsets */ /* HUBP */ From 94534f41fdf1ff1eb6c98e2e3e24d90fc5a99d04 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 16 Jun 2024 17:41:14 -0400 Subject: [PATCH 52/87] drm/amd/display: 3.2.290 This version brings along the following: - Enable DCC on DCN401 - Add reg definitions for DCN401 DCC - Remove duplicate null check - Remove always true condition - Validate function returns - Ensure curve to hw translation succeed - Use periodic detection for ipx/headless - Fix 1DLUT setting for NL SDR blending - Adjust reg field for DSC wait for disconnect - Remove a redundant check in authenticated_dp - Add HW cursor visual confirm - Fix cursor issues with ODMs and magnification - Wait for double buffer update on ODM changes - Reset DSC memory status - Program CURSOR_DST_X_OFFSET in viewport space - Add null checks before accessing struct elements - Fix reduced resolution and refresh rate - Make DML2.1 P-State method force per stream - Add workaround to restrict max frac urgent for DPM0 - Call dpmm when checking mode support - resync OTG after DIO FIFO resync - Always enable HPO for DCN4 dGPU - Use sw cursor for DCN401 with rotation - Add Replay general cmd - Check HDCP returned status - Check and log for function error codes - Check and log for function error codes - Remove useless function call - Fix uninitialized variables in dcn401 - Fix cursor size issues - Run DC_LOG_DC after checking link->link_enc - Remove redundant checks for pipe_ctx->stream - Send DP_TOTAL_LTTPR_CNT during detection if LTTPR is present - Fix cursor issues with ODMs and HW rotations - Remove unnecessary variable - Remove redundant var from display_rq_dig_calc in dml - Refactor dccg401_get_other_enable_symclk_fe Acked-by: Alex Hung Signed-off-by: Alex Hung 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(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 40f183816e31..900892855436 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.289" +#define DC_VER "3.2.290" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 9ff2e14cf013fa887e269bdc5ea3cffacada8635 Mon Sep 17 00:00:00 2001 From: Bob Zhou Date: Thu, 20 Jun 2024 15:40:06 +0800 Subject: [PATCH 53/87] drm/amdgpu: add missing error handling in function amdgpu_gmc_flush_gpu_tlb_pasid Fix the unchecked return value warning reported by Coverity, so add error handling. Signed-off-by: Bob Zhou Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 322b8ff67cde..3a7622611916 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -718,7 +718,11 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid, ndw += kiq->pmf->invalidate_tlbs_size; spin_lock(&adev->gfx.kiq[inst].ring_lock); - amdgpu_ring_alloc(ring, ndw); + r = amdgpu_ring_alloc(ring, ndw); + if (r) { + spin_unlock(&adev->gfx.kiq[inst].ring_lock); + goto error_unlock_reset; + } if (adev->gmc.flush_tlb_needs_extra_type_2) kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub); From bdbdc7cecd00305dc844a361f9883d3a21022027 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Fri, 21 Jun 2024 17:53:30 +0800 Subject: [PATCH 54/87] drm/amdgpu: Fix smatch static checker warning adev->gfx.imu.funcs could be NULL Signed-off-by: Hawking Zhang Reviewed-by: Likun Gao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index b4575765d7a8..5c17409439f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4498,11 +4498,11 @@ static int gfx_v11_0_hw_init(void *handle) /* RLC autoload sequence 1: Program rlc ram */ if (adev->gfx.imu.funcs->program_rlc_ram) adev->gfx.imu.funcs->program_rlc_ram(adev); + /* rlc autoload firmware */ + r = gfx_v11_0_rlc_backdoor_autoload_enable(adev); + if (r) + return r; } - /* rlc autoload firmware */ - r = gfx_v11_0_rlc_backdoor_autoload_enable(adev); - if (r) - return r; } else { if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { if (adev->gfx.imu.funcs && (amdgpu_dpm > 0)) { From 79ea35c7d84b73733ee5281a089168e71d0168d7 Mon Sep 17 00:00:00 2001 From: Julia Zhang Date: Mon, 3 Jun 2024 19:31:09 +0800 Subject: [PATCH 55/87] drm/amdgpu: avoid using null object of framebuffer Instead of using state->fb->obj[0] directly, get object from framebuffer by calling drm_gem_fb_get_obj() and return error code when object is null to avoid using null object of framebuffer. Reported-by: Fusheng Huang Signed-off-by: Julia Zhang Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index 821f9491565b..6415d0d039e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "amdgpu.h" @@ -310,7 +311,13 @@ static int amdgpu_vkms_prepare_fb(struct drm_plane *plane, return 0; } afb = to_amdgpu_framebuffer(new_state->fb); - obj = new_state->fb->obj[0]; + + obj = drm_gem_fb_get_obj(new_state->fb, 0); + if (!obj) { + DRM_ERROR("Failed to get obj from framebuffer\n"); + return -EINVAL; + } + rbo = gem_to_amdgpu_bo(obj); adev = amdgpu_ttm_adev(rbo->tbo.bdev); @@ -364,12 +371,19 @@ static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { struct amdgpu_bo *rbo; + struct drm_gem_object *obj; int r; if (!old_state->fb) return; - rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]); + obj = drm_gem_fb_get_obj(old_state->fb, 0); + if (!obj) { + DRM_ERROR("Failed to get obj from framebuffer\n"); + return; + } + + rbo = gem_to_amdgpu_bo(obj); r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { DRM_ERROR("failed to reserve rbo before unpin\n"); From fe86c4d1a24e0a09688110d217576347b162df99 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Mon, 3 Jun 2024 12:12:18 +0530 Subject: [PATCH 56/87] drm/amdgpu: Don't show false warning for reg list If reg list is already loaded on PSP 13.0.2 SOCs, psp will give TEE_ERR_CANCEL response on second time load. Avoid printing warn message for it. Signed-off-by: Lijo Lazar Reviewed-by: Feifei Xu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 25 +++++++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h | 5 +++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 93025522fbfc..f89de056a828 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -643,6 +643,20 @@ static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id) } } +static bool psp_err_warn(struct psp_context *psp) +{ + struct psp_gfx_cmd_resp *cmd = psp->cmd_buf_mem; + + /* This response indicates reg list is already loaded */ + if (amdgpu_ip_version(psp->adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 2) && + cmd->cmd_id == GFX_CMD_ID_LOAD_IP_FW && + cmd->cmd.cmd_load_ip_fw.fw_type == GFX_FW_TYPE_REG_LIST && + cmd->resp.status == TEE_ERROR_CANCEL) + return false; + + return true; +} + static int psp_cmd_submit_buf(struct psp_context *psp, struct amdgpu_firmware_info *ucode, @@ -702,10 +716,13 @@ psp_cmd_submit_buf(struct psp_context *psp, dev_warn(psp->adev->dev, "failed to load ucode %s(0x%X) ", amdgpu_ucode_name(ucode->ucode_id), ucode->ucode_id); - dev_warn(psp->adev->dev, - "psp gfx command %s(0x%X) failed and response status is (0x%X)\n", - psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id, - psp->cmd_buf_mem->resp.status); + if (psp_err_warn(psp)) + dev_warn( + psp->adev->dev, + "psp gfx command %s(0x%X) failed and response status is (0x%X)\n", + psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), + psp->cmd_buf_mem->cmd_id, + psp->cmd_buf_mem->resp.status); /* If any firmware (including CAP) load fails under SRIOV, it should * return failure to stop the VF from initializing. * Also return failure in case of timeout diff --git a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h index 7566973ed8f5..37b5ddd6f13b 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h @@ -464,8 +464,9 @@ struct psp_gfx_rb_frame #define PSP_ERR_UNKNOWN_COMMAND 0x00000100 enum tee_error_code { - TEE_SUCCESS = 0x00000000, - TEE_ERROR_NOT_SUPPORTED = 0xFFFF000A, + TEE_SUCCESS = 0x00000000, + TEE_ERROR_CANCEL = 0xFFFF0002, + TEE_ERROR_NOT_SUPPORTED = 0xFFFF000A, }; #endif /* _PSP_TEE_GFX_IF_H_ */ From 429508c84d95811dd1300181dfe84743caff9a38 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Jun 2024 09:54:37 -0400 Subject: [PATCH 57/87] drm/amd/display: Fix Makefile copyright notices Leftover copy pasta from original code. Reviewed-by: Hamza Mahfooz Signed-off-by: Alex Deucher Cc: Harry.Wentland@amd.com --- drivers/gpu/drm/amd/display/dc/dcn301/Makefile | 11 ++--------- drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 10 ++-------- drivers/gpu/drm/amd/display/dc/dcn314/Makefile | 11 ++--------- drivers/gpu/drm/amd/display/dc/dcn401/Makefile | 5 ++--- 4 files changed, 8 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile index fadf5e872e38..dc37dbf870df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile @@ -1,12 +1,5 @@ -# -# (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved -# -# All rights reserved. This notice is intended as a precaution against -# inadvertent publication and does not imply publication or any waiver -# of confidentiality. The year included in the foregoing notice is the -# year of creation of the work. -# -# Authors: AMD +# SPDX-License-Identifier: MIT +# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved. # # Makefile for dcn30. diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 62c8ab0e45aa..d9816313c3b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -1,12 +1,6 @@ +# SPDX-License-Identifier: MIT +# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved. # -# Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved -# -# All rights reserved. This notice is intended as a precaution against -# inadvertent publication and does not imply publication or any waiver -# of confidentiality. The year included in the foregoing notice is the -# year of creation of the work. -# -# Authors: AMD # # Makefile for dcn31. diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile index cac756c75b7f..15fdcf7c6466 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile @@ -1,12 +1,5 @@ -# -# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved -# -# All rights reserved. This notice is intended as a precaution against -# inadvertent publication and does not imply publication or any waiver -# of confidentiality. The year included in the foregoing notice is the -# year of creation of the work. -# -# Authors: AMD +# SPDX-License-Identifier: MIT +# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved. # # Makefile for dcn314. diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/Makefile b/drivers/gpu/drm/amd/display/dc/dcn401/Makefile index 2989e706bccf..ded1f3140beb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn401/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn401/Makefile @@ -1,6 +1,5 @@ -# -# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved. -# +# SPDX-License-Identifier: MIT +# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved. DCN401 += dcn401_dio_link_encoder.o DCN401 += dcn401_dio_stream_encoder.o From b72585f1c2228630e5fc5bf1b8a1f68cdcd8a446 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 24 Jun 2024 11:11:58 +0800 Subject: [PATCH 58/87] drm/amd/display: Use ARRAY_SIZE for array length Use of macro ARRAY_SIZE to calculate array size minimizes the redundant code and improves code reusability. ./drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c:164:45-46: WARNING: Use ARRAY_SIZE. ./drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c:183:47-48: WARNING: Use ARRAY_SIZE. ./drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c:237:45-46: WARNING: Use ARRAY_SIZE. ./drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c:257:47-48: WARNING: Use ARRAY_SIZE. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9405 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index 1b2df97226a3..7ecf76aea950 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -161,8 +161,7 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp, return MOD_HDCP_STATUS_DDC_FAILURE; if (is_dp_hdcp(hdcp)) { - int num_dpcd_addrs = sizeof(hdcp_dpcd_addrs) / - sizeof(hdcp_dpcd_addrs[0]); + int num_dpcd_addrs = ARRAY_SIZE(hdcp_dpcd_addrs); if (msg_id >= num_dpcd_addrs) return MOD_HDCP_STATUS_DDC_FAILURE; @@ -180,8 +179,7 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp, data_offset += cur_size; } } else { - int num_i2c_offsets = sizeof(hdcp_i2c_offsets) / - sizeof(hdcp_i2c_offsets[0]); + int num_i2c_offsets = ARRAY_SIZE(hdcp_i2c_offsets); if (msg_id >= num_i2c_offsets) return MOD_HDCP_STATUS_DDC_FAILURE; @@ -234,8 +232,7 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp, return MOD_HDCP_STATUS_DDC_FAILURE; if (is_dp_hdcp(hdcp)) { - int num_dpcd_addrs = sizeof(hdcp_dpcd_addrs) / - sizeof(hdcp_dpcd_addrs[0]); + int num_dpcd_addrs = ARRAY_SIZE(hdcp_dpcd_addrs); if (msg_id >= num_dpcd_addrs) return MOD_HDCP_STATUS_DDC_FAILURE; @@ -254,8 +251,7 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp, data_offset += cur_size; } } else { - int num_i2c_offsets = sizeof(hdcp_i2c_offsets) / - sizeof(hdcp_i2c_offsets[0]); + int num_i2c_offsets = ARRAY_SIZE(hdcp_i2c_offsets); if (msg_id >= num_i2c_offsets) return MOD_HDCP_STATUS_DDC_FAILURE; From 68936346b67d8a4605d8b66f0d345d6bb1f95f4d Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 24 Jun 2024 10:22:25 +0800 Subject: [PATCH 59/87] drm/amd/display: Remove unused function reverse_planes_order The function are defined in the amdgpu_dm.c file, but not called anywhere, so delete the unused function. drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:371:20: warning: unused function 'reverse_planes_order'. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9402 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 --------- 1 file changed, 9 deletions(-) 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 6e757ee2d74b..d743e2705399 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -368,15 +368,6 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, return false; } -static inline void reverse_planes_order(struct dc_surface_update *array_of_surface_update, - int planes_count) -{ - int i, j; - - for (i = 0, j = planes_count - 1; i < j; i++, j--) - swap(array_of_surface_update[i], array_of_surface_update[j]); -} - /* * DC will program planes with their z-order determined by their ordering * in the dc_surface_updates array. This comparator is used to sort them From e97db6d9f068098b35ff1f37db89826c77ea037e Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 24 Jun 2024 09:57:07 +0800 Subject: [PATCH 60/87] drm/amd/display: use swap() in is_config_schedulable() Use existing swap() function rather than duplicating its implementation. ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c:1171:103-104: WARNING opportunity for swap(). ./drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c:1231:99-100: WARNING opportunity for swap(). Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9400 Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- .../dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c index 00fedc00a735..603036df68ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c @@ -1163,7 +1163,6 @@ static bool is_config_schedulable( schedulable = true; /* sort disallow times from greatest to least */ - unsigned int temp; for (i = 0; i < s->pmo_dcn4.num_timing_groups; i++) { bool swapped = false; @@ -1172,9 +1171,8 @@ static bool is_config_schedulable( double jp1_disallow_us = s->pmo_dcn4.group_common_fams2_meta[s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1]].disallow_time_us; if (j_disallow_us < jp1_disallow_us) { /* swap as A < B */ - temp = s->pmo_dcn4.sorted_group_gtl_disallow_index[j]; - s->pmo_dcn4.sorted_group_gtl_disallow_index[j] = s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1]; - s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1] = temp; + swap(s->pmo_dcn4.sorted_group_gtl_disallow_index[j], + s->pmo_dcn4.sorted_group_gtl_disallow_index[j+1]); swapped = true; } } @@ -1232,9 +1230,8 @@ static bool is_config_schedulable( double jp1_period_us = s->pmo_dcn4.group_common_fams2_meta[s->pmo_dcn4.sorted_group_gtl_period_index[j + 1]].period_us; if (j_period_us < jp1_period_us) { /* swap as A < B */ - temp = s->pmo_dcn4.sorted_group_gtl_period_index[j]; - s->pmo_dcn4.sorted_group_gtl_period_index[j] = s->pmo_dcn4.sorted_group_gtl_period_index[j + 1]; - s->pmo_dcn4.sorted_group_gtl_period_index[j + 1] = temp; + swap(s->pmo_dcn4.sorted_group_gtl_period_index[j], + s->pmo_dcn4.sorted_group_gtl_period_index[j+1]); swapped = true; } } From 0b5f9e91ae39586aeeadddf51d0357d76ee5e49a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 24 Jun 2024 14:12:57 -0500 Subject: [PATCH 61/87] Documentation/amdgpu: Add Ryzen AI 300 series processors These have been announced so add them to the table. Acked-by: Alex Deucher Link: https://www.amd.com/en/products/processors/laptop/ryzen/300-series/amd-ryzen-ai-9-hx-370.html Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/apu-asic-info-table.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/gpu/amdgpu/apu-asic-info-table.csv b/Documentation/gpu/amdgpu/apu-asic-info-table.csv index 18868abe2a91..61140ba32793 100644 --- a/Documentation/gpu/amdgpu/apu-asic-info-table.csv +++ b/Documentation/gpu/amdgpu/apu-asic-info-table.csv @@ -11,3 +11,4 @@ Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8 Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11 Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11 +Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0 From 82c006509750351631738de6aa7e71d51e4d7a18 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 24 Jun 2024 14:14:44 -0500 Subject: [PATCH 62/87] Documentation/amdgpu: Add Ryzen 9000 series processors These have been announced so add them to the table. Acked-by: Alex Deucher Link: https://www.amd.com/en/products/processors/desktops/ryzen/9000-series/amd-ryzen-9-9950x.html Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/apu-asic-info-table.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/gpu/amdgpu/apu-asic-info-table.csv b/Documentation/gpu/amdgpu/apu-asic-info-table.csv index 61140ba32793..5dd4b8762d19 100644 --- a/Documentation/gpu/amdgpu/apu-asic-info-table.csv +++ b/Documentation/gpu/amdgpu/apu-asic-info-table.csv @@ -7,6 +7,7 @@ SteamDeck, VANGOGH, DCN 3.0.1, 10.3.1, VCN 3.1.0, 5.2.1, 11.5.0 Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1 Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3 Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 +Ryzen 9000 series (AM5), Granite Ridge, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8 Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11 From bf826ba9b4b17fb2bff507b8391a8e4babd227fa Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 19 Jun 2024 14:10:59 +0800 Subject: [PATCH 63/87] Revert "drm/amd/amdgpu: add module parameter for jpeg" This reverts commit d3620eeae82cccf8316e6754f8ddb52473e2e5ea. Revert this due to a final solution: commit ed3165d660d8 ("drm/amdgpu/jpeg5: reprogram doorbell setting after power up for each playback") Signed-off-by: Kenneth Feng Reviewed-by: Sonny Jiang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ---- 3 files changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7dab4768cee6..7cb11396e844 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -221,7 +221,6 @@ extern int amdgpu_mes; extern int amdgpu_mes_log_enable; extern int amdgpu_mes_kiq; extern int amdgpu_uni_mes; -extern int amdgpu_jpeg_test; extern int amdgpu_noretry; extern int amdgpu_force_asic_type; extern int amdgpu_smartshift_bias; @@ -1018,7 +1017,6 @@ struct amdgpu_device { /* jpeg */ struct amdgpu_jpeg jpeg; - bool enable_jpeg_test; /* vpe */ struct amdgpu_vpe vpe; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 0cb8aea93a70..7f265163eb1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2294,8 +2294,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(5, 0, 0): amdgpu_device_ip_block_add(adev, &vcn_v5_0_0_ip_block); amdgpu_device_ip_block_add(adev, &jpeg_v5_0_0_ip_block); - if (amdgpu_jpeg_test) - adev->enable_jpeg_test = true; break; default: dev_err(adev->dev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 9f2db858c6e0..78089f2f79f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -204,7 +204,6 @@ int amdgpu_force_asic_type = -1; int amdgpu_tmz = -1; /* auto */ uint amdgpu_freesync_vid_mode; int amdgpu_reset_method = -1; /* auto */ -int amdgpu_jpeg_test; int amdgpu_num_kcq = -1; int amdgpu_smartshift_bias; int amdgpu_use_xgmi_p2p = 1; @@ -940,9 +939,6 @@ module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444); MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco/bamaco)"); module_param_named(reset_method, amdgpu_reset_method, int, 0644); -MODULE_PARM_DESC(jpeg_test, "jpeg test(0 = disable (default), 1 = enable)"); -module_param_named(jpeg_test, amdgpu_jpeg_test, int, 0444); - /** * DOC: bad_page_threshold (int) Bad page threshold is specifies the * threshold value of faulty pages detected by RAS ECC, which may From afbf7955ff01e952dbdd465fa25a2ba92d00291c Mon Sep 17 00:00:00 2001 From: Danijel Slivka Date: Mon, 24 Jun 2024 07:58:24 +0200 Subject: [PATCH 64/87] drm/amdgpu: clear RB_OVERFLOW bit when enabling interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: Setting IH_RB_WPTR register to 0 will not clear the RB_OVERFLOW bit if RB_ENABLE is not set. How to fix: Set WPTR_OVERFLOW_CLEAR bit after RB_ENABLE bit is set. The RB_ENABLE bit is required to be set, together with WPTR_OVERFLOW_ENABLE bit so that setting WPTR_OVERFLOW_CLEAR bit would clear the RB_OVERFLOW. Signed-off-by: Danijel Slivka Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ih_v6_0.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c index 3cb64c8f7175..18a761d6ef33 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c @@ -135,6 +135,34 @@ static int ih_v6_0_toggle_ring_interrupts(struct amdgpu_device *adev, tmp = RREG32(ih_regs->ih_rb_cntl); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0)); + + if (enable) { + /* Unset the CLEAR_OVERFLOW bit to make sure the next step + * is switching the bit from 0 to 1 + */ + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); + if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) { + if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) + return -ETIMEDOUT; + } else { + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); + } + + /* Clear RB_OVERFLOW bit */ + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); + if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) { + if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) + return -ETIMEDOUT; + } else { + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); + } + + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows + * can be detected. + */ + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); + } + /* enable_intr field is only valid in ring0 */ if (ih == &adev->irq.ih) tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0)); From 29b6985de50b6bf4de77aa680b875a4362d7b30d Mon Sep 17 00:00:00 2001 From: Vignesh Chander Date: Sun, 16 Jun 2024 16:22:10 -0500 Subject: [PATCH 65/87] drm/amdgpu: Use dev_ prints for virtualization as it supports multi adapter So we can get clearer per device logging. Signed-off-by: Vignesh Chander Reviewed-by: Zhigang Luo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 19 +++++++++++-------- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 23 +++++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 6b71ee85ee65..65656afc6ed1 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -93,7 +93,7 @@ static int xgpu_ai_poll_ack(struct amdgpu_device *adev) timeout -= 5; } while (timeout > 1); - pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", AI_MAILBOX_POLL_ACK_TIMEDOUT); + dev_err(adev->dev, "Doesn't get TRN_MSG_ACK from pf in %d msec\n", AI_MAILBOX_POLL_ACK_TIMEDOUT); return -ETIME; } @@ -111,7 +111,7 @@ static int xgpu_ai_poll_msg(struct amdgpu_device *adev, enum idh_event event) timeout -= 10; } while (timeout > 1); - pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r); + dev_err(adev->dev, "Doesn't get msg:%d from pf, error=%d\n", event, r); return -ETIME; } @@ -132,7 +132,7 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev, xgpu_ai_mailbox_set_valid(adev, false); trn = xgpu_ai_peek_ack(adev); if (trn) { - pr_err("trn=%x ACK should not assert! wait again !\n", trn); + dev_err_ratelimited(adev->dev, "trn=%x ACK should not assert! wait again !\n", trn); msleep(1); } } while(trn); @@ -155,7 +155,7 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev, /* start to poll ack */ r = xgpu_ai_poll_ack(adev); if (r) - pr_err("Doesn't get ack from pf, continue\n"); + dev_err(adev->dev, "Doesn't get ack from pf, continue\n"); xgpu_ai_mailbox_set_valid(adev, false); } @@ -173,7 +173,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, req == IDH_REQ_GPU_RESET_ACCESS) { r = xgpu_ai_poll_msg(adev, IDH_READY_TO_ACCESS_GPU); if (r) { - pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n"); + dev_err(adev->dev, "Doesn't get READY_TO_ACCESS_GPU from pf, give up\n"); return r; } /* Retrieve checksum from mailbox2 */ @@ -231,7 +231,7 @@ static int xgpu_ai_mailbox_ack_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - DRM_DEBUG("get ack intr and do nothing.\n"); + dev_dbg(adev->dev, "get ack intr and do nothing.\n"); return 0; } @@ -258,12 +258,15 @@ static int xgpu_ai_wait_reset(struct amdgpu_device *adev) { int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT; do { - if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) + if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) { + dev_dbg(adev->dev, "Got AI IDH_FLR_NOTIFICATION_CMPL after %d ms\n", AI_MAILBOX_POLL_FLR_TIMEDOUT - timeout); return 0; + } msleep(10); timeout -= 10; } while (timeout > 1); - dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n"); + + dev_dbg(adev->dev, "waiting AI IDH_FLR_NOTIFICATION_CMPL timeout\n"); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 22af30a15a5f..17e1e8cc2437 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -91,7 +91,7 @@ static int xgpu_nv_poll_ack(struct amdgpu_device *adev) timeout -= 5; } while (timeout > 1); - pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", NV_MAILBOX_POLL_ACK_TIMEDOUT); + dev_err(adev->dev, "Doesn't get TRN_MSG_ACK from pf in %d msec \n", NV_MAILBOX_POLL_ACK_TIMEDOUT); return -ETIME; } @@ -106,13 +106,16 @@ static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event) do { r = xgpu_nv_mailbox_rcv_msg(adev, event); - if (!r) + if (!r) { + dev_dbg(adev->dev, "rcv_msg 0x%x after %llu ms\n", event, NV_MAILBOX_POLL_MSG_TIMEDOUT - timeout + now); return 0; + } msleep(10); now = (uint64_t)ktime_to_ms(ktime_get()); } while (timeout > now); + dev_dbg(adev->dev, "nv_poll_msg timed out\n"); return -ETIME; } @@ -133,11 +136,12 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev, xgpu_nv_mailbox_set_valid(adev, false); trn = xgpu_nv_peek_ack(adev); if (trn) { - pr_err("trn=%x ACK should not assert! wait again !\n", trn); + dev_err_ratelimited(adev->dev, "trn=%x ACK should not assert! wait again !\n", trn); msleep(1); } } while (trn); + dev_dbg(adev->dev, "trans_msg req = 0x%x, data1 = 0x%x\n", req, data1); WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW0, req); WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW1, data1); WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW2, data2); @@ -147,7 +151,7 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev, /* start to poll ack */ r = xgpu_nv_poll_ack(adev); if (r) - pr_err("Doesn't get ack from pf, continue\n"); + dev_err(adev->dev, "Doesn't get ack from pf, continue\n"); xgpu_nv_mailbox_set_valid(adev, false); } @@ -185,7 +189,7 @@ send_request: goto send_request; if (req != IDH_REQ_GPU_INIT_DATA) { - pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r); + dev_err(adev->dev, "Doesn't get msg:%d from pf, error=%d\n", event, r); return r; } else /* host doesn't support REQ_GPU_INIT_DATA handshake */ adev->virt.req_init_data_ver = 0; @@ -261,7 +265,7 @@ static int xgpu_nv_mailbox_ack_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - DRM_DEBUG("get ack intr and do nothing.\n"); + dev_dbg(adev->dev, "get ack intr and do nothing.\n"); return 0; } @@ -291,12 +295,15 @@ static int xgpu_nv_wait_reset(struct amdgpu_device *adev) { int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; do { - if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) + if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) { + dev_dbg(adev->dev, "Got NV IDH_FLR_NOTIFICATION_CMPL after %d ms\n", NV_MAILBOX_POLL_FLR_TIMEDOUT - timeout); return 0; + } msleep(10); timeout -= 10; } while (timeout > 1); - dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n"); + + dev_dbg(adev->dev, "waiting NV IDH_FLR_NOTIFICATION_CMPL timeout\n"); return -ETIME; } From 78146c1dcd220ae98fd5f4114f992299fc5ee161 Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Mon, 24 Jun 2024 11:21:06 +0800 Subject: [PATCH 66/87] drm/amdgpu: add variable to record the deferred error number read by driver Add variable to record the deferred error number read by driver. Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 64 +++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 +- drivers/gpu/drm/amd/amdgpu/umc_v12_0.c | 4 +- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 68e9935028db..f67ce3684aa7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -120,7 +120,7 @@ const char *get_ras_block_str(struct ras_common_if *ras_block) /* typical ECC bad page rate is 1 bad page per 100MB VRAM */ #define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL) -#define MAX_UMC_POISON_POLLING_TIME_ASYNC 100 //ms +#define MAX_UMC_POISON_POLLING_TIME_ASYNC 300 //ms #define AMDGPU_RAS_RETIRE_PAGE_INTERVAL 100 //ms @@ -2799,7 +2799,8 @@ static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log) memset(&ecc_log->ecc_key, 0xad, sizeof(ecc_log->ecc_key)); INIT_RADIX_TREE(&ecc_log->de_page_tree, GFP_KERNEL); - ecc_log->de_updated = false; + ecc_log->de_queried_count = 0; + ecc_log->prev_de_queried_count = 0; } static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log) @@ -2818,7 +2819,8 @@ static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log) mutex_unlock(&ecc_log->lock); mutex_destroy(&ecc_log->lock); - ecc_log->de_updated = false; + ecc_log->de_queried_count = 0; + ecc_log->prev_de_queried_count = 0; } static void amdgpu_ras_do_page_retirement(struct work_struct *work) @@ -2850,40 +2852,64 @@ static void amdgpu_ras_do_page_retirement(struct work_struct *work) mutex_unlock(&con->umc_ecc_log.lock); } -static void amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev, - uint32_t timeout_ms) +static int amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev, + uint32_t poison_creation_count) { int ret = 0; struct ras_ecc_log_info *ecc_log; struct ras_query_if info; - uint32_t timeout = timeout_ms; + uint32_t timeout = 0; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + uint64_t de_queried_count; + uint32_t new_detect_count, total_detect_count; + uint32_t need_query_count = poison_creation_count; + bool query_data_timeout = false; memset(&info, 0, sizeof(info)); info.head.block = AMDGPU_RAS_BLOCK__UMC; ecc_log = &ras->umc_ecc_log; - ecc_log->de_updated = false; + total_detect_count = 0; do { ret = amdgpu_ras_query_error_status(adev, &info); - if (ret) { - dev_err(adev->dev, "Failed to query ras error! ret:%d\n", ret); - return; + if (ret) + return ret; + + de_queried_count = ecc_log->de_queried_count; + if (de_queried_count > ecc_log->prev_de_queried_count) { + new_detect_count = de_queried_count - ecc_log->prev_de_queried_count; + ecc_log->prev_de_queried_count = de_queried_count; + timeout = 0; + } else { + new_detect_count = 0; } - if (timeout && !ecc_log->de_updated) { - msleep(1); - timeout--; - } - } while (timeout && !ecc_log->de_updated); + if (new_detect_count) { + total_detect_count += new_detect_count; + } else { + if (!timeout && need_query_count) + timeout = MAX_UMC_POISON_POLLING_TIME_ASYNC; - if (timeout_ms && !timeout) { - dev_warn(adev->dev, "Can't find deferred error\n"); - return; + if (timeout) { + if (!--timeout) { + query_data_timeout = true; + break; + } + msleep(1); + } + } + } while (total_detect_count < need_query_count); + + if (query_data_timeout) { + dev_warn(adev->dev, "Can't find deferred error! count: %u\n", + (need_query_count - total_detect_count)); + return -ENOENT; } - if (!ret) + if (total_detect_count) schedule_delayed_work(&ras->page_retirement_dwork, 0); + + return 0; } static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 83437fef9df5..748bbac666e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -469,7 +469,8 @@ struct ras_ecc_log_info { struct mutex lock; siphash_key_t ecc_key; struct radix_tree_root de_page_tree; - bool de_updated; + uint64_t de_queried_count; + uint64_t prev_de_queried_count; }; struct amdgpu_ras { diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index 6d6350f220b0..0faa21d8a7b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c @@ -557,7 +557,7 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev, ret = amdgpu_umc_logs_ecc_err(adev, &con->umc_ecc_log.de_page_tree, ecc_err); if (ret) { if (ret == -EEXIST) - con->umc_ecc_log.de_updated = true; + con->umc_ecc_log.de_queried_count++; else dev_err(adev->dev, "Fail to log ecc error! ret:%d\n", ret); @@ -566,7 +566,7 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev, return ret; } - con->umc_ecc_log.de_updated = true; + con->umc_ecc_log.de_queried_count++; return 0; } From cbda2758d8bfae323b846210a3e52f0ad5fe7164 Mon Sep 17 00:00:00 2001 From: Vignesh Chander Date: Mon, 24 Jun 2024 16:44:26 -0500 Subject: [PATCH 67/87] drm/amdgpu: process RAS fatal error MB notification For RAS error scenario, VF guest driver will check mailbox and set fed flag to avoid unnecessary HW accesses. additionally, poll for reset completion message first to avoid accidentally spamming multiple reset requests to host. v2: add another mailbox check for handling case where kfd detects timeout first v3: set host_flr bit and use wait_for_reset Signed-off-by: Vignesh Chander Reviewed-by: Zhigang Luo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 9 +++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 25 +++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +++- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 8 +++++++ drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h | 4 +++- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 8 +++++++ drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h | 5 +++-- 7 files changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 183e219b6a85..b27336a05aae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5069,7 +5069,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, struct amdgpu_hive_info *hive = NULL; if (test_bit(AMDGPU_HOST_FLR, &reset_context->flags)) { - amdgpu_virt_ready_to_reset(adev); + if (!amdgpu_ras_get_fed_status(adev)) + amdgpu_virt_ready_to_reset(adev); amdgpu_virt_wait_reset(adev); clear_bit(AMDGPU_HOST_FLR, &reset_context->flags); r = amdgpu_virt_request_full_gpu(adev, true); @@ -5837,6 +5838,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ /* Actual ASIC resets if needed.*/ /* Host driver will handle XGMI hive reset for SRIOV */ if (amdgpu_sriov_vf(adev)) { + if (amdgpu_ras_get_fed_status(adev) || amdgpu_virt_rcvd_ras_interrupt(adev)) { + dev_dbg(adev->dev, "Detected RAS error, wait for FLR completion\n"); + amdgpu_ras_set_fed(adev, true); + set_bit(AMDGPU_HOST_FLR, &reset_context->flags); + } + r = amdgpu_device_reset_sriov(adev, reset_context); if (AMDGPU_RETRY_SRIOV_RESET(r) && (retry_limit--) > 0) { amdgpu_virt_release_full_gpu(adev, true); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 63f2286858c4..ccb3d041c2b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -229,6 +229,22 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev) adev->virt.mm_table.gpu_addr = 0; } +/** + * amdgpu_virt_rcvd_ras_interrupt() - receive ras interrupt + * @adev: amdgpu device. + * Check whether host sent RAS error message + * Return: true if found, otherwise false + */ +bool amdgpu_virt_rcvd_ras_interrupt(struct amdgpu_device *adev) +{ + struct amdgpu_virt *virt = &adev->virt; + + if (!virt->ops || !virt->ops->rcvd_ras_intr) + return false; + + return virt->ops->rcvd_ras_intr(adev); +} + unsigned int amd_sriov_msg_checksum(void *obj, unsigned long obj_size, @@ -612,11 +628,14 @@ static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work) ret = amdgpu_virt_read_pf2vf_data(adev); if (ret) { adev->virt.vf2pf_update_retry_cnt++; - if ((adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) && - amdgpu_sriov_runtime(adev)) { + + if ((amdgpu_virt_rcvd_ras_interrupt(adev) || + adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) && + amdgpu_sriov_runtime(adev)) { + amdgpu_ras_set_fed(adev, true); if (amdgpu_reset_domain_schedule(adev->reset_domain, - &adev->kfd.reset_work)) + &adev->kfd.reset_work)) return; else dev_err(adev->dev, "Failed to queue work! at %s", __func__); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index f04cd1586c72..b42a8854dca0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -52,7 +52,7 @@ /* tonga/fiji use this offset */ #define mmBIF_IOV_FUNC_IDENTIFIER 0x1503 -#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 5 +#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 2 enum amdgpu_sriov_vf_mode { SRIOV_VF_MODE_BARE_METAL = 0, @@ -94,6 +94,7 @@ struct amdgpu_virt_ops { u32 data1, u32 data2, u32 data3); void (*ras_poison_handler)(struct amdgpu_device *adev, enum amdgpu_ras_block block); + bool (*rcvd_ras_intr)(struct amdgpu_device *adev); }; /* @@ -352,6 +353,7 @@ void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev); int amdgpu_virt_wait_reset(struct amdgpu_device *adev); int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev); void amdgpu_virt_free_mm_table(struct amdgpu_device *adev); +bool amdgpu_virt_rcvd_ras_interrupt(struct amdgpu_device *adev); void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev); void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev); void amdgpu_virt_exchange_data(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 65656afc6ed1..f5411b798e11 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -408,6 +408,13 @@ static void xgpu_ai_ras_poison_handler(struct amdgpu_device *adev, xgpu_ai_send_access_requests(adev, IDH_RAS_POISON); } +static bool xgpu_ai_rcvd_ras_intr(struct amdgpu_device *adev) +{ + enum idh_event msg = xgpu_ai_mailbox_peek_msg(adev); + + return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF); +} + const struct amdgpu_virt_ops xgpu_ai_virt_ops = { .req_full_gpu = xgpu_ai_request_full_gpu_access, .rel_full_gpu = xgpu_ai_release_full_gpu_access, @@ -417,4 +424,5 @@ const struct amdgpu_virt_ops xgpu_ai_virt_ops = { .trans_msg = xgpu_ai_mailbox_trans_msg, .req_init_data = xgpu_ai_request_init_data, .ras_poison_handler = xgpu_ai_ras_poison_handler, + .rcvd_ras_intr = xgpu_ai_rcvd_ras_intr, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h index c520b2fabfb9..ed57cbc150af 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h @@ -51,7 +51,9 @@ enum idh_event { IDH_FAIL, IDH_QUERY_ALIVE, IDH_REQ_GPU_INIT_DATA_READY, - + IDH_RAS_POISON_READY, + IDH_PF_SOFT_FLR_NOTIFICATION, + IDH_RAS_ERROR_DETECTED, IDH_TEXT_MESSAGE = 255, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 17e1e8cc2437..f47bd7ada4d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -449,6 +449,13 @@ static void xgpu_nv_ras_poison_handler(struct amdgpu_device *adev, } } +static bool xgpu_nv_rcvd_ras_intr(struct amdgpu_device *adev) +{ + enum idh_event msg = xgpu_nv_mailbox_peek_msg(adev); + + return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF); +} + const struct amdgpu_virt_ops xgpu_nv_virt_ops = { .req_full_gpu = xgpu_nv_request_full_gpu_access, .rel_full_gpu = xgpu_nv_release_full_gpu_access, @@ -458,4 +465,5 @@ const struct amdgpu_virt_ops xgpu_nv_virt_ops = { .wait_reset = xgpu_nv_wait_reset, .trans_msg = xgpu_nv_mailbox_trans_msg, .ras_poison_handler = xgpu_nv_ras_poison_handler, + .rcvd_ras_intr = xgpu_nv_rcvd_ras_intr, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h index 1e8fd90cab43..caf616a2c8a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h @@ -26,7 +26,7 @@ #define NV_MAILBOX_POLL_ACK_TIMEDOUT 500 #define NV_MAILBOX_POLL_MSG_TIMEDOUT 6000 -#define NV_MAILBOX_POLL_FLR_TIMEDOUT 5000 +#define NV_MAILBOX_POLL_FLR_TIMEDOUT 10000 #define NV_MAILBOX_POLL_MSG_REP_MAX 11 enum idh_request { @@ -52,7 +52,8 @@ enum idh_event { IDH_QUERY_ALIVE, IDH_REQ_GPU_INIT_DATA_READY, IDH_RAS_POISON_READY, - + IDH_PF_SOFT_FLR_NOTIFICATION, + IDH_RAS_ERROR_DETECTED, IDH_TEXT_MESSAGE = 255, }; From 5f08275cfd88609c86ee86d92efdb196d27c732d Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Mon, 24 Jun 2024 11:26:00 +0800 Subject: [PATCH 68/87] drm/amdgpu: refine poison creation interrupt handler In order to apply to the case where a large number of ras poison interrupts: 1. Change to use variable to record poison creation requests to avoid fifo full. 2. Prioritize handling poison creation requests instead of following the order of requests received by the driver. Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 39 +++++++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 1 + 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index f67ce3684aa7..6e7c4f1f86da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2105,10 +2105,8 @@ static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj if (amdgpu_ip_version(obj->adev, UMC_HWIP, 0) >= IP_VERSION(12, 0, 0)) { struct amdgpu_ras *con = amdgpu_ras_get_context(obj->adev); - amdgpu_ras_put_poison_req(obj->adev, - AMDGPU_RAS_BLOCK__UMC, 0, NULL, NULL, false); - atomic_inc(&con->page_retirement_req_cnt); + atomic_inc(&con->poison_creation_count); wake_up(&con->page_retirement_wq); } @@ -2939,9 +2937,10 @@ static int amdgpu_ras_page_retirement_thread(void *param) { struct amdgpu_device *adev = (struct amdgpu_device *)param; struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + uint32_t poison_creation_count; + int ret; struct ras_poison_msg poison_msg; enum amdgpu_ras_block ras_block; - bool poison_creation_is_handled = false; while (!kthread_should_stop()) { @@ -2952,7 +2951,18 @@ static int amdgpu_ras_page_retirement_thread(void *param) if (kthread_should_stop()) break; - atomic_dec(&con->page_retirement_req_cnt); + + do { + poison_creation_count = atomic_read(&con->poison_creation_count); + ret = amdgpu_ras_poison_creation_handler(adev, poison_creation_count); + if (ret == -EIO) + break; + + if (poison_creation_count) { + atomic_sub(poison_creation_count, &con->poison_creation_count); + atomic_sub(poison_creation_count, &con->page_retirement_req_cnt); + } + } while (atomic_read(&con->poison_creation_count)); if (!amdgpu_ras_get_poison_req(adev, &poison_msg)) continue; @@ -2962,24 +2972,7 @@ static int amdgpu_ras_page_retirement_thread(void *param) dev_dbg(adev->dev, "Start processing ras block %s(%d)\n", ras_block_str(ras_block), ras_block); - if (ras_block == AMDGPU_RAS_BLOCK__UMC) { - amdgpu_ras_poison_creation_handler(adev, - MAX_UMC_POISON_POLLING_TIME_ASYNC); - poison_creation_is_handled = true; - } else { - /* poison_creation_is_handled: - * false: no poison creation interrupt, but it has poison - * consumption interrupt. - * true: It has poison creation interrupt at the beginning, - * but it has no poison creation interrupt later. - */ - amdgpu_ras_poison_creation_handler(adev, - poison_creation_is_handled ? - 0 : MAX_UMC_POISON_POLLING_TIME_ASYNC); - amdgpu_ras_poison_consumption_handler(adev, &poison_msg); - poison_creation_is_handled = false; - } } return 0; @@ -3052,6 +3045,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) mutex_init(&con->page_retirement_lock); init_waitqueue_head(&con->page_retirement_wq); atomic_set(&con->page_retirement_req_cnt, 0); + atomic_set(&con->poison_creation_count, 0); con->page_retirement_thread = kthread_run(amdgpu_ras_page_retirement_thread, adev, "umc_page_retirement"); if (IS_ERR(con->page_retirement_thread)) { @@ -3100,6 +3094,7 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev) kthread_stop(con->page_retirement_thread); atomic_set(&con->page_retirement_req_cnt, 0); + atomic_set(&con->poison_creation_count, 0); mutex_destroy(&con->page_rsv_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 748bbac666e6..0fa1148e6642 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -532,6 +532,7 @@ struct amdgpu_ras { wait_queue_head_t page_retirement_wq; struct mutex page_retirement_lock; atomic_t page_retirement_req_cnt; + atomic_t poison_creation_count; struct mutex page_rsv_lock; DECLARE_KFIFO(poison_fifo, struct ras_poison_msg, 128); struct ras_ecc_log_info umc_ecc_log; From e278849cb2b663bca7dd67ba5d531ecb5b4557df Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Mon, 24 Jun 2024 11:33:19 +0800 Subject: [PATCH 69/87] drm/amdgpu: refine poison consumption interrupt handler 1. The poison fifo is only used for poison consumption requests. 2. Merge reset requests when poison fifo caches multiple poison consumption messages Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 55 +++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 11 ++--- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 6e7c4f1f86da..d3247533d15e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2911,23 +2911,41 @@ static int amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev, } static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev, - struct ras_poison_msg *poison_msg) + uint32_t msg_count, uint32_t *gpu_reset) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - uint32_t reset = poison_msg->reset; - uint16_t pasid = poison_msg->pasid; + uint32_t reset_flags = 0, reset = 0; + struct ras_poison_msg msg; + int ret, i; kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); - if (poison_msg->pasid_fn) - poison_msg->pasid_fn(adev, pasid, poison_msg->data); + for (i = 0; i < msg_count; i++) { + ret = amdgpu_ras_get_poison_req(adev, &msg); + if (!ret) + continue; + + if (msg.pasid_fn) + msg.pasid_fn(adev, msg.pasid, msg.data); + + reset_flags |= msg.reset; + } /* for RMA, amdgpu_ras_poison_creation_handler will trigger gpu reset */ - if (reset && !con->is_rma) { + if (reset_flags && !con->is_rma) { + if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET) + reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET; + else if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE2_RESET) + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; + else + reset = reset_flags; + flush_delayed_work(&con->page_retirement_dwork); con->gpu_reset_flags |= reset; amdgpu_ras_reset_gpu(adev); + + *gpu_reset = reset; } return 0; @@ -2937,10 +2955,9 @@ static int amdgpu_ras_page_retirement_thread(void *param) { struct amdgpu_device *adev = (struct amdgpu_device *)param; struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - uint32_t poison_creation_count; + uint32_t poison_creation_count, msg_count; + uint32_t gpu_reset; int ret; - struct ras_poison_msg poison_msg; - enum amdgpu_ras_block ras_block; while (!kthread_should_stop()) { @@ -2951,6 +2968,7 @@ static int amdgpu_ras_page_retirement_thread(void *param) if (kthread_should_stop()) break; + gpu_reset = 0; do { poison_creation_count = atomic_read(&con->poison_creation_count); @@ -2964,15 +2982,16 @@ static int amdgpu_ras_page_retirement_thread(void *param) } } while (atomic_read(&con->poison_creation_count)); - if (!amdgpu_ras_get_poison_req(adev, &poison_msg)) - continue; - - ras_block = poison_msg.block; - - dev_dbg(adev->dev, "Start processing ras block %s(%d)\n", - ras_block_str(ras_block), ras_block); - - amdgpu_ras_poison_consumption_handler(adev, &poison_msg); + if (ret != -EIO) { + msg_count = kfifo_len(&con->poison_fifo); + if (msg_count) { + ret = amdgpu_ras_poison_consumption_handler(adev, + msg_count, &gpu_reset); + if ((ret != -EIO) && + (gpu_reset != AMDGPU_RAS_GPU_RESET_MODE1_RESET)) + atomic_sub(msg_count, &con->page_retirement_req_cnt); + } + } } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 20e0e522fb51..2f84bdb8c594 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -293,14 +293,15 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev, amdgpu_ras_error_data_fini(&err_data); } else { - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - - amdgpu_ras_put_poison_req(adev, - block, pasid, pasid_fn, data, reset); + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + int ret; + ret = amdgpu_ras_put_poison_req(adev, + block, pasid, pasid_fn, data, reset); + if (!ret) { atomic_inc(&con->page_retirement_req_cnt); - wake_up(&con->page_retirement_wq); + } } } else { if (adev->virt.ops && adev->virt.ops->ras_poison_handler) From f852c9795c80361c4193ff02367c3390ebace7d9 Mon Sep 17 00:00:00 2001 From: YiPeng Chai Date: Mon, 24 Jun 2024 11:38:27 +0800 Subject: [PATCH 70/87] drm/amdgpu: add gpu reset check and exception handling Add gpu reset check and exception handling for page retirement. v2: Clear poison consumption messages cached in fifo after non mode-1 reset. Signed-off-by: YiPeng Chai Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d3247533d15e..4edd8e333d36 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1384,10 +1384,17 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i memset(&qctx, 0, sizeof(qctx)); qctx.event_id = amdgpu_ras_acquire_event_id(adev, amdgpu_ras_intr_triggered() ? RAS_EVENT_TYPE_ISR : RAS_EVENT_TYPE_INVALID); + + if (!down_read_trylock(&adev->reset_domain->sem)) { + ret = -EIO; + goto out_fini_err_data; + } + ret = amdgpu_ras_query_error_status_helper(adev, info, &err_data, &qctx, error_query_mode); + up_read(&adev->reset_domain->sem); if (ret) goto out_fini_err_data; @@ -2910,6 +2917,17 @@ static int amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev, return 0; } +static void amdgpu_ras_clear_poison_fifo(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_poison_msg msg; + int ret; + + do { + ret = kfifo_get(&con->poison_fifo, &msg); + } while (ret); +} + static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev, uint32_t msg_count, uint32_t *gpu_reset) { @@ -2946,6 +2964,9 @@ static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev, amdgpu_ras_reset_gpu(adev); *gpu_reset = reset; + + /* Wait for gpu recovery to complete */ + flush_work(&con->recovery_work); } return 0; @@ -2992,6 +3013,38 @@ static int amdgpu_ras_page_retirement_thread(void *param) atomic_sub(msg_count, &con->page_retirement_req_cnt); } } + + if ((ret == -EIO) || (gpu_reset == AMDGPU_RAS_GPU_RESET_MODE1_RESET)) { + /* gpu mode-1 reset is ongoing or just completed ras mode-1 reset */ + /* Clear poison creation request */ + atomic_set(&con->poison_creation_count, 0); + + /* Clear poison fifo */ + amdgpu_ras_clear_poison_fifo(adev); + + /* Clear all poison requests */ + atomic_set(&con->page_retirement_req_cnt, 0); + + if (ret == -EIO) { + /* Wait for mode-1 reset to complete */ + down_read(&adev->reset_domain->sem); + up_read(&adev->reset_domain->sem); + } + + /* Wake up work to save bad pages to eeprom */ + schedule_delayed_work(&con->page_retirement_dwork, 0); + } else if (gpu_reset) { + /* gpu just completed mode-2 reset or other reset */ + /* Clear poison consumption messages cached in fifo */ + msg_count = kfifo_len(&con->poison_fifo); + if (msg_count) { + amdgpu_ras_clear_poison_fifo(adev); + atomic_sub(msg_count, &con->page_retirement_req_cnt); + } + + /* Wake up work to save bad pages to eeprom */ + schedule_delayed_work(&con->page_retirement_dwork, 0); + } } return 0; From ad89e904e3aaa93628785546034ec77f3100cf79 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Tue, 25 Jun 2024 14:17:46 -0400 Subject: [PATCH 71/87] drm/amd: Add some missing register definitions Add some register offsets that are required for Display DCC on DCN401 Fixes: 2d072b445622 ("drm/amd: Add reg definitions for DCN401 DCC") Reported-by: Tom St Denis Signed-off-by: Aurabindo Pillai Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../include/asic_reg/dcn/dcn_4_1_0_offset.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h index 5dabf0abccce..15e5a65cf492 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_offset.h @@ -1777,6 +1777,8 @@ #define regDCHUBBUB_SDPIF_MEM_PWR_CTRL_BASE_IDX 2 #define regDCHUBBUB_SDPIF_MEM_PWR_STATUS 0x0487 #define regDCHUBBUB_SDPIF_MEM_PWR_STATUS_BASE_IDX 2 +#define regDCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL 0x0488 +#define regDCHUBBUB_SDPIF_MCACHE_INVALIDATION_CTL_BASE_IDX 2 // addressBlock: dcn_dcec_dchubbubl_hubbub_ret_path_dispdec @@ -2089,6 +2091,8 @@ #define regHUBP0_DCSURF_TILING_CONFIG_BASE_IDX 2 #define regHUBP0_DCSURF_PRI_VIEWPORT_START 0x05e9 #define regHUBP0_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2 +#define regHUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x05ea +#define regHUBP0_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2 #define regHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION 0x05eb #define regHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2 #define regHUBP0_DCSURF_PRI_VIEWPORT_START_C 0x05ec @@ -2121,6 +2125,8 @@ #define regHUBP0_DCHUBP_MALL_SUB_VP1_BASE_IDX 2 #define regHUBP0_DCHUBP_MALL_SUB_VP2 0x05fa #define regHUBP0_DCHUBP_MALL_SUB_VP2_BASE_IDX 2 +#define regHUBP0_DCHUBP_MCACHEID_CONFIG 0x05fb +#define regHUBP0_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2 #define regHUBP0_HUBPREQ_DEBUG_DB 0x05fc #define regHUBP0_HUBPREQ_DEBUG_DB_BASE_IDX 2 #define regHUBP0_HUBPREQ_DEBUG 0x05fd @@ -2378,6 +2384,8 @@ #define regHUBP1_DCSURF_TILING_CONFIG_BASE_IDX 2 #define regHUBP1_DCSURF_PRI_VIEWPORT_START 0x06c5 #define regHUBP1_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2 +#define regHUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x06c6 +#define regHUBP1_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2 #define regHUBP1_DCSURF_PRI_VIEWPORT_DIMENSION 0x06c7 #define regHUBP1_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2 #define regHUBP1_DCSURF_PRI_VIEWPORT_START_C 0x06c8 @@ -2410,6 +2418,8 @@ #define regHUBP1_DCHUBP_MALL_SUB_VP1_BASE_IDX 2 #define regHUBP1_DCHUBP_MALL_SUB_VP2 0x06d6 #define regHUBP1_DCHUBP_MALL_SUB_VP2_BASE_IDX 2 +#define regHUBP1_DCHUBP_MCACHEID_CONFIG 0x06d7 +#define regHUBP1_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2 #define regHUBP1_HUBPREQ_DEBUG_DB 0x06d8 #define regHUBP1_HUBPREQ_DEBUG_DB_BASE_IDX 2 #define regHUBP1_HUBPREQ_DEBUG 0x06d9 @@ -2667,6 +2677,8 @@ #define regHUBP2_DCSURF_TILING_CONFIG_BASE_IDX 2 #define regHUBP2_DCSURF_PRI_VIEWPORT_START 0x07a1 #define regHUBP2_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2 +#define regHUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x07a2 +#define regHUBP2_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2 #define regHUBP2_DCSURF_PRI_VIEWPORT_DIMENSION 0x07a3 #define regHUBP2_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2 #define regHUBP2_DCSURF_PRI_VIEWPORT_START_C 0x07a4 @@ -2699,6 +2711,8 @@ #define regHUBP2_DCHUBP_MALL_SUB_VP1_BASE_IDX 2 #define regHUBP2_DCHUBP_MALL_SUB_VP2 0x07b2 #define regHUBP2_DCHUBP_MALL_SUB_VP2_BASE_IDX 2 +#define regHUBP2_DCHUBP_MCACHEID_CONFIG 0x07b3 +#define regHUBP2_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2 #define regHUBP2_HUBPREQ_DEBUG_DB 0x07b4 #define regHUBP2_HUBPREQ_DEBUG_DB_BASE_IDX 2 #define regHUBP2_HUBPREQ_DEBUG 0x07b5 @@ -2957,6 +2971,8 @@ #define regHUBP3_DCSURF_TILING_CONFIG_BASE_IDX 2 #define regHUBP3_DCSURF_PRI_VIEWPORT_START 0x087d #define regHUBP3_DCSURF_PRI_VIEWPORT_START_BASE_IDX 2 +#define regHUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE 0x087e +#define regHUBP3_DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE_BASE_IDX 2 #define regHUBP3_DCSURF_PRI_VIEWPORT_DIMENSION 0x087f #define regHUBP3_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2 #define regHUBP3_DCSURF_PRI_VIEWPORT_START_C 0x0880 @@ -2989,6 +3005,8 @@ #define regHUBP3_DCHUBP_MALL_SUB_VP1_BASE_IDX 2 #define regHUBP3_DCHUBP_MALL_SUB_VP2 0x088e #define regHUBP3_DCHUBP_MALL_SUB_VP2_BASE_IDX 2 +#define regHUBP3_DCHUBP_MCACHEID_CONFIG 0x088f +#define regHUBP3_DCHUBP_MCACHEID_CONFIG_BASE_IDX 2 #define regHUBP3_HUBPREQ_DEBUG_DB 0x0890 #define regHUBP3_HUBPREQ_DEBUG_DB_BASE_IDX 2 #define regHUBP3_HUBPREQ_DEBUG 0x0891 From b17eecc08fba0c1d256f9a78fe13e5e568fe7081 Mon Sep 17 00:00:00 2001 From: Jane Jian Date: Tue, 25 Jun 2024 19:37:43 +0800 Subject: [PATCH 72/87] drm/amdgpu: normalize registers as local xcc to read/write in gfx_v9_4_3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [WHY] sriov has the higher bit violation when flushing tlb [HOW] normalize the registers to keep lower 16-bit(dword aligned) to aviod higher bit violation RLCG will mask xcd out and always assume it's accessing its own xcd v2 add check in wait mem that only do the normalization on regspace Signed-off-by: Jane Jian Reviewed-by: Lijo Lazar Acked-by: Christian König Acked-by: Yiqing Yao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 8d8763ebe027..1149595a02d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -55,6 +55,14 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_4_rlc.bin"); #define mmSMNAID_XCD1_MCA_SMU 0x38430400 /* SMN AID XCD1 */ #define mmSMNXCD_XCD0_MCA_SMU 0x40430400 /* SMN XCD XCD0 */ +#define XCC_REG_RANGE_0_LOW 0x2000 /* XCC gfxdec0 lower Bound */ +#define XCC_REG_RANGE_0_HIGH 0x3400 /* XCC gfxdec0 upper Bound */ +#define XCC_REG_RANGE_1_LOW 0xA000 /* XCC gfxdec1 lower Bound */ +#define XCC_REG_RANGE_1_HIGH 0x10000 /* XCC gfxdec1 upper Bound */ + +#define NORMALIZE_XCC_REG_OFFSET(offset) \ + (offset & 0xFFFF) + struct amdgpu_gfx_ras gfx_v9_4_3_ras; static void gfx_v9_4_3_set_ring_funcs(struct amdgpu_device *adev); @@ -217,9 +225,24 @@ static void gfx_v9_4_3_init_golden_registers(struct amdgpu_device *adev) } } +static uint32_t gfx_v9_4_3_normalize_xcc_reg_offset(uint32_t reg) +{ + uint32_t normalized_reg = NORMALIZE_XCC_REG_OFFSET(reg); + + /* If it is an XCC reg, normalize the reg to keep + lower 16 bits in local xcc */ + + if (((normalized_reg >= XCC_REG_RANGE_0_LOW) && (normalized_reg < XCC_REG_RANGE_0_HIGH)) || + ((normalized_reg >= XCC_REG_RANGE_1_LOW) && (normalized_reg < XCC_REG_RANGE_1_HIGH))) + return normalized_reg; + else + return reg; +} + static void gfx_v9_4_3_write_data_to_reg(struct amdgpu_ring *ring, int eng_sel, bool wc, uint32_t reg, uint32_t val) { + reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg); amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, WRITE_DATA_ENGINE_SEL(eng_sel) | WRITE_DATA_DST_SEL(0) | @@ -234,6 +257,12 @@ static void gfx_v9_4_3_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel, uint32_t addr1, uint32_t ref, uint32_t mask, uint32_t inv) { + /* Only do the normalization on regspace */ + if (mem_space == 0) { + addr0 = gfx_v9_4_3_normalize_xcc_reg_offset(addr0); + addr1 = gfx_v9_4_3_normalize_xcc_reg_offset(addr1); + } + amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); amdgpu_ring_write(ring, /* memory (1) or register (0) */ @@ -2725,6 +2754,8 @@ static void gfx_v9_4_3_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg, { struct amdgpu_device *adev = ring->adev; + reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg); + amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4)); amdgpu_ring_write(ring, 0 | /* src: register*/ (5 << 8) | /* dst: memory */ @@ -2742,6 +2773,8 @@ static void gfx_v9_4_3_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, { uint32_t cmd = 0; + reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg); + switch (ring->funcs->type) { case AMDGPU_RING_TYPE_GFX: cmd = WRITE_DATA_ENGINE_SEL(1) | WR_CONFIRM; From c96140000915b610d86f941450e15ca552de154a Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Wed, 26 Jun 2024 21:06:50 +0800 Subject: [PATCH 73/87] drm/amd/display: Add null check before access structs In enable_phantom_plane, we should better check null pointer before accessing various structs. Fixes: 09a4ec5da92c ("drm/amd/display: Refactor dc_state interface") Signed-off-by: Ma Ke Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c index 282d70e2b18a..3d29169dd6bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c @@ -750,6 +750,8 @@ static void enable_phantom_plane(struct dml2_context *ctx, ctx->config.svp_pstate.callbacks.dc, state, curr_pipe->plane_state); + if (!phantom_plane) + return; } memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); From ecbf60782662f0a388493685b85a645a0ba1613c Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Wed, 26 Jun 2024 13:13:57 -0400 Subject: [PATCH 74/87] drm/amd/display: Fix null pointer deref in dcn20_resource.c Fixes a hang thats triggered when MPV is run on a DCN401 dGPU: mpv --hwdec=vaapi --vo=gpu --hwdec-codecs=all and then enabling fullscreen playback (double click on the video) The following calltrace will be seen: [ 181.843989] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 181.843997] #PF: supervisor instruction fetch in kernel mode [ 181.844003] #PF: error_code(0x0010) - not-present page [ 181.844009] PGD 0 P4D 0 [ 181.844020] Oops: 0010 [#1] PREEMPT SMP NOPTI [ 181.844028] CPU: 6 PID: 1892 Comm: gnome-shell Tainted: G W OE 6.5.0-41-generic #41~22.04.2-Ubuntu [ 181.844038] Hardware name: System manufacturer System Product Name/CROSSHAIR VI HERO, BIOS 6302 10/23/2018 [ 181.844044] RIP: 0010:0x0 [ 181.844079] Code: Unable to access opcode bytes at 0xffffffffffffffd6. [ 181.844084] RSP: 0018:ffffb593c2b8f7b0 EFLAGS: 00010246 [ 181.844093] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004 [ 181.844099] RDX: ffffb593c2b8f804 RSI: ffffb593c2b8f7e0 RDI: ffff9e3c8e758400 [ 181.844105] RBP: ffffb593c2b8f7b8 R08: ffffb593c2b8f9c8 R09: ffffb593c2b8f96c [ 181.844110] R10: 0000000000000000 R11: 0000000000000000 R12: ffffb593c2b8f9c8 [ 181.844115] R13: 0000000000000001 R14: ffff9e3c88000000 R15: 0000000000000005 [ 181.844121] FS: 00007c6e323bb5c0(0000) GS:ffff9e3f85f80000(0000) knlGS:0000000000000000 [ 181.844128] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 181.844134] CR2: ffffffffffffffd6 CR3: 0000000140fbe000 CR4: 00000000003506e0 [ 181.844141] Call Trace: [ 181.844146] [ 181.844153] ? show_regs+0x6d/0x80 [ 181.844167] ? __die+0x24/0x80 [ 181.844179] ? page_fault_oops+0x99/0x1b0 [ 181.844192] ? do_user_addr_fault+0x31d/0x6b0 [ 181.844204] ? exc_page_fault+0x83/0x1b0 [ 181.844216] ? asm_exc_page_fault+0x27/0x30 [ 181.844237] dcn20_get_dcc_compression_cap+0x23/0x30 [amdgpu] [ 181.845115] amdgpu_dm_plane_validate_dcc.constprop.0+0xe5/0x180 [amdgpu] [ 181.845985] amdgpu_dm_plane_fill_plane_buffer_attributes+0x300/0x580 [amdgpu] [ 181.846848] fill_dc_plane_info_and_addr+0x258/0x350 [amdgpu] [ 181.847734] fill_dc_plane_attributes+0x162/0x350 [amdgpu] [ 181.848748] dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu] [ 181.849791] ? dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu] [ 181.850840] amdgpu_dm_atomic_check+0xdfe/0x1760 [amdgpu] Signed-off-by: Aurabindo Pillai Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/resource/dcn20/dcn20_resource.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index e783afbbb397..5e7cfa8e8ec9 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -2200,10 +2200,11 @@ bool dcn20_get_dcc_compression_cap(const struct dc *dc, const struct dc_dcc_surface_param *input, struct dc_surface_dcc_cap *output) { - return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( - dc->res_pool->hubbub, - input, - output); + if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap) + return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( + dc->res_pool->hubbub, input, output); + + return false; } static void dcn20_destroy_resource_pool(struct resource_pool **pool) From 291af3f59849c54aba2d96256680a5d4688f97f3 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Mon, 13 May 2024 20:51:18 +0800 Subject: [PATCH 75/87] drm/amdgpu: tolerate allocating GTT bo with dcc flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not return failure for allocating GTT bo with dcc flag on gfx12. This will improve compatibility for UMD. Signed-off-by: Frank Min Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 1f22b4208729..ebb3f87ef4f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -342,11 +342,6 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, if (args->in.domains & ~AMDGPU_GEM_DOMAIN_MASK) return -EINVAL; - if ((flags & AMDGPU_GEM_CREATE_GFX12_DCC) && - ((amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(12, 0, 0)) || - !(args->in.domains & AMDGPU_GEM_DOMAIN_VRAM))) - return -EINVAL; - if (!amdgpu_is_tmz(adev) && (flags & AMDGPU_GEM_CREATE_ENCRYPTED)) { DRM_NOTE_ONCE("Cannot allocate secure buffer since TMZ is disabled\n"); return -EINVAL; From d4b8386c86800bd9616dcfc82724243609c01c55 Mon Sep 17 00:00:00 2001 From: Sonny Jiang Date: Tue, 18 Jun 2024 14:37:05 -0400 Subject: [PATCH 76/87] drm/amdgpu/jpeg5: Add support for DPG mode Add DPG support for JPEG 5.0 Signed-off-by: Sonny Jiang Acked-by: Saleemkhan Jamadar Reviewed-by: David (Ming Qiang) Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h | 31 +++++ drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c | 159 ++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h | 6 + drivers/gpu/drm/amd/amdgpu/soc24.c | 1 + 4 files changed, 180 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h index aea31d61d991..f9cdd873ac9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h @@ -60,6 +60,37 @@ RREG32_SOC15(JPEG, inst_idx, mmUVD_DPG_LMA_DATA); \ }) +#define WREG32_SOC24_JPEG_DPG_MODE(inst_idx, offset, value, indirect) \ + do { \ + WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \ + regUVD_DPG_LMA_DATA, value); \ + WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \ + regUVD_DPG_LMA_MASK, 0xFFFFFFFF); \ + WREG32_SOC15( \ + JPEG, GET_INST(JPEG, inst_idx), \ + regUVD_DPG_LMA_CTL, \ + (UVD_DPG_LMA_CTL__READ_WRITE_MASK | \ + offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT | \ + indirect << UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT)); \ + } while (0) + +#define RREG32_SOC24_JPEG_DPG_MODE(inst_idx, offset, mask_en) \ + do { \ + WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \ + regUVD_DPG_LMA_MASK, 0xFFFFFFFF); \ + WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \ + regUVD_DPG_LMA_CTL, \ + (UVD_DPG_LMA_CTL__MASK_EN_MASK | \ + offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \ + RREG32_SOC15(JPEG, inst_idx, regUVD_DPG_LMA_DATA); \ + } while (0) + +#define ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, offset, value, indirect) \ + do { \ + *adev->jpeg.inst[inst_idx].dpg_sram_curr_addr++ = offset; \ + *adev->jpeg.inst[inst_idx].dpg_sram_curr_addr++ = value; \ + } while (0) + struct amdgpu_jpeg_reg{ unsigned jpeg_pitch[AMDGPU_MAX_JPEG_RINGS]; }; diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c index e766b9463759..d694a276498a 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c @@ -31,6 +31,7 @@ #include "vcn/vcn_5_0_0_offset.h" #include "vcn/vcn_5_0_0_sh_mask.h" #include "ivsrcid/vcn/irqsrcs_vcn_4_0.h" +#include "jpeg_v5_0_0.h" static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void jpeg_v5_0_0_set_irq_funcs(struct amdgpu_device *adev); @@ -137,6 +138,10 @@ static int jpeg_v5_0_0_hw_init(void *handle) adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0); + /* Skip ring test because pause DPG is not implemented. */ + if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) + return 0; + r = amdgpu_ring_test_helper(ring); if (r) return r; @@ -235,7 +240,7 @@ static void jpeg_v5_0_0_enable_clock_gating(struct amdgpu_device *adev) WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data); } -static int jpeg_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev) +static int jpeg_v5_0_0_disable_power_gating(struct amdgpu_device *adev) { uint32_t data = 0; @@ -248,14 +253,10 @@ static int jpeg_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev) WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0, ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); - /* keep the JPEG in static PG mode */ - WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0, - ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK); - return 0; } -static int jpeg_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev) +static int jpeg_v5_0_0_enable_power_gating(struct amdgpu_device *adev) { /* enable anti hang mechanism */ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), @@ -273,6 +274,121 @@ static int jpeg_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev) return 0; } +static void jpeg_engine_5_0_0_dpg_clock_gating_mode(struct amdgpu_device *adev, + int inst_idx, uint8_t indirect) +{ + uint32_t data = 0; + + // JPEG disable CGC + if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) + data = 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; + else + data = 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; + + data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; + data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT; + + if (indirect) { + ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect); + + // Turn on All JPEG clocks + data = 0; + ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_GATE, data, indirect); + } else { + WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect); + + // Turn on All JPEG clocks + data = 0; + WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_GATE, data, indirect); + } +} + +/** + * jpeg_v5_0_0_start_dpg_mode - Jpeg start with dpg mode + * + * @adev: amdgpu_device pointer + * @inst_idx: instance number index + * @indirect: indirectly write sram + * + * Start JPEG block with dpg mode + */ +static int jpeg_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) +{ + struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec; + uint32_t reg_data = 0; + + jpeg_v5_0_0_enable_power_gating(adev); + + // enable dynamic power gating mode + reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS); + reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK; + WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data); + + if (indirect) + adev->jpeg.inst[inst_idx].dpg_sram_curr_addr = + (uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr; + + jpeg_engine_5_0_0_dpg_clock_gating_mode(adev, inst_idx, indirect); + + /* MJPEG global tiling registers */ + if (indirect) + ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config, indirect); + else + WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG, + adev->gfx.config.gb_addr_config, 1); + + /* enable System Interrupt for JRBC */ + if (indirect) + ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_SYS_INT_EN, + JPEG_SYS_INT_EN__DJRBC0_MASK, indirect); + else + WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_SYS_INT_EN, + JPEG_SYS_INT_EN__DJRBC0_MASK, 1); + + if (indirect) { + /* add nop to workaround PSP size check */ + ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipUVD_NO_OP, 0, indirect); + + amdgpu_jpeg_psp_update_sram(adev, inst_idx, 0); + } + + WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL, + ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT | + VCN_JPEG_DB_CTRL__EN_MASK); + + WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0); + WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L)); + WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, + lower_32_bits(ring->gpu_addr)); + WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, + upper_32_bits(ring->gpu_addr)); + WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_RPTR, 0); + WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR, 0); + WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, 0x00000002L); + WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_SIZE, ring->ring_size / 4); + ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR); + + return 0; +} + +/** + * jpeg_v5_0_0_stop_dpg_mode - Jpeg stop with dpg mode + * + * @adev: amdgpu_device pointer + * @inst_idx: instance number index + * + * Stop JPEG block with dpg mode + */ +static void jpeg_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +{ + uint32_t reg_data = 0; + + reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS); + reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK; + WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data); +} + /** * jpeg_v5_0_0_start - start JPEG block * @@ -288,8 +404,13 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev) if (adev->pm.dpm_enabled) amdgpu_dpm_enable_jpeg(adev, true); + if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) { + r = jpeg_v5_0_0_start_dpg_mode(adev, 0, adev->jpeg.indirect_sram); + return r; + } + /* disable power gating */ - r = jpeg_v5_0_0_disable_static_power_gating(adev); + r = jpeg_v5_0_0_disable_power_gating(adev); if (r) return r; @@ -300,7 +421,6 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev) WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config); - /* enable JMI channel */ WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0, ~UVD_JMI_CNTL__SOFT_RESET_MASK); @@ -340,17 +460,22 @@ static int jpeg_v5_0_0_stop(struct amdgpu_device *adev) { int r; - /* reset JMI */ - WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), - UVD_JMI_CNTL__SOFT_RESET_MASK, - ~UVD_JMI_CNTL__SOFT_RESET_MASK); + if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) { + jpeg_v5_0_0_stop_dpg_mode(adev, 0); + } else { - jpeg_v5_0_0_enable_clock_gating(adev); + /* reset JMI */ + WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), + UVD_JMI_CNTL__SOFT_RESET_MASK, + ~UVD_JMI_CNTL__SOFT_RESET_MASK); - /* enable power gating */ - r = jpeg_v5_0_0_enable_static_power_gating(adev); - if (r) - return r; + jpeg_v5_0_0_enable_clock_gating(adev); + + /* enable power gating */ + r = jpeg_v5_0_0_enable_power_gating(adev); + if (r) + return r; + } if (adev->pm.dpm_enabled) amdgpu_dpm_enable_jpeg(adev, false); diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h index bd348336b215..5abb96159814 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h @@ -24,6 +24,12 @@ #ifndef __JPEG_V5_0_0_H__ #define __JPEG_V5_0_0_H__ +#define vcnipJPEG_CGC_GATE 0x4160 +#define vcnipJPEG_CGC_CTRL 0x4161 +#define vcnipJPEG_SYS_INT_EN 0x4141 +#define vcnipUVD_NO_OP 0x0029 +#define vcnipJPEG_DEC_GFX10_ADDR_CONFIG 0x404A + extern const struct amdgpu_ip_block_version jpeg_v5_0_0_ip_block; #endif /* __JPEG_V5_0_0_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/soc24.c b/drivers/gpu/drm/amd/amdgpu/soc24.c index a15673e2dc99..d27fb4ea6612 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc24.c +++ b/drivers/gpu/drm/amd/amdgpu/soc24.c @@ -428,6 +428,7 @@ static int soc24_common_early_init(void *handle) adev->pg_flags = AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_JPEG | + AMD_PG_SUPPORT_JPEG_DPG | AMD_PG_SUPPORT_VCN_DPG; adev->external_rev_id = adev->rev_id + 0x50; break; From 772e4d56dab5448eb120f74811eaa71d7a474c1f Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Thu, 2 May 2024 16:51:39 -0400 Subject: [PATCH 77/87] drm/amd/amdgpu: Add ISP support to amdgpu_discovery ISP hw block is supported in some of the AMD GPU versions, add support to discover ISP IP in amdgpu_discovery. v2: squash in documentation update (Alex) Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + drivers/gpu/drm/amd/include/amd_shared.h | 2 ++ 3 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7cb11396e844..5e588cc3d0f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -720,6 +720,7 @@ enum amd_hw_ip_block_type { XGMI_HWIP, DCI_HWIP, PCIE_HWIP, + ISP_HWIP, MAX_HWIP }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 7f265163eb1f..925198225563 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -225,6 +225,7 @@ static int hw_id_map[MAX_HWIP] = { [DCI_HWIP] = DCI_HWID, [PCIE_HWIP] = PCIE_HWID, [VPE_HWIP] = VPE_HWID, + [ISP_HWIP] = ISP_HWID, }; static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 36ee9d3d6d9c..f5b725f10a7c 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -86,6 +86,7 @@ enum amd_apu_flags { * @AMD_IP_BLOCK_TYPE_JPEG: JPEG Engine * @AMD_IP_BLOCK_TYPE_VPE: Video Processing Engine * @AMD_IP_BLOCK_TYPE_UMSCH_MM: User Mode Schduler for Multimedia +* @AMD_IP_BLOCK_TYPE_ISP: Image Signal Processor * @AMD_IP_BLOCK_TYPE_NUM: Total number of IP block types */ enum amd_ip_block_type { @@ -105,6 +106,7 @@ enum amd_ip_block_type { AMD_IP_BLOCK_TYPE_JPEG, AMD_IP_BLOCK_TYPE_VPE, AMD_IP_BLOCK_TYPE_UMSCH_MM, + AMD_IP_BLOCK_TYPE_ISP, AMD_IP_BLOCK_TYPE_NUM, }; From 8fcbfd53ead3d5faf8c79b7179aa1caecd44384c Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Thu, 2 May 2024 18:54:05 -0400 Subject: [PATCH 78/87] drm/amd/amdgpu: Add ISP driver support Add the isp driver in amdgpu to support ISP device on the APUs that supports ISP IP block. ISP hw block is used for camera front-end, pre and post processing operations. Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 278 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h | 51 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 + 7 files changed, 345 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index dfd2d594e143..a95f93056a5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -323,4 +323,7 @@ amdgpu-y += $(AMD_DISPLAY_FILES) endif +# add isp block +amdgpu-y += amdgpu_isp.o + obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5e588cc3d0f8..18738ad06980 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -112,6 +112,7 @@ #include "amdgpu_xcp.h" #include "amdgpu_seq64.h" #include "amdgpu_reg_state.h" +#include "amdgpu_isp.h" #define MAX_GPU_INSTANCE 64 @@ -1047,6 +1048,9 @@ struct amdgpu_device { /* display related functionality */ struct amdgpu_display_manager dm; + /* isp */ + struct amdgpu_isp isp; + /* mes */ bool enable_mes; bool enable_mes_kiq; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c new file mode 100644 index 000000000000..25e88661ac60 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#include +#include + +#include "amdgpu.h" +#include "amdgpu_isp.h" + +#define mmDAGB0_WRCLI5_V4_1 0x6811C +#define mmDAGB0_WRCLI9_V4_1 0x6812C +#define mmDAGB0_WRCLI10_V4_1 0x68130 +#define mmDAGB0_WRCLI14_V4_1 0x68140 +#define mmDAGB0_WRCLI19_V4_1 0x68154 +#define mmDAGB0_WRCLI20_V4_1 0x68158 + +static int isp_sw_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->isp.parent = adev->dev; + + adev->isp.cgs_device = amdgpu_cgs_create_device(adev); + if (!adev->isp.cgs_device) + return -EINVAL; + + return 0; +} + +static int isp_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->isp.cgs_device) + amdgpu_cgs_destroy_device(adev->isp.cgs_device); + + return 0; +} + +/** + * isp_hw_init - start and test isp block + * + * @handle: handle for amdgpu_device pointer + * + */ +static int isp_hw_init(void *handle) +{ + int r; + u64 isp_base; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + const struct amdgpu_ip_block *ip_block = + amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ISP); + + if (!ip_block) + return -EINVAL; + + if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) + return -EINVAL; + + isp_base = adev->rmmio_base; + + adev->isp.isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL); + if (!adev->isp.isp_cell) { + r = -ENOMEM; + DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__); + goto failure; + } + + adev->isp.isp_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); + if (!adev->isp.isp_res) { + r = -ENOMEM; + DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + goto failure; + } + + adev->isp.isp_pdata = kzalloc(sizeof(*adev->isp.isp_pdata), GFP_KERNEL); + if (!adev->isp.isp_pdata) { + r = -ENOMEM; + DRM_ERROR("%s: isp platform data alloc failed\n", __func__); + goto failure; + } + + /* initialize isp platform data */ + adev->isp.isp_pdata->adev = (void *)adev; + adev->isp.isp_pdata->asic_type = adev->asic_type; + adev->isp.isp_pdata->base_rmmio_size = adev->rmmio_size; + + adev->isp.isp_res[0].name = "isp_reg"; + adev->isp.isp_res[0].flags = IORESOURCE_MEM; + adev->isp.isp_res[0].start = isp_base; + adev->isp.isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; + + adev->isp.isp_cell[0].name = "amd_isp_capture"; + adev->isp.isp_cell[0].num_resources = 1; + adev->isp.isp_cell[0].resources = &adev->isp.isp_res[0]; + adev->isp.isp_cell[0].platform_data = adev->isp.isp_pdata; + adev->isp.isp_cell[0].pdata_size = sizeof(struct isp_platform_data); + + r = mfd_add_hotplug_devices(adev->isp.parent, adev->isp.isp_cell, 1); + if (r) { + DRM_ERROR("%s: add mfd hotplug device failed\n", __func__); + goto failure; + } + + /* + * Temporary WA added to disable MMHUB TLSi until the GART initialization + * is ready to support MMHUB TLSi and SAW for ISP HW to access GART memory + * using the TLSi path + */ + cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI5_V4_1 >> 2, 0xFE5FEAA8); + cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI9_V4_1 >> 2, 0xFE5FEAA8); + cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI10_V4_1 >> 2, 0xFE5FEAA8); + cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI14_V4_1 >> 2, 0xFE5FEAA8); + cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI19_V4_1 >> 2, 0xFE5FEAA8); + cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI20_V4_1 >> 2, 0xFE5FEAA8); + + return 0; + +failure: + + kfree(adev->isp.isp_pdata); + kfree(adev->isp.isp_res); + kfree(adev->isp.isp_cell); + + return r; +} + +/** + * isp_hw_fini - stop the hardware block + * + * @handle: handle for amdgpu_device pointer + * + */ +static int isp_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + /* remove isp mfd device */ + mfd_remove_devices(adev->isp.parent); + + kfree(adev->isp.isp_res); + kfree(adev->isp.isp_cell); + kfree(adev->isp.isp_pdata); + + return 0; +} + +static int isp_suspend(void *handle) +{ + return 0; +} + +static int isp_resume(void *handle) +{ + return 0; +} + +static int isp_load_fw_by_psp(struct amdgpu_device *adev) +{ + const struct common_firmware_header *hdr; + char ucode_prefix[30]; + char fw_name[40]; + int r = 0; + + /* get isp fw binary name and path */ + amdgpu_ucode_ip_version_decode(adev, ISP_HWIP, ucode_prefix, + sizeof(ucode_prefix)); + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix); + + /* read isp fw */ + r = amdgpu_ucode_request(adev, &adev->isp.fw, fw_name); + if (r) { + amdgpu_ucode_release(&adev->isp.fw); + return r; + } + + hdr = (const struct common_firmware_header *)adev->isp.fw->data; + + adev->firmware.ucode[AMDGPU_UCODE_ID_ISP].ucode_id = + AMDGPU_UCODE_ID_ISP; + adev->firmware.ucode[AMDGPU_UCODE_ID_ISP].fw = adev->isp.fw; + + adev->firmware.fw_size += + ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); + + return r; +} + +static int isp_early_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + ret = isp_load_fw_by_psp(adev); + if (ret) { + DRM_WARN("%s: isp fw load failed %d\n", __func__, ret); + /* allow amdgpu init to proceed though isp fw load fails */ + ret = 0; + } + + return ret; +} + +static bool isp_is_idle(void *handle) +{ + return true; +} + +static int isp_wait_for_idle(void *handle) +{ + return 0; +} + +static int isp_soft_reset(void *handle) +{ + return 0; +} + +static int isp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int isp_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +static const struct amd_ip_funcs isp_ip_funcs = { + .name = "isp_ip", + .early_init = isp_early_init, + .late_init = NULL, + .sw_init = isp_sw_init, + .sw_fini = isp_sw_fini, + .hw_init = isp_hw_init, + .hw_fini = isp_hw_fini, + .suspend = isp_suspend, + .resume = isp_resume, + .is_idle = isp_is_idle, + .wait_for_idle = isp_wait_for_idle, + .soft_reset = isp_soft_reset, + .set_clockgating_state = isp_set_clockgating_state, + .set_powergating_state = isp_set_powergating_state, +}; + +const struct amdgpu_ip_block_version isp_ip_block = { + .type = AMD_IP_BLOCK_TYPE_ISP, + .major = 4, + .minor = 1, + .rev = 0, + .funcs = &isp_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h new file mode 100644 index 000000000000..a11ec0543b93 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#ifndef __AMDGPU_ISP_H__ +#define __AMDGPU_ISP_H__ + +#define ISP_REGS_OFFSET_END 0x629A4 + +struct isp_platform_data { + void *adev; + u32 asic_type; + resource_size_t base_rmmio_size; +}; + +struct amdgpu_isp { + struct device *parent; + struct cgs_device *cgs_device; + struct mfd_cell *isp_cell; + struct resource *isp_res; + struct isp_platform_data *isp_pdata; + unsigned int harvest_config; + const struct firmware *fw; +}; + +extern const struct amdgpu_ip_block_version isp_ip_block; + +#endif /* __AMDGPU_ISP_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index f89de056a828..e15814d9ca17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -2559,6 +2559,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode, case AMDGPU_UCODE_ID_JPEG_RAM: *type = GFX_FW_TYPE_JPEG_RAM; break; + case AMDGPU_UCODE_ID_ISP: + *type = GFX_FW_TYPE_ISP; + break; case AMDGPU_UCODE_ID_MAXIMUM: default: return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 3588f1c5a007..4c7b53648a50 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -714,6 +714,8 @@ const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id) return "RS64_MEC_P2_STACK"; case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK: return "RS64_MEC_P3_STACK"; + case AMDGPU_UCODE_ID_ISP: + return "ISP"; default: return "UNKNOWN UCODE"; } @@ -1413,6 +1415,9 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, case VPE_HWIP: ip_name = "vpe"; break; + case ISP_HWIP: + ip_name = "isp"; + break; default: BUG(); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index f4e5285c4dd6..5bc37acd3981 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -523,6 +523,7 @@ enum AMDGPU_UCODE_ID { AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER, AMDGPU_UCODE_ID_P2S_TABLE, AMDGPU_UCODE_ID_JPEG_RAM, + AMDGPU_UCODE_ID_ISP, AMDGPU_UCODE_ID_MAXIMUM, }; From d232584ae369f13fea6b904cd7486357d5367ea5 Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Thu, 2 May 2024 19:05:57 -0400 Subject: [PATCH 79/87] drm/amd/amdgpu: Enable ISP in amdgpu_discovery Enable ISP for ISP V4.1.0 and V4.1.1 in amdgpu_discovery. Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 925198225563..b2b9498851a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -106,6 +106,7 @@ #include "jpeg_v5_0_0.h" #include "amdgpu_vpe.h" +#include "amdgpu_isp.h" #define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin" MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY); @@ -712,6 +713,10 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev, adev->sdma.sdma_mask &= ~(1U << harvest_info->list[i].number_instance); break; + case ISP_HWID: + adev->isp.harvest_config |= + ~(1U << harvest_info->list[i].number_instance); + break; default: break; } @@ -2377,6 +2382,20 @@ static int amdgpu_discovery_set_umsch_mm_ip_blocks(struct amdgpu_device *adev) return 0; } +static int amdgpu_discovery_set_isp_ip_blocks(struct amdgpu_device *adev) +{ + switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) { + case IP_VERSION(4, 1, 0): + case IP_VERSION(4, 1, 1): + amdgpu_device_ip_block_add(adev, &isp_ip_block); + break; + default: + break; + } + + return 0; +} + int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) { int r; @@ -2903,6 +2922,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) if (r) return r; + r = amdgpu_discovery_set_isp_ip_blocks(adev); + if (r) + return r; return 0; } From 8930b90be637972ccbc683887353e71c52a918d9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 May 2024 16:45:45 -0400 Subject: [PATCH 80/87] drm/amdgpu: fix Kconfig for ISP v2 Add new config option and set proper dependencies for ISP. v2: add missed guards, drop separate Kconfig Reviewed-by: Pratap Nirujogi Signed-off-by: Alex Deucher Cc: Pratap Nirujogi --- drivers/gpu/drm/amd/amdgpu/Kconfig | 11 +++++++++++ drivers/gpu/drm/amd/amdgpu/Makefile | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 4232ab27f990..0051fb1b437f 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -71,6 +71,17 @@ config DRM_AMDGPU_USERPTR This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it isn't already selected to enabled full userptr support. +config DRM_AMD_ISP + bool "Enable AMD Image Signal Processor IP support" + depends on DRM_AMDGPU + select MFD_CORE + select PM_GENERIC_DOMAINS if PM + help + Choose this option to enable ISP IP support for AMD SOCs. + This adds the ISP (Image Signal Processor) IP driver and wires + it up into the amdgpu driver. It is required for cameras + on APUs which utilize mipi cameras. + config DRM_AMDGPU_WERROR bool "Force the compiler to throw an error instead of a warning when compiling" depends on DRM_AMDGPU diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index a95f93056a5f..2ed06d516e04 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -324,6 +324,8 @@ amdgpu-y += $(AMD_DISPLAY_FILES) endif # add isp block +ifneq ($(CONFIG_DRM_AMD_ISP),) amdgpu-y += amdgpu_isp.o +endif obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 18738ad06980..137a88b8de45 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -112,7 +112,9 @@ #include "amdgpu_xcp.h" #include "amdgpu_seq64.h" #include "amdgpu_reg_state.h" +#if defined(CONFIG_DRM_AMD_ISP) #include "amdgpu_isp.h" +#endif #define MAX_GPU_INSTANCE 64 @@ -1048,8 +1050,10 @@ struct amdgpu_device { /* display related functionality */ struct amdgpu_display_manager dm; +#if defined(CONFIG_DRM_AMD_ISP) /* isp */ struct amdgpu_isp isp; +#endif /* mes */ bool enable_mes; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index b2b9498851a1..05031bfd0acf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -106,7 +106,9 @@ #include "jpeg_v5_0_0.h" #include "amdgpu_vpe.h" +#if defined(CONFIG_DRM_AMD_ISP) #include "amdgpu_isp.h" +#endif #define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin" MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY); @@ -713,10 +715,12 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev, adev->sdma.sdma_mask &= ~(1U << harvest_info->list[i].number_instance); break; +#if defined(CONFIG_DRM_AMD_ISP) case ISP_HWID: adev->isp.harvest_config |= ~(1U << harvest_info->list[i].number_instance); break; +#endif default: break; } @@ -2384,6 +2388,7 @@ static int amdgpu_discovery_set_umsch_mm_ip_blocks(struct amdgpu_device *adev) static int amdgpu_discovery_set_isp_ip_blocks(struct amdgpu_device *adev) { +#if defined(CONFIG_DRM_AMD_ISP) switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) { case IP_VERSION(4, 1, 0): case IP_VERSION(4, 1, 1): @@ -2392,6 +2397,7 @@ static int amdgpu_discovery_set_isp_ip_blocks(struct amdgpu_device *adev) default: break; } +#endif return 0; } From 0253d718a070ba109046299847fe8f3cf7568c3c Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Tue, 7 May 2024 22:49:46 -0400 Subject: [PATCH 81/87] drm/amd/amdgpu: Map ISP interrupts as generic IRQs Map ISP IH interrupts to Linux generic IRQ for ISP driver to handle the interrupts using MFD IORESOURCE_IRQ resource. Reviewed-by: Alex Deucher Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 31 ++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h | 2 + drivers/gpu/drm/amd/amdgpu/ih_v6_1.c | 6 ++ .../amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h | 62 +++++++++++++++++++ 5 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 013ff373e067..19ce4da285e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -466,7 +466,8 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev, } else if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) { DRM_DEBUG("Invalid src_id in IV: %d\n", src_id); - } else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) && + } else if (((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) || + (client_id == SOC15_IH_CLIENTID_ISP)) && adev->irq.virq[src_id]) { generic_handle_domain_irq(adev->irq.domain, src_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c index 25e88661ac60..52e53d2b8748 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -31,6 +31,8 @@ #include "amdgpu.h" #include "amdgpu_isp.h" +#include "ivsrcid/isp/irqsrcs_isp_4_1.h" + #define mmDAGB0_WRCLI5_V4_1 0x6811C #define mmDAGB0_WRCLI9_V4_1 0x6812C #define mmDAGB0_WRCLI10_V4_1 0x68130 @@ -38,6 +40,17 @@ #define mmDAGB0_WRCLI19_V4_1 0x68154 #define mmDAGB0_WRCLI20_V4_1 0x68158 +static const unsigned int isp_int_srcid[MAX_ISP_INT_SRC] = { + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 +}; + static int isp_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -69,11 +82,12 @@ static int isp_sw_fini(void *handle) */ static int isp_hw_init(void *handle) { - int r; - u64 isp_base; struct amdgpu_device *adev = (struct amdgpu_device *)handle; const struct amdgpu_ip_block *ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ISP); + u64 isp_base; + int int_idx; + int r; if (!ip_block) return -EINVAL; @@ -90,7 +104,7 @@ static int isp_hw_init(void *handle) goto failure; } - adev->isp.isp_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); + adev->isp.isp_res = kcalloc(9, sizeof(struct resource), GFP_KERNEL); if (!adev->isp.isp_res) { r = -ENOMEM; DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); @@ -114,8 +128,17 @@ static int isp_hw_init(void *handle) adev->isp.isp_res[0].start = isp_base; adev->isp.isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; + for (int_idx = 0; int_idx < MAX_ISP_INT_SRC; int_idx++) { + adev->isp.isp_res[int_idx + 1].name = "isp_irq"; + adev->isp.isp_res[int_idx + 1].flags = IORESOURCE_IRQ; + adev->isp.isp_res[int_idx + 1].start = + amdgpu_irq_create_mapping(adev, isp_int_srcid[int_idx]); + adev->isp.isp_res[int_idx + 1].end = + adev->isp.isp_res[int_idx + 1].start; + } + adev->isp.isp_cell[0].name = "amd_isp_capture"; - adev->isp.isp_cell[0].num_resources = 1; + adev->isp.isp_cell[0].num_resources = 9; adev->isp.isp_cell[0].resources = &adev->isp.isp_res[0]; adev->isp.isp_cell[0].platform_data = adev->isp.isp_pdata; adev->isp.isp_cell[0].pdata_size = sizeof(struct isp_platform_data); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h index a11ec0543b93..764d70beb9e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h @@ -30,6 +30,8 @@ #define ISP_REGS_OFFSET_END 0x629A4 +#define MAX_ISP_INT_SRC 8 + struct isp_platform_data { void *adev; u32 asic_type; diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c index 0fbf5fa7b0f8..2e0469feca1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c @@ -535,6 +535,12 @@ static void ih_v6_1_set_self_irq_funcs(struct amdgpu_device *adev) static int ih_v6_1_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret; + + ret = amdgpu_irq_add_domain(adev); + if (ret) { + return ret; + } ih_v6_1_set_interrupt_funcs(adev); ih_v6_1_set_self_irq_funcs(adev); diff --git a/drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h b/drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h new file mode 100644 index 000000000000..2ecdfd4f1b03 --- /dev/null +++ b/drivers/gpu/drm/amd/include/ivsrcid/isp/irqsrcs_isp_4_1.h @@ -0,0 +1,62 @@ +/* + * Copyright 2024 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __IRQSRCS_ISP_4_1_H__ +#define __IRQSRCS_ISP_4_1_H__ + + +#define ISP_4_1__SRCID__ISP_SEMA_WAIT_FAIL_TIMEOUT 0x12 // Semaphore wait fail timeout +#define ISP_4_1__SRCID__ISP_SEMA_WAIT_INCOMPLETE_TIMEOUT 0x13 // Semaphore wait incomplete timeout +#define ISP_4_1__SRCID__ISP_SEMA_SIGNAL_INCOMPLETE_TIMEOUT 0x14 // Semaphore signal incomplete timeout +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE5_CHANGED 0x15 // Ringbuffer base5 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT5 0x16 // Ringbuffer write point 5 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE6_CHANGED 0x17 // Ringbuffer base6 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT6 0x18 // Ringbuffer write point 6 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE7_CHANGED 0x19 // Ringbuffer base7 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT7 0x1A // Ringbuffer write point 7 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE8_CHANGED 0x1B // Ringbuffer base8 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT8 0x1C // Ringbuffer write point 8 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE9_CHANGED 0x00 // Ringbuffer base9 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9 0x01 // Ringbuffer write point 9 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE10_CHANGED 0x02 // Ringbuffer base10 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10 0x03 // Ringbuffer write point 10 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE11_CHANGED 0x04 // Ringbuffer base11 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11 0x05 // Ringbuffer write point 11 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE12_CHANGED 0x06 // Ringbuffer base12 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12 0x07 // Ringbuffer write point 12 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE13_CHANGED 0x08 // Ringbuffer base13 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13 0x09 // Ringbuffer write point 13 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE14_CHANGED 0x0A // Ringbuffer base14 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14 0x0B // Ringbuffer write point 14 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE15_CHANGED 0x0C // Ringbuffer base15 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15 0x0D // Ringbuffer write point 15 changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_BASE16_CHANGED 0x0E // Ringbuffer base16 address changed +#define ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 0x0F // Ringbuffer write point 16 changed +#define ISP_4_1__SRCID__ISP_MIPI0 0x29 // MIPI0 interrupt +#define ISP_4_1__SRCID__ISP_MIPI1 0x2A // MIPI1 interrupt +#define ISP_4_1__SRCID__ISP_I2C0 0x2B // I2C0 PAD interrupt +#define ISP_4_1__SRCID__ISP_I2C1 0x2C // I2C1 PAD interrupt +#define ISP_4_1__SRCID__ISP_FLASH0 0x2D // Flash0 interrupt +#define ISP_4_1__SRCID__ISP_FLASH1 0x2E // Flash1 interrupt +#define ISP_4_1__SRCID__ISP_DEBUG 0x2F // Debug information + +#endif From 05bafe95e580587ff5febf8ce242fa2f401a1f17 Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Fri, 17 May 2024 00:39:48 -0400 Subject: [PATCH 82/87] drm/amd/amdgpu: Add ISP4.1.0 and ISP4.1.1 modules Add independent IP centric modules for ISP4.1.0 and ISP4.1.1 hw blocks. Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 167 ++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h | 13 +- drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c | 149 ++++++++++++++++ drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h | 46 +++++ drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c | 137 ++++++++++++++ drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h | 39 ++++ 8 files changed, 427 insertions(+), 133 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c create mode 100644 drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h create mode 100644 drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c create mode 100644 drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 2ed06d516e04..9dd8294032ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -325,7 +325,10 @@ endif # add isp block ifneq ($(CONFIG_DRM_AMD_ISP),) -amdgpu-y += amdgpu_isp.o +amdgpu-y += \ + amdgpu_isp.o \ + isp_v4_1_0.o \ + isp_v4_1_1.o endif obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 05031bfd0acf..90475ddf1c03 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2391,8 +2391,10 @@ static int amdgpu_discovery_set_isp_ip_blocks(struct amdgpu_device *adev) #if defined(CONFIG_DRM_AMD_ISP) switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) { case IP_VERSION(4, 1, 0): + amdgpu_device_ip_block_add(adev, &isp_v4_1_0_ip_block); + break; case IP_VERSION(4, 1, 1): - amdgpu_device_ip_block_add(adev, &isp_ip_block); + amdgpu_device_ip_block_add(adev, &isp_v4_1_1_ip_block); break; default: break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c index 52e53d2b8748..240408486d6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -30,47 +30,16 @@ #include "amdgpu.h" #include "amdgpu_isp.h" - -#include "ivsrcid/isp/irqsrcs_isp_4_1.h" - -#define mmDAGB0_WRCLI5_V4_1 0x6811C -#define mmDAGB0_WRCLI9_V4_1 0x6812C -#define mmDAGB0_WRCLI10_V4_1 0x68130 -#define mmDAGB0_WRCLI14_V4_1 0x68140 -#define mmDAGB0_WRCLI19_V4_1 0x68154 -#define mmDAGB0_WRCLI20_V4_1 0x68158 - -static const unsigned int isp_int_srcid[MAX_ISP_INT_SRC] = { - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 -}; +#include "isp_v4_1_0.h" +#include "isp_v4_1_1.h" static int isp_sw_init(void *handle) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - adev->isp.parent = adev->dev; - - adev->isp.cgs_device = amdgpu_cgs_create_device(adev); - if (!adev->isp.cgs_device) - return -EINVAL; - return 0; } static int isp_sw_fini(void *handle) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->isp.cgs_device) - amdgpu_cgs_destroy_device(adev->isp.cgs_device); - return 0; } @@ -83,93 +52,18 @@ static int isp_sw_fini(void *handle) static int isp_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_isp *isp = &adev->isp; + const struct amdgpu_ip_block *ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ISP); - u64 isp_base; - int int_idx; - int r; if (!ip_block) return -EINVAL; - if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) - return -EINVAL; + if (isp->funcs->hw_init != NULL) + return isp->funcs->hw_init(isp); - isp_base = adev->rmmio_base; - - adev->isp.isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL); - if (!adev->isp.isp_cell) { - r = -ENOMEM; - DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__); - goto failure; - } - - adev->isp.isp_res = kcalloc(9, sizeof(struct resource), GFP_KERNEL); - if (!adev->isp.isp_res) { - r = -ENOMEM; - DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); - goto failure; - } - - adev->isp.isp_pdata = kzalloc(sizeof(*adev->isp.isp_pdata), GFP_KERNEL); - if (!adev->isp.isp_pdata) { - r = -ENOMEM; - DRM_ERROR("%s: isp platform data alloc failed\n", __func__); - goto failure; - } - - /* initialize isp platform data */ - adev->isp.isp_pdata->adev = (void *)adev; - adev->isp.isp_pdata->asic_type = adev->asic_type; - adev->isp.isp_pdata->base_rmmio_size = adev->rmmio_size; - - adev->isp.isp_res[0].name = "isp_reg"; - adev->isp.isp_res[0].flags = IORESOURCE_MEM; - adev->isp.isp_res[0].start = isp_base; - adev->isp.isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; - - for (int_idx = 0; int_idx < MAX_ISP_INT_SRC; int_idx++) { - adev->isp.isp_res[int_idx + 1].name = "isp_irq"; - adev->isp.isp_res[int_idx + 1].flags = IORESOURCE_IRQ; - adev->isp.isp_res[int_idx + 1].start = - amdgpu_irq_create_mapping(adev, isp_int_srcid[int_idx]); - adev->isp.isp_res[int_idx + 1].end = - adev->isp.isp_res[int_idx + 1].start; - } - - adev->isp.isp_cell[0].name = "amd_isp_capture"; - adev->isp.isp_cell[0].num_resources = 9; - adev->isp.isp_cell[0].resources = &adev->isp.isp_res[0]; - adev->isp.isp_cell[0].platform_data = adev->isp.isp_pdata; - adev->isp.isp_cell[0].pdata_size = sizeof(struct isp_platform_data); - - r = mfd_add_hotplug_devices(adev->isp.parent, adev->isp.isp_cell, 1); - if (r) { - DRM_ERROR("%s: add mfd hotplug device failed\n", __func__); - goto failure; - } - - /* - * Temporary WA added to disable MMHUB TLSi until the GART initialization - * is ready to support MMHUB TLSi and SAW for ISP HW to access GART memory - * using the TLSi path - */ - cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI5_V4_1 >> 2, 0xFE5FEAA8); - cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI9_V4_1 >> 2, 0xFE5FEAA8); - cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI10_V4_1 >> 2, 0xFE5FEAA8); - cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI14_V4_1 >> 2, 0xFE5FEAA8); - cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI19_V4_1 >> 2, 0xFE5FEAA8); - cgs_write_register(adev->isp.cgs_device, mmDAGB0_WRCLI20_V4_1 >> 2, 0xFE5FEAA8); - - return 0; - -failure: - - kfree(adev->isp.isp_pdata); - kfree(adev->isp.isp_res); - kfree(adev->isp.isp_cell); - - return r; + return -ENODEV; } /** @@ -181,15 +75,12 @@ failure: static int isp_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_isp *isp = &adev->isp; - /* remove isp mfd device */ - mfd_remove_devices(adev->isp.parent); + if (isp->funcs->hw_fini != NULL) + return isp->funcs->hw_fini(isp); - kfree(adev->isp.isp_res); - kfree(adev->isp.isp_cell); - kfree(adev->isp.isp_pdata); - - return 0; + return -ENODEV; } static int isp_suspend(void *handle) @@ -235,17 +126,29 @@ static int isp_load_fw_by_psp(struct amdgpu_device *adev) static int isp_early_init(void *handle) { - int ret = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_isp *isp = &adev->isp; - ret = isp_load_fw_by_psp(adev); - if (ret) { - DRM_WARN("%s: isp fw load failed %d\n", __func__, ret); - /* allow amdgpu init to proceed though isp fw load fails */ - ret = 0; + switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) { + case IP_VERSION(4, 1, 0): + isp_v4_1_0_set_isp_funcs(isp); + break; + case IP_VERSION(4, 1, 1): + isp_v4_1_1_set_isp_funcs(isp); + break; + default: + return -EINVAL; } - return ret; + isp->adev = adev; + isp->parent = adev->dev; + + if (isp_load_fw_by_psp(adev)) { + DRM_WARN("%s: isp fw load failed\n", __func__); + return 0; + } + + return 0; } static bool isp_is_idle(void *handle) @@ -292,10 +195,18 @@ static const struct amd_ip_funcs isp_ip_funcs = { .set_powergating_state = isp_set_powergating_state, }; -const struct amdgpu_ip_block_version isp_ip_block = { +const struct amdgpu_ip_block_version isp_v4_1_0_ip_block = { .type = AMD_IP_BLOCK_TYPE_ISP, .major = 4, .minor = 1, .rev = 0, .funcs = &isp_ip_funcs, }; + +const struct amdgpu_ip_block_version isp_v4_1_1_ip_block = { + .type = AMD_IP_BLOCK_TYPE_ISP, + .major = 4, + .minor = 1, + .rev = 1, + .funcs = &isp_ip_funcs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h index 764d70beb9e9..44e2ea8c9728 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h @@ -30,7 +30,7 @@ #define ISP_REGS_OFFSET_END 0x629A4 -#define MAX_ISP_INT_SRC 8 +struct amdgpu_isp; struct isp_platform_data { void *adev; @@ -38,9 +38,15 @@ struct isp_platform_data { resource_size_t base_rmmio_size; }; +struct isp_funcs { + int (*hw_init)(struct amdgpu_isp *isp); + int (*hw_fini)(struct amdgpu_isp *isp); +}; + struct amdgpu_isp { struct device *parent; - struct cgs_device *cgs_device; + struct amdgpu_device *adev; + const struct isp_funcs *funcs; struct mfd_cell *isp_cell; struct resource *isp_res; struct isp_platform_data *isp_pdata; @@ -48,6 +54,7 @@ struct amdgpu_isp { const struct firmware *fw; }; -extern const struct amdgpu_ip_block_version isp_ip_block; +extern const struct amdgpu_ip_block_version isp_v4_1_0_ip_block; +extern const struct amdgpu_ip_block_version isp_v4_1_1_ip_block; #endif /* __AMDGPU_ISP_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c new file mode 100644 index 000000000000..962da37fb1f7 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#include "amdgpu.h" +#include "isp_v4_1_0.h" + +static const unsigned int isp_4_1_0_int_srcid[MAX_ISP410_INT_SRC] = { + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 +}; + +static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) +{ + struct amdgpu_device *adev = isp->adev; + u64 isp_base; + int int_idx; + int r; + + if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) + return -EINVAL; + + isp_base = adev->rmmio_base; + + isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL); + if (!isp->isp_cell) { + r = -ENOMEM; + DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__); + goto failure; + } + + isp->isp_res = kcalloc(MAX_ISP410_INT_SRC + 1, sizeof(struct resource), + GFP_KERNEL); + if (!isp->isp_res) { + r = -ENOMEM; + DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + goto failure; + } + + isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); + if (!isp->isp_pdata) { + r = -ENOMEM; + DRM_ERROR("%s: isp platform data alloc failed\n", __func__); + goto failure; + } + + /* initialize isp platform data */ + isp->isp_pdata->adev = (void *)adev; + isp->isp_pdata->asic_type = adev->asic_type; + isp->isp_pdata->base_rmmio_size = adev->rmmio_size; + + isp->isp_res[0].name = "isp_4_1_0_reg"; + isp->isp_res[0].flags = IORESOURCE_MEM; + isp->isp_res[0].start = isp_base; + isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; + + for (int_idx = 0; int_idx < MAX_ISP410_INT_SRC; int_idx++) { + isp->isp_res[int_idx + 1].name = "isp_4_1_0_irq"; + isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ; + isp->isp_res[int_idx + 1].start = + amdgpu_irq_create_mapping(adev, isp_4_1_0_int_srcid[int_idx]); + isp->isp_res[int_idx + 1].end = + isp->isp_res[int_idx + 1].start; + } + + isp->isp_cell[0].name = "amd_isp_capture"; + isp->isp_cell[0].num_resources = MAX_ISP410_INT_SRC + 1; + isp->isp_cell[0].resources = &isp->isp_res[0]; + isp->isp_cell[0].platform_data = isp->isp_pdata; + isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); + + r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1); + if (r) { + DRM_ERROR("%s: add mfd hotplug device failed\n", __func__); + goto failure; + } + + /* + * Temporary WA added to disable MMHUB TLSi until the GART initialization + * is ready to support MMHUB TLSi and SAW for ISP HW to access GART memory + * using the TLSi path + */ + WREG32(mmDAGB0_WRCLI5_V4_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB0_WRCLI9_V4_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB0_WRCLI10_V4_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB0_WRCLI14_V4_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB0_WRCLI19_V4_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB0_WRCLI20_V4_1 >> 2, 0xFE5FEAA8); + + return 0; + +failure: + + kfree(isp->isp_pdata); + kfree(isp->isp_res); + kfree(isp->isp_cell); + + return r; +} + +static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp) +{ + mfd_remove_devices(isp->parent); + + kfree(isp->isp_res); + kfree(isp->isp_cell); + kfree(isp->isp_pdata); + + return 0; +} + +static const struct isp_funcs isp_v4_1_0_funcs = { + .hw_init = isp_v4_1_0_hw_init, + .hw_fini = isp_v4_1_0_hw_fini, +}; + +void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp) +{ + isp->funcs = &isp_v4_1_0_funcs; +} diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h new file mode 100644 index 000000000000..bd9e1f13c748 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#ifndef __ISP_V4_1_0_H__ +#define __ISP_V4_1_0_H__ + +#include "amdgpu_isp.h" + +#include "ivsrcid/isp/irqsrcs_isp_4_1.h" + +#define mmDAGB0_WRCLI5_V4_1 0x6811C +#define mmDAGB0_WRCLI9_V4_1 0x6812C +#define mmDAGB0_WRCLI10_V4_1 0x68130 +#define mmDAGB0_WRCLI14_V4_1 0x68140 +#define mmDAGB0_WRCLI19_V4_1 0x68154 +#define mmDAGB0_WRCLI20_V4_1 0x68158 + +#define MAX_ISP410_INT_SRC 8 + +void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp); + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c new file mode 100644 index 000000000000..4e17fa03f7b5 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#include "amdgpu.h" +#include "isp_v4_1_1.h" + +static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = { + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, + ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 +}; + +static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) +{ + struct amdgpu_device *adev = isp->adev; + u64 isp_base; + int int_idx; + int r; + + if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) + return -EINVAL; + + isp_base = adev->rmmio_base; + + isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL); + if (!isp->isp_cell) { + r = -ENOMEM; + DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__); + goto failure; + } + + isp->isp_res = kcalloc(MAX_ISP411_INT_SRC + 1, sizeof(struct resource), + GFP_KERNEL); + if (!isp->isp_res) { + r = -ENOMEM; + DRM_ERROR("%s: isp mfd res alloc failed\n", __func__); + goto failure; + } + + isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); + if (!isp->isp_pdata) { + r = -ENOMEM; + DRM_ERROR("%s: isp platform data alloc failed\n", __func__); + goto failure; + } + + /* initialize isp platform data */ + isp->isp_pdata->adev = (void *)adev; + isp->isp_pdata->asic_type = adev->asic_type; + isp->isp_pdata->base_rmmio_size = adev->rmmio_size; + + isp->isp_res[0].name = "isp_4_1_1_reg"; + isp->isp_res[0].flags = IORESOURCE_MEM; + isp->isp_res[0].start = isp_base; + isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; + + for (int_idx = 0; int_idx < MAX_ISP411_INT_SRC; int_idx++) { + isp->isp_res[int_idx + 1].name = "isp_4_1_1_irq"; + isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ; + isp->isp_res[int_idx + 1].start = + amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]); + isp->isp_res[int_idx + 1].end = + isp->isp_res[int_idx + 1].start; + } + + isp->isp_cell[0].name = "amd_isp_capture"; + isp->isp_cell[0].num_resources = MAX_ISP411_INT_SRC + 1; + isp->isp_cell[0].resources = &isp->isp_res[0]; + isp->isp_cell[0].platform_data = isp->isp_pdata; + isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); + + r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1); + if (r) { + DRM_ERROR("%s: add mfd hotplug device failed\n", __func__); + goto failure; + } + + return 0; + +failure: + + kfree(isp->isp_pdata); + kfree(isp->isp_res); + kfree(isp->isp_cell); + + return r; +} + +static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp) +{ + mfd_remove_devices(isp->parent); + + kfree(isp->isp_res); + kfree(isp->isp_cell); + kfree(isp->isp_pdata); + + return 0; +} + +static const struct isp_funcs isp_v4_1_1_funcs = { + .hw_init = isp_v4_1_1_hw_init, + .hw_fini = isp_v4_1_1_hw_fini, +}; + +void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp) +{ + isp->funcs = &isp_v4_1_1_funcs; +} diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h new file mode 100644 index 000000000000..dfb9522c9d6a --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +#ifndef __ISP_V4_1_1_H__ +#define __ISP_V4_1_1_H__ + +#include "amdgpu_isp.h" + +#include "ivsrcid/isp/irqsrcs_isp_4_1.h" + +#define MAX_ISP411_INT_SRC 8 + +void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp); + +#endif From 062666ffbc80e15154315550d2aa171c23e76c61 Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Thu, 16 May 2024 02:39:14 -0400 Subject: [PATCH 83/87] drm/amd/amdgpu: Disable MMHUB prefetch for ISP v4.1.1 Disable MMHUB prefetch for ISP v4.1.1 as a temporary WA until the GART supports MMHUB TLSi and SAW for ISP HW to access GART memory using the TLSi path. Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c | 12 ++++++++++++ drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c index 4e17fa03f7b5..67f95f05ecca 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c @@ -104,6 +104,18 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) goto failure; } + /* + * Temporary WA added to disable MMHUB TLSi until the GART initialization + * is ready to support MMHUB TLSi and SAW for ISP HW to access GART memory + * using the TLSi path + */ + WREG32(mmDAGB1_WRCLI5_V4_1_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB1_WRCLI9_V4_1_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB1_WRCLI10_V4_1_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB1_WRCLI14_V4_1_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB1_WRCLI19_V4_1_1 >> 2, 0xFE5FEAA8); + WREG32(mmDAGB1_WRCLI20_V4_1_1 >> 2, 0xFE5FEAA8); + return 0; failure: diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h index dfb9522c9d6a..6bfb1de191a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h @@ -32,6 +32,13 @@ #include "ivsrcid/isp/irqsrcs_isp_4_1.h" +#define mmDAGB1_WRCLI5_V4_1_1 0x68420 +#define mmDAGB1_WRCLI9_V4_1_1 0x68430 +#define mmDAGB1_WRCLI10_V4_1_1 0x68434 +#define mmDAGB1_WRCLI14_V4_1_1 0x68444 +#define mmDAGB1_WRCLI19_V4_1_1 0x68458 +#define mmDAGB1_WRCLI20_V4_1_1 0x6845C + #define MAX_ISP411_INT_SRC 8 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp); From 7c2d3112b212c9eb64dad7b28a8b1a4a7ad03062 Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Mon, 27 May 2024 15:05:47 -0400 Subject: [PATCH 84/87] drm/amd/amdgpu: Fix 'snprintf' output truncation warning snprintf can truncate the output fw filename if the isp ucode_prefix exceeds 29 characters. Knowing ISP ucode_prefix is in the format isp_x_x_x, limiting the size of ucode_prefix[] to 10 characters to fix the warning. Fixes the below warning: drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c: In function 'isp_early_init': drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c:192:58: warning: 'snprintf' output may be truncated before the last format character [-Wformat-truncation=] 192 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix); | ^ In function 'isp_load_fw_by_psp', inlined from 'isp_early_init' at drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c:218:8: drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c:192:9: note: 'snprintf' output between 12 and 41 bytes into a destination of size 40 192 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Reported-by: kernel test robot Reviewed-by: Mario Limonciello Signed-off-by: Pratap Nirujogi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c index 240408486d6b..2a3f4668cb9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -96,7 +96,7 @@ static int isp_resume(void *handle) static int isp_load_fw_by_psp(struct amdgpu_device *adev) { const struct common_firmware_header *hdr; - char ucode_prefix[30]; + char ucode_prefix[10]; char fw_name[40]; int r = 0; From 75be61aa77feb09f829104fa74b359bee74f0363 Mon Sep 17 00:00:00 2001 From: Pratap Nirujogi Date: Tue, 28 May 2024 15:21:44 -0400 Subject: [PATCH 85/87] drm/amd/amdgpu: Enable MMHUB prefetch for ISP v4.1.0 and 4.1.1 Remove temporary WA to disable ISP prefetch as MMHUB SAW is initialized to support ISP HW access GART memory using the TLSi path with prefetch enabled. Signed-off-by: Pratap Nirujogi Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c | 12 ------------ drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h | 7 ------- drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c | 12 ------------ drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h | 7 ------- 4 files changed, 38 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c index 962da37fb1f7..aac107898bae 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c @@ -104,18 +104,6 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp) goto failure; } - /* - * Temporary WA added to disable MMHUB TLSi until the GART initialization - * is ready to support MMHUB TLSi and SAW for ISP HW to access GART memory - * using the TLSi path - */ - WREG32(mmDAGB0_WRCLI5_V4_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB0_WRCLI9_V4_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB0_WRCLI10_V4_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB0_WRCLI14_V4_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB0_WRCLI19_V4_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB0_WRCLI20_V4_1 >> 2, 0xFE5FEAA8); - return 0; failure: diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h index bd9e1f13c748..315f2822410c 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h @@ -32,13 +32,6 @@ #include "ivsrcid/isp/irqsrcs_isp_4_1.h" -#define mmDAGB0_WRCLI5_V4_1 0x6811C -#define mmDAGB0_WRCLI9_V4_1 0x6812C -#define mmDAGB0_WRCLI10_V4_1 0x68130 -#define mmDAGB0_WRCLI14_V4_1 0x68140 -#define mmDAGB0_WRCLI19_V4_1 0x68154 -#define mmDAGB0_WRCLI20_V4_1 0x68158 - #define MAX_ISP410_INT_SRC 8 void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp); diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c index 67f95f05ecca..4e17fa03f7b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c @@ -104,18 +104,6 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) goto failure; } - /* - * Temporary WA added to disable MMHUB TLSi until the GART initialization - * is ready to support MMHUB TLSi and SAW for ISP HW to access GART memory - * using the TLSi path - */ - WREG32(mmDAGB1_WRCLI5_V4_1_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB1_WRCLI9_V4_1_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB1_WRCLI10_V4_1_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB1_WRCLI14_V4_1_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB1_WRCLI19_V4_1_1 >> 2, 0xFE5FEAA8); - WREG32(mmDAGB1_WRCLI20_V4_1_1 >> 2, 0xFE5FEAA8); - return 0; failure: diff --git a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h index 6bfb1de191a0..dfb9522c9d6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h +++ b/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h @@ -32,13 +32,6 @@ #include "ivsrcid/isp/irqsrcs_isp_4_1.h" -#define mmDAGB1_WRCLI5_V4_1_1 0x68420 -#define mmDAGB1_WRCLI9_V4_1_1 0x68430 -#define mmDAGB1_WRCLI10_V4_1_1 0x68434 -#define mmDAGB1_WRCLI14_V4_1_1 0x68444 -#define mmDAGB1_WRCLI19_V4_1_1 0x68458 -#define mmDAGB1_WRCLI20_V4_1_1 0x6845C - #define MAX_ISP411_INT_SRC 8 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp); From 71fe4494847f03dda3932417769418c02431615c Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Thu, 30 May 2024 22:48:34 +0800 Subject: [PATCH 86/87] drm/amdgpu: refine isp firmware loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refine isp firmware loading Signed-off-by: Yang Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c index 2a3f4668cb9b..215bae809153 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -97,16 +97,14 @@ static int isp_load_fw_by_psp(struct amdgpu_device *adev) { const struct common_firmware_header *hdr; char ucode_prefix[10]; - char fw_name[40]; int r = 0; /* get isp fw binary name and path */ amdgpu_ucode_ip_version_decode(adev, ISP_HWIP, ucode_prefix, sizeof(ucode_prefix)); - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix); /* read isp fw */ - r = amdgpu_ucode_request(adev, &adev->isp.fw, fw_name); + r = amdgpu_ucode_request(adev, &adev->isp.fw, "amdgpu/%s.bin", ucode_prefix); if (r) { amdgpu_ucode_release(&adev->isp.fw); return r; From 15eb8573ad72a97b8f70e3c88b9bef6ddc861f77 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 18 Jun 2024 11:43:05 -0500 Subject: [PATCH 87/87] drm/amd: Don't initialize ISP hardware without FW Although designs may contain an ISP IP block, the camera might be a USB camera. Because of this the ISP firmware is considered optional from amdgpu. However if the firmware doesn't get loaded the hardware should not be initialized. Adjust the return code for early init to ensure the IP block doesn't go through the other init and fini sequences. Also decrease the message about firmware load failure to debug so it's not as alarming to users. Acked-by: Alex Deucher Reviewed-by: Pratap Nirujogi Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c index 215bae809153..4766e99dd98f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c @@ -142,8 +142,8 @@ static int isp_early_init(void *handle) isp->parent = adev->dev; if (isp_load_fw_by_psp(adev)) { - DRM_WARN("%s: isp fw load failed\n", __func__); - return 0; + DRM_DEBUG_DRIVER("%s: isp fw load failed\n", __func__); + return -ENOENT; } return 0;