All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 00/44] VCN instance rework
@ 2025-01-31 16:56 Alex Deucher
  2025-01-31 16:56 ` [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances Alex Deucher
                   ` (43 more replies)
  0 siblings, 44 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:56 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

These series reworks how instances are handled
for VCN to better split the state between instances.

This allows for per instance powergating and opens
the path to further splitting VCN IP blocks
per instance in the future if that is desirable. Per
instance powergating is needed for per engine resets
and can help save power on devices with multiple VCN
instances.

V3: Suggestions from Lijo, optimize fw binary storage

Alex Deucher (44):
  drm/amdgpu/vcn2.5: split code along instances
  drm/amdgpu/vcn3.0: split code along instances
  drm/amdgpu/vcn4.0: split code along instances
  drm/amdgpu/vcn4.0.3: split code along instances
  drm/amdgpu/vcn4.0.5: split code along instances
  drm/amdgpu/vcn5.0.0: split code along instances
  drm/amdgpu/vcn5.0.1: split code along instances
  drm/amdgpu/vcn: switch work handler to be per instance
  drm/amdgpu/vcn: make powergating status per instance
  drm/amdgpu/vcn: move more instanced data to vcn_instance
  drm/amdgpu/vcn: switch vcn helpers to be instance based
  drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst
  drm/amdgpu/vcn1.0: convert internal functions to use vcn_inst
  drm/amdgpu/vcn2.0: convert internal functions to use vcn_inst
  drm/amdgpu/vcn2.5: convert internal functions to use vcn_inst
  drm/amdgpu/vcn4.0: convert internal functions to use vcn_inst
  drm/amdgpu/vcn4.0.3: convert internal functions to use vcn_inst
  drm/amdgpu/vcn4.0.5: convert internal functions to use vcn_inst
  drm/amdgpu/vcn5.0.0: convert internal functions to use vcn_inst
  drm/amdgpu/vcn5.0.1: convert internal functions to use vcn_inst
  drm/amdgpu/vcn: adjust pause_dpg_mode function signature
  drm/amdgpu/vcn: add new per instance callback for powergating
  drm/amdgpu/vcn1.0: add set_pg_state callback
  drm/amdgpu/vcn2.0: add set_pg_state callback
  drm/amdgpu/vcn2.5: add set_pg_state callback
  drm/amdgpu/vcn3.0: add set_pg_state callback
  drm/amdgpu/vcn4.0: add set_pg_state callback
  drm/amdgpu/vcn4.0.3: add set_pg_state callback
  drm/amdgpu/vcn4.0.5: add set_pg_state callback
  drm/amdgpu/vcn5.0.0: add set_pg_state callback
  drm/amdgpu/vcn5.0.1: add set_pg_state callback
  drm/amdgpu/vcn: use per instance callbacks for idle work handler
  drm/amdgpu/vcn: add a generic helper for set_power_gating_state
  drm/amdgpu/vcn1.0: use generic set_power_gating_state helper
  drm/amdgpu/vcn2.0: use generic set_power_gating_state helper
  drm/amdgpu/vcn2.5: use generic set_power_gating_state helper
  drm/amdgpu/vcn3.0: use generic set_power_gating_state helper
  drm/amdgpu/vcn4.0: use generic set_power_gating_state helper
  drm/amdgpu/vcn4.0.3: use generic set_power_gating_state helper
  drm/amdgpu/vcn4.0.5: use generic set_power_gating_state helper
  drm/amdgpu/vcn5.0.0: use generic set_power_gating_state helper
  drm/amdgpu/vcn5.0.1: use generic set_power_gating_state helper
  drm/amdgpu/vcn: optimize firmware storage
  drm/amdgpu/vcn: use dev_info() for firmware information

 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c   |    2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c   |  464 ++++-----
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h   |   47 +-
 drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c    |    6 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c     |  193 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c     |  213 +++--
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c     | 1033 +++++++++++----------
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c     |  658 +++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c     |  661 ++++++-------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c   |  611 ++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c   |  647 +++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c   |  588 ++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c   |  499 +++++-----
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c |    8 +-
 14 files changed, 2951 insertions(+), 2679 deletions(-)

-- 
2.48.1


^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
@ 2025-01-31 16:56 ` Alex Deucher
  2025-02-04 15:35   ` Boyuan Zhang
  2025-01-31 16:56 ` [PATCH 02/44] drm/amdgpu/vcn3.0: " Alex Deucher
                   ` (42 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:56 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 841 +++++++++++++-------------
 1 file changed, 411 insertions(+), 430 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index b518202955cad..b9be304aa294b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -452,64 +452,62 @@ static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block)
  * vcn_v2_5_mc_resume - memory controller programming
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to resume
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v2_5_mc_resume(struct amdgpu_device *adev)
+static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i)
 {
 	uint32_t size;
 	uint32_t offset;
-	int i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
 
-		size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[i].fw->size + 4);
-		/* cache window 0: fw */
-		if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
-			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
-				(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo));
-			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
-				(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi));
-			WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0, 0);
-			offset = 0;
-		} else {
-			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
-				lower_32_bits(adev->vcn.inst[i].gpu_addr));
-			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
-				upper_32_bits(adev->vcn.inst[i].gpu_addr));
-			offset = size;
-			WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0,
-				AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
-		}
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE0, size);
+	if (adev->vcn.harvest_config & (1 << i))
+		return;
 
-		/* cache window 1: stack */
-		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
-			lower_32_bits(adev->vcn.inst[i].gpu_addr + offset));
-		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
-			upper_32_bits(adev->vcn.inst[i].gpu_addr + offset));
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET1, 0);
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
-
-		/* cache window 2: context */
-		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
-			lower_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
-		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
-			upper_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET2, 0);
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
-
-		/* non-cache window */
-		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
-			lower_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
-		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
-			upper_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_OFFSET0, 0);
-		WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_SIZE0,
-			AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
+	size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[i].fw->size + 4);
+	/* cache window 0: fw */
+	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo));
+		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi));
+		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0, 0);
+		offset = 0;
+	} else {
+		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+			     lower_32_bits(adev->vcn.inst[i].gpu_addr));
+		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+			     upper_32_bits(adev->vcn.inst[i].gpu_addr));
+		offset = size;
+		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0,
+			     AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
 	}
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE0, size);
+
+	/* cache window 1: stack */
+	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
+		     lower_32_bits(adev->vcn.inst[i].gpu_addr + offset));
+	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
+		     upper_32_bits(adev->vcn.inst[i].gpu_addr + offset));
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET1, 0);
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
+
+	/* cache window 2: context */
+	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
+		     lower_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
+	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
+		     upper_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET2, 0);
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
+
+	/* non-cache window */
+	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
+		     lower_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
+	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
+		     upper_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_OFFSET0, 0);
+	WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_SIZE0,
+		     AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
 }
 
 static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
@@ -612,117 +610,115 @@ static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
  * vcn_v2_5_disable_clock_gating - disable VCN clock gating
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to disable clockgating on
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev)
+static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i)
 {
 	uint32_t data;
-	int i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		/* UVD disable CGC */
-		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
-		if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
-			data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
-		else
-			data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
-		data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
-		data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
-		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
-
-		data = RREG32_SOC15(VCN, i, mmUVD_CGC_GATE);
-		data &= ~(UVD_CGC_GATE__SYS_MASK
-			| UVD_CGC_GATE__UDEC_MASK
-			| UVD_CGC_GATE__MPEG2_MASK
-			| UVD_CGC_GATE__REGS_MASK
-			| UVD_CGC_GATE__RBC_MASK
-			| UVD_CGC_GATE__LMI_MC_MASK
-			| UVD_CGC_GATE__LMI_UMC_MASK
-			| UVD_CGC_GATE__IDCT_MASK
-			| UVD_CGC_GATE__MPRD_MASK
-			| UVD_CGC_GATE__MPC_MASK
-			| UVD_CGC_GATE__LBSI_MASK
-			| UVD_CGC_GATE__LRBBM_MASK
-			| UVD_CGC_GATE__UDEC_RE_MASK
-			| UVD_CGC_GATE__UDEC_CM_MASK
-			| UVD_CGC_GATE__UDEC_IT_MASK
-			| UVD_CGC_GATE__UDEC_DB_MASK
-			| UVD_CGC_GATE__UDEC_MP_MASK
-			| UVD_CGC_GATE__WCB_MASK
-			| UVD_CGC_GATE__VCPU_MASK
-			| UVD_CGC_GATE__MMSCH_MASK);
-
-		WREG32_SOC15(VCN, i, mmUVD_CGC_GATE, data);
-
-		SOC15_WAIT_ON_RREG(VCN, i, mmUVD_CGC_GATE, 0,  0xFFFFFFFF);
-
-		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
-		data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_CM_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_IT_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_DB_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_MP_MODE_MASK
-			| UVD_CGC_CTRL__SYS_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_MODE_MASK
-			| UVD_CGC_CTRL__MPEG2_MODE_MASK
-			| UVD_CGC_CTRL__REGS_MODE_MASK
-			| UVD_CGC_CTRL__RBC_MODE_MASK
-			| UVD_CGC_CTRL__LMI_MC_MODE_MASK
-			| UVD_CGC_CTRL__LMI_UMC_MODE_MASK
-			| UVD_CGC_CTRL__IDCT_MODE_MASK
-			| UVD_CGC_CTRL__MPRD_MODE_MASK
-			| UVD_CGC_CTRL__MPC_MODE_MASK
-			| UVD_CGC_CTRL__LBSI_MODE_MASK
-			| UVD_CGC_CTRL__LRBBM_MODE_MASK
-			| UVD_CGC_CTRL__WCB_MODE_MASK
-			| UVD_CGC_CTRL__VCPU_MODE_MASK
-			| UVD_CGC_CTRL__MMSCH_MODE_MASK);
-		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
-
-		/* turn on */
-		data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE);
-		data |= (UVD_SUVD_CGC_GATE__SRE_MASK
-			| UVD_SUVD_CGC_GATE__SIT_MASK
-			| UVD_SUVD_CGC_GATE__SMP_MASK
-			| UVD_SUVD_CGC_GATE__SCM_MASK
-			| UVD_SUVD_CGC_GATE__SDB_MASK
-			| UVD_SUVD_CGC_GATE__SRE_H264_MASK
-			| UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
-			| UVD_SUVD_CGC_GATE__SIT_H264_MASK
-			| UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
-			| UVD_SUVD_CGC_GATE__SCM_H264_MASK
-			| UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
-			| UVD_SUVD_CGC_GATE__SDB_H264_MASK
-			| UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
-			| UVD_SUVD_CGC_GATE__SCLR_MASK
-			| UVD_SUVD_CGC_GATE__UVD_SC_MASK
-			| UVD_SUVD_CGC_GATE__ENT_MASK
-			| UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
-			| UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
-			| UVD_SUVD_CGC_GATE__SITE_MASK
-			| UVD_SUVD_CGC_GATE__SRE_VP9_MASK
-			| UVD_SUVD_CGC_GATE__SCM_VP9_MASK
-			| UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
-			| UVD_SUVD_CGC_GATE__SDB_VP9_MASK
-			| UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
-		WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE, data);
-
-		data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
-		data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+	if (adev->vcn.harvest_config & (1 << i))
+		return;
+	/* UVD disable CGC */
+	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
+	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+		data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+	else
+		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
+
+	data = RREG32_SOC15(VCN, i, mmUVD_CGC_GATE);
+	data &= ~(UVD_CGC_GATE__SYS_MASK
+		  | UVD_CGC_GATE__UDEC_MASK
+		  | UVD_CGC_GATE__MPEG2_MASK
+		  | UVD_CGC_GATE__REGS_MASK
+		  | UVD_CGC_GATE__RBC_MASK
+		  | UVD_CGC_GATE__LMI_MC_MASK
+		  | UVD_CGC_GATE__LMI_UMC_MASK
+		  | UVD_CGC_GATE__IDCT_MASK
+		  | UVD_CGC_GATE__MPRD_MASK
+		  | UVD_CGC_GATE__MPC_MASK
+		  | UVD_CGC_GATE__LBSI_MASK
+		  | UVD_CGC_GATE__LRBBM_MASK
+		  | UVD_CGC_GATE__UDEC_RE_MASK
+		  | UVD_CGC_GATE__UDEC_CM_MASK
+		  | UVD_CGC_GATE__UDEC_IT_MASK
+		  | UVD_CGC_GATE__UDEC_DB_MASK
+		  | UVD_CGC_GATE__UDEC_MP_MASK
+		  | UVD_CGC_GATE__WCB_MASK
+		  | UVD_CGC_GATE__VCPU_MASK
+		  | UVD_CGC_GATE__MMSCH_MASK);
+
+	WREG32_SOC15(VCN, i, mmUVD_CGC_GATE, data);
+
+	SOC15_WAIT_ON_RREG(VCN, i, mmUVD_CGC_GATE, 0,  0xFFFFFFFF);
+
+	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
+	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
+		  | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
+		  | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
+		  | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
+		  | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
+		  | UVD_CGC_CTRL__SYS_MODE_MASK
+		  | UVD_CGC_CTRL__UDEC_MODE_MASK
+		  | UVD_CGC_CTRL__MPEG2_MODE_MASK
+		  | UVD_CGC_CTRL__REGS_MODE_MASK
+		  | UVD_CGC_CTRL__RBC_MODE_MASK
+		  | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+		  | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+		  | UVD_CGC_CTRL__IDCT_MODE_MASK
+		  | UVD_CGC_CTRL__MPRD_MODE_MASK
+		  | UVD_CGC_CTRL__MPC_MODE_MASK
+		  | UVD_CGC_CTRL__LBSI_MODE_MASK
+		  | UVD_CGC_CTRL__LRBBM_MODE_MASK
+		  | UVD_CGC_CTRL__WCB_MODE_MASK
+		  | UVD_CGC_CTRL__VCPU_MODE_MASK
+		  | UVD_CGC_CTRL__MMSCH_MODE_MASK);
+	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
+
+	/* turn on */
+	data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE);
+	data |= (UVD_SUVD_CGC_GATE__SRE_MASK
+		 | UVD_SUVD_CGC_GATE__SIT_MASK
+		 | UVD_SUVD_CGC_GATE__SMP_MASK
+		 | UVD_SUVD_CGC_GATE__SCM_MASK
+		 | UVD_SUVD_CGC_GATE__SDB_MASK
+		 | UVD_SUVD_CGC_GATE__SRE_H264_MASK
+		 | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
+		 | UVD_SUVD_CGC_GATE__SIT_H264_MASK
+		 | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
+		 | UVD_SUVD_CGC_GATE__SCM_H264_MASK
+		 | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
+		 | UVD_SUVD_CGC_GATE__SDB_H264_MASK
+		 | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
+		 | UVD_SUVD_CGC_GATE__SCLR_MASK
+		 | UVD_SUVD_CGC_GATE__UVD_SC_MASK
+		 | UVD_SUVD_CGC_GATE__ENT_MASK
+		 | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
+		 | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
+		 | UVD_SUVD_CGC_GATE__SITE_MASK
+		 | UVD_SUVD_CGC_GATE__SRE_VP9_MASK
+		 | UVD_SUVD_CGC_GATE__SCM_VP9_MASK
+		 | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
+		 | UVD_SUVD_CGC_GATE__SDB_VP9_MASK
+		 | UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
+	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE, data);
+
+	data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
+	data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
+		  | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
 			| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
-		WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
-	}
+		  | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
 }
 
 static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
@@ -774,65 +770,63 @@ static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
 }
 
 /**
- * vcn_v2_5_enable_clock_gating - enable VCN clock gating
+ * vcn_v2_5_enable_clock_gating_inst - enable VCN clock gating
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to enable clockgating on
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev)
+static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i)
 {
 	uint32_t data = 0;
-	int i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		/* enable UVD CGC */
-		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
-		if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
-			data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
-		else
-			data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
-		data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
-		data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
-		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
-
-		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
-		data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_CM_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_IT_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_DB_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_MP_MODE_MASK
-			| UVD_CGC_CTRL__SYS_MODE_MASK
-			| UVD_CGC_CTRL__UDEC_MODE_MASK
-			| UVD_CGC_CTRL__MPEG2_MODE_MASK
-			| UVD_CGC_CTRL__REGS_MODE_MASK
-			| UVD_CGC_CTRL__RBC_MODE_MASK
-			| UVD_CGC_CTRL__LMI_MC_MODE_MASK
-			| UVD_CGC_CTRL__LMI_UMC_MODE_MASK
-			| UVD_CGC_CTRL__IDCT_MODE_MASK
-			| UVD_CGC_CTRL__MPRD_MODE_MASK
-			| UVD_CGC_CTRL__MPC_MODE_MASK
-			| UVD_CGC_CTRL__LBSI_MODE_MASK
-			| UVD_CGC_CTRL__LRBBM_MODE_MASK
-			| UVD_CGC_CTRL__WCB_MODE_MASK
-			| UVD_CGC_CTRL__VCPU_MODE_MASK);
-		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
-
-		data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
-		data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
-			| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
-		WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
-	}
+	if (adev->vcn.harvest_config & (1 << i))
+		return;
+	/* enable UVD CGC */
+	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
+	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+		data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+	else
+		data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
+
+	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
+	data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
+		 | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
+		 | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
+		 | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
+		 | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
+		 | UVD_CGC_CTRL__SYS_MODE_MASK
+		 | UVD_CGC_CTRL__UDEC_MODE_MASK
+		 | UVD_CGC_CTRL__MPEG2_MODE_MASK
+		 | UVD_CGC_CTRL__REGS_MODE_MASK
+		 | UVD_CGC_CTRL__RBC_MODE_MASK
+		 | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+		 | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+		 | UVD_CGC_CTRL__IDCT_MODE_MASK
+		 | UVD_CGC_CTRL__MPRD_MODE_MASK
+		 | UVD_CGC_CTRL__MPC_MODE_MASK
+		 | UVD_CGC_CTRL__LBSI_MODE_MASK
+		 | UVD_CGC_CTRL__LRBBM_MODE_MASK
+		 | UVD_CGC_CTRL__WCB_MODE_MASK
+		 | UVD_CGC_CTRL__VCPU_MODE_MASK);
+	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
+
+	data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
+	data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+		 | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
 }
 
 static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
@@ -1006,197 +1000,185 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 	return 0;
 }
 
-static int vcn_v2_5_start(struct amdgpu_device *adev)
+static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
 {
+	volatile struct amdgpu_fw_shared *fw_shared =
+		adev->vcn.inst[i].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
 	uint32_t rb_bufsz, tmp;
-	int i, j, k, r;
+	int j, k, r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, true, i);
-	}
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, true, i);
 
-		/* disable register anti-hang mechanism */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
-			~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		/* set uvd status busy */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
-	}
+	/* disable register anti-hang mechanism */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
+		 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+	/* set uvd status busy */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
 		return 0;
 
-	/*SW clock gating */
-	vcn_v2_5_disable_clock_gating(adev);
+	/* SW clock gating */
+	vcn_v2_5_disable_clock_gating(adev, i);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
-			~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* setup mmUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
-		tmp &= ~0xff;
-		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp | 0x8|
-			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
-			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		/* setup mmUVD_MPC_CNTL */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
-		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
-		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
-		WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
-
-		/* setup UVD_MPC_SET_MUXA0 */
-		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
-			((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
-			(0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
-			(0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
-			(0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUXB0 */
-		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
-			((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
-			(0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
-			(0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
-			(0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
-
-		/* setup mmUVD_MPC_SET_MUX */
-		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
-			((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
-			(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
-			(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
-	}
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
 
-	vcn_v2_5_mc_resume(adev);
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
-			adev->gfx.config.gb_addr_config);
-		WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
-			adev->gfx.config.gb_addr_config);
+	/* setup mmUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
+	tmp &= ~0xff;
+	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp | 0x8|
+		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	/* setup mmUVD_MPC_CNTL */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
+	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+	WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
+
+	/* setup UVD_MPC_SET_MUXA0 */
+	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
+		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUXB0 */
+	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
+		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+	/* setup mmUVD_MPC_SET_MUX */
+	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
+		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+	vcn_v2_5_mc_resume(adev, i);
 
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
-			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+	WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
 
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
 
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		for (k = 0; k < 10; ++k) {
-			uint32_t status;
-
-			for (j = 0; j < 100; ++j) {
-				status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
-				if (status & 2)
-					break;
-				if (amdgpu_emu_mode == 1)
-					msleep(500);
-				else
-					mdelay(10);
-			}
-			r = 0;
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (k = 0; k < 10; ++k) {
+		uint32_t status;
+
+		for (j = 0; j < 100; ++j) {
+			status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
 			if (status & 2)
 				break;
+			if (amdgpu_emu_mode == 1)
+				msleep(500);
+			else
+				mdelay(10);
+		}
+		r = 0;
+		if (status & 2)
+			break;
 
-			DRM_ERROR("VCN decode not responding, trying to reset the VCPU!!!\n");
-			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
-				UVD_VCPU_CNTL__BLK_RST_MASK,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
-			mdelay(10);
-			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
+		DRM_ERROR("VCN decode not responding, trying to reset the VCPU!!!\n");
+		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
+			 UVD_VCPU_CNTL__BLK_RST_MASK,
+			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+		mdelay(10);
+		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
+			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-			mdelay(10);
-			r = -1;
-		}
+		mdelay(10);
+		r = -1;
+	}
 
-		if (r) {
-			DRM_ERROR("VCN decode not responding, giving up!!!\n");
-			return r;
-		}
+	if (r) {
+		DRM_ERROR("VCN decode not responding, giving up!!!\n");
+		return r;
+	}
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
-			UVD_MASTINT_EN__VCPU_EN_MASK,
-			~UVD_MASTINT_EN__VCPU_EN_MASK);
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
-			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
+	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
 
-		ring = &adev->vcn.inst[i].ring_dec;
-		/* force RBC into idle state */
-		rb_bufsz = order_base_2(ring->ring_size);
-		tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
-		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
+	ring = &adev->vcn.inst[i].ring_dec;
+	/* force RBC into idle state */
+	rb_bufsz = order_base_2(ring->ring_size);
+	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
+	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
 
-		fw_shared->multi_queue.decode_queue_mode |= FW_QUEUE_RING_RESET;
-		/* program the RB_BASE for ring buffer */
-		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
-			lower_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
-			upper_32_bits(ring->gpu_addr));
+	fw_shared->multi_queue.decode_queue_mode |= FW_QUEUE_RING_RESET;
+	/* program the RB_BASE for ring buffer */
+	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
+		     lower_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
+		     upper_32_bits(ring->gpu_addr));
 
-		/* Initialize the ring buffer's read and write pointers */
-		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
 
-		ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
-		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
-				lower_32_bits(ring->wptr));
-		fw_shared->multi_queue.decode_queue_mode &= ~FW_QUEUE_RING_RESET;
+	ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
+	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
+		     lower_32_bits(ring->wptr));
+	fw_shared->multi_queue.decode_queue_mode &= ~FW_QUEUE_RING_RESET;
 
-		fw_shared->multi_queue.encode_generalpurpose_queue_mode |= FW_QUEUE_RING_RESET;
-		ring = &adev->vcn.inst[i].ring_enc[0];
-		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
-		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
-		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
-		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
-		fw_shared->multi_queue.encode_generalpurpose_queue_mode &= ~FW_QUEUE_RING_RESET;
-
-		fw_shared->multi_queue.encode_lowlatency_queue_mode |= FW_QUEUE_RING_RESET;
-		ring = &adev->vcn.inst[i].ring_enc[1];
-		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
-		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
-		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
-		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
-		fw_shared->multi_queue.encode_lowlatency_queue_mode &= ~FW_QUEUE_RING_RESET;
-	}
+	fw_shared->multi_queue.encode_generalpurpose_queue_mode |= FW_QUEUE_RING_RESET;
+	ring = &adev->vcn.inst[i].ring_enc[0];
+	WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
+	WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
+	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
+	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
+	fw_shared->multi_queue.encode_generalpurpose_queue_mode &= ~FW_QUEUE_RING_RESET;
+
+	fw_shared->multi_queue.encode_lowlatency_queue_mode |= FW_QUEUE_RING_RESET;
+	ring = &adev->vcn.inst[i].ring_enc[1];
+	WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
+	WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
+	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
+	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
+	fw_shared->multi_queue.encode_lowlatency_queue_mode &= ~FW_QUEUE_RING_RESET;
 
 	return 0;
 }
@@ -1425,72 +1407,66 @@ static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 	return 0;
 }
 
-static int vcn_v2_5_stop(struct amdgpu_device *adev)
+static int vcn_v2_5_stop(struct amdgpu_device *adev, int i)
 {
 	uint32_t tmp;
-	int i, r = 0;
+	int r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v2_5_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v2_5_stop_dpg_mode(adev, i);
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
-		if (r)
-			return r;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+	if (r)
+		return r;
 
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__READ_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block LMI UMC channel */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
+	/* block LMI UMC channel */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
 
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
-			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
-			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+	/* block VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
-		/* reset VCPU */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__BLK_RST_MASK,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* reset VCPU */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
-			~(UVD_VCPU_CNTL__CLK_EN_MASK));
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
 
-		/* clear status */
-		WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
+	/* clear status */
+	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
 
-		vcn_v2_5_enable_clock_gating(adev);
+	vcn_v2_5_enable_clock_gating(adev, i);
 
-		/* enable register anti-hang mechanism */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS),
-			UVD_POWER_STATUS__UVD_POWER_STATUS_MASK,
-			~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
-	}
+	/* enable register anti-hang mechanism */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS),
+		 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK,
+		 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, false, i);
-	}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, false, i);
 
 	return 0;
 }
@@ -1811,16 +1787,19 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 {
 	struct amdgpu_device *adev = ip_block->adev;
 	bool enable = (state == AMD_CG_STATE_GATE);
+	int i;
 
 	if (amdgpu_sriov_vf(adev))
 		return 0;
 
-	if (enable) {
-		if (!vcn_v2_5_is_idle(adev))
-			return -EBUSY;
-		vcn_v2_5_enable_clock_gating(adev);
-	} else {
-		vcn_v2_5_disable_clock_gating(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (enable) {
+			if (!vcn_v2_5_is_idle(adev))
+				return -EBUSY;
+			vcn_v2_5_enable_clock_gating(adev, i);
+		} else {
+			vcn_v2_5_disable_clock_gating(adev, i);
+		}
 	}
 
 	return 0;
@@ -1830,20 +1809,22 @@ static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	if (amdgpu_sriov_vf(adev))
 		return 0;
 
-	if(state == adev->vcn.cur_state)
+	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v2_5_stop(adev);
-	else
-		ret = vcn_v2_5_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret |= vcn_v2_5_stop(adev, i);
+		else
+			ret |= vcn_v2_5_start(adev, i);
+	}
 
-	if(!ret)
+	if (!ret)
 		adev->vcn.cur_state = state;
 
 	return ret;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 02/44] drm/amdgpu/vcn3.0: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
  2025-01-31 16:56 ` [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances Alex Deucher
@ 2025-01-31 16:56 ` Alex Deucher
  2025-02-04 15:40   ` Boyuan Zhang
  2025-01-31 16:56 ` [PATCH 03/44] drm/amdgpu/vcn4.0: " Alex Deucher
                   ` (41 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:56 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 436 +++++++++++++-------------
 1 file changed, 213 insertions(+), 223 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 63ddd4cca9109..a3627700ed48d 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -1134,192 +1134,186 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 	return 0;
 }
 
-static int vcn_v3_0_start(struct amdgpu_device *adev)
+static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t rb_bufsz, tmp;
-	int i, j, k, r;
+	int j, k, r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, true, i);
-	}
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, true, i);
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		/* disable VCN power gating */
-		vcn_v3_0_disable_static_power_gating(adev, i);
+	/* disable VCN power gating */
+	vcn_v3_0_disable_static_power_gating(adev, i);
 
-		/* set VCN status busy */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
+	/* set VCN status busy */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
 
-		/*SW clock gating */
-		vcn_v3_0_disable_clock_gating(adev, i);
+	/* SW clock gating */
+	vcn_v3_0_disable_clock_gating(adev, i);
 
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
-			~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
-			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
-
-		tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
-		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
-
-		/* setup mmUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
-		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp |
-			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
-			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		/* setup mmUVD_MPC_CNTL */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
-		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
-		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
-		WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
-
-		/* setup UVD_MPC_SET_MUXA0 */
-		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
-			((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
-			(0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
-			(0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
-			(0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUXB0 */
-		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
-			((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
-			(0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
-			(0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
-			(0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
-
-		/* setup mmUVD_MPC_SET_MUX */
-		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
-			((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
-			(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
-			(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
-
-		vcn_v3_0_mc_resume(adev, i);
-
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG,
-			adev->gfx.config.gb_addr_config);
-
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
 
-		for (j = 0; j < 10; ++j) {
-			uint32_t status;
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-			for (k = 0; k < 100; ++k) {
-				status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
-				if (status & 2)
-					break;
-				mdelay(10);
-			}
-			r = 0;
-			if (status & 2)
-				break;
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
 
-			DRM_ERROR("VCN[%d] decode not responding, trying to reset the VCPU!!!\n", i);
-			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
-				UVD_VCPU_CNTL__BLK_RST_MASK,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
-			mdelay(10);
-			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
+	tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
+	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
+
+	/* setup mmUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
+	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp |
+		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	/* setup mmUVD_MPC_CNTL */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
+	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+	WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
+
+	/* setup UVD_MPC_SET_MUXA0 */
+	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
+		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUXB0 */
+	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
+		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+	/* setup mmUVD_MPC_SET_MUX */
+	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
+		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+	vcn_v3_0_mc_resume(adev, i);
+
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (j = 0; j < 10; ++j) {
+		uint32_t status;
+
+		for (k = 0; k < 100; ++k) {
+			status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
+			if (status & 2)
+				break;
 			mdelay(10);
-			r = -1;
 		}
+		r = 0;
+		if (status & 2)
+			break;
 
-		if (r) {
-			DRM_ERROR("VCN[%d] decode not responding, giving up!!!\n", i);
-			return r;
-		}
+		DRM_ERROR("VCN[%d] decode not responding, trying to reset the VCPU!!!\n", i);
+		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
+			 UVD_VCPU_CNTL__BLK_RST_MASK,
+			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+		mdelay(10);
+		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
+			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+		mdelay(10);
+		r = -1;
+	}
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
-			UVD_MASTINT_EN__VCPU_EN_MASK,
-			~UVD_MASTINT_EN__VCPU_EN_MASK);
+	if (r) {
+		DRM_ERROR("VCN[%d] decode not responding, giving up!!!\n", i);
+		return r;
+	}
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
-			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		ring = &adev->vcn.inst[i].ring_dec;
-		/* force RBC into idle state */
-		rb_bufsz = order_base_2(ring->ring_size);
-		tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
-		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
-		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
+	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		fw_shared->multi_queue.decode_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
+	ring = &adev->vcn.inst[i].ring_dec;
+	/* force RBC into idle state */
+	rb_bufsz = order_base_2(ring->ring_size);
+	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
+	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
+	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
 
-		/* programm the RB_BASE for ring buffer */
-		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
-			lower_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
-			upper_32_bits(ring->gpu_addr));
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared->multi_queue.decode_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
 
-		/* Initialize the ring buffer's read and write pointers */
-		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
+	/* programm the RB_BASE for ring buffer */
+	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
+		     lower_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
+		     upper_32_bits(ring->gpu_addr));
 
-		WREG32_SOC15(VCN, i, mmUVD_SCRATCH2, 0);
-		ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
-		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
-			lower_32_bits(ring->wptr));
-		fw_shared->rb.wptr = lower_32_bits(ring->wptr);
-		fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
-
-		if (amdgpu_ip_version(adev, UVD_HWIP, 0) !=
-		    IP_VERSION(3, 0, 33)) {
-			fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
-			ring = &adev->vcn.inst[i].ring_enc[0];
-			WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
-			WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
-			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
-			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-			WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
-			fw_shared->multi_queue.encode_generalpurpose_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
-
-			fw_shared->multi_queue.encode_lowlatency_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
-			ring = &adev->vcn.inst[i].ring_enc[1];
-			WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
-			WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
-			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
-			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
-			WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
-			fw_shared->multi_queue.encode_lowlatency_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
-		}
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
+
+	WREG32_SOC15(VCN, i, mmUVD_SCRATCH2, 0);
+	ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
+	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
+		     lower_32_bits(ring->wptr));
+	fw_shared->rb.wptr = lower_32_bits(ring->wptr);
+	fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
+
+	if (amdgpu_ip_version(adev, UVD_HWIP, 0) !=
+	    IP_VERSION(3, 0, 33)) {
+		fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
+		ring = &adev->vcn.inst[i].ring_enc[0];
+		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
+		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
+		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
+		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
+		fw_shared->multi_queue.encode_generalpurpose_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
+
+		fw_shared->multi_queue.encode_lowlatency_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
+		ring = &adev->vcn.inst[i].ring_enc[1];
+		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
+		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
+		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
+		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
+		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
+		fw_shared->multi_queue.encode_lowlatency_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
 	}
 
 	return 0;
@@ -1565,79 +1559,73 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 	return 0;
 }
 
-static int vcn_v3_0_stop(struct amdgpu_device *adev)
+static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
 {
 	uint32_t tmp;
-	int i, r = 0;
+	int r = 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v3_0_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v3_0_stop_dpg_mode(adev, i);
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
-		if (r)
-			return r;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+	if (r)
+		return r;
 
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__READ_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* disable LMI UMC channel */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
-			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	/* disable LMI UMC channel */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
-			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+	/* block VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
-		/* reset VCPU */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__BLK_RST_MASK,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* reset VCPU */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
-			~(UVD_VCPU_CNTL__CLK_EN_MASK));
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
 
-		/* apply soft reset */
-		tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
-		tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
+	/* apply soft reset */
+	tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
+	tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
 
-		/* clear status */
-		WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
+	/* clear status */
+	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
 
-		/* apply HW clock gating */
-		vcn_v3_0_enable_clock_gating(adev, i);
+	/* apply HW clock gating */
+	vcn_v3_0_enable_clock_gating(adev, i);
 
-		/* enable VCN power gating */
-		vcn_v3_0_enable_static_power_gating(adev, i);
-	}
+	/* enable VCN power gating */
+	vcn_v3_0_enable_static_power_gating(adev, i);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, false, i);
-	}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, false, i);
 
 	return 0;
 }
@@ -2163,7 +2151,7 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	/* for SRIOV, guest should not control VCN Power-gating
 	 * MMSCH FW should control Power-gating and clock-gating
@@ -2177,10 +2165,12 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v3_0_stop(adev);
-	else
-		ret = vcn_v3_0_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret |= vcn_v3_0_stop(adev, i);
+		else
+			ret |= vcn_v3_0_start(adev, i);
+	}
 
 	if (!ret)
 		adev->vcn.cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 03/44] drm/amdgpu/vcn4.0: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
  2025-01-31 16:56 ` [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances Alex Deucher
  2025-01-31 16:56 ` [PATCH 02/44] drm/amdgpu/vcn3.0: " Alex Deucher
@ 2025-01-31 16:56 ` Alex Deucher
  2025-02-04 15:50   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 04/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
                   ` (40 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:56 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 436 +++++++++++++-------------
 1 file changed, 215 insertions(+), 221 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 00551d6f03701..c3eb4278bf465 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1087,182 +1087,177 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
  * vcn_v4_0_start - VCN start
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to start
  *
  * Start VCN block
  */
-static int vcn_v4_0_start(struct amdgpu_device *adev)
+static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
-	int i, j, k, r;
+	int j, k, r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, true, i);
-	}
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, true, i);
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		/* disable VCN power gating */
-		vcn_v4_0_disable_static_power_gating(adev, i);
-
-		/* set VCN status busy */
-		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
-
-		/*SW clock gating */
-		vcn_v4_0_disable_clock_gating(adev, i);
-
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-				UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
-				~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
-				~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
-
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-
-		/* setup regUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
-		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
-				UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
-				UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-				UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-				UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		/* setup regUVD_MPC_CNTL */
-		tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
-		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
-		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
-		WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
-
-		/* setup UVD_MPC_SET_MUXA0 */
-		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
-				((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
-				 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
-				 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
-				 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUXB0 */
-		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
-				((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
-				 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
-				 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
-				 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUX */
-		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
-				((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
-				 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
-				 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
-
-		vcn_v4_0_mc_resume(adev, i);
-
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
-				adev->gfx.config.gb_addr_config);
-
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
-				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		for (j = 0; j < 10; ++j) {
-			uint32_t status;
-
-			for (k = 0; k < 100; ++k) {
-				status = RREG32_SOC15(VCN, i, regUVD_STATUS);
-				if (status & 2)
-					break;
-				mdelay(10);
-				if (amdgpu_emu_mode == 1)
-					msleep(1);
-			}
+	/* disable VCN power gating */
+	vcn_v4_0_disable_static_power_gating(adev, i);
+
+	/* set VCN status busy */
+	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
+
+	/*SW clock gating */
+	vcn_v4_0_disable_clock_gating(adev, i);
+
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
 
-			if (amdgpu_emu_mode == 1) {
-				r = -1;
-				if (status & 2) {
-					r = 0;
-					break;
-				}
-			} else {
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+
+	/* setup regUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
+	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
+		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	/* setup regUVD_MPC_CNTL */
+	tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
+	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+	WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
+
+	/* setup UVD_MPC_SET_MUXA0 */
+	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
+		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUXB0 */
+	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
+		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUX */
+	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
+		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+	vcn_v4_0_mc_resume(adev, i);
+
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (j = 0; j < 10; ++j) {
+		uint32_t status;
+
+		for (k = 0; k < 100; ++k) {
+			status = RREG32_SOC15(VCN, i, regUVD_STATUS);
+			if (status & 2)
+				break;
+			mdelay(10);
+			if (amdgpu_emu_mode == 1)
+				msleep(1);
+		}
+
+		if (amdgpu_emu_mode == 1) {
+			r = -1;
+			if (status & 2) {
 				r = 0;
-				if (status & 2)
-					break;
-
-				dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
-				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-							UVD_VCPU_CNTL__BLK_RST_MASK,
-							~UVD_VCPU_CNTL__BLK_RST_MASK);
-				mdelay(10);
-				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-						~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-				mdelay(10);
-				r = -1;
+				break;
 			}
+		} else {
+			r = 0;
+			if (status & 2)
+				break;
+
+			dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
+			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+				 UVD_VCPU_CNTL__BLK_RST_MASK,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+			mdelay(10);
+			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+			mdelay(10);
+			r = -1;
 		}
+	}
 
-		if (r) {
-			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
-			return r;
-		}
+	if (r) {
+		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+		return r;
+	}
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
-				UVD_MASTINT_EN__VCPU_EN_MASK,
-				~UVD_MASTINT_EN__VCPU_EN_MASK);
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
-				~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		ring = &adev->vcn.inst[i].ring_enc[0];
-		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
-				ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
-				VCN_RB1_DB_CTRL__EN_MASK);
-
-		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
-		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
-
-		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
-		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
-		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
-		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
-		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
-
-		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
-		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
-		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
-
-		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
-		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
-		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
-	}
+	ring = &adev->vcn.inst[i].ring_enc[0];
+	WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
+		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+		     VCN_RB1_DB_CTRL__EN_MASK);
+
+	WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
+	WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
+
+	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+	WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
+	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
+
+	tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
+	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
+	ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
+
+	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
 
 	return 0;
 }
@@ -1549,86 +1544,83 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
  * vcn_v4_0_stop - VCN stop
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to stop
  *
  * Stop VCN block
  */
-static int vcn_v4_0_stop(struct amdgpu_device *adev)
+static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	uint32_t tmp;
-	int i, r = 0;
+	int r = 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			vcn_v4_0_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+		vcn_v4_0_stop_dpg_mode(adev, i);
+		return 0;
+	}
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
-		if (r)
-			return r;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+	if (r)
+		return r;
 
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__READ_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* disable LMI UMC channel */
-		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
-			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	/* disable LMI UMC channel */
+	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
-				UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+	/* block VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
-		/* reset VCPU */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-				UVD_VCPU_CNTL__BLK_RST_MASK,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* reset VCPU */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-				~(UVD_VCPU_CNTL__CLK_EN_MASK));
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
 
-		/* apply soft reset */
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+	/* apply soft reset */
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
 
-		/* clear status */
-		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
+	/* clear status */
+	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
 
-		/* apply HW clock gating */
-		vcn_v4_0_enable_clock_gating(adev, i);
+	/* apply HW clock gating */
+	vcn_v4_0_enable_clock_gating(adev, i);
 
-		/* enable VCN power gating */
-		vcn_v4_0_enable_static_power_gating(adev, i);
-	}
+	/* enable VCN power gating */
+	vcn_v4_0_enable_static_power_gating(adev, i);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, false, i);
-	}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, false, i);
 
 	return 0;
 }
@@ -2051,7 +2043,7 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	/* for SRIOV, guest should not control VCN Power-gating
 	 * MMSCH FW should control Power-gating and clock-gating
@@ -2065,10 +2057,12 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v4_0_stop(adev);
-	else
-		ret = vcn_v4_0_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret |= vcn_v4_0_stop(adev, i);
+		else
+			ret |= vcn_v4_0_start(adev, i);
+	}
 
 	if (!ret)
 		adev->vcn.cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 04/44] drm/amdgpu/vcn4.0.3: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (2 preceding siblings ...)
  2025-01-31 16:56 ` [PATCH 03/44] drm/amdgpu/vcn4.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-04 15:50   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 05/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
                   ` (39 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 417 ++++++++++++------------
 1 file changed, 206 insertions(+), 211 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index f0716c10f23e4..6293d1dc02fec 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1117,177 +1117,172 @@ static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev)
  * vcn_v4_0_3_start - VCN start
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to start
  *
  * Start VCN block
  */
-static int vcn_v4_0_3_start(struct amdgpu_device *adev)
+static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
-	int i, j, k, r, vcn_inst;
+	int j, k, r, vcn_inst;
 	uint32_t tmp;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, true, i);
-	}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, true, i);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		vcn_inst = GET_INST(VCN, i);
-		/* set VCN status busy */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) |
-		      UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
-
-		/*SW clock gating */
-		vcn_v4_0_3_disable_clock_gating(adev, i);
-
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
-			 UVD_VCPU_CNTL__CLK_EN_MASK,
-			 ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
-			 ~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
-			 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
-
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
-		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
-
-		/* setup regUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL,
-			     tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
-				     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-				     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-				     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		/* setup regUVD_MPC_CNTL */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL);
-		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
-		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp);
-
-		/* setup UVD_MPC_SET_MUXA0 */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0,
-			     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
-			      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
-			      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
-			      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUXB0 */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0,
-			     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
-			      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
-			      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
-			      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUX */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX,
-			     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
-			      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
-			      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
-
-		vcn_v4_0_3_mc_resume(adev, i);
-
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
-			     adev->gfx.config.gb_addr_config);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
-			     adev->gfx.config.gb_addr_config);
-
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
-			 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
-			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+	vcn_inst = GET_INST(VCN, i);
+	/* set VCN status busy */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) |
+		UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
 
-		for (j = 0; j < 10; ++j) {
-			uint32_t status;
+	/* SW clock gating */
+	vcn_v4_0_3_disable_clock_gating(adev, i);
 
-			for (k = 0; k < 100; ++k) {
-				status = RREG32_SOC15(VCN, vcn_inst,
-						      regUVD_STATUS);
-				if (status & 2)
-					break;
-				mdelay(10);
-			}
-			r = 0;
-			if (status & 2)
-				break;
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK,
+		 ~UVD_VCPU_CNTL__CLK_EN_MASK);
 
-			DRM_DEV_ERROR(adev->dev,
-				"VCN decode not responding, trying to reset the VCPU!!!\n");
-			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
-						  regUVD_VCPU_CNTL),
-				 UVD_VCPU_CNTL__BLK_RST_MASK,
-				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
-			mdelay(10);
-			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
-						  regUVD_VCPU_CNTL),
-				 0, ~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+	/* setup regUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL,
+		     tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	/* setup regUVD_MPC_CNTL */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL);
+	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp);
+
+	/* setup UVD_MPC_SET_MUXA0 */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0,
+		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUXB0 */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0,
+		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUX */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX,
+		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+	vcn_v4_0_3_mc_resume(adev, i);
+
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
 
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (j = 0; j < 10; ++j) {
+		uint32_t status;
+
+		for (k = 0; k < 100; ++k) {
+			status = RREG32_SOC15(VCN, vcn_inst,
+					      regUVD_STATUS);
+			if (status & 2)
+				break;
 			mdelay(10);
-			r = -1;
 		}
+		r = 0;
+		if (status & 2)
+			break;
 
-		if (r) {
-			DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n");
-			return r;
-		}
+		DRM_DEV_ERROR(adev->dev,
+			      "VCN decode not responding, trying to reset the VCPU!!!\n");
+		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
+					  regUVD_VCPU_CNTL),
+			 UVD_VCPU_CNTL__BLK_RST_MASK,
+			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+		mdelay(10);
+		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
+					  regUVD_VCPU_CNTL),
+			 0, ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
-			 UVD_MASTINT_EN__VCPU_EN_MASK,
-			 ~UVD_MASTINT_EN__VCPU_EN_MASK);
+		mdelay(10);
+		r = -1;
+	}
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
-			 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	if (r) {
+		DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n");
+		return r;
+	}
 
-		ring = &adev->vcn.inst[i].ring_enc[0];
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		/* program the RB_BASE for ring buffer */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
-			     lower_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI,
-			     upper_32_bits(ring->gpu_addr));
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE,
-			     ring->ring_size / sizeof(uint32_t));
+	ring = &adev->vcn.inst[i].ring_enc[0];
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
-		/* resetting ring, fw should not check RB ring */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
-		tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK);
-		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+	/* program the RB_BASE for ring buffer */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
+		     lower_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI,
+		     upper_32_bits(ring->gpu_addr));
+
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE,
+		     ring->ring_size / sizeof(uint32_t));
+
+	/* resetting ring, fw should not check RB ring */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+	tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK);
+	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
 
-		/* Initialize the ring buffer's read and write pointers */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
 
-		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
-		tmp |= VCN_RB_ENABLE__RB_EN_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+	tmp |= VCN_RB_ENABLE__RB_EN_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
 
-		ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
-		fw_shared->sq.queue_mode &=
-			cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF));
+	ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+	fw_shared->sq.queue_mode &=
+		cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF));
 
-	}
 	return 0;
 }
 
@@ -1327,86 +1322,84 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
  * vcn_v4_0_3_stop - VCN stop
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to stop
  *
  * Stop VCN block
  */
-static int vcn_v4_0_3_stop(struct amdgpu_device *adev)
+static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
-	int i, r = 0, vcn_inst;
+	int r = 0, vcn_inst;
 	uint32_t tmp;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		vcn_inst = GET_INST(VCN, i);
+	vcn_inst = GET_INST(VCN, i);
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			vcn_v4_0_3_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+		vcn_v4_0_3_stop_dpg_mode(adev, i);
+		return 0;
+	}
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS,
-				       UVD_STATUS__IDLE, 0x7);
-		if (r)
-			goto Done;
-
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__READ_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
-				       tmp);
-		if (r)
-			goto Done;
-
-		/* stall UMC channel */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
-			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
-				       tmp);
-		if (r)
-			goto Done;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS,
+			       UVD_STATUS__IDLE, 0x7);
+	if (r)
+		goto Done;
+
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
+			       tmp);
+	if (r)
+		goto Done;
+
+	/* stall UMC channel */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
+			       tmp);
+	if (r)
+		goto Done;
 
-		/* Unblock VCPU Register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
-			 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-			 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+	/* Unblock VCPU Register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
-			 UVD_VCPU_CNTL__BLK_RST_MASK,
-			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
-			 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
 
-		/* reset LMI UMC/LMI/VCPU */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+	/* reset LMI UMC/LMI/VCPU */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
 
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
 
-		/* clear VCN status */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
+	/* clear VCN status */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
+
+	/* apply HW clock gating */
+	vcn_v4_0_3_enable_clock_gating(adev, i);
 
-		/* apply HW clock gating */
-		vcn_v4_0_3_enable_clock_gating(adev, i);
-	}
 Done:
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, false, i);
-	}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, false, i);
 
 	return 0;
 }
@@ -1663,7 +1656,7 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	/* for SRIOV, guest should not control VCN Power-gating
 	 * MMSCH FW should control Power-gating and clock-gating
@@ -1677,10 +1670,12 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v4_0_3_stop(adev);
-	else
-		ret = vcn_v4_0_3_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret |= vcn_v4_0_3_stop(adev, i);
+		else
+			ret |= vcn_v4_0_3_start(adev, i);
+	}
 
 	if (!ret)
 		adev->vcn.cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 05/44] drm/amdgpu/vcn4.0.5: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (3 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 04/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-04 15:51   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 06/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
                   ` (38 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 438 ++++++++++++------------
 1 file changed, 216 insertions(+), 222 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 23d3c16c9d9f2..bf0da0da12512 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -990,183 +990,178 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
  * vcn_v4_0_5_start - VCN start
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to start
  *
  * Start VCN block
  */
-static int vcn_v4_0_5_start(struct amdgpu_device *adev)
+static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
-	int i, j, k, r;
+	int j, k, r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, true, i);
-	}
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, true, i);
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		/* disable VCN power gating */
-		vcn_v4_0_5_disable_static_power_gating(adev, i);
-
-		/* set VCN status busy */
-		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
-
-		/*SW clock gating */
-		vcn_v4_0_5_disable_clock_gating(adev, i);
-
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-				UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
-				~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
-				~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
-
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-
-		/* setup regUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
-		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
-				UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
-				UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-				UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-				UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		/* setup regUVD_MPC_CNTL */
-		tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
-		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
-		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
-		WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
-
-		/* setup UVD_MPC_SET_MUXA0 */
-		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
-				((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
-				 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
-				 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
-				 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUXB0 */
-		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
-				((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
-				 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
-				 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
-				 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
-
-		/* setup UVD_MPC_SET_MUX */
-		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
-				((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
-				 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
-				 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
-
-		vcn_v4_0_5_mc_resume(adev, i);
-
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
-				adev->gfx.config.gb_addr_config);
-
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
-				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		for (j = 0; j < 10; ++j) {
-			uint32_t status;
-
-			for (k = 0; k < 100; ++k) {
-				status = RREG32_SOC15(VCN, i, regUVD_STATUS);
-				if (status & 2)
-					break;
-				mdelay(10);
-				if (amdgpu_emu_mode == 1)
-					msleep(1);
-			}
+	/* disable VCN power gating */
+	vcn_v4_0_5_disable_static_power_gating(adev, i);
+
+	/* set VCN status busy */
+	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
 
-			if (amdgpu_emu_mode == 1) {
-				r = -1;
-				if (status & 2) {
-					r = 0;
-					break;
-				}
-			} else {
+	/* SW clock gating */
+	vcn_v4_0_5_disable_clock_gating(adev, i);
+
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+
+	/* setup regUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
+	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
+		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	/* setup regUVD_MPC_CNTL */
+	tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
+	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+	WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
+
+	/* setup UVD_MPC_SET_MUXA0 */
+	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
+		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUXB0 */
+	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
+		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+	/* setup UVD_MPC_SET_MUX */
+	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
+		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+	vcn_v4_0_5_mc_resume(adev, i);
+
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (j = 0; j < 10; ++j) {
+		uint32_t status;
+
+		for (k = 0; k < 100; ++k) {
+			status = RREG32_SOC15(VCN, i, regUVD_STATUS);
+			if (status & 2)
+				break;
+			mdelay(10);
+			if (amdgpu_emu_mode == 1)
+				msleep(1);
+		}
+
+		if (amdgpu_emu_mode == 1) {
+			r = -1;
+			if (status & 2) {
 				r = 0;
-				if (status & 2)
-					break;
-
-				dev_err(adev->dev,
-					"VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
-				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-							UVD_VCPU_CNTL__BLK_RST_MASK,
-							~UVD_VCPU_CNTL__BLK_RST_MASK);
-				mdelay(10);
-				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-						~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-				mdelay(10);
-				r = -1;
+				break;
 			}
+		} else {
+			r = 0;
+			if (status & 2)
+				break;
+
+			dev_err(adev->dev,
+				"VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
+			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+				 UVD_VCPU_CNTL__BLK_RST_MASK,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+			mdelay(10);
+			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+			mdelay(10);
+			r = -1;
 		}
+	}
 
-		if (r) {
-			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
-			return r;
-		}
+	if (r) {
+		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+		return r;
+	}
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
-				UVD_MASTINT_EN__VCPU_EN_MASK,
-				~UVD_MASTINT_EN__VCPU_EN_MASK);
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
-				~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		ring = &adev->vcn.inst[i].ring_enc[0];
-		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
-				ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
-				VCN_RB1_DB_CTRL__EN_MASK);
-
-		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
-		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
-
-		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
-		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
-		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
-		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
-		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
-
-		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
-		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
-		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
-
-		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
-		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
-		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
-	}
+	ring = &adev->vcn.inst[i].ring_enc[0];
+	WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
+		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+		     VCN_RB1_DB_CTRL__EN_MASK);
+
+	WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
+	WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
+
+	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+	WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
+	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
+
+	tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
+	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
+	ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
+
+	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
 
 	return 0;
 }
@@ -1203,86 +1198,83 @@ static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
  * vcn_v4_0_5_stop - VCN stop
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to stop
  *
  * Stop VCN block
  */
-static int vcn_v4_0_5_stop(struct amdgpu_device *adev)
+static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	uint32_t tmp;
-	int i, r = 0;
+	int r = 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			vcn_v4_0_5_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+		vcn_v4_0_5_stop_dpg_mode(adev, i);
+		return 0;
+	}
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
-		if (r)
-			return r;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+	if (r)
+		return r;
 
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__READ_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* disable LMI UMC channel */
-		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
-			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	/* disable LMI UMC channel */
+	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
-				UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+	/* block VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
-		/* reset VCPU */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-				UVD_VCPU_CNTL__BLK_RST_MASK,
-				~UVD_VCPU_CNTL__BLK_RST_MASK);
+	/* reset VCPU */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
 
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-				~(UVD_VCPU_CNTL__CLK_EN_MASK));
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
 
-		/* apply soft reset */
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+	/* apply soft reset */
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
 
-		/* clear status */
-		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
+	/* clear status */
+	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
 
-		/* apply HW clock gating */
-		vcn_v4_0_5_enable_clock_gating(adev, i);
+	/* apply HW clock gating */
+	vcn_v4_0_5_enable_clock_gating(adev, i);
 
-		/* enable VCN power gating */
-		vcn_v4_0_5_enable_static_power_gating(adev, i);
-	}
+	/* enable VCN power gating */
+	vcn_v4_0_5_enable_static_power_gating(adev, i);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, false, i);
-	}
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, false, i);
 
 	return 0;
 }
@@ -1536,15 +1528,17 @@ static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 		enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v4_0_5_stop(adev);
-	else
-		ret = vcn_v4_0_5_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret |= vcn_v4_0_5_stop(adev, i);
+		else
+			ret |= vcn_v4_0_5_start(adev, i);
+	}
 
 	if (!ret)
 		adev->vcn.cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 06/44] drm/amdgpu/vcn5.0.0: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (4 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 05/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-04 15:56   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 07/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
                   ` (37 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 386 ++++++++++++------------
 1 file changed, 190 insertions(+), 196 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index b6d78381ebfbc..6b777ed01d445 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -767,154 +767,149 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
  * vcn_v5_0_0_start - VCN start
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to start
  *
  * Start VCN block
  */
-static int vcn_v5_0_0_start(struct amdgpu_device *adev)
+static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
-	int i, j, k, r;
+	int j, k, r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, true, i);
-	}
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, true, i);
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		/* disable VCN power gating */
-		vcn_v5_0_0_disable_static_power_gating(adev, i);
-
-		/* set VCN status busy */
-		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
-
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
-			~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
-			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
-
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-
-		/* setup regUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
-		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
-			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
-			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		vcn_v5_0_0_mc_resume(adev, i);
-
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
-			adev->gfx.config.gb_addr_config);
-
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		for (j = 0; j < 10; ++j) {
-			uint32_t status;
-
-			for (k = 0; k < 100; ++k) {
-				status = RREG32_SOC15(VCN, i, regUVD_STATUS);
-				if (status & 2)
-					break;
-				mdelay(10);
-				if (amdgpu_emu_mode == 1)
-					msleep(1);
-			}
+	/* disable VCN power gating */
+	vcn_v5_0_0_disable_static_power_gating(adev, i);
+
+	/* set VCN status busy */
+	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
+
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
 
-			if (amdgpu_emu_mode == 1) {
-				r = -1;
-				if (status & 2) {
-					r = 0;
-					break;
-				}
-			} else {
+	/* setup regUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
+	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
+		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	vcn_v5_0_0_mc_resume(adev, i);
+
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (j = 0; j < 10; ++j) {
+		uint32_t status;
+
+		for (k = 0; k < 100; ++k) {
+			status = RREG32_SOC15(VCN, i, regUVD_STATUS);
+			if (status & 2)
+				break;
+			mdelay(10);
+			if (amdgpu_emu_mode == 1)
+				msleep(1);
+		}
+
+		if (amdgpu_emu_mode == 1) {
+			r = -1;
+			if (status & 2) {
 				r = 0;
-				if (status & 2)
-					break;
-
-				dev_err(adev->dev,
-					"VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
-				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-							UVD_VCPU_CNTL__BLK_RST_MASK,
-							~UVD_VCPU_CNTL__BLK_RST_MASK);
-				mdelay(10);
-				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-							~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-				mdelay(10);
-				r = -1;
+				break;
 			}
+		} else {
+			r = 0;
+			if (status & 2)
+				break;
+
+			dev_err(adev->dev,
+				"VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
+			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+				 UVD_VCPU_CNTL__BLK_RST_MASK,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+			mdelay(10);
+			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+			mdelay(10);
+			r = -1;
 		}
+	}
 
-		if (r) {
-			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
-			return r;
-		}
+	if (r) {
+		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+		return r;
+	}
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
-				UVD_MASTINT_EN__VCPU_EN_MASK,
-				~UVD_MASTINT_EN__VCPU_EN_MASK);
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
-			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		ring = &adev->vcn.inst[i].ring_enc[0];
-		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
-			ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
-			VCN_RB1_DB_CTRL__EN_MASK);
-
-		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
-		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
-
-		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
-		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
-		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
-		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
-		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
-
-		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
-		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
-		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
-
-		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
-		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
-		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
-	}
+	ring = &adev->vcn.inst[i].ring_enc[0];
+	WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
+		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+		     VCN_RB1_DB_CTRL__EN_MASK);
+
+	WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
+	WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
+
+	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+	WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
+	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
+
+	tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
+	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
+	ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
+
+	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
 
 	return 0;
 }
@@ -953,83 +948,80 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
  * vcn_v5_0_0_stop - VCN stop
  *
  * @adev: amdgpu_device pointer
+ * @i: instance to stop
  *
  * Stop VCN block
  */
-static int vcn_v5_0_0_stop(struct amdgpu_device *adev)
+static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
 	uint32_t tmp;
-	int i, r = 0;
+	int r = 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			vcn_v5_0_0_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+		vcn_v5_0_0_stop_dpg_mode(adev, i);
+		return 0;
+	}
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
-		if (r)
-			return r;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+	if (r)
+		return r;
 
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-		      UVD_LMI_STATUS__READ_CLEAN_MASK |
-		      UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-		      UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* disable LMI UMC channel */
-		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
-		      UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	/* disable LMI UMC channel */
+	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
-			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* reset VCPU */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__BLK_RST_MASK,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
-			~(UVD_VCPU_CNTL__CLK_EN_MASK));
-
-		/* apply soft reset */
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
-
-		/* clear status */
-		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
-
-		/* enable VCN power gating */
-		vcn_v5_0_0_enable_static_power_gating(adev, i);
-	}
+	/* block VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->pm.dpm_enabled)
-			amdgpu_dpm_enable_vcn(adev, false, i);
-	}
+	/* reset VCPU */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+
+	/* apply soft reset */
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+
+	/* clear status */
+	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
+
+	/* enable VCN power gating */
+	vcn_v5_0_0_enable_static_power_gating(adev, i);
+
+	if (adev->pm.dpm_enabled)
+		amdgpu_dpm_enable_vcn(adev, false, i);
 
 	return 0;
 }
@@ -1279,15 +1271,17 @@ static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 		enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v5_0_0_stop(adev);
-	else
-		ret = vcn_v5_0_0_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret |= vcn_v5_0_0_stop(adev, i);
+		else
+			ret |= vcn_v5_0_0_start(adev, i);
+	}
 
 	if (!ret)
 		adev->vcn.cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 07/44] drm/amdgpu/vcn5.0.1: split code along instances
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (5 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 06/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-04 15:57   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 08/44] drm/amdgpu/vcn: switch work handler to be per instance Alex Deucher
                   ` (36 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Split the code on a per instance basis.  This will allow
us to use the per instance functions in the future to
handle more things per instance.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 352 ++++++++++++------------
 1 file changed, 174 insertions(+), 178 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 8b463c977d08f..25abb303d6698 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -568,149 +568,145 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
  *
  * Start VCN block
  */
-static int vcn_v5_0_1_start(struct amdgpu_device *adev)
+static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
-	int i, j, k, r, vcn_inst;
+	int j, k, r, vcn_inst;
 
 	if (adev->pm.dpm_enabled)
 		amdgpu_dpm_enable_uvd(adev, true);
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			r = vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
 
-		vcn_inst = GET_INST(VCN, i);
+	vcn_inst = GET_INST(VCN, i);
 
-		/* set VCN status busy */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
-
-		/* enable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
-
-		/* disable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
-			~UVD_MASTINT_EN__VCPU_EN_MASK);
-
-		/* enable LMI MC and UMC channels */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
-			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
-
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
-		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
-
-		/* setup regUVD_LMI_CTRL */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
-			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
-			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
-			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
-			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
-
-		vcn_v5_0_1_mc_resume(adev, i);
-
-		/* VCN global tiling registers */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
-			adev->gfx.config.gb_addr_config);
-
-		/* unblock VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* release VCPU reset to boot */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		for (j = 0; j < 10; ++j) {
-			uint32_t status;
-
-			for (k = 0; k < 100; ++k) {
-				status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
-				if (status & 2)
-					break;
-				mdelay(100);
-				if (amdgpu_emu_mode == 1)
-					msleep(20);
-			}
+	/* set VCN status busy */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
+
+	/* enable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+	/* disable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+	/* enable LMI MC and UMC channels */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
+		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+	/* setup regUVD_LMI_CTRL */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
+		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+	vcn_v5_0_1_mc_resume(adev, i);
+
+	/* VCN global tiling registers */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
+		     adev->gfx.config.gb_addr_config);
+
+	/* unblock VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	/* release VCPU reset to boot */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	for (j = 0; j < 10; ++j) {
+		uint32_t status;
+
+		for (k = 0; k < 100; ++k) {
+			status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
+			if (status & 2)
+				break;
+			mdelay(100);
+			if (amdgpu_emu_mode == 1)
+				msleep(20);
+		}
 
-			if (amdgpu_emu_mode == 1) {
-				r = -1;
-				if (status & 2) {
-					r = 0;
-					break;
-				}
-			} else {
+		if (amdgpu_emu_mode == 1) {
+			r = -1;
+			if (status & 2) {
 				r = 0;
-				if (status & 2)
-					break;
-
-				dev_err(adev->dev,
-				    "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
-				WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
-							UVD_VCPU_CNTL__BLK_RST_MASK,
-							~UVD_VCPU_CNTL__BLK_RST_MASK);
-				mdelay(10);
-				WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
-							~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-				mdelay(10);
-				r = -1;
+				break;
 			}
+		} else {
+			r = 0;
+			if (status & 2)
+				break;
+
+			dev_err(adev->dev,
+				"VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
+			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+				 UVD_VCPU_CNTL__BLK_RST_MASK,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+			mdelay(10);
+			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+			mdelay(10);
+			r = -1;
 		}
+	}
 
-		if (r) {
-			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
-			return r;
-		}
+	if (r) {
+		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+		return r;
+	}
 
-		/* enable master interrupt */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
-				UVD_MASTINT_EN__VCPU_EN_MASK,
-				~UVD_MASTINT_EN__VCPU_EN_MASK);
+	/* enable master interrupt */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
+		 UVD_MASTINT_EN__VCPU_EN_MASK,
+		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
 
-		/* clear the busy bit of VCN_STATUS */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
-			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+	/* clear the busy bit of VCN_STATUS */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
+		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
 
-		ring = &adev->vcn.inst[i].ring_enc[0];
+	ring = &adev->vcn.inst[i].ring_enc[0];
 
-		WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
-			ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
-			VCN_RB1_DB_CTRL__EN_MASK);
+	WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
+		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+		     VCN_RB1_DB_CTRL__EN_MASK);
 
-		/* Read DB_CTRL to flush the write DB_CTRL command. */
-		RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
+	/* Read DB_CTRL to flush the write DB_CTRL command. */
+	RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
 
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
 
-		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
-		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
-		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
+	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
 
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
-		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
-		ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
+	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
+	ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
 
-		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
-		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
-		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
-	}
+	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
 
 	return 0;
 }
@@ -750,71 +746,69 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
  *
  * Stop VCN block
  */
-static int vcn_v5_0_1_stop(struct amdgpu_device *adev)
+static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i)
 {
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	uint32_t tmp;
-	int i, r = 0, vcn_inst;
+	int r = 0, vcn_inst;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		vcn_inst = GET_INST(VCN, i);
+	vcn_inst = GET_INST(VCN, i);
 
-		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
-		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-			vcn_v5_0_1_stop_dpg_mode(adev, i);
-			continue;
-		}
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+		vcn_v5_0_1_stop_dpg_mode(adev, i);
+		return 0;
+	}
 
-		/* wait for vcn idle */
-		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
-		if (r)
-			return r;
+	/* wait for vcn idle */
+	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+	if (r)
+		return r;
 
-		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
-		      UVD_LMI_STATUS__READ_CLEAN_MASK |
-		      UVD_LMI_STATUS__WRITE_CLEAN_MASK |
-		      UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__READ_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* disable LMI UMC channel */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
-		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
-		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
-		      UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
-		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
-		if (r)
-			return r;
+	/* disable LMI UMC channel */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
+	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
+	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
+	if (r)
+		return r;
 
-		/* block VCPU register access */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
-			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
-			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
-
-		/* reset VCPU */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
-			UVD_VCPU_CNTL__BLK_RST_MASK,
-			~UVD_VCPU_CNTL__BLK_RST_MASK);
-
-		/* disable VCPU clock */
-		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
-			~(UVD_VCPU_CNTL__CLK_EN_MASK));
-
-		/* apply soft reset */
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
-		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
-		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
-		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
-
-		/* clear status */
-		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
-	}
+	/* block VCPU register access */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
+		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+	/* reset VCPU */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+		 UVD_VCPU_CNTL__BLK_RST_MASK,
+		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+	/* disable VCPU clock */
+	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+
+	/* apply soft reset */
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+	/* clear status */
+	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
 
 	if (adev->pm.dpm_enabled)
 		amdgpu_dpm_enable_uvd(adev, false);
@@ -1010,15 +1004,17 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret;
+	int ret = 0, i;
 
 	if (state == adev->vcn.cur_state)
 		return 0;
 
-	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v5_0_1_stop(adev);
-	else
-		ret = vcn_v5_0_1_start(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		if (state == AMD_PG_STATE_GATE)
+			ret = vcn_v5_0_1_stop(adev, i);
+		else
+			ret = vcn_v5_0_1_start(adev, i);
+	}
 
 	if (!ret)
 		adev->vcn.cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 08/44] drm/amdgpu/vcn: switch work handler to be per instance
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (6 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 07/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-04 20:59   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 09/44] drm/amdgpu/vcn: make powergating status " Alex Deucher
                   ` (35 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Have a separate work handler for each VCN instance. This
paves the way for per instance VCN power gating at runtime.

v2: index instances directly on vcn1.0 and 2.0 to make
it clear that they only support a single instance (Lijo)

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 84 +++++++++++++------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  8 ++-
 drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c  |  2 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   | 17 ++---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  4 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  4 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  5 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  4 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  5 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  5 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |  4 +-
 12 files changed, 80 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 83faf6e6788a2..0c3081a198d9e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -100,6 +100,9 @@ int amdgpu_vcn_early_init(struct amdgpu_device *adev)
 
 	amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		adev->vcn.inst[i].adev = adev;
+		adev->vcn.inst[i].inst = i;
+
 		if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
 			r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
 						 AMDGPU_UCODE_REQUIRED,
@@ -124,12 +127,13 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
 	unsigned int fw_shared_size, log_offset;
 	int i, r;
 
-	INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
-	mutex_init(&adev->vcn.vcn_pg_lock);
 	mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
-	atomic_set(&adev->vcn.total_submission_cnt, 0);
-	for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
+		atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
+		INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
 		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
+	}
 
 	if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
 	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
@@ -277,10 +281,10 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
 			amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
 
 		amdgpu_ucode_release(&adev->vcn.inst[j].fw);
+		mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
 	}
 
 	mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
-	mutex_destroy(&adev->vcn.vcn_pg_lock);
 
 	return 0;
 }
@@ -331,8 +335,10 @@ int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
 int amdgpu_vcn_suspend(struct amdgpu_device *adev)
 {
 	bool in_ras_intr = amdgpu_ras_intr_triggered();
+	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
 
 	/* err_event_athub will corrupt VCPU buffer, so we need to
 	 * restore fw data and clear buffer in amdgpu_vcn_resume() */
@@ -388,46 +394,45 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
 
 static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 {
-	struct amdgpu_device *adev =
-		container_of(work, struct amdgpu_device, vcn.idle_work.work);
+	struct amdgpu_vcn_inst *vcn_inst =
+		container_of(work, struct amdgpu_vcn_inst, idle_work.work);
+	struct amdgpu_device *adev = vcn_inst->adev;
 	unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
-	unsigned int i, j;
+	unsigned int i = vcn_inst->inst, j;
 	int r = 0;
 
-	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
-		if (adev->vcn.harvest_config & (1 << j))
-			continue;
-
-		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
-			fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
+	if (adev->vcn.harvest_config & (1 << i))
+		return;
 
-		/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
-		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
-		    !adev->vcn.using_unified_queue) {
-			struct dpg_pause_state new_state;
+	for (j = 0; j < adev->vcn.num_enc_rings; ++j)
+		fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
 
-			if (fence[j] ||
-				unlikely(atomic_read(&adev->vcn.inst[j].dpg_enc_submission_cnt)))
-				new_state.fw_based = VCN_DPG_STATE__PAUSE;
-			else
-				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
+	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
+	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
+	    !adev->vcn.using_unified_queue) {
+		struct dpg_pause_state new_state;
 
-			adev->vcn.pause_dpg_mode(adev, j, &new_state);
-		}
+		if (fence[i] ||
+		    unlikely(atomic_read(&vcn_inst->dpg_enc_submission_cnt)))
+			new_state.fw_based = VCN_DPG_STATE__PAUSE;
+		else
+			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 
-		fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);
-		fences += fence[j];
+		adev->vcn.pause_dpg_mode(adev, i, &new_state);
 	}
 
-	if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) {
+	fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
+	fences += fence[i];
+
+	if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) {
 		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
-		       AMD_PG_STATE_GATE);
+						       AMD_PG_STATE_GATE);
 		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
-				false);
+						    false);
 		if (r)
 			dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
 	} else {
-		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
+		schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT);
 	}
 }
 
@@ -436,18 +441,18 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 	struct amdgpu_device *adev = ring->adev;
 	int r = 0;
 
-	atomic_inc(&adev->vcn.total_submission_cnt);
+	atomic_inc(&adev->vcn.inst[ring->me].total_submission_cnt);
 
-	if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) {
+	if (!cancel_delayed_work_sync(&adev->vcn.inst[ring->me].idle_work)) {
 		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
 				true);
 		if (r)
 			dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
 	}
 
-	mutex_lock(&adev->vcn.vcn_pg_lock);
+	mutex_lock(&adev->vcn.inst[ring->me].vcn_pg_lock);
 	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
-	       AMD_PG_STATE_UNGATE);
+					       AMD_PG_STATE_UNGATE);
 
 	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
@@ -472,7 +477,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 
 		adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
 	}
-	mutex_unlock(&adev->vcn.vcn_pg_lock);
+	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
 }
 
 void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
@@ -485,9 +490,10 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
 	    !adev->vcn.using_unified_queue)
 		atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
 
-	atomic_dec(&ring->adev->vcn.total_submission_cnt);
+	atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
 
-	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
+	schedule_delayed_work(&ring->adev->vcn.inst[ring->me].idle_work,
+			      VCN_IDLE_TIMEOUT);
 }
 
 int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index c92f683ee5958..f1685283c2f13 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -295,6 +295,8 @@ struct amdgpu_vcn_fw_shared {
 };
 
 struct amdgpu_vcn_inst {
+	struct amdgpu_device	*adev;
+	int			inst;
 	struct amdgpu_bo	*vcpu_bo;
 	void			*cpu_addr;
 	uint64_t		gpu_addr;
@@ -316,6 +318,9 @@ struct amdgpu_vcn_inst {
 	const struct firmware	*fw; /* VCN firmware */
 	uint8_t			vcn_config;
 	uint32_t		vcn_codec_disable_mask;
+	atomic_t		total_submission_cnt;
+	struct mutex		vcn_pg_lock;
+	struct delayed_work	idle_work;
 };
 
 struct amdgpu_vcn_ras {
@@ -324,7 +329,6 @@ struct amdgpu_vcn_ras {
 
 struct amdgpu_vcn {
 	unsigned		fw_version;
-	struct delayed_work	idle_work;
 	unsigned		num_enc_rings;
 	enum amd_powergating_state cur_state;
 	bool			indirect_sram;
@@ -332,9 +336,7 @@ struct amdgpu_vcn {
 	uint8_t	num_vcn_inst;
 	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
 	struct amdgpu_vcn_reg	 internal;
-	struct mutex		 vcn_pg_lock;
 	struct mutex		vcn1_jpeg1_workaround;
-	atomic_t		 total_submission_cnt;
 
 	unsigned	harvest_config;
 	int (*pause_dpg_mode)(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
index 03b8b7cd5229b..8031406e20ff9 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
@@ -604,7 +604,7 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
 static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
 {
 	struct	amdgpu_device *adev = ring->adev;
-	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
+	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 	int		cnt = 0;
 
 	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 5ea96c9835170..b90d41cd001c8 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -150,7 +150,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
 		return r;
 
 	/* Override the work func */
-	adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler;
+	adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler;
 
 	amdgpu_vcn_setup_ucode(adev);
 
@@ -277,7 +277,7 @@ static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
+	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 		(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
@@ -301,7 +301,7 @@ static int vcn_v1_0_suspend(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	bool idle_work_unexecuted;
 
-	idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.idle_work);
+	idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 	if (idle_work_unexecuted) {
 		if (adev->pm.dpm_enabled)
 			amdgpu_dpm_enable_vcn(adev, false, 0);
@@ -1828,8 +1828,9 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 
 static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 {
-	struct amdgpu_device *adev =
-		container_of(work, struct amdgpu_device, vcn.idle_work.work);
+	struct amdgpu_vcn_inst *vcn_inst =
+		container_of(work, struct amdgpu_vcn_inst, idle_work.work);
+	struct amdgpu_device *adev = vcn_inst->adev;
 	unsigned int fences = 0, i;
 
 	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
@@ -1862,14 +1863,14 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
 			       AMD_PG_STATE_GATE);
 	} else {
-		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
+		schedule_delayed_work(&adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
 	}
 }
 
 static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
 {
 	struct	amdgpu_device *adev = ring->adev;
-	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
+	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 
 	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
 
@@ -1921,7 +1922,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
 
 void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
 {
-	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
+	schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
 	mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index e42cfc731ad8e..a51691c6d6110 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -313,7 +313,7 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
+	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 	    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index b9be304aa294b..6fb08ed093101 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -390,12 +390,12 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+
 		if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 		    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
 		     RREG32_SOC15(VCN, i, mmUVD_STATUS)))
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index a3627700ed48d..70a1b85a4efae 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -422,12 +422,12 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index c3eb4278bf465..4a846c9a2b039 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -359,11 +359,12 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
+
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 6293d1dc02fec..8343cee899c71 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -349,8 +349,10 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
 static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
 
 	if (adev->vcn.cur_state != AMD_PG_STATE_GATE)
 		vcn_v4_0_3_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index bf0da0da12512..e784f1457ee0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -300,11 +300,12 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
+
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 6b777ed01d445..03c7252e28ba9 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -280,11 +280,12 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
+
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 25abb303d6698..5950ec4c7f6db 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -206,8 +206,10 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block)
 static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
-	cancel_delayed_work_sync(&adev->vcn.idle_work);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
 
 	return 0;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 09/44] drm/amdgpu/vcn: make powergating status per instance
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (7 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 08/44] drm/amdgpu/vcn: switch work handler to be per instance Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05  1:50   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance Alex Deucher
                   ` (34 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Store it per instance so we can track it per instance.

v2: index instances directly on vcn1.0 and 2.0 to make
it clear that they only support a single instance (Lijo)

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h   |  2 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c     |  6 +--
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c     | 11 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c     | 43 +++++++++++-----
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c     | 49 ++++++++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c     | 60 ++++++++++++---------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c   | 63 ++++++++++++++---------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c   | 48 +++++++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c   | 48 +++++++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c   | 40 +++++++++-----
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c |  8 +--
 11 files changed, 241 insertions(+), 137 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index f1685283c2f13..0bcf4d1c7175d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -320,6 +320,7 @@ struct amdgpu_vcn_inst {
 	uint32_t		vcn_codec_disable_mask;
 	atomic_t		total_submission_cnt;
 	struct mutex		vcn_pg_lock;
+	enum amd_powergating_state cur_state;
 	struct delayed_work	idle_work;
 };
 
@@ -330,7 +331,6 @@ struct amdgpu_vcn_ras {
 struct amdgpu_vcn {
 	unsigned		fw_version;
 	unsigned		num_enc_rings;
-	enum amd_powergating_state cur_state;
 	bool			indirect_sram;
 
 	uint8_t	num_vcn_inst;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index b90d41cd001c8..757cacf11a817 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -280,7 +280,7 @@ static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-		(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+		(adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
 		 RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
 		vcn_v1_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
 	}
@@ -1813,7 +1813,7 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	int ret;
 	struct amdgpu_device *adev = ip_block->adev;
 
-	if (state == adev->vcn.cur_state)
+	if (state == adev->vcn.inst[0].cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1822,7 +1822,7 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 		ret = vcn_v1_0_start(adev);
 
 	if (!ret)
-		adev->vcn.cur_state = state;
+		adev->vcn.inst[0].cur_state = state;
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index a51691c6d6110..e55c1f8f260e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -316,8 +316,8 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-	    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
-	      RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
+	    (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
+	     RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
 		vcn_v2_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
 
 	return 0;
@@ -1810,11 +1810,11 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
+		adev->vcn.inst[0].cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.cur_state)
+	if (state == adev->vcn.inst[0].cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1823,7 +1823,8 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 		ret = vcn_v2_0_start(adev);
 
 	if (!ret)
-		adev->vcn.cur_state = state;
+		adev->vcn.inst[0].cur_state = state;
+
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 6fb08ed093101..1d3780a2d8513 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -95,8 +95,11 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_5[] = {
 static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+					       enum amd_powergating_state state,
+					       int i);
 static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-				enum amd_powergating_state state);
+					  enum amd_powergating_state state);
 static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,
 				int inst_idx, struct dpg_pause_state *new_state);
 static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
@@ -397,9 +400,9 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
 		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
 
 		if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-		    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+		    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
 		     RREG32_SOC15(VCN, i, mmUVD_STATUS)))
-			vcn_v2_5_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+			vcn_v2_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
 
 		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
 			amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
@@ -1805,27 +1808,39 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
+static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+					       enum amd_powergating_state state,
+					       int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
+	int ret;
 
 	if (amdgpu_sriov_vf(adev))
 		return 0;
 
-	if (state == adev->vcn.cur_state)
+	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret |= vcn_v2_5_stop(adev, i);
-		else
-			ret |= vcn_v2_5_start(adev, i);
-	}
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v2_5_stop(adev, i);
+	else
+		ret = vcn_v2_5_start(adev, i);
 
 	if (!ret)
-		adev->vcn.cur_state = state;
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
+static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
+					  enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0, i;
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		ret |= vcn_v2_5_set_powergating_state_inst(ip_block,
+							   state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 70a1b85a4efae..13b9ed96cccda 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -105,8 +105,11 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev);
 static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+					       enum amd_powergating_state state,
+					       int i);
 static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-			enum amd_powergating_state state);
+					  enum amd_powergating_state state);
 static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
 			int inst_idx, struct dpg_pause_state *new_state);
 
@@ -430,9 +433,11 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
-				 RREG32_SOC15(VCN, i, mmUVD_STATUS))) {
-				vcn_v3_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			     RREG32_SOC15(VCN, i, mmUVD_STATUS))) {
+				vcn_v3_0_set_powergating_state_inst(ip_block,
+								    AMD_PG_STATE_GATE,
+								    i);
 			}
 		}
 	}
@@ -2147,33 +2152,45 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
+static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+					       enum amd_powergating_state state,
+					       int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
+	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
 	 * MMSCH FW should control Power-gating and clock-gating
 	 * guest should avoid touching CGC and PG
 	 */
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
+		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.cur_state)
+	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret |= vcn_v3_0_stop(adev, i);
-		else
-			ret |= vcn_v3_0_start(adev, i);
-	}
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v3_0_stop(adev, i);
+	else
+		ret = vcn_v3_0_start(adev, i);
 
 	if (!ret)
-		adev->vcn.cur_state = state;
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
+static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
+					  enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0, i;
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		ret |= vcn_v3_0_set_powergating_state_inst(ip_block,
+							   state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 4a846c9a2b039..dbbeeffc90726 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -96,8 +96,11 @@ static int amdgpu_ih_clientid_vcns[] = {
 static int vcn_v4_0_start_sriov(struct amdgpu_device *adev);
 static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+					       enum amd_powergating_state state,
+					       int i);
 static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-        enum amd_powergating_state state);
+					  enum amd_powergating_state state);
 static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev,
         int inst_idx, struct dpg_pause_state *new_state);
 static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -367,9 +370,9 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+				(adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
 				 RREG32_SOC15(VCN, i, regUVD_STATUS))) {
-				vcn_v4_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+				vcn_v4_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
 			}
 		}
 		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
@@ -2032,41 +2035,52 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-/**
- * vcn_v4_0_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: amdgpu_ip_block pointer
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
+static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+					       enum amd_powergating_state state,
+					       int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
+	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
 	 * MMSCH FW should control Power-gating and clock-gating
 	 * guest should avoid touching CGC and PG
 	 */
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
+		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.cur_state)
+	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret |= vcn_v4_0_stop(adev, i);
-		else
-			ret |= vcn_v4_0_start(adev, i);
-	}
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v4_0_stop(adev, i);
+	else
+		ret = vcn_v4_0_start(adev, i);
 
 	if (!ret)
-		adev->vcn.cur_state = state;
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
+/**
+ * vcn_v4_0_set_powergating_state - set VCN block powergating state
+ *
+ * @ip_block: amdgpu_ip_block pointer
+ * @state: power gating state
+ *
+ * Set VCN block powergating state
+ */
+static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
+					  enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0, i;
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		ret |= vcn_v4_0_set_powergating_state_inst(ip_block, state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 8343cee899c71..8396ef6831b69 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -87,8 +87,11 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_3[] = {
 static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev);
 static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i);
 static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
-		enum amd_powergating_state state);
+					    enum amd_powergating_state state);
 static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev,
 		int inst_idx, struct dpg_pause_state *new_state);
 static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -351,11 +354,12 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
 
-	if (adev->vcn.cur_state != AMD_PG_STATE_GATE)
-		vcn_v4_0_3_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+		if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE)
+			vcn_v4_0_3_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
+	}
 
 	return 0;
 }
@@ -1646,41 +1650,52 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-/**
- * vcn_v4_0_3_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: amdgpu_ip_block pointer
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
+static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
+	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
 	 * MMSCH FW should control Power-gating and clock-gating
 	 * guest should avoid touching CGC and PG
 	 */
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
+		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.cur_state)
+	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret |= vcn_v4_0_3_stop(adev, i);
-		else
-			ret |= vcn_v4_0_3_start(adev, i);
-	}
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v4_0_3_stop(adev, i);
+	else
+		ret = vcn_v4_0_3_start(adev, i);
 
 	if (!ret)
-		adev->vcn.cur_state = state;
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
+/**
+ * vcn_v4_0_3_set_powergating_state - set VCN block powergating state
+ *
+ * @ip_block: amdgpu_ip_block pointer
+ * @state: power gating state
+ *
+ * Set VCN block powergating state
+ */
+static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
+					    enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0, i;
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		vcn_v4_0_3_set_powergating_state_inst(ip_block, state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index e784f1457ee0a..f6b347fcdb7ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -95,8 +95,11 @@ static int amdgpu_ih_clientid_vcns[] = {
 
 static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i);
 static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-		enum amd_powergating_state state);
+					    enum amd_powergating_state state);
 static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev,
 		int inst_idx, struct dpg_pause_state *new_state);
 static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -308,9 +311,9 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
-				RREG32_SOC15(VCN, i, regUVD_STATUS))) {
-				vcn_v4_0_5_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			     RREG32_SOC15(VCN, i, regUVD_STATUS))) {
+				vcn_v4_0_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
 			}
 		}
 	}
@@ -1517,6 +1520,27 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
+static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0;
+
+	if (state == adev->vcn.inst[i].cur_state)
+		return 0;
+
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v4_0_5_stop(adev, i);
+	else
+		ret = vcn_v4_0_5_start(adev, i);
+
+	if (!ret)
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
 /**
  * vcn_v4_0_5_set_powergating_state - set VCN block powergating state
  *
@@ -1526,23 +1550,13 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
  * Set VCN block powergating state
  */
 static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-		enum amd_powergating_state state)
+					    enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	if (state == adev->vcn.cur_state)
-		return 0;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret |= vcn_v4_0_5_stop(adev, i);
-		else
-			ret |= vcn_v4_0_5_start(adev, i);
-	}
-
-	if (!ret)
-		adev->vcn.cur_state = state;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		vcn_v4_0_5_set_powergating_state_inst(ip_block, state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 03c7252e28ba9..c5d59edf3a482 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -78,8 +78,11 @@ static int amdgpu_ih_clientid_vcns[] = {
 
 static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i);
 static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-		enum amd_powergating_state state);
+					    enum amd_powergating_state state);
 static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev,
 		int inst_idx, struct dpg_pause_state *new_state);
 static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -288,9 +291,9 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
-				RREG32_SOC15(VCN, i, regUVD_STATUS))) {
-				vcn_v5_0_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			     RREG32_SOC15(VCN, i, regUVD_STATUS))) {
+				vcn_v5_0_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
 			}
 		}
 	}
@@ -1260,6 +1263,27 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
+static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0;
+
+	if (state == adev->vcn.inst[i].cur_state)
+		return 0;
+
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v5_0_0_stop(adev, i);
+	else
+		ret = vcn_v5_0_0_start(adev, i);
+
+	if (!ret)
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
 /**
  * vcn_v5_0_0_set_powergating_state - set VCN block powergating state
  *
@@ -1269,23 +1293,13 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
  * Set VCN block powergating state
  */
 static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-		enum amd_powergating_state state)
+					    enum amd_powergating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	if (state == adev->vcn.cur_state)
-		return 0;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret |= vcn_v5_0_0_stop(adev, i);
-		else
-			ret |= vcn_v5_0_0_start(adev, i);
-	}
-
-	if (!ret)
-		adev->vcn.cur_state = state;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		vcn_v5_0_0_set_powergating_state_inst(ip_block, state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 5950ec4c7f6db..51a2d70a65c9e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -40,8 +40,11 @@
 
 static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i);
 static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
-		enum amd_powergating_state state);
+					    enum amd_powergating_state state);
 static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
 
 /**
@@ -994,6 +997,27 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
+static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
+						 enum amd_powergating_state state,
+						 int i)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0;
+
+	if (state == adev->vcn.inst[i].cur_state)
+		return 0;
+
+	if (state == AMD_PG_STATE_GATE)
+		ret = vcn_v5_0_1_stop(adev, i);
+	else
+		ret = vcn_v5_0_1_start(adev, i);
+
+	if (!ret)
+		adev->vcn.inst[i].cur_state = state;
+
+	return ret;
+}
+
 /**
  * vcn_v5_0_1_set_powergating_state - set VCN block powergating state
  *
@@ -1008,18 +1032,8 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	if (state == adev->vcn.cur_state)
-		return 0;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (state == AMD_PG_STATE_GATE)
-			ret = vcn_v5_0_1_stop(adev, i);
-		else
-			ret = vcn_v5_0_1_start(adev, i);
-	}
-
-	if (!ret)
-		adev->vcn.cur_state = state;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		vcn_v5_0_1_set_powergating_state_inst(ip_block, state, i);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 51c2a7f4aba28..e8cf4aa6c43dd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -2037,15 +2037,15 @@ static int smu_hw_fini(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
 		return 0;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
 		smu_dpm_set_vcn_enable(smu, false, i);
+		adev->vcn.inst[i].cur_state = AMD_PG_STATE_GATE;
+	}
 	smu_dpm_set_jpeg_enable(smu, false);
+	adev->jpeg.cur_state = AMD_PG_STATE_GATE;
 	smu_dpm_set_vpe_enable(smu, false);
 	smu_dpm_set_umsch_mm_enable(smu, false);
 
-	adev->vcn.cur_state = AMD_PG_STATE_GATE;
-	adev->jpeg.cur_state = AMD_PG_STATE_GATE;
-
 	if (!smu->pm_enabled)
 		return 0;
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (8 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 09/44] drm/amdgpu/vcn: make powergating status " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05  3:06   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 11/44] drm/amdgpu/vcn: switch vcn helpers to be instance based Alex Deucher
                   ` (33 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Move more per instance data into the per instance structure.

v2: index instances directly on vcn1.0 and 2.0 to make
it clear that they only support a single instance (Lijo)

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 196 ++++++++++++------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  17 +-
 drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c  |   4 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   |  42 ++---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  92 +++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  51 +++---
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  67 ++++----
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  19 ++-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  14 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  18 ++-
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  16 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |   8 +-
 13 files changed, 279 insertions(+), 267 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 2c76bc5e25d92..5ee2ae66ed36b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -480,7 +480,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
 			if (adev->vcn.harvest_config & (1 << i))
 				continue;
 
-			for (j = 0; j < adev->vcn.num_enc_rings; j++)
+			for (j = 0; j < adev->vcn.inst[i].num_enc_rings; j++)
 				if (adev->vcn.inst[i].ring_enc[j].sched.ready)
 					++num_rings;
 		}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 0c3081a198d9e..9901b8e17f305 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -127,93 +127,88 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
 	unsigned int fw_shared_size, log_offset;
 	int i, r;
 
-	mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
 		mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
 		atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
 		INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
 		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
-	}
-
-	if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
-	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
-		adev->vcn.indirect_sram = true;
-
-	/*
-	 * Some Steam Deck's BIOS versions are incompatible with the
-	 * indirect SRAM mode, leading to amdgpu being unable to get
-	 * properly probed (and even potentially crashing the kernel).
-	 * Hence, check for these versions here - notice this is
-	 * restricted to Vangogh (Deck's APU).
-	 */
-	if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
-		const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
-
-		if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
-		     !strncmp("F7A0114", bios_ver, 7))) {
-			adev->vcn.indirect_sram = false;
-			dev_info(adev->dev,
-				"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
+		if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
+		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
+			adev->vcn.inst[i].indirect_sram = true;
+
+		/*
+		 * Some Steam Deck's BIOS versions are incompatible with the
+		 * indirect SRAM mode, leading to amdgpu being unable to get
+		 * properly probed (and even potentially crashing the kernel).
+		 * Hence, check for these versions here - notice this is
+		 * restricted to Vangogh (Deck's APU).
+		 */
+		if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
+			const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
+
+			if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
+					 !strncmp("F7A0114", bios_ver, 7))) {
+				adev->vcn.inst[i].indirect_sram = false;
+				dev_info(adev->dev,
+					 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
+			}
 		}
-	}
 
-	/* from vcn4 and above, only unified queue is used */
-	adev->vcn.using_unified_queue =
-		amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
-
-	hdr = (const struct common_firmware_header *)adev->vcn.inst[0].fw->data;
-	adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
-
-	/* Bit 20-23, it is encode major and non-zero for new naming convention.
-	 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
-	 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
-	 * is zero in old naming convention, this field is always zero so far.
-	 * These four bits are used to tell which naming convention is present.
-	 */
-	fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
-	if (fw_check) {
-		unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
-
-		fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
-		enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
-		enc_major = fw_check;
-		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
-		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
-		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
-			enc_major, enc_minor, dec_ver, vep, fw_rev);
-	} else {
-		unsigned int version_major, version_minor, family_id;
+		/* from vcn4 and above, only unified queue is used */
+		adev->vcn.inst[i].using_unified_queue =
+			amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
+
+		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
+		adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
+		adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
+
+		/* Bit 20-23, it is encode major and non-zero for new naming convention.
+		 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
+		 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
+		 * is zero in old naming convention, this field is always zero so far.
+		 * These four bits are used to tell which naming convention is present.
+		 */
+		fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
+		if (fw_check) {
+			unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
+
+			fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
+			enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
+			enc_major = fw_check;
+			dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
+			vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
+			DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
+				 enc_major, enc_minor, dec_ver, vep, fw_rev);
+		} else {
+			unsigned int version_major, version_minor, family_id;
 
-		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
-		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
-		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
-		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
-			version_major, version_minor, family_id);
-	}
+			family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
+			version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
+			version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
+			DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
+				 version_major, version_minor, family_id);
+		}
 
-	bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
-	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+		bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
+		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+			bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
 
-	if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
-		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
-		log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
-	} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
-		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
-		log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
-	} else {
-		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
-		log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
-	}
-
-	bo_size += fw_shared_size;
+		if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
+			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
+			log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
+		} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
+			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
+			log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
+		} else {
+			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
+			log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
+		}
 
-	if (amdgpu_vcnfw_log)
-		bo_size += AMDGPU_VCNFW_LOG_SIZE;
+		bo_size += fw_shared_size;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
+		if (amdgpu_vcnfw_log)
+			bo_size += AMDGPU_VCNFW_LOG_SIZE;
 
 		r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
 					    AMDGPU_GEM_DOMAIN_VRAM |
@@ -239,7 +234,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
 			adev->vcn.inst[i].fw_shared.log_offset = log_offset;
 		}
 
-		if (adev->vcn.indirect_sram) {
+		if (adev->vcn.inst[i].indirect_sram) {
 			r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
 					AMDGPU_GEM_DOMAIN_VRAM |
 					AMDGPU_GEM_DOMAIN_GTT,
@@ -277,15 +272,14 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
 
 		amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
 
-		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
+		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i)
 			amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
 
 		amdgpu_ucode_release(&adev->vcn.inst[j].fw);
 		mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
+		mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround);
 	}
 
-	mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
-
 	return 0;
 }
 
@@ -404,12 +398,12 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 	if (adev->vcn.harvest_config & (1 << i))
 		return;
 
-	for (j = 0; j < adev->vcn.num_enc_rings; ++j)
+	for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
 		fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
 
 	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
-	    !adev->vcn.using_unified_queue) {
+	    !adev->vcn.inst[i].using_unified_queue) {
 		struct dpg_pause_state new_state;
 
 		if (fence[i] ||
@@ -418,7 +412,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 		else
 			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 
-		adev->vcn.pause_dpg_mode(adev, i, &new_state);
+		adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state);
 	}
 
 	fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
@@ -456,7 +450,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 
 	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
-	    !adev->vcn.using_unified_queue) {
+	    !adev->vcn.inst[ring->me].using_unified_queue) {
 		struct dpg_pause_state new_state;
 
 		if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
@@ -466,7 +460,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 			unsigned int fences = 0;
 			unsigned int i;
 
-			for (i = 0; i < adev->vcn.num_enc_rings; ++i)
+			for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i)
 				fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
 
 			if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
@@ -475,7 +469,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 		}
 
-		adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
+		adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state);
 	}
 	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
 }
@@ -487,7 +481,7 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
 	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
 	if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
 	    ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
-	    !adev->vcn.using_unified_queue)
+	    !adev->vcn.inst[ring->me].using_unified_queue)
 		atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
 
 	atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
@@ -511,7 +505,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
 	r = amdgpu_ring_alloc(ring, 3);
 	if (r)
 		return r;
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
 	amdgpu_ring_write(ring, 0xDEADBEEF);
 	amdgpu_ring_commit(ring);
 	for (i = 0; i < adev->usec_timeout; i++) {
@@ -576,14 +570,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
 		goto err;
 
 	ib = &job->ibs[0];
-	ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
+	ib->ptr[0] = PACKET0(adev->vcn.inst[ring->me].internal.data0, 0);
 	ib->ptr[1] = addr;
-	ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
+	ib->ptr[2] = PACKET0(adev->vcn.inst[ring->me].internal.data1, 0);
 	ib->ptr[3] = addr >> 32;
-	ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
+	ib->ptr[4] = PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0);
 	ib->ptr[5] = 0;
 	for (i = 6; i < 16; i += 2) {
-		ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
+		ib->ptr[i] = PACKET0(adev->vcn.inst[ring->me].internal.nop, 0);
 		ib->ptr[i+1] = 0;
 	}
 	ib->length_dw = 16;
@@ -746,7 +740,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
 	uint32_t ib_pack_in_dw;
 	int i, r;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		ib_size_dw += 8;
 
 	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -759,7 +753,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
 	ib->length_dw = 0;
 
 	/* single queue headers */
-	if (adev->vcn.using_unified_queue) {
+	if (adev->vcn.inst[ring->me].using_unified_queue) {
 		ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
 						+ 4 + 2; /* engine info + decoding ib in dw */
 		ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
@@ -778,7 +772,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
 	for (i = ib->length_dw; i < ib_size_dw; ++i)
 		ib->ptr[i] = 0x0;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
 
 	r = amdgpu_job_submit_direct(job, ring, &f);
@@ -876,7 +870,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
 	uint64_t addr;
 	int i, r;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		ib_size_dw += 8;
 
 	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -890,7 +884,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
 
 	ib->length_dw = 0;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
 
 	ib->ptr[ib->length_dw++] = 0x00000018;
@@ -912,7 +906,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
 	for (i = ib->length_dw; i < ib_size_dw; ++i)
 		ib->ptr[i] = 0x0;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
 
 	r = amdgpu_job_submit_direct(job, ring, &f);
@@ -943,7 +937,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
 	uint64_t addr;
 	int i, r;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		ib_size_dw += 8;
 
 	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -957,7 +951,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
 
 	ib->length_dw = 0;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
 
 	ib->ptr[ib->length_dw++] = 0x00000018;
@@ -979,7 +973,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
 	for (i = ib->length_dw; i < ib_size_dw; ++i)
 		ib->ptr[i] = 0x0;
 
-	if (adev->vcn.using_unified_queue)
+	if (adev->vcn.inst[ring->me].using_unified_queue)
 		amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
 
 	r = amdgpu_job_submit_direct(job, ring, &f);
@@ -1396,7 +1390,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
 	struct dentry *root = minor->debugfs_root;
 	char name[32];
 
-	if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.using_unified_queue)
+	if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.inst[0].using_unified_queue)
 		return;
 	sprintf(name, "amdgpu_vcn_sched_mask");
 	debugfs_create_file(name, 0600, root, adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 0bcf4d1c7175d..3b059f51894b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -322,6 +322,15 @@ struct amdgpu_vcn_inst {
 	struct mutex		vcn_pg_lock;
 	enum amd_powergating_state cur_state;
 	struct delayed_work	idle_work;
+	unsigned		fw_version;
+	unsigned		num_enc_rings;
+	bool			indirect_sram;
+	struct amdgpu_vcn_reg	 internal;
+	struct mutex		vcn1_jpeg1_workaround;
+	int (*pause_dpg_mode)(struct amdgpu_device *adev,
+			      int inst_idx,
+			      struct dpg_pause_state *new_state);
+	bool using_unified_queue;
 };
 
 struct amdgpu_vcn_ras {
@@ -330,24 +339,16 @@ struct amdgpu_vcn_ras {
 
 struct amdgpu_vcn {
 	unsigned		fw_version;
-	unsigned		num_enc_rings;
-	bool			indirect_sram;
-
 	uint8_t	num_vcn_inst;
 	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
-	struct amdgpu_vcn_reg	 internal;
-	struct mutex		vcn1_jpeg1_workaround;
 
 	unsigned	harvest_config;
-	int (*pause_dpg_mode)(struct amdgpu_device *adev,
-		int inst_idx, struct dpg_pause_state *new_state);
 
 	struct ras_common_if    *ras_if;
 	struct amdgpu_vcn_ras   *ras;
 
 	uint16_t inst_mask;
 	uint8_t	num_inst_per_aid;
-	bool using_unified_queue;
 
 	/* IP reg dump */
 	uint32_t		*ip_dump;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
index 8031406e20ff9..9e428e669ada6 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
@@ -607,12 +607,12 @@ static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
 	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 	int		cnt = 0;
 
-	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
+	mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
 
 	if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
 		DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
 
-	for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
+	for (cnt = 0; cnt < adev->vcn.inst[0].num_enc_rings; cnt++) {
 		if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
 			DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 757cacf11a817..c870d9ba64c69 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -105,7 +105,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
 
-	adev->vcn.num_enc_rings = 2;
+	adev->vcn.inst[0].num_enc_rings = 2;
 
 	vcn_v1_0_set_dec_ring_funcs(adev);
 	vcn_v1_0_set_enc_ring_funcs(adev);
@@ -138,7 +138,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
 		return r;
 
 	/* VCN ENC TRAP */
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_1_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
 					&adev->vcn.inst->irq);
 		if (r)
@@ -166,18 +166,18 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
 	if (r)
 		return r;
 
-	adev->vcn.internal.scratch9 = adev->vcn.inst->external.scratch9 =
+	adev->vcn.inst[0].internal.scratch9 = adev->vcn.inst->external.scratch9 =
 		SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
-	adev->vcn.internal.data0 = adev->vcn.inst->external.data0 =
+	adev->vcn.inst[0].internal.data0 = adev->vcn.inst->external.data0 =
 		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
-	adev->vcn.internal.data1 = adev->vcn.inst->external.data1 =
+	adev->vcn.inst[0].internal.data1 = adev->vcn.inst->external.data1 =
 		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
-	adev->vcn.internal.cmd = adev->vcn.inst->external.cmd =
+	adev->vcn.inst[0].internal.cmd = adev->vcn.inst->external.cmd =
 		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
-	adev->vcn.internal.nop = adev->vcn.inst->external.nop =
+	adev->vcn.inst[0].internal.nop = adev->vcn.inst->external.nop =
 		SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
 
 		ring = &adev->vcn.inst->ring_enc[i];
@@ -189,7 +189,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
+	adev->vcn.inst[0].pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
 
 	if (amdgpu_vcnfw_log) {
 		volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
@@ -253,7 +253,7 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block)
 	if (r)
 		return r;
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		ring = &adev->vcn.inst->ring_enc[i];
 		r = amdgpu_ring_test_helper(ring);
 		if (r)
@@ -1833,7 +1833,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 	struct amdgpu_device *adev = vcn_inst->adev;
 	unsigned int fences = 0, i;
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
 		fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
@@ -1849,7 +1849,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 		else
 			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
 
-		adev->vcn.pause_dpg_mode(adev, 0, &new_state);
+		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
 	}
 
 	fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
@@ -1872,7 +1872,7 @@ static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
 	struct	amdgpu_device *adev = ring->adev;
 	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
 
-	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
+	mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
 
 	if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec))
 		DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
@@ -1898,7 +1898,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
 		struct dpg_pause_state new_state;
 		unsigned int fences = 0, i;
 
-		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
+		for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
 			fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
 
 		if (fences)
@@ -1916,14 +1916,14 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
 		else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
 			new_state.jpeg = VCN_DPG_STATE__PAUSE;
 
-		adev->vcn.pause_dpg_mode(adev, 0, &new_state);
+		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
 	}
 }
 
 void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
 {
 	schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
-	mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
+	mutex_unlock(&ring->adev->vcn.inst[0].vcn1_jpeg1_workaround);
 }
 
 static void vcn_v1_0_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
@@ -2057,11 +2057,11 @@ static int vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
 		uint32_t reg = amdgpu_ib_get_value(ib, i);
 		uint32_t val = amdgpu_ib_get_value(ib, i + 1);
 
-		if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
+		if (reg == PACKET0(p->adev->vcn.inst[0].internal.data0, 0)) {
 			msg_lo = val;
-		} else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
+		} else if (reg == PACKET0(p->adev->vcn.inst[0].internal.data1, 0)) {
 			msg_hi = val;
-		} else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0)) {
+		} else if (reg == PACKET0(p->adev->vcn.inst[0].internal.cmd, 0)) {
 			r = vcn_v1_0_validate_bo(p, job,
 						 ((u64)msg_hi) << 32 | msg_lo);
 			if (r)
@@ -2146,7 +2146,7 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
 {
 	int i;
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
 		adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
 }
 
@@ -2157,7 +2157,7 @@ static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
 
 static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev)
 {
-	adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2;
+	adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 2;
 	adev->vcn.inst->irq.funcs = &vcn_v1_0_irq_funcs;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index e55c1f8f260e9..b0a957664250c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -110,9 +110,9 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 
 	if (amdgpu_sriov_vf(adev))
-		adev->vcn.num_enc_rings = 1;
+		adev->vcn.inst[0].num_enc_rings = 1;
 	else
-		adev->vcn.num_enc_rings = 2;
+		adev->vcn.inst[0].num_enc_rings = 2;
 
 	vcn_v2_0_set_dec_ring_funcs(adev);
 	vcn_v2_0_set_enc_ring_funcs(adev);
@@ -145,7 +145,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
 		return r;
 
 	/* VCN ENC TRAP */
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
 				      i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
 				      &adev->vcn.inst->irq);
@@ -175,25 +175,25 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
 	if (r)
 		return r;
 
-	adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
-	adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
-	adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
-	adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
-	adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
-	adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
 
-	adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
 	adev->vcn.inst->external.scratch9 = SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
-	adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
 	adev->vcn.inst->external.data0 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
-	adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
 	adev->vcn.inst->external.data1 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
-	adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
 	adev->vcn.inst->external.cmd = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
-	adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
+	adev->vcn.inst[0].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
 	adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
 
 		ring = &adev->vcn.inst->ring_enc[i];
@@ -210,7 +210,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	adev->vcn.pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
+	adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
 
 	r = amdgpu_virt_alloc_mm_table(adev);
 	if (r)
@@ -292,7 +292,7 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev))
 		ring->sched.ready = false;
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		ring = &adev->vcn.inst->ring_enc[i];
 		r = amdgpu_ring_test_helper(ring);
 		if (r)
@@ -981,7 +981,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
 		amdgpu_dpm_enable_vcn(adev, true, 0);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram);
+		return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram);
 
 	vcn_v2_0_disable_static_power_gating(adev);
 
@@ -1421,9 +1421,9 @@ void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
 	amdgpu_ring_write(ring, 0);
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
 }
 
@@ -1438,7 +1438,7 @@ void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[0].internal.cmd, 0));
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
 }
 
@@ -1458,7 +1458,7 @@ void vcn_v2_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
 	WARN_ON(ring->wptr % 2 || count % 2);
 
 	for (i = 0; i < count / 2; i++) {
-		amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.nop, 0));
+		amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.nop, 0));
 		amdgpu_ring_write(ring, 0);
 	}
 }
@@ -1479,25 +1479,25 @@ void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
 	struct amdgpu_device *adev = ring->adev;
 
 	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.context_id, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.context_id, 0));
 	amdgpu_ring_write(ring, seq);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
 	amdgpu_ring_write(ring, addr & 0xffffffff);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
 	amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
 	amdgpu_ring_write(ring, 0);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
 	amdgpu_ring_write(ring, 0);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
 
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
 }
@@ -1520,14 +1520,14 @@ void vcn_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
 	struct amdgpu_device *adev = ring->adev;
 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_vmid, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_vmid, 0));
 	amdgpu_ring_write(ring, vmid);
 
-	amdgpu_ring_write(ring,	PACKET0(adev->vcn.internal.ib_bar_low, 0));
+	amdgpu_ring_write(ring,	PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_low, 0));
 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
-	amdgpu_ring_write(ring,	PACKET0(adev->vcn.internal.ib_bar_high, 0));
+	amdgpu_ring_write(ring,	PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_high, 0));
 	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
-	amdgpu_ring_write(ring,	PACKET0(adev->vcn.internal.ib_size, 0));
+	amdgpu_ring_write(ring,	PACKET0(adev->vcn.inst[ring->me].internal.ib_size, 0));
 	amdgpu_ring_write(ring, ib->length_dw);
 }
 
@@ -1536,16 +1536,16 @@ void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
 	amdgpu_ring_write(ring, reg << 2);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
 	amdgpu_ring_write(ring, val);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.gp_scratch8, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.gp_scratch8, 0));
 	amdgpu_ring_write(ring, mask);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
 
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
 }
@@ -1570,13 +1570,13 @@ void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
 	amdgpu_ring_write(ring, reg << 2);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
 	amdgpu_ring_write(ring, val);
 
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
 
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
 }
@@ -1777,9 +1777,9 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
 	r = amdgpu_ring_alloc(ring, 4);
 	if (r)
 		return r;
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
 	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
-	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
+	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
 	amdgpu_ring_write(ring, 0xDEADBEEF);
 	amdgpu_ring_commit(ring);
 	for (i = 0; i < adev->usec_timeout; i++) {
@@ -1863,7 +1863,7 @@ static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev,
 	adev->vcn.inst->ring_dec.wptr_old = 0;
 	vcn_v2_0_dec_ring_set_wptr(&adev->vcn.inst->ring_dec);
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
 		adev->vcn.inst->ring_enc[i].wptr = 0;
 		adev->vcn.inst->ring_enc[i].wptr_old = 0;
 		vcn_v2_0_enc_ring_set_wptr(&adev->vcn.inst->ring_enc[i]);
@@ -1989,7 +1989,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev)
 			SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2),
 			AMDGPU_VCN_CONTEXT_SIZE);
 
-		for (r = 0; r < adev->vcn.num_enc_rings; ++r) {
+		for (r = 0; r < adev->vcn.inst[0].num_enc_rings; ++r) {
 			ring = &adev->vcn.inst->ring_enc[r];
 			ring->wptr = 0;
 			MMSCH_V2_0_INSERT_DIRECT_WT(
@@ -2178,7 +2178,7 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
 {
 	int i;
 
-	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
+	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
 		adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs;
 }
 
@@ -2189,7 +2189,7 @@ static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
 
 static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev)
 {
-	adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 1;
+	adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 1;
 	adev->vcn.inst->irq.funcs = &vcn_v2_0_irq_funcs;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 1d3780a2d8513..a3bac39e4c9db 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -121,11 +121,13 @@ static int amdgpu_ih_clientid_vcns[] = {
 static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
 	if (amdgpu_sriov_vf(adev)) {
 		adev->vcn.num_vcn_inst = 2;
 		adev->vcn.harvest_config = 0;
-		adev->vcn.num_enc_rings = 1;
+		for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+			adev->vcn.inst[i].num_enc_rings = 1;
 	} else {
 		u32 harvest;
 		int i;
@@ -134,13 +136,12 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
 			harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING);
 			if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
 				adev->vcn.harvest_config |= 1 << i;
+			adev->vcn.inst[i].num_enc_rings = 2;
 		}
 		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
 					AMDGPU_VCN_HARVEST_VCN1))
 			/* both instances are harvested, disable the block */
 			return -ENOENT;
-
-		adev->vcn.num_enc_rings = 2;
 	}
 
 	vcn_v2_5_set_dec_ring_funcs(adev);
@@ -176,7 +177,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 
 		/* VCN ENC TRAP */
-		for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
 			r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j],
 				i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[j].irq);
 			if (r)
@@ -205,22 +206,22 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 
 		if (adev->vcn.harvest_config & (1 << j))
 			continue;
-		adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
-		adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
-
-		adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
+
+		adev->vcn.inst[j].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
 		adev->vcn.inst[j].external.scratch9 = SOC15_REG_OFFSET(VCN, j, mmUVD_SCRATCH9);
-		adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
 		adev->vcn.inst[j].external.data0 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA0);
-		adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
 		adev->vcn.inst[j].external.data1 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA1);
-		adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
 		adev->vcn.inst[j].external.cmd = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_CMD);
-		adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
+		adev->vcn.inst[j].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
 		adev->vcn.inst[j].external.nop = SOC15_REG_OFFSET(VCN, j, mmUVD_NO_OP);
 
 		ring = &adev->vcn.inst[j].ring_dec;
@@ -240,7 +241,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 		if (r)
 			return r;
 
-		for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
 			enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
 
 			ring = &adev->vcn.inst[j].ring_enc[i];
@@ -268,6 +269,9 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 
 		if (amdgpu_vcnfw_log)
 			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+
+		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+			adev->vcn.inst[i].pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
 	}
 
 	if (amdgpu_sriov_vf(adev)) {
@@ -276,9 +280,6 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
-
 	r = amdgpu_vcn_ras_sw_init(adev);
 	if (r)
 		return r;
@@ -369,7 +370,7 @@ static int vcn_v2_5_hw_init(struct amdgpu_ip_block *ip_block)
 			if (r)
 				return r;
 
-			for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+			for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
 				ring = &adev->vcn.inst[j].ring_enc[i];
 				r = amdgpu_ring_test_helper(ring);
 				if (r)
@@ -1018,7 +1019,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
 		amdgpu_dpm_enable_vcn(adev, true, i);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	/* disable register anti-hang mechanism */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
@@ -1746,7 +1747,7 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
 	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
 		if (adev->vcn.harvest_config & (1 << j))
 			continue;
-		for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
 			adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs;
 			adev->vcn.inst[j].ring_enc[i].me = j;
 		}
@@ -1917,10 +1918,10 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
-		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs;
 
-		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs;
 	}
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 13b9ed96cccda..fabe4d75a7f6b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -127,11 +127,13 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
 	if (amdgpu_sriov_vf(adev)) {
 		adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
 		adev->vcn.harvest_config = 0;
-		adev->vcn.num_enc_rings = 1;
+		for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+			adev->vcn.inst[i].num_enc_rings = 1;
 
 	} else {
 		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
@@ -139,11 +141,13 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
 			/* both instances are harvested, disable the block */
 			return -ENOENT;
 
-		if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
-		    IP_VERSION(3, 0, 33))
-			adev->vcn.num_enc_rings = 0;
-		else
-			adev->vcn.num_enc_rings = 2;
+		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+			if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
+			    IP_VERSION(3, 0, 33))
+				adev->vcn.inst[i].num_enc_rings = 0;
+			else
+				adev->vcn.inst[i].num_enc_rings = 2;
+		}
 	}
 
 	vcn_v3_0_set_dec_ring_funcs(adev);
@@ -198,22 +202,22 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
-		adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
-		adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
 
-		adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
 		adev->vcn.inst[i].external.scratch9 = SOC15_REG_OFFSET(VCN, i, mmUVD_SCRATCH9);
-		adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
 		adev->vcn.inst[i].external.data0 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA0);
-		adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
 		adev->vcn.inst[i].external.data1 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA1);
-		adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
 		adev->vcn.inst[i].external.cmd = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_CMD);
-		adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
+		adev->vcn.inst[i].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
 		adev->vcn.inst[i].external.nop = SOC15_REG_OFFSET(VCN, i, mmUVD_NO_OP);
 
 		/* VCN DEC TRAP */
@@ -227,7 +231,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 		ring = &adev->vcn.inst[i].ring_dec;
 		ring->use_doorbell = true;
 		if (amdgpu_sriov_vf(adev)) {
-			ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1);
+			ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1);
 		} else {
 			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i;
 		}
@@ -239,7 +243,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 		if (r)
 			return r;
 
-		for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
+		for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
 			enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(j);
 
 			/* VCN ENC TRAP */
@@ -251,7 +255,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 			ring = &adev->vcn.inst[i].ring_enc[j];
 			ring->use_doorbell = true;
 			if (amdgpu_sriov_vf(adev)) {
-				ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1) + 1 + j;
+				ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1) + 1 + j;
 			} else {
 				ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i;
 			}
@@ -277,6 +281,9 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 
 		if (amdgpu_vcnfw_log)
 			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+
+		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+			adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
 	}
 
 	if (amdgpu_sriov_vf(adev)) {
@@ -284,8 +291,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 		if (r)
 			return r;
 	}
-	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		adev->vcn.pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
 
 	/* Allocate memory for VCN IP Dump buffer */
 	ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
@@ -373,7 +378,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
 				ring->sched.ready = true;
 			}
 
-			for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
+			for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
 				ring = &adev->vcn.inst[i].ring_enc[j];
 				if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) {
 					ring->sched.ready = false;
@@ -401,7 +406,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
 			if (r)
 				return r;
 
-			for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
+			for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
 				ring = &adev->vcn.inst[i].ring_enc[j];
 				r = amdgpu_ring_test_helper(ring);
 				if (r)
@@ -1153,7 +1158,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
 		amdgpu_dpm_enable_vcn(adev, true, i);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
 	vcn_v3_0_disable_static_power_gating(adev, i);
@@ -1433,7 +1438,7 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
 			mmUVD_VCPU_CACHE_SIZE2),
 			AMDGPU_VCN_CONTEXT_SIZE);
 
-		for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
+		for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
 			ring = &adev->vcn.inst[i].ring_enc[j];
 			ring->wptr = 0;
 			rb_addr = ring->gpu_addr;
@@ -1921,11 +1926,11 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
 		uint32_t reg = amdgpu_ib_get_value(ib, i);
 		uint32_t val = amdgpu_ib_get_value(ib, i + 1);
 
-		if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
+		if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data0, 0)) {
 			msg_lo = val;
-		} else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
+		} else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data1, 0)) {
 			msg_hi = val;
-		} else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0) &&
+		} else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.cmd, 0) &&
 			   val == 0) {
 			r = vcn_v3_0_dec_msg(p, job,
 					     ((u64)msg_hi) << 32 | msg_lo);
@@ -2089,7 +2094,7 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
+		for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
 			adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs;
 			adev->vcn.inst[i].ring_enc[j].me = i;
 		}
@@ -2255,7 +2260,7 @@ static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].irq.funcs = &vcn_v3_0_irq_funcs;
 	}
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index dbbeeffc90726..ee87594fafa60 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -129,8 +129,9 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
 		}
 	}
 
-	/* re-use enc ring as unified ring */
-	adev->vcn.num_enc_rings = 1;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		/* re-use enc ring as unified ring */
+		adev->vcn.inst[i].num_enc_rings = 1;
 
 	vcn_v4_0_set_unified_ring_funcs(adev);
 	vcn_v4_0_set_irq_funcs(adev);
@@ -214,7 +215,8 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
 		ring = &adev->vcn.inst[i].ring_enc[0];
 		ring->use_doorbell = true;
 		if (amdgpu_sriov_vf(adev))
-			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * (adev->vcn.num_enc_rings + 1) + 1;
+			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i *
+				(adev->vcn.inst[i].num_enc_rings + 1) + 1;
 		else
 			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;
 		ring->vm_hub = AMDGPU_MMHUB0(0);
@@ -226,6 +228,9 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 
 		vcn_v4_0_fw_shared_init(adev, i);
+
+		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+			adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
 	}
 
 	/* TODO: Add queue reset mask when FW fully supports it */
@@ -238,8 +243,6 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
 
 	r = amdgpu_vcn_ras_sw_init(adev);
 	if (r)
@@ -1111,7 +1114,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
 	vcn_v4_0_disable_static_power_gating(adev, i);
@@ -2172,10 +2175,10 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs;
 
-		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs;
 	}
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 8396ef6831b69..35854e074d142 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -114,9 +114,11 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
 static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
-	/* re-use enc ring as unified ring */
-	adev->vcn.num_enc_rings = 1;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		/* re-use enc ring as unified ring */
+		adev->vcn.inst[i].num_enc_rings = 1;
 
 	vcn_v4_0_3_set_unified_ring_funcs(adev);
 	vcn_v4_0_3_set_irq_funcs(adev);
@@ -194,6 +196,9 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 
 		vcn_v4_0_3_fw_shared_init(adev, i);
+
+		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+			adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
 	}
 
 	/* TODO: Add queue reset mask when FW fully supports it */
@@ -206,9 +211,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		adev->vcn.pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
-
 	if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
 		r = amdgpu_vcn_ras_sw_init(adev);
 		if (r) {
@@ -1138,7 +1140,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
 		amdgpu_dpm_enable_vcn(adev, true, i);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	vcn_inst = GET_INST(VCN, i);
 	/* set VCN status busy */
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index f6b347fcdb7ed..0700a5f96084c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -115,9 +115,11 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
-	/* re-use enc ring as unified ring */
-	adev->vcn.num_enc_rings = 1;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		/* re-use enc ring as unified ring */
+		adev->vcn.inst[i].num_enc_rings = 1;
 	vcn_v4_0_5_set_unified_ring_funcs(adev);
 	vcn_v4_0_5_set_irq_funcs(adev);
 
@@ -173,7 +175,7 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
 		ring->use_doorbell = true;
 		if (amdgpu_sriov_vf(adev))
 			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
-						i * (adev->vcn.num_enc_rings + 1) + 1;
+						i * (adev->vcn.inst[i].num_enc_rings + 1) + 1;
 		else
 			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
 						2 + 8 * i;
@@ -198,6 +200,9 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
 
 		if (amdgpu_vcnfw_log)
 			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+
+		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+			adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
 	}
 
 	if (amdgpu_sriov_vf(adev)) {
@@ -206,9 +211,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
-
 	/* Allocate memory for VCN IP Dump buffer */
 	ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
 	if (!ptr) {
@@ -1014,7 +1016,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
 	vcn_v4_0_5_disable_static_power_gating(adev, i);
@@ -1624,7 +1626,7 @@ static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs;
 	}
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index c5d59edf3a482..eeb3c9875ad50 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -98,9 +98,11 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
-	/* re-use enc ring as unified ring */
-	adev->vcn.num_enc_rings = 1;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		/* re-use enc ring as unified ring */
+		adev->vcn.inst[i].num_enc_rings = 1;
 
 	vcn_v5_0_0_set_unified_ring_funcs(adev);
 	vcn_v5_0_0_set_irq_funcs(adev);
@@ -184,15 +186,15 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
 
 		if (amdgpu_vcnfw_log)
 			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+
+		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+			adev->vcn.inst[i].pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
 	}
 
 	/* TODO: Add queue reset mask when FW fully supports it */
 	adev->vcn.supported_reset =
 		amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
 
-	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
-
 	vcn_v5_0_0_alloc_ip_dump(adev);
 
 	r = amdgpu_vcn_sysfs_reset_mask_init(adev);
@@ -791,7 +793,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
 	vcn_v5_0_0_disable_static_power_gating(adev, i);
@@ -1367,7 +1369,7 @@ static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
+		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
 		adev->vcn.inst[i].irq.funcs = &vcn_v5_0_0_irq_funcs;
 	}
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 51a2d70a65c9e..f428d23eb2857 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -58,9 +58,11 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	int i;
 
-	/* re-use enc ring as unified ring */
-	adev->vcn.num_enc_rings = 1;
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
+		/* re-use enc ring as unified ring */
+		adev->vcn.inst[i].num_enc_rings = 1;
 
 	vcn_v5_0_1_set_unified_ring_funcs(adev);
 	vcn_v5_0_1_set_irq_funcs(adev);
@@ -586,7 +588,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
 
 	vcn_inst = GET_INST(VCN, i);
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 11/44] drm/amdgpu/vcn: switch vcn helpers to be instance based
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (9 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 13:23   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 12/44] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst Alex Deucher
                   ` (32 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the instance to the helpers.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 437 ++++++++++++------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  12 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   |  16 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  16 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  71 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  65 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  69 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  70 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  63 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  67 ++--
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |  64 ++--
 11 files changed, 541 insertions(+), 409 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 9901b8e17f305..010cc64a950a4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -93,192 +93,186 @@ MODULE_FIRMWARE(FIRMWARE_VCN5_0_1);
 
 static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
 
-int amdgpu_vcn_early_init(struct amdgpu_device *adev)
+int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i)
 {
 	char ucode_prefix[25];
-	int r, i;
+	int r;
 
+	adev->vcn.inst[i].adev = adev;
+	adev->vcn.inst[i].inst = i;
 	amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
-	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
-		adev->vcn.inst[i].adev = adev;
-		adev->vcn.inst[i].inst = i;
-
-		if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
-			r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
-						 AMDGPU_UCODE_REQUIRED,
-						 "amdgpu/%s_%d.bin", ucode_prefix, i);
-		else
-			r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
-						 AMDGPU_UCODE_REQUIRED,
-						 "amdgpu/%s.bin", ucode_prefix);
-		if (r) {
-			amdgpu_ucode_release(&adev->vcn.inst[i].fw);
-			return r;
-		}
+
+	if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
+		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
+					 AMDGPU_UCODE_REQUIRED,
+					 "amdgpu/%s_%d.bin", ucode_prefix, i);
+	else
+		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
+					 AMDGPU_UCODE_REQUIRED,
+					 "amdgpu/%s.bin", ucode_prefix);
+	if (r) {
+		amdgpu_ucode_release(&adev->vcn.inst[i].fw);
+		return r;
 	}
 	return r;
 }
 
-int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
+int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
 {
 	unsigned long bo_size;
 	const struct common_firmware_header *hdr;
 	unsigned char fw_check;
 	unsigned int fw_shared_size, log_offset;
-	int i, r;
+	int r;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
-		mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
-		mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
-		atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
-		INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
-		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
-		if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
-		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
-			adev->vcn.inst[i].indirect_sram = true;
-
-		/*
-		 * Some Steam Deck's BIOS versions are incompatible with the
-		 * indirect SRAM mode, leading to amdgpu being unable to get
-		 * properly probed (and even potentially crashing the kernel).
-		 * Hence, check for these versions here - notice this is
-		 * restricted to Vangogh (Deck's APU).
-		 */
-		if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
-			const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
-
-			if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
-					 !strncmp("F7A0114", bios_ver, 7))) {
-				adev->vcn.inst[i].indirect_sram = false;
-				dev_info(adev->dev,
-					 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
-			}
+	mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
+	mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
+	atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
+	INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
+	atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
+	if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
+	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
+		adev->vcn.inst[i].indirect_sram = true;
+
+	/*
+	 * Some Steam Deck's BIOS versions are incompatible with the
+	 * indirect SRAM mode, leading to amdgpu being unable to get
+	 * properly probed (and even potentially crashing the kernel).
+	 * Hence, check for these versions here - notice this is
+	 * restricted to Vangogh (Deck's APU).
+	 */
+	if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
+		const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
+
+		if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
+				 !strncmp("F7A0114", bios_ver, 7))) {
+			adev->vcn.inst[i].indirect_sram = false;
+			dev_info(adev->dev,
+				 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
 		}
+	}
 
-		/* from vcn4 and above, only unified queue is used */
-		adev->vcn.inst[i].using_unified_queue =
-			amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
+	/* from vcn4 and above, only unified queue is used */
+	adev->vcn.inst[i].using_unified_queue =
+		amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
+
+	hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
+	adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
+	adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
+
+	/* Bit 20-23, it is encode major and non-zero for new naming convention.
+	 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
+	 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
+	 * is zero in old naming convention, this field is always zero so far.
+	 * These four bits are used to tell which naming convention is present.
+	 */
+	fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
+	if (fw_check) {
+		unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
+
+		fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
+		enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
+		enc_major = fw_check;
+		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
+		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
+		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
+			 enc_major, enc_minor, dec_ver, vep, fw_rev);
+	} else {
+		unsigned int version_major, version_minor, family_id;
 
-		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
-		adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
-		adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
-
-		/* Bit 20-23, it is encode major and non-zero for new naming convention.
-		 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
-		 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
-		 * is zero in old naming convention, this field is always zero so far.
-		 * These four bits are used to tell which naming convention is present.
-		 */
-		fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
-		if (fw_check) {
-			unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
-
-			fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
-			enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
-			enc_major = fw_check;
-			dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
-			vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
-			DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
-				 enc_major, enc_minor, dec_ver, vep, fw_rev);
-		} else {
-			unsigned int version_major, version_minor, family_id;
+		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
+		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
+		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
+		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
+			 version_major, version_minor, family_id);
+	}
 
-			family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
-			version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
-			version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
-			DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
-				 version_major, version_minor, family_id);
-		}
+	bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
+	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
 
-		bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
-		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-			bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+	if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
+		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
+		log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
+	} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
+		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
+		log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
+	} else {
+		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
+		log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
+	}
 
-		if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
-			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
-			log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
-		} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
-			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
-			log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
-		} else {
-			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
-			log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
-		}
+	bo_size += fw_shared_size;
+
+	if (amdgpu_vcnfw_log)
+		bo_size += AMDGPU_VCNFW_LOG_SIZE;
+
+	r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
+				    AMDGPU_GEM_DOMAIN_VRAM |
+				    AMDGPU_GEM_DOMAIN_GTT,
+				    &adev->vcn.inst[i].vcpu_bo,
+				    &adev->vcn.inst[i].gpu_addr,
+				    &adev->vcn.inst[i].cpu_addr);
+	if (r) {
+		dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
+		return r;
+	}
 
-		bo_size += fw_shared_size;
+	adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +
+		bo_size - fw_shared_size;
+	adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +
+		bo_size - fw_shared_size;
 
-		if (amdgpu_vcnfw_log)
-			bo_size += AMDGPU_VCNFW_LOG_SIZE;
+	adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;
 
-		r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
+	if (amdgpu_vcnfw_log) {
+		adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
+		adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
+		adev->vcn.inst[i].fw_shared.log_offset = log_offset;
+	}
+
+	if (adev->vcn.inst[i].indirect_sram) {
+		r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
 					    AMDGPU_GEM_DOMAIN_VRAM |
 					    AMDGPU_GEM_DOMAIN_GTT,
-					    &adev->vcn.inst[i].vcpu_bo,
-					    &adev->vcn.inst[i].gpu_addr,
-					    &adev->vcn.inst[i].cpu_addr);
+					    &adev->vcn.inst[i].dpg_sram_bo,
+					    &adev->vcn.inst[i].dpg_sram_gpu_addr,
+					    &adev->vcn.inst[i].dpg_sram_cpu_addr);
 		if (r) {
-			dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
+			dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
 			return r;
 		}
-
-		adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +
-				bo_size - fw_shared_size;
-		adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +
-				bo_size - fw_shared_size;
-
-		adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;
-
-		if (amdgpu_vcnfw_log) {
-			adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
-			adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
-			adev->vcn.inst[i].fw_shared.log_offset = log_offset;
-		}
-
-		if (adev->vcn.inst[i].indirect_sram) {
-			r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
-					AMDGPU_GEM_DOMAIN_VRAM |
-					AMDGPU_GEM_DOMAIN_GTT,
-					&adev->vcn.inst[i].dpg_sram_bo,
-					&adev->vcn.inst[i].dpg_sram_gpu_addr,
-					&adev->vcn.inst[i].dpg_sram_cpu_addr);
-			if (r) {
-				dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
-				return r;
-			}
-		}
 	}
 
 	return 0;
 }
 
-int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
+int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i)
 {
-	int i, j;
+	int j;
 
-	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
-		if (adev->vcn.harvest_config & (1 << j))
-			continue;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
 
-		amdgpu_bo_free_kernel(
-			&adev->vcn.inst[j].dpg_sram_bo,
-			&adev->vcn.inst[j].dpg_sram_gpu_addr,
-			(void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);
+	amdgpu_bo_free_kernel(
+		&adev->vcn.inst[i].dpg_sram_bo,
+		&adev->vcn.inst[i].dpg_sram_gpu_addr,
+		(void **)&adev->vcn.inst[i].dpg_sram_cpu_addr);
 
-		kvfree(adev->vcn.inst[j].saved_bo);
+	kvfree(adev->vcn.inst[i].saved_bo);
 
-		amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,
-					  &adev->vcn.inst[j].gpu_addr,
-					  (void **)&adev->vcn.inst[j].cpu_addr);
+	amdgpu_bo_free_kernel(&adev->vcn.inst[i].vcpu_bo,
+			      &adev->vcn.inst[i].gpu_addr,
+			      (void **)&adev->vcn.inst[i].cpu_addr);
 
-		amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
+	amdgpu_ring_fini(&adev->vcn.inst[i].ring_dec);
 
-		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i)
-			amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
+	for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
+		amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]);
 
-		amdgpu_ucode_release(&adev->vcn.inst[j].fw);
-		mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
-		mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround);
-	}
+	amdgpu_ucode_release(&adev->vcn.inst[i].fw);
+	mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock);
+	mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
 
 	return 0;
 }
@@ -298,91 +292,102 @@ bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type t
 	return ret;
 }
 
-int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
+static int amdgpu_vcn_save_vcpu_bo_inst(struct amdgpu_device *adev, int i)
 {
 	unsigned int size;
 	void *ptr;
-	int i, idx;
+	int idx;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		if (adev->vcn.inst[i].vcpu_bo == NULL)
-			return 0;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
+	if (adev->vcn.inst[i].vcpu_bo == NULL)
+		return 0;
 
-		size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
-		ptr = adev->vcn.inst[i].cpu_addr;
+	size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
+	ptr = adev->vcn.inst[i].cpu_addr;
 
-		adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
-		if (!adev->vcn.inst[i].saved_bo)
-			return -ENOMEM;
+	adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
+	if (!adev->vcn.inst[i].saved_bo)
+		return -ENOMEM;
 
-		if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-			memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
-			drm_dev_exit(idx);
-		}
+	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
+		memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
+		drm_dev_exit(idx);
+	}
+
+	return 0;
+}
+
+int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
+{
+	int ret, i;
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		ret = amdgpu_vcn_save_vcpu_bo_inst(adev, i);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
 }
 
-int amdgpu_vcn_suspend(struct amdgpu_device *adev)
+int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i)
 {
 	bool in_ras_intr = amdgpu_ras_intr_triggered();
-	int i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
+
+	cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
 
 	/* err_event_athub will corrupt VCPU buffer, so we need to
 	 * restore fw data and clear buffer in amdgpu_vcn_resume() */
 	if (in_ras_intr)
 		return 0;
 
-	return amdgpu_vcn_save_vcpu_bo(adev);
+	return amdgpu_vcn_save_vcpu_bo_inst(adev, i);
 }
 
-int amdgpu_vcn_resume(struct amdgpu_device *adev)
+int amdgpu_vcn_resume(struct amdgpu_device *adev, int i)
 {
 	unsigned int size;
 	void *ptr;
-	int i, idx;
+	int idx;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		if (adev->vcn.harvest_config & (1 << i))
-			continue;
-		if (adev->vcn.inst[i].vcpu_bo == NULL)
-			return -EINVAL;
+	if (adev->vcn.harvest_config & (1 << i))
+		return 0;
+	if (adev->vcn.inst[i].vcpu_bo == NULL)
+		return -EINVAL;
+
+	size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
+	ptr = adev->vcn.inst[i].cpu_addr;
 
-		size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
-		ptr = adev->vcn.inst[i].cpu_addr;
+	if (adev->vcn.inst[i].saved_bo != NULL) {
+		if (drm_dev_enter(adev_to_drm(adev), &idx)) {
+			memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
+			drm_dev_exit(idx);
+		}
+		kvfree(adev->vcn.inst[i].saved_bo);
+		adev->vcn.inst[i].saved_bo = NULL;
+	} else {
+		const struct common_firmware_header *hdr;
+		unsigned int offset;
 
-		if (adev->vcn.inst[i].saved_bo != NULL) {
+		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
+		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+			offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
 			if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-				memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
+				memcpy_toio(adev->vcn.inst[i].cpu_addr,
+					    adev->vcn.inst[i].fw->data + offset,
+					    le32_to_cpu(hdr->ucode_size_bytes));
 				drm_dev_exit(idx);
 			}
-			kvfree(adev->vcn.inst[i].saved_bo);
-			adev->vcn.inst[i].saved_bo = NULL;
-		} else {
-			const struct common_firmware_header *hdr;
-			unsigned int offset;
-
-			hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
-			if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
-				offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
-				if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-					memcpy_toio(adev->vcn.inst[i].cpu_addr,
-						    adev->vcn.inst[i].fw->data + offset,
-						    le32_to_cpu(hdr->ucode_size_bytes));
-					drm_dev_exit(idx);
-				}
-				size -= le32_to_cpu(hdr->ucode_size_bytes);
-				ptr += le32_to_cpu(hdr->ucode_size_bytes);
-			}
-			memset_io(ptr, 0, size);
+			size -= le32_to_cpu(hdr->ucode_size_bytes);
+			ptr += le32_to_cpu(hdr->ucode_size_bytes);
 		}
+		memset_io(ptr, 0, size);
 	}
+
 	return 0;
 }
 
@@ -1058,36 +1063,32 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
 	}
 }
 
-void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
+void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i)
 {
-	int i;
 	unsigned int idx;
 
 	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
 		const struct common_firmware_header *hdr;
 
-		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
-			if (adev->vcn.harvest_config & (1 << i))
-				continue;
+		if (adev->vcn.harvest_config & (1 << i))
+			return;
 
-			hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
-			/* currently only support 2 FW instances */
-			if (i >= 2) {
-				dev_info(adev->dev, "More then 2 VCN FW instances!\n");
-				break;
-			}
-			idx = AMDGPU_UCODE_ID_VCN + i;
-			adev->firmware.ucode[idx].ucode_id = idx;
-			adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw;
-			adev->firmware.fw_size +=
-				ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
-
-			if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
-			    IP_VERSION(4, 0, 3) ||
-			    amdgpu_ip_version(adev, UVD_HWIP, 0) ==
-			    IP_VERSION(5, 0, 1))
-				break;
+		if ((amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 3) ||
+		     amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 1))
+		    && (i > 0))
+			return;
+
+		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
+		/* currently only support 2 FW instances */
+		if (i >= 2) {
+			dev_info(adev->dev, "More then 2 VCN FW instances!\n");
+			return;
 		}
+		idx = AMDGPU_UCODE_ID_VCN + i;
+		adev->firmware.ucode[idx].ucode_id = idx;
+		adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw;
+		adev->firmware.fw_size +=
+			ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
 	}
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 3b059f51894b9..5f92cf28cc752 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -503,11 +503,11 @@ enum vcn_ring_type {
 	VCN_UNIFIED_RING,
 };
 
-int amdgpu_vcn_early_init(struct amdgpu_device *adev);
-int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
-int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
-int amdgpu_vcn_suspend(struct amdgpu_device *adev);
-int amdgpu_vcn_resume(struct amdgpu_device *adev);
+int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i);
+int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i);
+int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i);
+int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i);
+int amdgpu_vcn_resume(struct amdgpu_device *adev, int i);
 void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring);
 void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring);
 
@@ -525,7 +525,7 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
 
 enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring);
 
-void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev);
+void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i);
 
 void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn);
 void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index c870d9ba64c69..f74767843e85d 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -113,7 +113,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
 
 	jpeg_v1_0_early_init(ip_block);
 
-	return amdgpu_vcn_early_init(adev);
+	return amdgpu_vcn_early_init(adev, 0);
 }
 
 /**
@@ -145,16 +145,16 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	r = amdgpu_vcn_sw_init(adev);
+	r = amdgpu_vcn_sw_init(adev, 0);
 	if (r)
 		return r;
 
 	/* Override the work func */
 	adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler;
 
-	amdgpu_vcn_setup_ucode(adev);
+	amdgpu_vcn_setup_ucode(adev, 0);
 
-	r = amdgpu_vcn_resume(adev);
+	r = amdgpu_vcn_resume(adev, 0);
 	if (r)
 		return r;
 
@@ -223,13 +223,13 @@ static int vcn_v1_0_sw_fini(struct amdgpu_ip_block *ip_block)
 	int r;
 	struct amdgpu_device *adev = ip_block->adev;
 
-	r = amdgpu_vcn_suspend(adev);
+	r = amdgpu_vcn_suspend(adev, 0);
 	if (r)
 		return r;
 
 	jpeg_v1_0_sw_fini(ip_block);
 
-	r = amdgpu_vcn_sw_fini(adev);
+	r = amdgpu_vcn_sw_fini(adev, 0);
 
 	kfree(adev->vcn.ip_dump);
 
@@ -311,7 +311,7 @@ static int vcn_v1_0_suspend(struct amdgpu_ip_block *ip_block)
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(adev);
+	r = amdgpu_vcn_suspend(adev, 0);
 
 	return r;
 }
@@ -327,7 +327,7 @@ static int vcn_v1_0_resume(struct amdgpu_ip_block *ip_block)
 {
 	int r;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
+	r = amdgpu_vcn_resume(ip_block->adev, 0);
 	if (r)
 		return r;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index b0a957664250c..8ff5a9d67cbd2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -118,7 +118,7 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v2_0_set_enc_ring_funcs(adev);
 	vcn_v2_0_set_irq_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	return amdgpu_vcn_early_init(adev, 0);
 }
 
 /**
@@ -153,13 +153,13 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
 			return r;
 	}
 
-	r = amdgpu_vcn_sw_init(adev);
+	r = amdgpu_vcn_sw_init(adev, 0);
 	if (r)
 		return r;
 
-	amdgpu_vcn_setup_ucode(adev);
+	amdgpu_vcn_setup_ucode(adev, 0);
 
-	r = amdgpu_vcn_resume(adev);
+	r = amdgpu_vcn_resume(adev, 0);
 	if (r)
 		return r;
 
@@ -254,11 +254,11 @@ static int vcn_v2_0_sw_fini(struct amdgpu_ip_block *ip_block)
 
 	amdgpu_virt_free_mm_table(adev);
 
-	r = amdgpu_vcn_suspend(adev);
+	r = amdgpu_vcn_suspend(adev, 0);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_sw_fini(adev);
+	r = amdgpu_vcn_sw_fini(adev, 0);
 
 	kfree(adev->vcn.ip_dump);
 
@@ -338,7 +338,7 @@ static int vcn_v2_0_suspend(struct amdgpu_ip_block *ip_block)
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	r = amdgpu_vcn_suspend(ip_block->adev, 0);
 
 	return r;
 }
@@ -354,7 +354,7 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block)
 {
 	int r;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
+	r = amdgpu_vcn_resume(ip_block->adev, 0);
 	if (r)
 		return r;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index a3bac39e4c9db..4f9f3de023ffd 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -121,7 +121,7 @@ static int amdgpu_ih_clientid_vcns[] = {
 static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	if (amdgpu_sriov_vf(adev)) {
 		adev->vcn.num_vcn_inst = 2;
@@ -139,7 +139,7 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
 			adev->vcn.inst[i].num_enc_rings = 2;
 		}
 		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
-					AMDGPU_VCN_HARVEST_VCN1))
+						 AMDGPU_VCN_HARVEST_VCN1))
 			/* both instances are harvested, disable the block */
 			return -ENOENT;
 	}
@@ -149,7 +149,13 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v2_5_set_irq_funcs(adev);
 	vcn_v2_5_set_ras_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 /**
@@ -168,6 +174,8 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 
 	for (j = 0; j < adev->vcn.num_vcn_inst; j++) {
+		volatile struct amdgpu_fw_shared *fw_shared;
+
 		if (adev->vcn.harvest_config & (1 << j))
 			continue;
 		/* VCN DEC TRAP */
@@ -189,23 +197,17 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
 			VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].ras_poison_irq);
 		if (r)
 			return r;
-	}
-
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
 
-	amdgpu_vcn_setup_ucode(adev);
+		r = amdgpu_vcn_sw_init(adev, j);
+		if (r)
+			return r;
 
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
+		amdgpu_vcn_setup_ucode(adev, j);
 
-	for (j = 0; j < adev->vcn.num_vcn_inst; j++) {
-		volatile struct amdgpu_fw_shared *fw_shared;
+		r = amdgpu_vcn_resume(adev, j);
+		if (r)
+			return r;
 
-		if (adev->vcn.harvest_config & (1 << j))
-			continue;
 		adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
 		adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
 		adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
@@ -323,15 +325,18 @@ static int vcn_v2_5_sw_fini(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev))
 		amdgpu_virt_free_mm_table(adev);
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
-
-	r = amdgpu_vcn_sw_fini(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	kfree(adev->vcn.ip_dump);
 
-	return r;
+	return 0;
 }
 
 /**
@@ -421,15 +426,20 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v2_5_suspend(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
 	r = vcn_v2_5_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
-	return r;
+	return 0;
 }
 
 /**
@@ -441,11 +451,14 @@ static int vcn_v2_5_suspend(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v2_5_hw_init(ip_block);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index fabe4d75a7f6b..724f36467b068 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -127,7 +127,7 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	if (amdgpu_sriov_vf(adev)) {
 		adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
@@ -154,7 +154,12 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v3_0_set_enc_ring_funcs(adev);
 	vcn_v3_0_set_irq_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+	return 0;
 }
 
 /**
@@ -173,16 +178,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 	uint32_t *ptr;
 	struct amdgpu_device *adev = ip_block->adev;
 
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
-
-	amdgpu_vcn_setup_ucode(adev);
-
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
-
 	/*
 	 * Note: doorbell assignment is fixed for SRIOV multiple VCN engines
 	 * Formula:
@@ -202,6 +197,16 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
+		r = amdgpu_vcn_sw_init(adev, i);
+		if (r)
+			return r;
+
+		amdgpu_vcn_setup_ucode(adev, i);
+
+		r = amdgpu_vcn_resume(adev, i);
+		if (r)
+			return r;
+
 		adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
 		adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
 		adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
@@ -333,14 +338,18 @@ static int vcn_v3_0_sw_fini(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev))
 		amdgpu_virt_free_mm_table(adev);
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
 
-	r = amdgpu_vcn_sw_fini(adev);
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	kfree(adev->vcn.ip_dump);
-	return r;
+	return 0;
 }
 
 /**
@@ -459,15 +468,20 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v3_0_suspend(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
 	r = vcn_v3_0_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
-	return r;
+	return 0;
 }
 
 /**
@@ -479,11 +493,14 @@ static int vcn_v3_0_suspend(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v3_0_resume(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v3_0_hw_init(ip_block);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index ee87594fafa60..1200815b3eee8 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -117,7 +117,7 @@ static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev);
 static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	if (amdgpu_sriov_vf(adev)) {
 		adev->vcn.harvest_config = VCN_HARVEST_MMSCH;
@@ -137,7 +137,13 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v4_0_set_irq_funcs(adev);
 	vcn_v4_0_set_ras_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 static int vcn_v4_0_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
@@ -180,20 +186,20 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
 	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0);
 	uint32_t *ptr;
 
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
-
-	amdgpu_vcn_setup_ucode(adev);
-
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
+		r = amdgpu_vcn_sw_init(adev, i);
+		if (r)
+			return r;
+
+		amdgpu_vcn_setup_ucode(adev, i);
+
+		r = amdgpu_vcn_resume(adev, i);
+		if (r)
+			return r;
+
 		/* Init instance 0 sched_score to 1, so it's scheduled after other instances */
 		if (i == 0)
 			atomic_set(&adev->vcn.inst[i].sched_score, 1);
@@ -294,16 +300,23 @@ static int vcn_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev))
 		amdgpu_virt_free_mm_table(adev);
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
+	}
 
 	amdgpu_vcn_sysfs_reset_mask_fini(adev);
-	r = amdgpu_vcn_sw_fini(adev);
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	kfree(adev->vcn.ip_dump);
 
-	return r;
+	return 0;
 }
 
 /**
@@ -394,15 +407,20 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v4_0_suspend(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
 	r = vcn_v4_0_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
-	return r;
+	return 0;
 }
 
 /**
@@ -414,11 +432,14 @@ static int vcn_v4_0_suspend(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v4_0_resume(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v4_0_hw_init(ip_block);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 35854e074d142..1407cb4b553b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -114,7 +114,7 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
 static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
 		/* re-use enc ring as unified ring */
@@ -124,7 +124,13 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v4_0_3_set_irq_funcs(adev);
 	vcn_v4_0_3_set_ras_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 static int vcn_v4_0_3_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
@@ -156,16 +162,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
 	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_3);
 	uint32_t *ptr;
 
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
-
-	amdgpu_vcn_setup_ucode(adev);
-
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
-
 	/* VCN DEC TRAP */
 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
 		VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
@@ -173,6 +169,17 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
 		return r;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+
+		r = amdgpu_vcn_sw_init(adev, i);
+		if (r)
+			return r;
+
+		amdgpu_vcn_setup_ucode(adev, i);
+
+		r = amdgpu_vcn_resume(adev, i);
+		if (r)
+			return r;
+
 		vcn_inst = GET_INST(VCN, i);
 
 		ring = &adev->vcn.inst[i].ring_enc[0];
@@ -261,16 +268,23 @@ static int vcn_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev))
 		amdgpu_virt_free_mm_table(adev);
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
+	}
 
 	amdgpu_vcn_sysfs_reset_mask_fini(adev);
-	r = amdgpu_vcn_sw_fini(adev);
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	kfree(adev->vcn.ip_dump);
 
-	return r;
+	return 0;
 }
 
 /**
@@ -375,15 +389,20 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v4_0_3_suspend(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
 	r = vcn_v4_0_3_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
+	}
 
-	return r;
+	return 0;
 }
 
 /**
@@ -395,11 +414,14 @@ static int vcn_v4_0_3_suspend(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v4_0_3_resume(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v4_0_3_hw_init(ip_block);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 0700a5f96084c..c3a2826a59631 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -115,7 +115,7 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
 		/* re-use enc ring as unified ring */
@@ -123,7 +123,13 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v4_0_5_set_unified_ring_funcs(adev);
 	vcn_v4_0_5_set_irq_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 /**
@@ -141,15 +147,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
 	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_5);
 	uint32_t *ptr;
 
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
-
-	amdgpu_vcn_setup_ucode(adev);
-
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
 		volatile struct amdgpu_vcn4_fw_shared *fw_shared;
@@ -157,6 +154,16 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
+		r = amdgpu_vcn_sw_init(adev, i);
+		if (r)
+			return r;
+
+		amdgpu_vcn_setup_ucode(adev, i);
+
+		r = amdgpu_vcn_resume(adev, i);
+		if (r)
+			return r;
+
 		atomic_set(&adev->vcn.inst[i].sched_score, 0);
 
 		/* VCN UNIFIED TRAP */
@@ -252,15 +259,19 @@ static int vcn_v4_0_5_sw_fini(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_sriov_vf(adev))
 		amdgpu_virt_free_mm_table(adev);
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
 
-	r = amdgpu_vcn_sw_fini(adev);
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	kfree(adev->vcn.ip_dump);
 
-	return r;
+	return 0;
 }
 
 /**
@@ -332,13 +343,18 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v4_0_5_suspend(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
 	r = vcn_v4_0_5_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	return r;
 }
@@ -352,11 +368,14 @@ static int vcn_v4_0_5_suspend(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v4_0_5_resume(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v4_0_5_hw_init(ip_block);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index eeb3c9875ad50..d3e4d02c12a06 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -98,7 +98,7 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
 		/* re-use enc ring as unified ring */
@@ -107,7 +107,13 @@ static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v5_0_0_set_unified_ring_funcs(adev);
 	vcn_v5_0_0_set_irq_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 void vcn_v5_0_0_alloc_ip_dump(struct amdgpu_device *adev)
@@ -138,22 +144,22 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i, r;
 
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
-
-	amdgpu_vcn_setup_ucode(adev);
-
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
-
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
 		volatile struct amdgpu_vcn5_fw_shared *fw_shared;
 
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
+		r = amdgpu_vcn_sw_init(adev, i);
+		if (r)
+			return r;
+
+		amdgpu_vcn_setup_ucode(adev, i);
+
+		r = amdgpu_vcn_resume(adev, i);
+		if (r)
+			return r;
+
 		atomic_set(&adev->vcn.inst[i].sched_score, 0);
 
 		/* VCN UNIFIED TRAP */
@@ -231,16 +237,23 @@ static int vcn_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
 		drm_dev_exit(idx);
 	}
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
+	}
 
 	amdgpu_vcn_sysfs_reset_mask_fini(adev);
-	r = amdgpu_vcn_sw_fini(adev);
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	kfree(adev->vcn.ip_dump);
 
-	return r;
+	return 0;
 }
 
 /**
@@ -312,13 +325,18 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v5_0_0_suspend(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
 	r = vcn_v5_0_0_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(ip_block->adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	return r;
 }
@@ -332,11 +350,14 @@ static int vcn_v5_0_0_suspend(struct amdgpu_ip_block *ip_block)
  */
 static int vcn_v5_0_0_resume(struct amdgpu_ip_block *ip_block)
 {
-	int r;
+	struct amdgpu_device *adev = ip_block->adev;
+	int r, i;
 
-	r = amdgpu_vcn_resume(ip_block->adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v5_0_0_hw_init(ip_block);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index f428d23eb2857..f49fdf2bb6e33 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -58,7 +58,7 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int i;
+	int i, r;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
 		/* re-use enc ring as unified ring */
@@ -67,7 +67,13 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v5_0_1_set_unified_ring_funcs(adev);
 	vcn_v5_0_1_set_irq_funcs(adev);
 
-	return amdgpu_vcn_early_init(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		r = amdgpu_vcn_early_init(adev, i);
+		if (r)
+			return r;
+	}
+
+	return 0;
 }
 
 /**
@@ -83,16 +89,6 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_ring *ring;
 	int i, r, vcn_inst;
 
-	r = amdgpu_vcn_sw_init(adev);
-	if (r)
-		return r;
-
-	amdgpu_vcn_setup_ucode(adev);
-
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
-
 	/* VCN UNIFIED TRAP */
 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
 		VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
@@ -104,6 +100,16 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block)
 
 		vcn_inst = GET_INST(VCN, i);
 
+		r = amdgpu_vcn_sw_init(adev, i);
+		if (r)
+			return r;
+
+		amdgpu_vcn_setup_ucode(adev, i);
+
+		r = amdgpu_vcn_resume(adev, i);
+		if (r)
+			return r;
+
 		ring = &adev->vcn.inst[i].ring_enc[0];
 		ring->use_doorbell = true;
 		ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 9 * vcn_inst;
@@ -157,17 +163,23 @@ static int vcn_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block)
 		drm_dev_exit(idx);
 	}
 
-	r = amdgpu_vcn_suspend(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(adev, i);
+		if (r)
+			return r;
+	}
 
-	r = amdgpu_vcn_sw_fini(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_sw_fini(adev, i);
+		if (r)
+			return r;
+	}
 
 	amdgpu_vcn_sysfs_reset_mask_fini(adev);
 
 	kfree(adev->vcn.ip_dump);
 
-	return r;
+	return 0;
 }
 
 /**
@@ -229,13 +241,17 @@ static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block)
 static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int r;
+	int r, i;
 
 	r = vcn_v5_0_1_hw_fini(ip_block);
 	if (r)
 		return r;
 
-	r = amdgpu_vcn_suspend(adev);
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_suspend(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	return r;
 }
@@ -250,11 +266,13 @@ static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block)
 static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	int r;
+	int r, i;
 
-	r = amdgpu_vcn_resume(adev);
-	if (r)
-		return r;
+	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		r = amdgpu_vcn_resume(ip_block->adev, i);
+		if (r)
+			return r;
+	}
 
 	r = vcn_v5_0_1_hw_init(ip_block);
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 12/44] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (10 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 11/44] drm/amdgpu/vcn: switch vcn helpers to be instance based Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:00   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 13/44] drm/amdgpu/vcn1.0: " Alex Deucher
                   ` (31 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 79 ++++++++++++++++++---------
 1 file changed, 52 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 724f36467b068..f6f4f04d74339 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -510,13 +510,14 @@ static int vcn_v3_0_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v3_0_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst)
+static void vcn_v3_0_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst].fw->size + 4);
 	uint32_t offset;
 
@@ -565,8 +566,11 @@ static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst)
 		AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
 }
 
-static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst_idx].fw->size + 4);
 	uint32_t offset;
 
@@ -661,8 +665,10 @@ static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
 		UVD, inst_idx, mmUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
 }
 
-static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v3_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data = 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -712,8 +718,10 @@ static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int
 	WREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS, data);
 }
 
-static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v3_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -765,8 +773,10 @@ static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v3_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	/* VCN disable CGC */
@@ -893,9 +903,12 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
 	WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
-		uint8_t sram_sel, int inst_idx, uint8_t indirect)
+static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					   uint8_t sram_sel,
+					   uint8_t indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 
 	/* enable sw clock gating control */
@@ -949,8 +962,10 @@ static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v3_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	/* enable VCN CGC */
@@ -1009,8 +1024,10 @@ static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
 	WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v3_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
 	uint32_t rb_bufsz, tmp;
@@ -1028,7 +1045,7 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 		adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
 
 	/* enable clock gating */
-	vcn_v3_0_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+	vcn_v3_0_clock_gating_dpg_mode(vinst, 0, indirect);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -1077,7 +1094,7 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
 
-	vcn_v3_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v3_0_mc_resume_dpg_mode(vinst, indirect);
 
 	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
 		VCN, inst_idx, mmUVD_REG_XX_MASK), 0x10, 0, indirect);
@@ -1161,8 +1178,10 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 	return 0;
 }
 
-static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
+static int vcn_v3_0_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t rb_bufsz, tmp;
@@ -1175,17 +1194,17 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
 		amdgpu_dpm_enable_vcn(adev, true, i);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v3_0_start_dpg_mode(vinst, vinst->indirect_sram);
 
 	/* disable VCN power gating */
-	vcn_v3_0_disable_static_power_gating(adev, i);
+	vcn_v3_0_disable_static_power_gating(vinst);
 
 	/* set VCN status busy */
 	tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
 	WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
 
 	/* SW clock gating */
-	vcn_v3_0_disable_clock_gating(adev, i);
+	vcn_v3_0_disable_clock_gating(vinst);
 
 	/* enable VCPU clock */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
@@ -1238,7 +1257,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
 		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v3_0_mc_resume(adev, i);
+	vcn_v3_0_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG,
@@ -1555,8 +1574,10 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
 	return 0;
 }
 
-static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static int vcn_v3_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
@@ -1586,8 +1607,10 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 	return 0;
 }
 
-static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
+static int vcn_v3_0_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	uint32_t tmp;
 	int r = 0;
 
@@ -1595,7 +1618,7 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
 		return 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v3_0_stop_dpg_mode(adev, i);
+		return vcn_v3_0_stop_dpg_mode(vinst);
 
 	/* wait for vcn idle */
 	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
@@ -1646,10 +1669,10 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
 
 	/* apply HW clock gating */
-	vcn_v3_0_enable_clock_gating(adev, i);
+	vcn_v3_0_enable_clock_gating(vinst);
 
 	/* enable VCN power gating */
-	vcn_v3_0_enable_static_power_gating(adev, i);
+	vcn_v3_0_enable_static_power_gating(vinst);
 
 	if (adev->pm.dpm_enabled)
 		amdgpu_dpm_enable_vcn(adev, false, i);
@@ -2159,15 +2182,16 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
 		if (enable) {
 			if (RREG32_SOC15(VCN, i, mmUVD_STATUS) != UVD_STATUS__IDLE)
 				return -EBUSY;
-			vcn_v3_0_enable_clock_gating(adev, i);
+			vcn_v3_0_enable_clock_gating(vinst);
 		} else {
-			vcn_v3_0_disable_clock_gating(adev, i);
+			vcn_v3_0_disable_clock_gating(vinst);
 		}
 	}
 
@@ -2179,6 +2203,7 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 					       int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
@@ -2194,9 +2219,9 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v3_0_stop(adev, i);
+		ret = vcn_v3_0_stop(vinst);
 	else
-		ret = vcn_v3_0_start(adev, i);
+		ret = vcn_v3_0_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 13/44] drm/amdgpu/vcn1.0: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (11 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 12/44] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:01   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 14/44] drm/amdgpu/vcn2.0: " Alex Deucher
                   ` (30 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 85 ++++++++++++++++-----------
 1 file changed, 51 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index f74767843e85d..613f17be9d829 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -81,7 +81,7 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_1_0[] = {
 	SOC15_REG_ENTRY_STR(VCN, 0, mmUVD_DPG_PAUSE)
 };
 
-static int vcn_v1_0_stop(struct amdgpu_device *adev);
+static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst);
 static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -339,12 +339,13 @@ static int vcn_v1_0_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v1_0_mc_resume_spg_mode - memory controller programming
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
+static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
 	uint32_t offset;
 
@@ -410,8 +411,9 @@ static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
 			adev->gfx.config.gb_addr_config);
 }
 
-static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
+static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
 	uint32_t offset;
 
@@ -485,12 +487,13 @@ static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
 /**
  * vcn_v1_0_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev)
+static void vcn_v1_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data;
 
 	/* JPEG disable CGC */
@@ -615,8 +618,9 @@ static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev)
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev)
+static void vcn_v1_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data = 0;
 
 	/* enable JPEG CGC */
@@ -680,8 +684,10 @@ static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev)
 	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel)
+static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					   uint8_t sram_sel)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t reg_data = 0;
 
 	/* disable JPEG CGC */
@@ -734,8 +740,9 @@ static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t s
 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SUVD_CGC_CTRL, 0, 0xFFFFFFFF, sram_sel);
 }
 
-static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev)
+static void vcn_1_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data = 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -779,8 +786,9 @@ static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev)
 	WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
 }
 
-static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev)
+static void vcn_1_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data = 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -823,12 +831,13 @@ static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev)
 /**
  * vcn_v1_0_start_spg_mode - start VCN block
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Setup and start the VCN block
  */
-static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
+static int vcn_v1_0_start_spg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
 	uint32_t rb_bufsz, tmp;
 	uint32_t lmi_swap_cntl;
@@ -837,13 +846,13 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
 	/* disable byte swapping */
 	lmi_swap_cntl = 0;
 
-	vcn_1_0_disable_static_power_gating(adev);
+	vcn_1_0_disable_static_power_gating(vinst);
 
 	tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
 	WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp);
 
 	/* disable clock gating */
-	vcn_v1_0_disable_clock_gating(adev);
+	vcn_v1_0_disable_clock_gating(vinst);
 
 	/* disable interupt */
 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), 0,
@@ -885,7 +894,7 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
 		(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v1_0_mc_resume_spg_mode(adev);
+	vcn_v1_0_mc_resume_spg_mode(vinst);
 
 	WREG32_SOC15(UVD, 0, mmUVD_REG_XX_MASK_1_0, 0x10);
 	WREG32_SOC15(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK_1_0,
@@ -1001,8 +1010,9 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
 	return 0;
 }
 
-static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
+static int vcn_v1_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
 	uint32_t rb_bufsz, tmp;
 	uint32_t lmi_swap_cntl;
@@ -1010,7 +1020,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
 	/* disable byte swapping */
 	lmi_swap_cntl = 0;
 
-	vcn_1_0_enable_static_power_gating(adev);
+	vcn_1_0_enable_static_power_gating(vinst);
 
 	/* enable dynamic power gating mode */
 	tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
@@ -1019,7 +1029,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
 	WREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS, tmp);
 
 	/* enable clock gating */
-	vcn_v1_0_clock_gating_dpg_mode(adev, 0);
+	vcn_v1_0_clock_gating_dpg_mode(vinst, 0);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -1068,7 +1078,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0xFFFFFFFF, 0);
 
-	vcn_v1_0_mc_resume_dpg_mode(adev);
+	vcn_v1_0_mc_resume_dpg_mode(vinst);
 
 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_REG_XX_MASK, 0x10, 0xFFFFFFFF, 0);
 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK, 0x3, 0xFFFFFFFF, 0);
@@ -1085,7 +1095,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MASTINT_EN,
 			UVD_MASTINT_EN__VCPU_EN_MASK, UVD_MASTINT_EN__VCPU_EN_MASK, 0);
 
-	vcn_v1_0_clock_gating_dpg_mode(adev, 1);
+	vcn_v1_0_clock_gating_dpg_mode(vinst, 1);
 	/* setup mmUVD_LMI_CTRL */
 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_CTRL,
 		(8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
@@ -1145,21 +1155,24 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
 	return 0;
 }
 
-static int vcn_v1_0_start(struct amdgpu_device *adev)
+static int vcn_v1_0_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+
 	return (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ?
-		vcn_v1_0_start_dpg_mode(adev) : vcn_v1_0_start_spg_mode(adev);
+		vcn_v1_0_start_dpg_mode(vinst) : vcn_v1_0_start_spg_mode(vinst);
 }
 
 /**
  * vcn_v1_0_stop_spg_mode - stop VCN block
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * stop the VCN block
  */
-static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev)
+static int vcn_v1_0_stop_spg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	int tmp;
 
 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
@@ -1199,13 +1212,14 @@ static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev)
 
 	WREG32_SOC15(UVD, 0, mmUVD_STATUS, 0);
 
-	vcn_v1_0_enable_clock_gating(adev);
-	vcn_1_0_enable_static_power_gating(adev);
+	vcn_v1_0_enable_clock_gating(vinst);
+	vcn_1_0_enable_static_power_gating(vinst);
 	return 0;
 }
 
-static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev)
+static int vcn_v1_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t tmp;
 
 	/* Wait for power status to be UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF */
@@ -1237,14 +1251,15 @@ static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev)
 	return 0;
 }
 
-static int vcn_v1_0_stop(struct amdgpu_device *adev)
+static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	int r;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		r = vcn_v1_0_stop_dpg_mode(adev);
+		r = vcn_v1_0_stop_dpg_mode(vinst);
 	else
-		r = vcn_v1_0_stop_spg_mode(adev);
+		r = vcn_v1_0_stop_spg_mode(vinst);
 
 	return r;
 }
@@ -1399,16 +1414,17 @@ static int vcn_v1_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
 	bool enable = (state == AMD_CG_STATE_GATE);
 
 	if (enable) {
 		/* wait for STATUS to clear */
 		if (!vcn_v1_0_is_idle(adev))
 			return -EBUSY;
-		vcn_v1_0_enable_clock_gating(adev);
+		vcn_v1_0_enable_clock_gating(vinst);
 	} else {
 		/* disable HW gating and enable Sw gating */
-		vcn_v1_0_disable_clock_gating(adev);
+		vcn_v1_0_disable_clock_gating(vinst);
 	}
 	return 0;
 }
@@ -1812,14 +1828,15 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	 */
 	int ret;
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
 
 	if (state == adev->vcn.inst[0].cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v1_0_stop(adev);
+		ret = vcn_v1_0_stop(vinst);
 	else
-		ret = vcn_v1_0_start(adev);
+		ret = vcn_v1_0_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[0].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 14/44] drm/amdgpu/vcn2.0: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (12 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 13/44] drm/amdgpu/vcn1.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:01   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 15/44] drm/amdgpu/vcn2.5: " Alex Deucher
                   ` (29 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

v2: index instances directly on vcn1.0 and 2.0 to make
it clear that they only support a single instance (Lijo)

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 66 ++++++++++++++++-----------
 1 file changed, 39 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index 8ff5a9d67cbd2..aa61d3b54f8c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -370,8 +370,9 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block)
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
+static void vcn_v2_0_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
 	uint32_t offset;
 
@@ -426,8 +427,10 @@ static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
 	WREG32_SOC15(UVD, 0, mmUVD_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
 }
 
-static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirect)
+static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
 	uint32_t offset;
 
@@ -525,12 +528,13 @@ static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirec
 /**
  * vcn_v2_0_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v2_0_disable_clock_gating(struct amdgpu_device *adev)
+static void vcn_v2_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data;
 
 	if (amdgpu_sriov_vf(adev))
@@ -634,9 +638,10 @@ static void vcn_v2_0_disable_clock_gating(struct amdgpu_device *adev)
 	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
+static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
 		uint8_t sram_sel, uint8_t indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t reg_data = 0;
 
 	/* enable sw clock gating control */
@@ -685,12 +690,13 @@ static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
 /**
  * vcn_v2_0_enable_clock_gating - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v2_0_enable_clock_gating(struct amdgpu_device *adev)
+static void vcn_v2_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data = 0;
 
 	if (amdgpu_sriov_vf(adev))
@@ -743,8 +749,9 @@ static void vcn_v2_0_enable_clock_gating(struct amdgpu_device *adev)
 	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v2_0_disable_static_power_gating(struct amdgpu_device *adev)
+static void vcn_v2_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data = 0;
 
 	if (amdgpu_sriov_vf(adev))
@@ -792,8 +799,9 @@ static void vcn_v2_0_disable_static_power_gating(struct amdgpu_device *adev)
 	WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
 }
 
-static void vcn_v2_0_enable_static_power_gating(struct amdgpu_device *adev)
+static void vcn_v2_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t data = 0;
 
 	if (amdgpu_sriov_vf(adev))
@@ -834,13 +842,14 @@ static void vcn_v2_0_enable_static_power_gating(struct amdgpu_device *adev)
 	}
 }
 
-static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
+static int vcn_v2_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
 	uint32_t rb_bufsz, tmp;
 
-	vcn_v2_0_enable_static_power_gating(adev);
+	vcn_v2_0_enable_static_power_gating(vinst);
 
 	/* enable dynamic power gating mode */
 	tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
@@ -852,7 +861,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
 		adev->vcn.inst->dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst->dpg_sram_cpu_addr;
 
 	/* enable clock gating */
-	vcn_v2_0_clock_gating_dpg_mode(adev, 0, indirect);
+	vcn_v2_0_clock_gating_dpg_mode(vinst, 0, indirect);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -901,7 +910,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
 
-	vcn_v2_0_mc_resume_dpg_mode(adev, indirect);
+	vcn_v2_0_mc_resume_dpg_mode(vinst, indirect);
 
 	WREG32_SOC15_DPG_MODE(0, SOC15_DPG_MODE_OFFSET(
 		UVD, 0, mmUVD_REG_XX_MASK), 0x10, 0, indirect);
@@ -969,8 +978,9 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
 	return 0;
 }
 
-static int vcn_v2_0_start(struct amdgpu_device *adev)
+static int vcn_v2_0_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
 	uint32_t rb_bufsz, tmp;
@@ -981,16 +991,16 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
 		amdgpu_dpm_enable_vcn(adev, true, 0);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram);
+		return vcn_v2_0_start_dpg_mode(vinst, adev->vcn.inst->indirect_sram);
 
-	vcn_v2_0_disable_static_power_gating(adev);
+	vcn_v2_0_disable_static_power_gating(vinst);
 
 	/* set uvd status busy */
 	tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
 	WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp);
 
 	/*SW clock gating */
-	vcn_v2_0_disable_clock_gating(adev);
+	vcn_v2_0_disable_clock_gating(vinst);
 
 	/* enable VCPU clock */
 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CNTL),
@@ -1034,7 +1044,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
 		(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v2_0_mc_resume(adev);
+	vcn_v2_0_mc_resume(vinst);
 
 	/* release VCPU reset to boot */
 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0,
@@ -1142,8 +1152,9 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
 	return 0;
 }
 
-static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev)
+static int vcn_v2_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
@@ -1172,13 +1183,14 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev)
 	return 0;
 }
 
-static int vcn_v2_0_stop(struct amdgpu_device *adev)
+static int vcn_v2_0_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
 	uint32_t tmp;
 	int r;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-		r = vcn_v2_0_stop_dpg_mode(adev);
+		r = vcn_v2_0_stop_dpg_mode(vinst);
 		if (r)
 			return r;
 		goto power_off;
@@ -1230,8 +1242,8 @@ static int vcn_v2_0_stop(struct amdgpu_device *adev)
 	/* clear status */
 	WREG32_SOC15(VCN, 0, mmUVD_STATUS, 0);
 
-	vcn_v2_0_enable_clock_gating(adev);
-	vcn_v2_0_enable_static_power_gating(adev);
+	vcn_v2_0_enable_clock_gating(vinst);
+	vcn_v2_0_enable_static_power_gating(vinst);
 
 power_off:
 	if (adev->pm.dpm_enabled)
@@ -1348,10 +1360,10 @@ static int vcn_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 		/* wait for STATUS to clear */
 		if (!vcn_v2_0_is_idle(adev))
 			return -EBUSY;
-		vcn_v2_0_enable_clock_gating(adev);
+		vcn_v2_0_enable_clock_gating(&adev->vcn.inst[0]);
 	} else {
 		/* disable HW gating and enable Sw gating */
-		vcn_v2_0_disable_clock_gating(adev);
+		vcn_v2_0_disable_clock_gating(&adev->vcn.inst[0]);
 	}
 	return 0;
 }
@@ -1818,9 +1830,9 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v2_0_stop(adev);
+		ret = vcn_v2_0_stop(adev->vcn.inst);
 	else
-		ret = vcn_v2_0_start(adev);
+		ret = vcn_v2_0_start(adev->vcn.inst);
 
 	if (!ret)
 		adev->vcn.inst[0].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 15/44] drm/amdgpu/vcn2.5: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (13 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 14/44] drm/amdgpu/vcn2.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:02   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 16/44] drm/amdgpu/vcn4.0: " Alex Deucher
                   ` (28 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 79 +++++++++++++++++----------
 1 file changed, 50 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 4f9f3de023ffd..69cf42a4a3f18 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -468,13 +468,14 @@ static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v2_5_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @i: instance to resume
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i)
+static void vcn_v2_5_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	uint32_t size;
 	uint32_t offset;
 
@@ -527,8 +528,11 @@ static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i)
 		     AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
 }
 
-static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst_idx].fw->size + 4);
 	uint32_t offset;
 
@@ -626,13 +630,14 @@ static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
 /**
  * vcn_v2_5_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @i: instance to disable clockgating on
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i)
+static void vcn_v2_5_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	uint32_t data;
 
 	if (adev->vcn.harvest_config & (1 << i))
@@ -738,9 +743,11 @@ static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
-		uint8_t sram_sel, int inst_idx, uint8_t indirect)
+static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+		uint8_t sram_sel, uint8_t indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 
 	/* enable sw clock gating control */
@@ -789,13 +796,14 @@ static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
 /**
  * vcn_v2_5_enable_clock_gating_inst - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @i: instance to enable clockgating on
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i)
+static void vcn_v2_5_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	uint32_t data = 0;
 
 	if (adev->vcn.harvest_config & (1 << i))
@@ -846,9 +854,11 @@ static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
+static void vcn_v2_6_enable_ras(struct amdgpu_vcn_inst *vinst,
 				bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t tmp;
 
 	if (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(2, 6, 0))
@@ -873,8 +883,10 @@ static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
 			      tmp, 0, indirect);
 }
 
-static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v2_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
 	uint32_t rb_bufsz, tmp;
@@ -892,7 +904,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 		adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
 
 	/* enable clock gating */
-	vcn_v2_5_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+	vcn_v2_5_clock_gating_dpg_mode(vinst, 0, indirect);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -941,7 +953,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
 
-	vcn_v2_5_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v2_5_mc_resume_dpg_mode(vinst, indirect);
 
 	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
 		VCN, 0, mmUVD_REG_XX_MASK), 0x10, 0, indirect);
@@ -952,7 +964,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
 		VCN, 0, mmUVD_LMI_CTRL2), 0, 0, indirect);
 
-	vcn_v2_6_enable_ras(adev, inst_idx, indirect);
+	vcn_v2_6_enable_ras(vinst, indirect);
 
 	/* unblock VCPU register access */
 	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
@@ -1017,8 +1029,10 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 	return 0;
 }
 
-static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
+static int vcn_v2_5_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_fw_shared *fw_shared =
 		adev->vcn.inst[i].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
@@ -1032,7 +1046,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
 		amdgpu_dpm_enable_vcn(adev, true, i);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v2_5_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
 
 	/* disable register anti-hang mechanism */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
@@ -1046,7 +1060,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
 		return 0;
 
 	/* SW clock gating */
-	vcn_v2_5_disable_clock_gating(adev, i);
+	vcn_v2_5_disable_clock_gating(vinst);
 
 	/* enable VCPU clock */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
@@ -1091,7 +1105,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
 		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v2_5_mc_resume(adev, i);
+	vcn_v2_5_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
@@ -1396,8 +1410,10 @@ static int vcn_v2_5_sriov_start(struct amdgpu_device *adev)
 	return vcn_v2_5_mmsch_start(adev, &adev->virt.mm_table);
 }
 
-static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static int vcn_v2_5_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t tmp;
 
 	/* Wait for power status to be 1 */
@@ -1424,15 +1440,17 @@ static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 	return 0;
 }
 
-static int vcn_v2_5_stop(struct amdgpu_device *adev, int i)
+static int vcn_v2_5_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	uint32_t tmp;
 	int r;
 
 	if (adev->vcn.harvest_config & (1 << i))
 		return 0;
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v2_5_stop_dpg_mode(adev, i);
+		return vcn_v2_5_stop_dpg_mode(vinst);
 
 	/* wait for vcn idle */
 	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
@@ -1475,7 +1493,7 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i)
 	/* clear status */
 	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
 
-	vcn_v2_5_enable_clock_gating(adev, i);
+	vcn_v2_5_enable_clock_gating(vinst);
 
 	/* enable register anti-hang mechanism */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS),
@@ -1810,12 +1828,14 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 		return 0;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (enable) {
 			if (!vcn_v2_5_is_idle(adev))
 				return -EBUSY;
-			vcn_v2_5_enable_clock_gating(adev, i);
+			vcn_v2_5_enable_clock_gating(vinst);
 		} else {
-			vcn_v2_5_disable_clock_gating(adev, i);
+			vcn_v2_5_disable_clock_gating(vinst);
 		}
 	}
 
@@ -1827,6 +1847,7 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 					       int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret;
 
 	if (amdgpu_sriov_vf(adev))
@@ -1836,9 +1857,9 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v2_5_stop(adev, i);
+		ret = vcn_v2_5_stop(vinst);
 	else
-		ret = vcn_v2_5_start(adev, i);
+		ret = vcn_v2_5_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 16/44] drm/amdgpu/vcn4.0: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (14 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 15/44] drm/amdgpu/vcn2.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:03   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 17/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
                   ` (27 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 116 +++++++++++++++-----------
 1 file changed, 67 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 1200815b3eee8..3d70e2cc81982 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -449,13 +449,14 @@ static int vcn_v4_0_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v4_0_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -509,14 +510,16 @@ static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v4_0_mc_resume_dpg_mode - memory controller programming for dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Let the VCN memory controller know it's offsets with dpg mode
  */
-static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 	hdr = (const struct common_firmware_header *)adev->vcn.inst[inst_idx].fw->data;
@@ -616,13 +619,14 @@ static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
 /**
  * vcn_v4_0_disable_static_power_gating - disable VCN static power gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable static power gating for VCN block
  */
-static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data = 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -681,13 +685,14 @@ static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int
 /**
  * vcn_v4_0_enable_static_power_gating - enable VCN static power gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable static power gating for VCN block
  */
-static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -736,13 +741,14 @@ static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int
 /**
  * vcn_v4_0_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -847,16 +853,18 @@ static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v4_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  * @sram_sel: sram select
- * @inst_idx: instance number index
  * @indirect: indirectly write sram
  *
  * Disable clock gating for VCN block with dpg mode
  */
-static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
-      int inst_idx, uint8_t indirect)
+static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+						   uint8_t sram_sel,
+						   uint8_t indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -904,13 +912,14 @@ static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, u
 /**
  * vcn_v4_0_enable_clock_gating - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -960,9 +969,11 @@ static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
 	WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
 }
 
-static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx,
+static void vcn_v4_0_enable_ras(struct amdgpu_vcn_inst *vinst,
 				bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t tmp;
 
 	if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
@@ -985,14 +996,15 @@ static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx,
 /**
  * vcn_v4_0_start_dpg_mode - VCN start with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Start VCN block with dpg mode
  */
-static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v4_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -1010,7 +1022,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 		adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
 
 	/* enable clock gating */
-	vcn_v4_0_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+	vcn_v4_0_disable_clock_gating_dpg_mode(vinst, 0, indirect);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -1058,7 +1070,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
 
-	vcn_v4_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v4_0_mc_resume_dpg_mode(vinst, indirect);
 
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
 	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
@@ -1070,7 +1082,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
 		VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);
 
-	vcn_v4_0_enable_ras(adev, inst_idx, indirect);
+	vcn_v4_0_enable_ras(vinst, indirect);
 
 	/* enable master interrupt */
 	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
@@ -1114,13 +1126,14 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
 /**
  * vcn_v4_0_start - VCN start
  *
- * @adev: amdgpu_device pointer
- * @i: instance to start
+ * @vinst: VCN instance
  *
  * Start VCN block
  */
-static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
+static int vcn_v4_0_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -1135,17 +1148,17 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v4_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
-	vcn_v4_0_disable_static_power_gating(adev, i);
+	vcn_v4_0_disable_static_power_gating(vinst);
 
 	/* set VCN status busy */
 	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
 	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
 
 	/*SW clock gating */
-	vcn_v4_0_disable_clock_gating(adev, i);
+	vcn_v4_0_disable_clock_gating(vinst);
 
 	/* enable VCPU clock */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
@@ -1198,7 +1211,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
 		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v4_0_mc_resume(adev, i);
+	vcn_v4_0_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
@@ -1541,13 +1554,14 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev)
 /**
  * vcn_v4_0_stop_dpg_mode - VCN stop with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  *
  * Stop VCN block with dpg mode
  */
-static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v4_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
@@ -1571,13 +1585,14 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 /**
  * vcn_v4_0_stop - VCN stop
  *
- * @adev: amdgpu_device pointer
- * @i: instance to stop
+ * @vinst: VCN instance
  *
  * Stop VCN block
  */
-static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
+static int vcn_v4_0_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	uint32_t tmp;
 	int r = 0;
@@ -1589,7 +1604,7 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
 	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-		vcn_v4_0_stop_dpg_mode(adev, i);
+		vcn_v4_0_stop_dpg_mode(vinst);
 		return 0;
 	}
 
@@ -1642,10 +1657,10 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
 
 	/* apply HW clock gating */
-	vcn_v4_0_enable_clock_gating(adev, i);
+	vcn_v4_0_enable_clock_gating(vinst);
 
 	/* enable VCN power gating */
-	vcn_v4_0_enable_static_power_gating(adev, i);
+	vcn_v4_0_enable_static_power_gating(vinst);
 
 	if (adev->pm.dpm_enabled)
 		amdgpu_dpm_enable_vcn(adev, false, i);
@@ -2044,15 +2059,17 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
 		if (enable) {
 			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
 				return -EBUSY;
-			vcn_v4_0_enable_clock_gating(adev, i);
+			vcn_v4_0_enable_clock_gating(vinst);
 		} else {
-			vcn_v4_0_disable_clock_gating(adev, i);
+			vcn_v4_0_disable_clock_gating(vinst);
 		}
 	}
 
@@ -2064,6 +2081,7 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 					       int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
@@ -2079,9 +2097,9 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v4_0_stop(adev, i);
+		ret = vcn_v4_0_stop(vinst);
 	else
-		ret = vcn_v4_0_start(adev, i);
+		ret = vcn_v4_0_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 17/44] drm/amdgpu/vcn4.0.3: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (15 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 16/44] drm/amdgpu/vcn4.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:03   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 18/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
                   ` (26 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 93 ++++++++++++++-----------
 1 file changed, 54 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 1407cb4b553b7..a3fbfaac76603 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -431,13 +431,14 @@ static int vcn_v4_0_3_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v4_0_3_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v4_0_3_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t offset, size, vcn_inst;
 	const struct common_firmware_header *hdr;
 
@@ -505,14 +506,16 @@ static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx)
 /**
  * vcn_v4_0_3_mc_resume_dpg_mode - memory controller programming for dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Let the VCN memory controller know it's offsets with dpg mode
  */
-static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					  bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -619,13 +622,14 @@ static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
 /**
  * vcn_v4_0_3_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t data;
 	int vcn_inst;
 
@@ -712,16 +716,18 @@ static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst
 /**
  * vcn_v4_0_3_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  * @sram_sel: sram select
- * @inst_idx: instance number index
  * @indirect: indirectly write sram
  *
  * Disable clock gating for VCN block with dpg mode
  */
-static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
-				int inst_idx, uint8_t indirect)
+static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+						     uint8_t sram_sel,
+						     uint8_t indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -763,13 +769,14 @@ static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev,
 /**
  * vcn_v4_0_3_enable_clock_gating - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t data;
 	int vcn_inst;
 
@@ -814,14 +821,16 @@ static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_
 /**
  * vcn_v4_0_3_start_dpg_mode - VCN start with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Start VCN block with dpg mode
  */
-static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared =
 						adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
@@ -849,7 +858,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 	}
 
 	/* enable clock gating */
-	vcn_v4_0_3_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+	vcn_v4_0_3_disable_clock_gating_dpg_mode(vinst, 0, indirect);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -899,7 +908,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
 
-	vcn_v4_0_3_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v4_0_3_mc_resume_dpg_mode(vinst, indirect);
 
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
 	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
@@ -1146,13 +1155,14 @@ static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev)
 /**
  * vcn_v4_0_3_start - VCN start
  *
- * @adev: amdgpu_device pointer
- * @i: instance to start
+ * @vinst: VCN instance
  *
  * Start VCN block
  */
-static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
+static int vcn_v4_0_3_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	int j, k, r, vcn_inst;
@@ -1162,7 +1172,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
 		amdgpu_dpm_enable_vcn(adev, true, i);
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
 
 	vcn_inst = GET_INST(VCN, i);
 	/* set VCN status busy */
@@ -1171,7 +1181,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
 
 	/* SW clock gating */
-	vcn_v4_0_3_disable_clock_gating(adev, i);
+	vcn_v4_0_3_disable_clock_gating(vinst);
 
 	/* enable VCPU clock */
 	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
@@ -1225,7 +1235,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
 		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v4_0_3_mc_resume(adev, i);
+	vcn_v4_0_3_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
@@ -1319,13 +1329,14 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
 /**
  * vcn_v4_0_3_stop_dpg_mode - VCN stop with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  *
  * Stop VCN block with dpg mode
  */
-static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t tmp;
 	int vcn_inst;
 
@@ -1351,13 +1362,14 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 /**
  * vcn_v4_0_3_stop - VCN stop
  *
- * @adev: amdgpu_device pointer
- * @i: instance to stop
+ * @vinst: VCN instance
  *
  * Stop VCN block
  */
-static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
+static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	int r = 0, vcn_inst;
 	uint32_t tmp;
@@ -1368,7 +1380,7 @@ static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
 	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-		vcn_v4_0_3_stop_dpg_mode(adev, i);
+		vcn_v4_0_3_stop_dpg_mode(vinst);
 		return 0;
 	}
 
@@ -1425,7 +1437,7 @@ static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
 
 	/* apply HW clock gating */
-	vcn_v4_0_3_enable_clock_gating(adev, i);
+	vcn_v4_0_3_enable_clock_gating(vinst);
 
 Done:
 	if (adev->pm.dpm_enabled)
@@ -1662,13 +1674,15 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (enable) {
 			if (RREG32_SOC15(VCN, GET_INST(VCN, i),
 					 regUVD_STATUS) != UVD_STATUS__IDLE)
 				return -EBUSY;
-			vcn_v4_0_3_enable_clock_gating(adev, i);
+			vcn_v4_0_3_enable_clock_gating(vinst);
 		} else {
-			vcn_v4_0_3_disable_clock_gating(adev, i);
+			vcn_v4_0_3_disable_clock_gating(vinst);
 		}
 	}
 	return 0;
@@ -1679,6 +1693,7 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
@@ -1694,9 +1709,9 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v4_0_3_stop(adev, i);
+		ret = vcn_v4_0_3_stop(vinst);
 	else
-		ret = vcn_v4_0_3_start(adev, i);
+		ret = vcn_v4_0_3_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 18/44] drm/amdgpu/vcn4.0.5: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (16 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 17/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:04   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 19/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
                   ` (25 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 111 ++++++++++++++----------
 1 file changed, 64 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index c3a2826a59631..295f39b2222d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -385,13 +385,14 @@ static int vcn_v4_0_5_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v4_0_5_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_5_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -445,14 +446,16 @@ static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v4_0_5_mc_resume_dpg_mode - memory controller programming for dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Let the VCN memory controller know it's offsets with dpg mode
  */
-static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					  bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -559,13 +562,14 @@ static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
 /**
  * vcn_v4_0_5_disable_static_power_gating - disable VCN static power gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable static power gating for VCN block
  */
-static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data = 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -618,13 +622,14 @@ static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, i
 /**
  * vcn_v4_0_5_enable_static_power_gating - enable VCN static power gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable static power gating for VCN block
  */
-static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -660,13 +665,14 @@ static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, in
 /**
  * vcn_v4_0_5_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -771,16 +777,18 @@ static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst
 /**
  * vcn_v4_0_5_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  * @sram_sel: sram select
- * @inst_idx: instance number index
  * @indirect: indirectly write sram
  *
  * Disable clock gating for VCN block with dpg mode
  */
-static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
-		int inst_idx, uint8_t indirect)
+static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+						     uint8_t sram_sel,
+						     uint8_t indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -828,13 +836,14 @@ static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev,
 /**
  * vcn_v4_0_5_enable_clock_gating - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
@@ -887,14 +896,16 @@ static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v4_0_5_start_dpg_mode - VCN start with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Start VCN block with dpg mode
  */
-static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -913,7 +924,7 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 					(uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
 
 	/* enable clock gating */
-	vcn_v4_0_5_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+	vcn_v4_0_5_disable_clock_gating_dpg_mode(vinst, 0, indirect);
 
 	/* enable VCPU clock */
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
@@ -961,7 +972,7 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
 
-	vcn_v4_0_5_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v4_0_5_mc_resume_dpg_mode(vinst, indirect);
 
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
 	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
@@ -1014,13 +1025,14 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 /**
  * vcn_v4_0_5_start - VCN start
  *
- * @adev: amdgpu_device pointer
- * @i: instance to start
+ * @vinst: VCN instance
  *
  * Start VCN block
  */
-static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
+static int vcn_v4_0_5_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -1035,17 +1047,17 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v4_0_5_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
-	vcn_v4_0_5_disable_static_power_gating(adev, i);
+	vcn_v4_0_5_disable_static_power_gating(vinst);
 
 	/* set VCN status busy */
 	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
 	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
 
 	/* SW clock gating */
-	vcn_v4_0_5_disable_clock_gating(adev, i);
+	vcn_v4_0_5_disable_clock_gating(vinst);
 
 	/* enable VCPU clock */
 	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
@@ -1098,7 +1110,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
 		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
 		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
 
-	vcn_v4_0_5_mc_resume(adev, i);
+	vcn_v4_0_5_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
@@ -1194,13 +1206,14 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
 /**
  * vcn_v4_0_5_stop_dpg_mode - VCN stop with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  *
  * Stop VCN block with dpg mode
  */
-static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t tmp;
 
 	/* Wait for power status to be 1 */
@@ -1222,13 +1235,14 @@ static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 /**
  * vcn_v4_0_5_stop - VCN stop
  *
- * @adev: amdgpu_device pointer
- * @i: instance to stop
+ * @vinst: VCN instance
  *
  * Stop VCN block
  */
-static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
+static int vcn_v4_0_5_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	uint32_t tmp;
 	int r = 0;
@@ -1240,7 +1254,7 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
 	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-		vcn_v4_0_5_stop_dpg_mode(adev, i);
+		vcn_v4_0_5_stop_dpg_mode(vinst);
 		return 0;
 	}
 
@@ -1293,10 +1307,10 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
 
 	/* apply HW clock gating */
-	vcn_v4_0_5_enable_clock_gating(adev, i);
+	vcn_v4_0_5_enable_clock_gating(vinst);
 
 	/* enable VCN power gating */
-	vcn_v4_0_5_enable_static_power_gating(adev, i);
+	vcn_v4_0_5_enable_static_power_gating(vinst);
 
 	if (adev->pm.dpm_enabled)
 		amdgpu_dpm_enable_vcn(adev, false, i);
@@ -1526,15 +1540,17 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
 		if (enable) {
 			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
 				return -EBUSY;
-			vcn_v4_0_5_enable_clock_gating(adev, i);
+			vcn_v4_0_5_enable_clock_gating(vinst);
 		} else {
-			vcn_v4_0_5_disable_clock_gating(adev, i);
+			vcn_v4_0_5_disable_clock_gating(vinst);
 		}
 	}
 
@@ -1546,15 +1562,16 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
 	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v4_0_5_stop(adev, i);
+		ret = vcn_v4_0_5_stop(vinst);
 	else
-		ret = vcn_v4_0_5_start(adev, i);
+		ret = vcn_v4_0_5_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 19/44] drm/amdgpu/vcn5.0.0: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (17 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 18/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:05   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 20/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
                   ` (24 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 99 ++++++++++++++-----------
 1 file changed, 55 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index d3e4d02c12a06..a71960d899e38 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -367,13 +367,14 @@ static int vcn_v5_0_0_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v5_0_0_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_0_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -427,14 +428,16 @@ static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v5_0_0_mc_resume_dpg_mode - memory controller programming for dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Let the VCN memory controller know it's offsets with dpg mode
  */
-static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					  bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -537,13 +540,14 @@ static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
 /**
  * vcn_v5_0_0_disable_static_power_gating - disable VCN static power gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable static power gating for VCN block
  */
-static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data = 0;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -604,13 +608,14 @@ static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, i
 /**
  * vcn_v5_0_0_enable_static_power_gating - enable VCN static power gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable static power gating for VCN block
  */
-static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t data;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
@@ -650,12 +655,11 @@ static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, in
 /**
  * vcn_v5_0_0_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
 	return;
 }
@@ -664,15 +668,15 @@ static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst
 /**
  * vcn_v5_0_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  * @sram_sel: sram select
- * @inst_idx: instance number index
  * @indirect: indirectly write sram
  *
  * Disable clock gating for VCN block with dpg mode
  */
-static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
-	int inst_idx, uint8_t indirect)
+static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
+						     uint8_t sram_sel,
+						     uint8_t indirect)
 {
 	return;
 }
@@ -681,12 +685,11 @@ static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev,
 /**
  * vcn_v5_0_0_enable_clock_gating - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
 	return;
 }
@@ -694,14 +697,16 @@ static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v5_0_0_start_dpg_mode - VCN start with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Start VCN block with dpg mode
  */
-static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_vcn5_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -741,7 +746,7 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 	WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
 		VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect);
 
-	vcn_v5_0_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v5_0_0_mc_resume_dpg_mode(vinst, indirect);
 
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
 	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
@@ -793,13 +798,14 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 /**
  * vcn_v5_0_0_start - VCN start
  *
- * @adev: amdgpu_device pointer
- * @i: instance to start
+ * @vinst: VCN instance
  *
  * Start VCN block
  */
-static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
+static int vcn_v5_0_0_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -814,10 +820,10 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v5_0_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
 
 	/* disable VCN power gating */
-	vcn_v5_0_0_disable_static_power_gating(adev, i);
+	vcn_v5_0_0_disable_static_power_gating(vinst);
 
 	/* set VCN status busy */
 	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
@@ -848,7 +854,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
 		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
 		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
 
-	vcn_v5_0_0_mc_resume(adev, i);
+	vcn_v5_0_0_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
@@ -944,13 +950,14 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
 /**
  * vcn_v5_0_0_stop_dpg_mode - VCN stop with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  *
  * Stop VCN block with dpg mode
  */
-static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
@@ -974,13 +981,14 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 /**
  * vcn_v5_0_0_stop - VCN stop
  *
- * @adev: amdgpu_device pointer
- * @i: instance to stop
+ * @vinst: VCN instance
  *
  * Stop VCN block
  */
-static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
+static int vcn_v5_0_0_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
 	uint32_t tmp;
 	int r = 0;
@@ -992,7 +1000,7 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
 	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-		vcn_v5_0_0_stop_dpg_mode(adev, i);
+		vcn_v5_0_0_stop_dpg_mode(vinst);
 		return 0;
 	}
 
@@ -1045,7 +1053,7 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
 	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
 
 	/* enable VCN power gating */
-	vcn_v5_0_0_enable_static_power_gating(adev, i);
+	vcn_v5_0_0_enable_static_power_gating(vinst);
 
 	if (adev->pm.dpm_enabled)
 		amdgpu_dpm_enable_vcn(adev, false, i);
@@ -1271,15 +1279,17 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
 		if (enable) {
 			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
 				return -EBUSY;
-			vcn_v5_0_0_enable_clock_gating(adev, i);
+			vcn_v5_0_0_enable_clock_gating(vinst);
 		} else {
-			vcn_v5_0_0_disable_clock_gating(adev, i);
+			vcn_v5_0_0_disable_clock_gating(vinst);
 		}
 	}
 
@@ -1291,15 +1301,16 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
 	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v5_0_0_stop(adev, i);
+		ret = vcn_v5_0_0_stop(vinst);
 	else
-		ret = vcn_v5_0_0_start(adev, i);
+		ret = vcn_v5_0_0_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 20/44] drm/amdgpu/vcn5.0.1: convert internal functions to use vcn_inst
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (18 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 19/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-05 15:05   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 21/44] drm/amdgpu/vcn: adjust pause_dpg_mode function signature Alex Deucher
                   ` (23 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Pass the vcn instance structure to these functions rather
than adev and the instance number.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 71 ++++++++++++++-----------
 1 file changed, 41 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index f49fdf2bb6e33..8eccb45b04d2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -282,13 +282,14 @@ static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block)
 /**
  * vcn_v5_0_1_mc_resume - memory controller programming
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Let the VCN memory controller know it's offsets
  */
-static void vcn_v5_0_1_mc_resume(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_1_mc_resume(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst = vinst->inst;
 	uint32_t offset, size, vcn_inst;
 	const struct common_firmware_header *hdr;
 
@@ -344,14 +345,16 @@ static void vcn_v5_0_1_mc_resume(struct amdgpu_device *adev, int inst)
 /**
  * vcn_v5_0_1_mc_resume_dpg_mode - memory controller programming for dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Let the VCN memory controller know it's offsets with dpg mode
  */
-static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
+					  bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t offset, size;
 	const struct common_firmware_header *hdr;
 
@@ -456,38 +459,38 @@ static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
 /**
  * vcn_v5_0_1_disable_clock_gating - disable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Disable clock gating for VCN block
  */
-static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
 }
 
 /**
  * vcn_v5_0_1_enable_clock_gating - enable VCN clock gating
  *
- * @adev: amdgpu_device pointer
- * @inst: instance number
+ * @vinst: VCN instance
  *
  * Enable clock gating for VCN block
  */
-static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_device *adev, int inst)
+static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
 {
 }
 
 /**
  * vcn_v5_0_1_start_dpg_mode - VCN start with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @indirect: indirectly write sram
  *
  * Start VCN block with dpg mode
  */
-static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     bool indirect)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared =
 		adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
 	struct amdgpu_ring *ring;
@@ -535,7 +538,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 	WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
 		VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect);
 
-	vcn_v5_0_1_mc_resume_dpg_mode(adev, inst_idx, indirect);
+	vcn_v5_0_1_mc_resume_dpg_mode(vinst, indirect);
 
 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
 	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
@@ -589,12 +592,14 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
 /**
  * vcn_v5_0_1_start - VCN start
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Start VCN block
  */
-static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
+static int vcn_v5_0_1_start(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t tmp;
@@ -606,7 +611,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
 	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
-		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
+		return vcn_v5_0_1_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
 
 	vcn_inst = GET_INST(VCN, i);
 
@@ -639,7 +644,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
 		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
 		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
 
-	vcn_v5_0_1_mc_resume(adev, i);
+	vcn_v5_0_1_mc_resume(vinst);
 
 	/* VCN global tiling registers */
 	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
@@ -739,13 +744,14 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
 /**
  * vcn_v5_0_1_stop_dpg_mode - VCN stop with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  *
  * Stop VCN block with dpg mode
  */
-static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t tmp;
 	int vcn_inst;
 
@@ -767,12 +773,14 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
 /**
  * vcn_v5_0_1_stop - VCN stop
  *
- * @adev: amdgpu_device pointer
+ * @vinst: VCN instance
  *
  * Stop VCN block
  */
-static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i)
+static int vcn_v5_0_1_stop(struct amdgpu_vcn_inst *vinst)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int i = vinst->inst;
 	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
 	uint32_t tmp;
 	int r = 0, vcn_inst;
@@ -783,7 +791,7 @@ static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i)
 	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
 
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
-		vcn_v5_0_1_stop_dpg_mode(adev, i);
+		vcn_v5_0_1_stop_dpg_mode(vinst);
 		return 0;
 	}
 
@@ -1005,12 +1013,14 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (enable) {
 			if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE)
 				return -EBUSY;
-			vcn_v5_0_1_enable_clock_gating(adev, i);
+			vcn_v5_0_1_enable_clock_gating(vinst);
 		} else {
-			vcn_v5_0_1_disable_clock_gating(adev, i);
+			vcn_v5_0_1_disable_clock_gating(vinst);
 		}
 	}
 
@@ -1022,15 +1032,16 @@ static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
 	if (state == adev->vcn.inst[i].cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v5_0_1_stop(adev, i);
+		ret = vcn_v5_0_1_stop(vinst);
 	else
-		ret = vcn_v5_0_1_start(adev, i);
+		ret = vcn_v5_0_1_start(vinst);
 
 	if (!ret)
 		adev->vcn.inst[i].cur_state = state;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 21/44] drm/amdgpu/vcn: adjust pause_dpg_mode function signature
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (19 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 20/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 13:40   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 22/44] drm/amdgpu/vcn: add new per instance callback for powergating Alex Deucher
                   ` (22 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Change it to take a vcn instance rather than adev to align
with the vcn instance changes.

TODO: clean up the function internals to use the vinst state
directly rather than accessing it indirectly via adev->vcn.inst[].

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c |  4 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  3 +--
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   | 14 ++++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   | 12 +++++++-----
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   | 10 ++++++----
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   | 12 +++++++-----
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   | 15 ++++++++-------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 11 +++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 13 +++++++------
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 15 ++++++++-------
 10 files changed, 59 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 010cc64a950a4..a2250747a7c81 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -417,7 +417,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 		else
 			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 
-		adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state);
+		adev->vcn.inst[i].pause_dpg_mode(vcn_inst, &new_state);
 	}
 
 	fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
@@ -474,7 +474,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 		}
 
-		adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state);
+		adev->vcn.inst[ring->me].pause_dpg_mode(&adev->vcn.inst[ring->me], &new_state);
 	}
 	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 5f92cf28cc752..8d34e3814ab19 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -327,8 +327,7 @@ struct amdgpu_vcn_inst {
 	bool			indirect_sram;
 	struct amdgpu_vcn_reg	 internal;
 	struct mutex		vcn1_jpeg1_workaround;
-	int (*pause_dpg_mode)(struct amdgpu_device *adev,
-			      int inst_idx,
+	int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst,
 			      struct dpg_pause_state *new_state);
 	bool using_unified_queue;
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 613f17be9d829..3d56660fd90a9 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -87,8 +87,8 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 				enum amd_powergating_state state);
-static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
-				int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state);
 
 static void vcn_v1_0_idle_work_handler(struct work_struct *work);
 static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);
@@ -1264,9 +1264,11 @@ static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst)
 	return r;
 }
 
-static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
-				int inst_idx, struct dpg_pause_state *new_state)
+static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	int ret_code;
 	uint32_t reg_data = 0;
 	uint32_t reg_data2 = 0;
@@ -1866,7 +1868,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 		else
 			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
 
-		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
+		adev->vcn.inst->pause_dpg_mode(vcn_inst, &new_state);
 	}
 
 	fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
@@ -1933,7 +1935,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
 		else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
 			new_state.jpeg = VCN_DPG_STATE__PAUSE;
 
-		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
+		adev->vcn.inst->pause_dpg_mode(adev->vcn.inst, &new_state);
 	}
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index aa61d3b54f8c2..e4305687749a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -94,8 +94,8 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 				enum amd_powergating_state state);
-static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,
-				int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state);
 static int vcn_v2_0_start_sriov(struct amdgpu_device *adev);
 /**
  * vcn_v2_0_early_init - set function pointers and load microcode
@@ -1158,7 +1158,7 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
-	vcn_v2_0_pause_dpg_mode(adev, 0, &state);
+	vcn_v2_0_pause_dpg_mode(vinst, &state);
 	/* Wait for power status to be 1 */
 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS, 1,
 		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
@@ -1252,9 +1252,11 @@ static int vcn_v2_0_stop(struct amdgpu_vcn_inst *vinst)
 	return 0;
 }
 
-static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,
-				int inst_idx, struct dpg_pause_state *new_state)
+static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	struct amdgpu_ring *ring;
 	uint32_t reg_data = 0;
 	int ret_code;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 69cf42a4a3f18..d5921a954948e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -100,8 +100,8 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 					       int i);
 static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state);
-static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,
-				int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state);
 static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
 static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev);
 
@@ -1506,9 +1506,11 @@ static int vcn_v2_5_stop(struct amdgpu_vcn_inst *vinst)
 	return 0;
 }
 
-static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,
-				int inst_idx, struct dpg_pause_state *new_state)
+static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	struct amdgpu_ring *ring;
 	uint32_t reg_data = 0;
 	int ret_code = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index f6f4f04d74339..2a17a7e108001 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -110,8 +110,8 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 					       int i);
 static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state);
-static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
-			int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state);
 
 static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring);
 static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
@@ -1581,7 +1581,7 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
-	vcn_v3_0_pause_dpg_mode(adev, inst_idx, &state);
+	vcn_v3_0_pause_dpg_mode(vinst, &state);
 
 	/* Wait for power status to be 1 */
 	SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS, 1,
@@ -1680,9 +1680,11 @@ static int vcn_v3_0_stop(struct amdgpu_vcn_inst *vinst)
 	return 0;
 }
 
-static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
-		   int inst_idx, struct dpg_pause_state *new_state)
+static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	volatile struct amdgpu_fw_shared *fw_shared;
 	struct amdgpu_ring *ring;
 	uint32_t reg_data = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 3d70e2cc81982..2ad217470c8c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -101,8 +101,8 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 					       int i);
 static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state);
-static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev,
-        int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state);
 static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev);
 
@@ -1565,7 +1565,7 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
-	vcn_v4_0_pause_dpg_mode(adev, inst_idx, &state);
+	vcn_v4_0_pause_dpg_mode(vinst, &state);
 	/* Wait for power status to be 1 */
 	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
 		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
@@ -1671,15 +1671,16 @@ static int vcn_v4_0_stop(struct amdgpu_vcn_inst *vinst)
 /**
  * vcn_v4_0_pause_dpg_mode - VCN pause with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @new_state: pause state
  *
  * Pause dpg mode for VCN block
  */
-static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
-      struct dpg_pause_state *new_state)
+static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				   struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 	int ret_code;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index a3fbfaac76603..ae7733c0d032e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -92,8 +92,8 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i);
 static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
-static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev,
-		int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     struct dpg_pause_state *new_state);
 static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
 static void vcn_v4_0_3_set_ras_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev,
@@ -1449,14 +1449,13 @@ static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst)
 /**
  * vcn_v4_0_3_pause_dpg_mode - VCN pause with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @new_state: pause state
  *
  * Pause dpg mode for VCN block
  */
-static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
-				struct dpg_pause_state *new_state)
+static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     struct dpg_pause_state *new_state)
 {
 
 	return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 295f39b2222d5..a00c74d287a69 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -100,8 +100,8 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i);
 static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
-static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev,
-		int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     struct dpg_pause_state *new_state);
 static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
 
 /**
@@ -1321,15 +1321,16 @@ static int vcn_v4_0_5_stop(struct amdgpu_vcn_inst *vinst)
 /**
  * vcn_v4_0_5_pause_dpg_mode - VCN pause with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @new_state: pause state
  *
  * Pause dpg mode for VCN block
  */
-static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
-		struct dpg_pause_state *new_state)
+static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 	int ret_code;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index a71960d899e38..91b57b86dc58a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -83,8 +83,8 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 						 int i);
 static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
-static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev,
-		int inst_idx, struct dpg_pause_state *new_state);
+static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     struct dpg_pause_state *new_state);
 static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
 
 /**
@@ -961,7 +961,7 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
 	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
 	uint32_t tmp;
 
-	vcn_v5_0_0_pause_dpg_mode(adev, inst_idx, &state);
+	vcn_v5_0_0_pause_dpg_mode(vinst, &state);
 
 	/* Wait for power status to be 1 */
 	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
@@ -1064,15 +1064,16 @@ static int vcn_v5_0_0_stop(struct amdgpu_vcn_inst *vinst)
 /**
  * vcn_v5_0_0_pause_dpg_mode - VCN pause with dpg mode
  *
- * @adev: amdgpu_device pointer
- * @inst_idx: instance number index
+ * @vinst: VCN instance
  * @new_state: pause state
  *
  * Pause dpg mode for VCN block
  */
-static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
-	struct dpg_pause_state *new_state)
+static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
+				     struct dpg_pause_state *new_state)
 {
+	struct amdgpu_device *adev = vinst->adev;
+	int inst_idx = vinst->inst;
 	uint32_t reg_data = 0;
 	int ret_code;
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 22/44] drm/amdgpu/vcn: add new per instance callback for powergating
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (20 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 21/44] drm/amdgpu/vcn: adjust pause_dpg_mode function signature Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 13:40   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 23/44] drm/amdgpu/vcn1.0: add set_pg_state callback Alex Deucher
                   ` (21 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

This is per instance so add a new function pointer for it.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 8d34e3814ab19..508fa022df78c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -329,6 +329,8 @@ struct amdgpu_vcn_inst {
 	struct mutex		vcn1_jpeg1_workaround;
 	int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst,
 			      struct dpg_pause_state *new_state);
+	int (*set_pg_state)(struct amdgpu_vcn_inst *vinst,
+			    enum amd_powergating_state state);
 	bool using_unified_queue;
 };
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 23/44] drm/amdgpu/vcn1.0: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (21 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 22/44] drm/amdgpu/vcn: add new per instance callback for powergating Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 13:46   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 24/44] drm/amdgpu/vcn2.0: " Alex Deucher
                   ` (20 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 32 ++++++++++++++++++---------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 3d56660fd90a9..fdb954c7377eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -85,6 +85,8 @@ static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst);
 static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state);
 static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 				enum amd_powergating_state state);
 static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -106,6 +108,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 
 	adev->vcn.inst[0].num_enc_rings = 2;
+	adev->vcn.inst[0].set_pg_state = vcn_v1_0_set_pg_state;
 
 	vcn_v1_0_set_dec_ring_funcs(adev);
 	vcn_v1_0_set_enc_ring_funcs(adev);
@@ -276,13 +279,14 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block)
 static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
 
-	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
+	cancel_delayed_work_sync(&vinst->idle_work);
 
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-		(adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
-		 RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
-		vcn_v1_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+	    (vinst->cur_state != AMD_PG_STATE_GATE &&
+	     RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
+		vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 	}
 
 	return 0;
@@ -1818,8 +1822,8 @@ static void vcn_v1_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t coun
 	}
 }
 
-static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
+static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state)
 {
 	/* This doesn't actually powergate the VCN block.
 	 * That's done in the dpm code via the SMC.  This
@@ -1829,10 +1833,8 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	 * the smc and the hw blocks
 	 */
 	int ret;
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
 
-	if (state == adev->vcn.inst[0].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1841,10 +1843,20 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 		ret = vcn_v1_0_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[0].cur_state = state;
+		vinst->cur_state = state;
+
 	return ret;
 }
 
+static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
+					  enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
+
+	return vinst->set_pg_state(vinst, state);
+}
+
 static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 {
 	struct amdgpu_vcn_inst *vcn_inst =
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 24/44] drm/amdgpu/vcn2.0: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (22 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 23/44] drm/amdgpu/vcn1.0: add set_pg_state callback Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 25/44] drm/amdgpu/vcn2.5: " Alex Deucher
                   ` (19 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 35 ++++++++++++++++++---------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index e4305687749a8..ecbf0dd0b6603 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -92,6 +92,8 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_0[] = {
 static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state);
 static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 				enum amd_powergating_state state);
 static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -114,6 +116,7 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
 	else
 		adev->vcn.inst[0].num_enc_rings = 2;
 
+	adev->vcn.inst->set_pg_state = vcn_v2_0_set_pg_state;
 	vcn_v2_0_set_dec_ring_funcs(adev);
 	vcn_v2_0_set_enc_ring_funcs(adev);
 	vcn_v2_0_set_irq_funcs(adev);
@@ -312,13 +315,14 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
 static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
 
-	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
+	cancel_delayed_work_sync(&vinst->idle_work);
 
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-	    (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
+	    (vinst->cur_state != AMD_PG_STATE_GATE &&
 	     RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
-		vcn_v2_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+		vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 
 	return 0;
 }
@@ -1810,8 +1814,8 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
 }
 
 
-static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
+static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state)
 {
 	/* This doesn't actually powergate the VCN block.
 	 * That's done in the dpm code via the SMC.  This
@@ -1821,27 +1825,36 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	 * the smc and the hw blocks
 	 */
 	int ret;
-	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_device *adev = vinst->adev;
 
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.inst[0].cur_state = AMD_PG_STATE_UNGATE;
+		vinst->cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.inst[0].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
-		ret = vcn_v2_0_stop(adev->vcn.inst);
+		ret = vcn_v2_0_stop(vinst);
 	else
-		ret = vcn_v2_0_start(adev->vcn.inst);
+		ret = vcn_v2_0_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[0].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
 
+static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
+					  enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
+
+	return vinst->set_pg_state(vinst, state);
+}
+
 static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev,
 				struct amdgpu_mm_table *table)
 {
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 25/44] drm/amdgpu/vcn2.5: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (23 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 24/44] drm/amdgpu/vcn2.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 26/44] drm/amdgpu/vcn3.0: " Alex Deucher
                   ` (18 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 37 +++++++++++++++------------
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index d5921a954948e..f5889d1bd0d4c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -95,9 +95,8 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_5[] = {
 static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-					       enum amd_powergating_state state,
-					       int i);
+static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state);
 static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state);
 static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -150,6 +149,8 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v2_5_set_ras_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		adev->vcn.inst[i].set_pg_state = vcn_v2_5_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -400,18 +401,20 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+		cancel_delayed_work_sync(&vinst->idle_work);
 
 		if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-		    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+		    (vinst->cur_state != AMD_PG_STATE_GATE &&
 		     RREG32_SOC15(VCN, i, mmUVD_STATUS)))
-			vcn_v2_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
+			vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 
 		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
-			amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
+			amdgpu_irq_put(adev, &vinst->ras_poison_irq, 0);
 	}
 
 	return 0;
@@ -1844,18 +1847,16 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-					       enum amd_powergating_state state,
-					       int i)
+static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+	struct amdgpu_device *adev = vinst->adev;
 	int ret;
 
 	if (amdgpu_sriov_vf(adev))
 		return 0;
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1864,7 +1865,7 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 		ret = vcn_v2_5_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -1875,9 +1876,11 @@ static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		ret |= vcn_v2_5_set_powergating_state_inst(ip_block,
-							   state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 26/44] drm/amdgpu/vcn3.0: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (24 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 25/44] drm/amdgpu/vcn2.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 27/44] drm/amdgpu/vcn4.0: " Alex Deucher
                   ` (17 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 39 ++++++++++++++-------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 2a17a7e108001..353aab5565702 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -105,9 +105,8 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev);
 static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-					       enum amd_powergating_state state,
-					       int i);
+static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state);
 static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state);
 static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -155,6 +154,8 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v3_0_set_irq_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+		adev->vcn.inst[i].set_pg_state = vcn_v3_0_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -440,18 +441,18 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+		cancel_delayed_work_sync(&vinst->idle_work);
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			    (vinst->cur_state != AMD_PG_STATE_GATE &&
 			     RREG32_SOC15(VCN, i, mmUVD_STATUS))) {
-				vcn_v3_0_set_powergating_state_inst(ip_block,
-								    AMD_PG_STATE_GATE,
-								    i);
+				vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 			}
 		}
 	}
@@ -2200,12 +2201,10 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-					       enum amd_powergating_state state,
-					       int i)
+static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+	struct amdgpu_device *adev = vinst->adev;
 	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
@@ -2213,11 +2212,11 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 	 * guest should avoid touching CGC and PG
 	 */
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
+		vinst->cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -2226,7 +2225,7 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 		ret = vcn_v3_0_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -2237,9 +2236,11 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		ret |= vcn_v3_0_set_powergating_state_inst(ip_block,
-							   state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 27/44] drm/amdgpu/vcn4.0: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (25 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 26/44] drm/amdgpu/vcn3.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 28/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
                   ` (16 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 38 +++++++++++++++------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 2ad217470c8c6..790b533605849 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -96,9 +96,8 @@ static int amdgpu_ih_clientid_vcns[] = {
 static int vcn_v4_0_start_sriov(struct amdgpu_device *adev);
 static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-					       enum amd_powergating_state state,
-					       int i);
+static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state);
 static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					  enum amd_powergating_state state);
 static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -138,6 +137,8 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v4_0_set_ras_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		adev->vcn.inst[i].set_pg_state = vcn_v4_0_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -379,20 +380,22 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+		cancel_delayed_work_sync(&vinst->idle_work);
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-				(adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			    (vinst->cur_state != AMD_PG_STATE_GATE &&
 				 RREG32_SOC15(VCN, i, regUVD_STATUS))) {
-				vcn_v4_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
+				vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 			}
 		}
 		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
-			amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
+			amdgpu_irq_put(adev, &vinst->ras_poison_irq, 0);
 	}
 
 	return 0;
@@ -2077,12 +2080,10 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-					       enum amd_powergating_state state,
-					       int i)
+static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				 enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+	struct amdgpu_device *adev = vinst->adev;
 	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
@@ -2090,11 +2091,11 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 	 * guest should avoid touching CGC and PG
 	 */
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
+		vinst->cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -2103,7 +2104,7 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
 		ret = vcn_v4_0_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -2122,8 +2123,11 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		ret |= vcn_v4_0_set_powergating_state_inst(ip_block, state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 28/44] drm/amdgpu/vcn4.0.3: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (26 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 27/44] drm/amdgpu/vcn4.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 29/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
                   ` (15 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 36 ++++++++++++++-----------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index ae7733c0d032e..219e95c1e35ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -87,9 +87,8 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_3[] = {
 static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev);
 static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i);
+static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state);
 static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
 static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -125,6 +124,8 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v4_0_3_set_ras_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		adev->vcn.inst[i].set_pg_state = vcn_v4_0_3_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -371,10 +372,12 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		cancel_delayed_work_sync(&vinst->idle_work);
 
-		if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE)
-			vcn_v4_0_3_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
+		if (vinst->cur_state != AMD_PG_STATE_GATE)
+			vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 	}
 
 	return 0;
@@ -1687,12 +1690,10 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i)
+static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+	struct amdgpu_device *adev = vinst->adev;
 	int ret = 0;
 
 	/* for SRIOV, guest should not control VCN Power-gating
@@ -1700,11 +1701,11 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 	 * guest should avoid touching CGC and PG
 	 */
 	if (amdgpu_sriov_vf(adev)) {
-		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
+		vinst->cur_state = AMD_PG_STATE_UNGATE;
 		return 0;
 	}
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1713,7 +1714,7 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 		ret = vcn_v4_0_3_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -1732,8 +1733,11 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		vcn_v4_0_3_set_powergating_state_inst(ip_block, state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 29/44] drm/amdgpu/vcn4.0.5: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (27 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 28/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 30/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
                   ` (14 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 33 ++++++++++++++-----------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index a00c74d287a69..0ac41249755db 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -95,9 +95,8 @@ static int amdgpu_ih_clientid_vcns[] = {
 
 static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i);
+static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state);
 static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
 static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -124,6 +123,8 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v4_0_5_set_irq_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		adev->vcn.inst[i].set_pg_state = vcn_v4_0_5_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -317,16 +318,18 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+		cancel_delayed_work_sync(&vinst->idle_work);
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			    (vinst->cur_state != AMD_PG_STATE_GATE &&
 			     RREG32_SOC15(VCN, i, regUVD_STATUS))) {
-				vcn_v4_0_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
+				vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 			}
 		}
 	}
@@ -1558,15 +1561,12 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i)
+static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1575,7 +1575,7 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 		ret = vcn_v4_0_5_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -1594,8 +1594,11 @@ static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		vcn_v4_0_5_set_powergating_state_inst(ip_block, state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 30/44] drm/amdgpu/vcn5.0.0: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (28 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 29/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 31/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
                   ` (13 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 33 ++++++++++++++-----------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 91b57b86dc58a..9588153079675 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -78,9 +78,8 @@ static int amdgpu_ih_clientid_vcns[] = {
 
 static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i);
+static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state);
 static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
 static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
@@ -108,6 +107,8 @@ static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v5_0_0_set_irq_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		adev->vcn.inst[i].set_pg_state = vcn_v5_0_0_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -299,16 +300,18 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
 	int i;
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
 
-		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
+		cancel_delayed_work_sync(&vinst->idle_work);
 
 		if (!amdgpu_sriov_vf(adev)) {
 			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
+			    (vinst->cur_state != AMD_PG_STATE_GATE &&
 			     RREG32_SOC15(VCN, i, regUVD_STATUS))) {
-				vcn_v5_0_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
+				vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
 			}
 		}
 	}
@@ -1297,15 +1300,12 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i)
+static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1314,7 +1314,7 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 		ret = vcn_v5_0_0_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -1333,8 +1333,11 @@ static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		vcn_v5_0_0_set_powergating_state_inst(ip_block, state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 31/44] drm/amdgpu/vcn5.0.1: add set_pg_state callback
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (29 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 30/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 32/44] drm/amdgpu/vcn: use per instance callbacks for idle work handler Alex Deucher
                   ` (12 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Rework the code as a vcn instance callback.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 8eccb45b04d2c..5ef267fde190c 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -40,9 +40,8 @@
 
 static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev);
-static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i);
+static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state);
 static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
 					    enum amd_powergating_state state);
 static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -68,6 +67,8 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
 	vcn_v5_0_1_set_irq_funcs(adev);
 
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		adev->vcn.inst[i].set_pg_state = vcn_v5_0_1_set_pg_state;
+
 		r = amdgpu_vcn_early_init(adev, i);
 		if (r)
 			return r;
@@ -1027,15 +1028,12 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 	return 0;
 }
 
-static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
-						 enum amd_powergating_state state,
-						 int i)
+static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst,
+				   enum amd_powergating_state state)
 {
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
 	int ret = 0;
 
-	if (state == adev->vcn.inst[i].cur_state)
+	if (state == vinst->cur_state)
 		return 0;
 
 	if (state == AMD_PG_STATE_GATE)
@@ -1044,7 +1042,7 @@ static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
 		ret = vcn_v5_0_1_start(vinst);
 
 	if (!ret)
-		adev->vcn.inst[i].cur_state = state;
+		vinst->cur_state = state;
 
 	return ret;
 }
@@ -1063,8 +1061,11 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
 	struct amdgpu_device *adev = ip_block->adev;
 	int ret = 0, i;
 
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
-		vcn_v5_0_1_set_powergating_state_inst(ip_block, state, i);
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
 
 	return ret;
 }
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 32/44] drm/amdgpu/vcn: use per instance callbacks for idle work handler
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (30 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 31/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 13:53   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 33/44] drm/amdgpu/vcn: add a generic helper for set_power_gating_state Alex Deucher
                   ` (11 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Use the vcn instance power gating callbacks rather than
the IP powergating callback.  This limits power gating to
only the instance in use rather than all of the instances.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 27 ++++++++++++-------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index a2250747a7c81..81bfd8a9d8268 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -424,8 +424,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 	fences += fence[i];
 
 	if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) {
-		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
-						       AMD_PG_STATE_GATE);
+		vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE);
 		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
 						    false);
 		if (r)
@@ -438,45 +437,45 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 {
 	struct amdgpu_device *adev = ring->adev;
+	struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me];
 	int r = 0;
 
-	atomic_inc(&adev->vcn.inst[ring->me].total_submission_cnt);
+	atomic_inc(&vcn_inst->total_submission_cnt);
 
-	if (!cancel_delayed_work_sync(&adev->vcn.inst[ring->me].idle_work)) {
+	if (!cancel_delayed_work_sync(&vcn_inst->idle_work)) {
 		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
 				true);
 		if (r)
 			dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
 	}
 
-	mutex_lock(&adev->vcn.inst[ring->me].vcn_pg_lock);
-	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
-					       AMD_PG_STATE_UNGATE);
+	mutex_lock(&vcn_inst->vcn_pg_lock);
+	vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE);
 
 	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
-	    !adev->vcn.inst[ring->me].using_unified_queue) {
+	    !vcn_inst->using_unified_queue) {
 		struct dpg_pause_state new_state;
 
 		if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
-			atomic_inc(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
+			atomic_inc(&vcn_inst->dpg_enc_submission_cnt);
 			new_state.fw_based = VCN_DPG_STATE__PAUSE;
 		} else {
 			unsigned int fences = 0;
 			unsigned int i;
 
-			for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i)
-				fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
+			for (i = 0; i < vcn_inst->num_enc_rings; ++i)
+				fences += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[i]);
 
-			if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
+			if (fences || atomic_read(&vcn_inst->dpg_enc_submission_cnt))
 				new_state.fw_based = VCN_DPG_STATE__PAUSE;
 			else
 				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 		}
 
-		adev->vcn.inst[ring->me].pause_dpg_mode(&adev->vcn.inst[ring->me], &new_state);
+		vcn_inst->pause_dpg_mode(vcn_inst, &new_state);
 	}
-	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
+	mutex_unlock(&vcn_inst->vcn_pg_lock);
 }
 
 void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 33/44] drm/amdgpu/vcn: add a generic helper for set_power_gating_state
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (31 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 32/44] drm/amdgpu/vcn: use per instance callbacks for idle work handler Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 13:54   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 34/44] drm/amdgpu/vcn1.0: use generic set_power_gating_state helper Alex Deucher
                   ` (10 subsequent siblings)
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

It's common for all VCN variants.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 23 +++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  3 +++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 81bfd8a9d8268..e4ef0fb970b29 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -1397,3 +1397,26 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
 			    &amdgpu_debugfs_vcn_sched_mask_fops);
 #endif
 }
+
+/**
+ * vcn_set_powergating_state - set VCN block powergating state
+ *
+ * @ip_block: amdgpu_ip_block pointer
+ * @state: power gating state
+ *
+ * Set VCN block powergating state
+ */
+int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
+			      enum amd_powergating_state state)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0, i;
+
+	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
+
+		ret |= vinst->set_pg_state(vinst, state);
+	}
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 508fa022df78c..a023f46ec904a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -546,4 +546,7 @@ int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev);
 void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev);
 void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev);
 
+int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
+			      enum amd_powergating_state state);
+
 #endif
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 34/44] drm/amdgpu/vcn1.0: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (32 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 33/44] drm/amdgpu/vcn: add a generic helper for set_power_gating_state Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 35/44] drm/amdgpu/vcn2.0: " Alex Deucher
                   ` (9 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index fdb954c7377eb..f3d41ddd0a2bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -87,8 +87,6 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				 enum amd_powergating_state state);
-static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-				enum amd_powergating_state state);
 static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				   struct dpg_pause_state *new_state);
 
@@ -1848,15 +1846,6 @@ static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
-
-	return vinst->set_pg_state(vinst, state);
-}
-
 static void vcn_v1_0_idle_work_handler(struct work_struct *work)
 {
 	struct amdgpu_vcn_inst *vcn_inst =
@@ -2029,7 +2018,7 @@ static const struct amd_ip_funcs vcn_v1_0_ip_funcs = {
 	.is_idle = vcn_v1_0_is_idle,
 	.wait_for_idle = vcn_v1_0_wait_for_idle,
 	.set_clockgating_state = vcn_v1_0_set_clockgating_state,
-	.set_powergating_state = vcn_v1_0_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v1_0_dump_ip_state,
 	.print_ip_state = vcn_v1_0_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 35/44] drm/amdgpu/vcn2.0: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (33 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 34/44] drm/amdgpu/vcn1.0: use generic set_power_gating_state helper Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 36/44] drm/amdgpu/vcn2.5: " Alex Deucher
                   ` (8 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index ecbf0dd0b6603..5409a8779457f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -94,8 +94,6 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				 enum amd_powergating_state state);
-static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-				enum amd_powergating_state state);
 static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				   struct dpg_pause_state *new_state);
 static int vcn_v2_0_start_sriov(struct amdgpu_device *adev);
@@ -1846,15 +1844,6 @@ static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
-
-	return vinst->set_pg_state(vinst, state);
-}
-
 static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev,
 				struct amdgpu_mm_table *table)
 {
@@ -2132,7 +2121,7 @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = {
 	.is_idle = vcn_v2_0_is_idle,
 	.wait_for_idle = vcn_v2_0_wait_for_idle,
 	.set_clockgating_state = vcn_v2_0_set_clockgating_state,
-	.set_powergating_state = vcn_v2_0_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v2_0_dump_ip_state,
 	.print_ip_state = vcn_v2_0_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 36/44] drm/amdgpu/vcn2.5: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (34 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 35/44] drm/amdgpu/vcn2.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 37/44] drm/amdgpu/vcn3.0: " Alex Deucher
                   ` (7 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index f5889d1bd0d4c..9229b6dadbe32 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -97,8 +97,6 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				 enum amd_powergating_state state);
-static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state);
 static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				   struct dpg_pause_state *new_state);
 static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
@@ -1870,21 +1868,6 @@ static int vcn_v2_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 static int vcn_v2_5_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -2037,7 +2020,7 @@ static const struct amd_ip_funcs vcn_v2_5_ip_funcs = {
 	.is_idle = vcn_v2_5_is_idle,
 	.wait_for_idle = vcn_v2_5_wait_for_idle,
 	.set_clockgating_state = vcn_v2_5_set_clockgating_state,
-	.set_powergating_state = vcn_v2_5_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v2_5_dump_ip_state,
 	.print_ip_state = vcn_v2_5_print_ip_state,
 };
@@ -2054,7 +2037,7 @@ static const struct amd_ip_funcs vcn_v2_6_ip_funcs = {
         .is_idle = vcn_v2_5_is_idle,
         .wait_for_idle = vcn_v2_5_wait_for_idle,
         .set_clockgating_state = vcn_v2_5_set_clockgating_state,
-        .set_powergating_state = vcn_v2_5_set_powergating_state,
+        .set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v2_5_dump_ip_state,
 	.print_ip_state = vcn_v2_5_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 37/44] drm/amdgpu/vcn3.0: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (35 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 36/44] drm/amdgpu/vcn2.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 38/44] drm/amdgpu/vcn4.0: " Alex Deucher
                   ` (6 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 19 +------------------
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 353aab5565702..2fb3eb3b007d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -107,8 +107,6 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				 enum amd_powergating_state state);
-static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state);
 static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				   struct dpg_pause_state *new_state);
 
@@ -2230,21 +2228,6 @@ static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 static int vcn_v3_0_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -2383,7 +2366,7 @@ static const struct amd_ip_funcs vcn_v3_0_ip_funcs = {
 	.is_idle = vcn_v3_0_is_idle,
 	.wait_for_idle = vcn_v3_0_wait_for_idle,
 	.set_clockgating_state = vcn_v3_0_set_clockgating_state,
-	.set_powergating_state = vcn_v3_0_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v3_0_dump_ip_state,
 	.print_ip_state = vcn_v3_0_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 38/44] drm/amdgpu/vcn4.0: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (36 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 37/44] drm/amdgpu/vcn3.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 39/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
                   ` (5 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 27 +--------------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 790b533605849..fe93d65a7684d 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -98,8 +98,6 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				 enum amd_powergating_state state);
-static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state);
 static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				   struct dpg_pause_state *new_state);
 static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -2109,29 +2107,6 @@ static int vcn_v4_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-/**
- * vcn_v4_0_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: amdgpu_ip_block pointer
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					  enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 /**
  * vcn_v4_0_set_ras_interrupt_state - set VCN block RAS interrupt state
  *
@@ -2300,7 +2275,7 @@ static const struct amd_ip_funcs vcn_v4_0_ip_funcs = {
 	.is_idle = vcn_v4_0_is_idle,
 	.wait_for_idle = vcn_v4_0_wait_for_idle,
 	.set_clockgating_state = vcn_v4_0_set_clockgating_state,
-	.set_powergating_state = vcn_v4_0_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v4_0_dump_ip_state,
 	.print_ip_state = vcn_v4_0_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 39/44] drm/amdgpu/vcn4.0.3: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (37 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 38/44] drm/amdgpu/vcn4.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 40/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
                   ` (4 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 27 +------------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 219e95c1e35ee..7f4120b372df1 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -89,8 +89,6 @@ static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				   enum amd_powergating_state state);
-static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state);
 static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				     struct dpg_pause_state *new_state);
 static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -1719,29 +1717,6 @@ static int vcn_v4_0_3_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-/**
- * vcn_v4_0_3_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: amdgpu_ip_block pointer
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 /**
  * vcn_v4_0_3_set_interrupt_state - set VCN block interrupt state
  *
@@ -1899,7 +1874,7 @@ static const struct amd_ip_funcs vcn_v4_0_3_ip_funcs = {
 	.is_idle = vcn_v4_0_3_is_idle,
 	.wait_for_idle = vcn_v4_0_3_wait_for_idle,
 	.set_clockgating_state = vcn_v4_0_3_set_clockgating_state,
-	.set_powergating_state = vcn_v4_0_3_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v4_0_3_dump_ip_state,
 	.print_ip_state = vcn_v4_0_3_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 40/44] drm/amdgpu/vcn4.0.5: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (38 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 39/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 41/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
                   ` (3 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 27 +------------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 0ac41249755db..0d6a97c4bf8f6 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -97,8 +97,6 @@ static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				   enum amd_powergating_state state);
-static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state);
 static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				     struct dpg_pause_state *new_state);
 static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -1580,29 +1578,6 @@ static int vcn_v4_0_5_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-/**
- * vcn_v4_0_5_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: amdgpu_ip_block pointer
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 /**
  * vcn_v4_0_5_process_interrupt - process VCN block interrupt
  *
@@ -1744,7 +1719,7 @@ static const struct amd_ip_funcs vcn_v4_0_5_ip_funcs = {
 	.is_idle = vcn_v4_0_5_is_idle,
 	.wait_for_idle = vcn_v4_0_5_wait_for_idle,
 	.set_clockgating_state = vcn_v4_0_5_set_clockgating_state,
-	.set_powergating_state = vcn_v4_0_5_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v4_0_5_dump_ip_state,
 	.print_ip_state = vcn_v4_0_5_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 41/44] drm/amdgpu/vcn5.0.0: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (39 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 40/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 42/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
                   ` (2 subsequent siblings)
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 27 +------------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 9588153079675..4a2854238c618 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -80,8 +80,6 @@ static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				   enum amd_powergating_state state);
-static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state);
 static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
 				     struct dpg_pause_state *new_state);
 static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
@@ -1319,29 +1317,6 @@ static int vcn_v5_0_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-/**
- * vcn_v5_0_0_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: amdgpu_ip_block pointer
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 /**
  * vcn_v5_0_0_process_interrupt - process VCN block interrupt
  *
@@ -1483,7 +1458,7 @@ static const struct amd_ip_funcs vcn_v5_0_0_ip_funcs = {
 	.is_idle = vcn_v5_0_0_is_idle,
 	.wait_for_idle = vcn_v5_0_0_wait_for_idle,
 	.set_clockgating_state = vcn_v5_0_0_set_clockgating_state,
-	.set_powergating_state = vcn_v5_0_0_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v5_0_0_dump_ip_state,
 	.print_ip_state = vcn_v5_0_0_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 42/44] drm/amdgpu/vcn5.0.1: use generic set_power_gating_state helper
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (40 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 41/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-01-31 16:57 ` [PATCH 43/44] drm/amdgpu/vcn: optimize firmware storage Alex Deucher
  2025-01-31 16:57 ` [PATCH 44/44] drm/amdgpu/vcn: use dev_info() for firmware information Alex Deucher
  43 siblings, 0 replies; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

No need for an IP specific version.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 27 +------------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
index 5ef267fde190c..b7e9d4e909d72 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
@@ -42,8 +42,6 @@ static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev);
 static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst,
 				   enum amd_powergating_state state);
-static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state);
 static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
 
 /**
@@ -1047,29 +1045,6 @@ static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst,
 	return ret;
 }
 
-/**
- * vcn_v5_0_1_set_powergating_state - set VCN block powergating state
- *
- * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
- * @state: power gating state
- *
- * Set VCN block powergating state
- */
-static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
-					    enum amd_powergating_state state)
-{
-	struct amdgpu_device *adev = ip_block->adev;
-	int ret = 0, i;
-
-	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
-		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
-
-		ret |= vinst->set_pg_state(vinst, state);
-	}
-
-	return ret;
-}
-
 /**
  * vcn_v5_0_1_process_interrupt - process VCN block interrupt
  *
@@ -1148,7 +1123,7 @@ static const struct amd_ip_funcs vcn_v5_0_1_ip_funcs = {
 	.soft_reset = NULL,
 	.post_soft_reset = NULL,
 	.set_clockgating_state = vcn_v5_0_1_set_clockgating_state,
-	.set_powergating_state = vcn_v5_0_1_set_powergating_state,
+	.set_powergating_state = vcn_set_powergating_state,
 	.dump_ip_state = vcn_v5_0_0_dump_ip_state,
 	.print_ip_state = vcn_v5_0_0_print_ip_state,
 };
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 43/44] drm/amdgpu/vcn: optimize firmware storage
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (41 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 42/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 14:48   ` Boyuan Zhang
  2025-01-31 16:57 ` [PATCH 44/44] drm/amdgpu/vcn: use dev_info() for firmware information Alex Deucher
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

If each instance uses the same fw image, only store one
copy in the driver.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 30 +++++++++++++++++--------
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  4 +++-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  3 +++
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index e4ef0fb970b29..edbcb11c382a2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -102,18 +102,25 @@ int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i)
 	adev->vcn.inst[i].inst = i;
 	amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
 
-	if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
+	if (i != 0 && adev->vcn.per_inst_fw) {
 		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
 					 AMDGPU_UCODE_REQUIRED,
 					 "amdgpu/%s_%d.bin", ucode_prefix, i);
-	else
-		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
-					 AMDGPU_UCODE_REQUIRED,
-					 "amdgpu/%s.bin", ucode_prefix);
-	if (r) {
-		amdgpu_ucode_release(&adev->vcn.inst[i].fw);
-		return r;
+		if (r)
+			amdgpu_ucode_release(&adev->vcn.inst[i].fw);
+	} else {
+		if (!adev->vcn.inst[0].fw) {
+			r = amdgpu_ucode_request(adev, &adev->vcn.inst[0].fw,
+						 AMDGPU_UCODE_REQUIRED,
+						 "amdgpu/%s.bin", ucode_prefix);
+			if (r)
+				amdgpu_ucode_release(&adev->vcn.inst[0].fw);
+		} else {
+			r = 0;
+		}
+		adev->vcn.inst[i].fw = adev->vcn.inst[0].fw;
 	}
+
 	return r;
 }
 
@@ -270,7 +277,12 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i)
 	for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
 		amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]);
 
-	amdgpu_ucode_release(&adev->vcn.inst[i].fw);
+	if (adev->vcn.per_inst_fw) {
+		amdgpu_ucode_release(&adev->vcn.inst[i].fw);
+	} else {
+		amdgpu_ucode_release(&adev->vcn.inst[0].fw);
+		adev->vcn.inst[i].fw = NULL;
+	}
 	mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock);
 	mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index a023f46ec904a..26c9c2d90f455 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -339,7 +339,6 @@ struct amdgpu_vcn_ras {
 };
 
 struct amdgpu_vcn {
-	unsigned		fw_version;
 	uint8_t	num_vcn_inst;
 	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
 
@@ -356,6 +355,9 @@ struct amdgpu_vcn {
 
 	uint32_t		supported_reset;
 	uint32_t		caps;
+
+	bool			per_inst_fw;
+	unsigned		fw_version;
 };
 
 struct amdgpu_fw_shared_rb_ptrs_struct {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 0d6a97c4bf8f6..347a2c40c32d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -114,6 +114,9 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
 	struct amdgpu_device *adev = ip_block->adev;
 	int i, r;
 
+	if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6))
+		adev->vcn.per_inst_fw = true;
+
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
 		/* re-use enc ring as unified ring */
 		adev->vcn.inst[i].num_enc_rings = 1;
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 44/44] drm/amdgpu/vcn: use dev_info() for firmware information
  2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
                   ` (42 preceding siblings ...)
  2025-01-31 16:57 ` [PATCH 43/44] drm/amdgpu/vcn: optimize firmware storage Alex Deucher
@ 2025-01-31 16:57 ` Alex Deucher
  2025-02-06 14:49   ` Boyuan Zhang
  43 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-01-31 16:57 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

To properly handle multiple GPUs.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index edbcb11c382a2..8d8b39e6d197a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -182,7 +182,8 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
 		enc_major = fw_check;
 		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
 		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
-		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
+		dev_info(adev->dev,
+			 "Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
 			 enc_major, enc_minor, dec_ver, vep, fw_rev);
 	} else {
 		unsigned int version_major, version_minor, family_id;
@@ -190,7 +191,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
 		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
 		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
 		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
-		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
+		dev_info(adev->dev, "Found VCN firmware Version: %u.%u Family ID: %u\n",
 			 version_major, version_minor, family_id);
 	}
 
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances
  2025-01-31 16:56 ` [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances Alex Deucher
@ 2025-02-04 15:35   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:35 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 37917 bytes --]


On 2025-01-31 11:56, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 841 +++++++++++++-------------
>   1 file changed, 411 insertions(+), 430 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index b518202955cad..b9be304aa294b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -452,64 +452,62 @@ static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block)
>    * vcn_v2_5_mc_resume - memory controller programming
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to resume
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v2_5_mc_resume(struct amdgpu_device *adev)
> +static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i)
>   {
>   	uint32_t size;
>   	uint32_t offset;
> -	int i;
> -
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
>   
> -		size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[i].fw->size + 4);
> -		/* cache window 0: fw */
> -		if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
> -			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
> -				(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo));
> -			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
> -				(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi));
> -			WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0, 0);
> -			offset = 0;
> -		} else {
> -			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
> -				lower_32_bits(adev->vcn.inst[i].gpu_addr));
> -			WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
> -				upper_32_bits(adev->vcn.inst[i].gpu_addr));
> -			offset = size;
> -			WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0,
> -				AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
> -		}
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE0, size);
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return;
>   
> -		/* cache window 1: stack */
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
> -			lower_32_bits(adev->vcn.inst[i].gpu_addr + offset));
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
> -			upper_32_bits(adev->vcn.inst[i].gpu_addr + offset));
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET1, 0);
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
> -
> -		/* cache window 2: context */
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
> -			lower_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
> -			upper_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET2, 0);
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
> -
> -		/* non-cache window */
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
> -			lower_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
> -			upper_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_OFFSET0, 0);
> -		WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_SIZE0,
> -			AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
> +	size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[i].fw->size + 4);
> +	/* cache window 0: fw */
> +	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
> +		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
> +			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo));
> +		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
> +			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi));
> +		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0, 0);
> +		offset = 0;
> +	} else {
> +		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
> +			     lower_32_bits(adev->vcn.inst[i].gpu_addr));
> +		WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
> +			     upper_32_bits(adev->vcn.inst[i].gpu_addr));
> +		offset = size;
> +		WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET0,
> +			     AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
>   	}
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE0, size);
> +
> +	/* cache window 1: stack */
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
> +		     lower_32_bits(adev->vcn.inst[i].gpu_addr + offset));
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
> +		     upper_32_bits(adev->vcn.inst[i].gpu_addr + offset));
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET1, 0);
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
> +
> +	/* cache window 2: context */
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
> +		     lower_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
> +		     upper_32_bits(adev->vcn.inst[i].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_OFFSET2, 0);
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
> +
> +	/* non-cache window */
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
> +		     lower_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
> +		     upper_32_bits(adev->vcn.inst[i].fw_shared.gpu_addr));
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_OFFSET0, 0);
> +	WREG32_SOC15(VCN, i, mmUVD_VCPU_NONCACHE_SIZE0,
> +		     AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
>   }
>   
>   static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> @@ -612,117 +610,115 @@ static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
>    * vcn_v2_5_disable_clock_gating - disable VCN clock gating
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to disable clockgating on
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev)
> +static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i)
>   {
>   	uint32_t data;
> -	int i;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		/* UVD disable CGC */
> -		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> -		if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> -			data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
> -		else
> -			data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
> -		data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
> -		data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
> -		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> -
> -		data = RREG32_SOC15(VCN, i, mmUVD_CGC_GATE);
> -		data &= ~(UVD_CGC_GATE__SYS_MASK
> -			| UVD_CGC_GATE__UDEC_MASK
> -			| UVD_CGC_GATE__MPEG2_MASK
> -			| UVD_CGC_GATE__REGS_MASK
> -			| UVD_CGC_GATE__RBC_MASK
> -			| UVD_CGC_GATE__LMI_MC_MASK
> -			| UVD_CGC_GATE__LMI_UMC_MASK
> -			| UVD_CGC_GATE__IDCT_MASK
> -			| UVD_CGC_GATE__MPRD_MASK
> -			| UVD_CGC_GATE__MPC_MASK
> -			| UVD_CGC_GATE__LBSI_MASK
> -			| UVD_CGC_GATE__LRBBM_MASK
> -			| UVD_CGC_GATE__UDEC_RE_MASK
> -			| UVD_CGC_GATE__UDEC_CM_MASK
> -			| UVD_CGC_GATE__UDEC_IT_MASK
> -			| UVD_CGC_GATE__UDEC_DB_MASK
> -			| UVD_CGC_GATE__UDEC_MP_MASK
> -			| UVD_CGC_GATE__WCB_MASK
> -			| UVD_CGC_GATE__VCPU_MASK
> -			| UVD_CGC_GATE__MMSCH_MASK);
> -
> -		WREG32_SOC15(VCN, i, mmUVD_CGC_GATE, data);
> -
> -		SOC15_WAIT_ON_RREG(VCN, i, mmUVD_CGC_GATE, 0,  0xFFFFFFFF);
> -
> -		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> -		data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_CM_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_IT_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_DB_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_MP_MODE_MASK
> -			| UVD_CGC_CTRL__SYS_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_MODE_MASK
> -			| UVD_CGC_CTRL__MPEG2_MODE_MASK
> -			| UVD_CGC_CTRL__REGS_MODE_MASK
> -			| UVD_CGC_CTRL__RBC_MODE_MASK
> -			| UVD_CGC_CTRL__LMI_MC_MODE_MASK
> -			| UVD_CGC_CTRL__LMI_UMC_MODE_MASK
> -			| UVD_CGC_CTRL__IDCT_MODE_MASK
> -			| UVD_CGC_CTRL__MPRD_MODE_MASK
> -			| UVD_CGC_CTRL__MPC_MODE_MASK
> -			| UVD_CGC_CTRL__LBSI_MODE_MASK
> -			| UVD_CGC_CTRL__LRBBM_MODE_MASK
> -			| UVD_CGC_CTRL__WCB_MODE_MASK
> -			| UVD_CGC_CTRL__VCPU_MODE_MASK
> -			| UVD_CGC_CTRL__MMSCH_MODE_MASK);
> -		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> -
> -		/* turn on */
> -		data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE);
> -		data |= (UVD_SUVD_CGC_GATE__SRE_MASK
> -			| UVD_SUVD_CGC_GATE__SIT_MASK
> -			| UVD_SUVD_CGC_GATE__SMP_MASK
> -			| UVD_SUVD_CGC_GATE__SCM_MASK
> -			| UVD_SUVD_CGC_GATE__SDB_MASK
> -			| UVD_SUVD_CGC_GATE__SRE_H264_MASK
> -			| UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
> -			| UVD_SUVD_CGC_GATE__SIT_H264_MASK
> -			| UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
> -			| UVD_SUVD_CGC_GATE__SCM_H264_MASK
> -			| UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
> -			| UVD_SUVD_CGC_GATE__SDB_H264_MASK
> -			| UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
> -			| UVD_SUVD_CGC_GATE__SCLR_MASK
> -			| UVD_SUVD_CGC_GATE__UVD_SC_MASK
> -			| UVD_SUVD_CGC_GATE__ENT_MASK
> -			| UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
> -			| UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
> -			| UVD_SUVD_CGC_GATE__SITE_MASK
> -			| UVD_SUVD_CGC_GATE__SRE_VP9_MASK
> -			| UVD_SUVD_CGC_GATE__SCM_VP9_MASK
> -			| UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
> -			| UVD_SUVD_CGC_GATE__SDB_VP9_MASK
> -			| UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
> -		WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE, data);
> -
> -		data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
> -		data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return;
> +	/* UVD disable CGC */
> +	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> +	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> +		data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
> +	else
> +		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
> +	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
> +	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
> +	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> +
> +	data = RREG32_SOC15(VCN, i, mmUVD_CGC_GATE);
> +	data &= ~(UVD_CGC_GATE__SYS_MASK
> +		  | UVD_CGC_GATE__UDEC_MASK
> +		  | UVD_CGC_GATE__MPEG2_MASK
> +		  | UVD_CGC_GATE__REGS_MASK
> +		  | UVD_CGC_GATE__RBC_MASK
> +		  | UVD_CGC_GATE__LMI_MC_MASK
> +		  | UVD_CGC_GATE__LMI_UMC_MASK
> +		  | UVD_CGC_GATE__IDCT_MASK
> +		  | UVD_CGC_GATE__MPRD_MASK
> +		  | UVD_CGC_GATE__MPC_MASK
> +		  | UVD_CGC_GATE__LBSI_MASK
> +		  | UVD_CGC_GATE__LRBBM_MASK
> +		  | UVD_CGC_GATE__UDEC_RE_MASK
> +		  | UVD_CGC_GATE__UDEC_CM_MASK
> +		  | UVD_CGC_GATE__UDEC_IT_MASK
> +		  | UVD_CGC_GATE__UDEC_DB_MASK
> +		  | UVD_CGC_GATE__UDEC_MP_MASK
> +		  | UVD_CGC_GATE__WCB_MASK
> +		  | UVD_CGC_GATE__VCPU_MASK
> +		  | UVD_CGC_GATE__MMSCH_MASK);
> +
> +	WREG32_SOC15(VCN, i, mmUVD_CGC_GATE, data);
> +
> +	SOC15_WAIT_ON_RREG(VCN, i, mmUVD_CGC_GATE, 0,  0xFFFFFFFF);
> +
> +	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> +	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
> +		  | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
> +		  | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
> +		  | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
> +		  | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
> +		  | UVD_CGC_CTRL__SYS_MODE_MASK
> +		  | UVD_CGC_CTRL__UDEC_MODE_MASK
> +		  | UVD_CGC_CTRL__MPEG2_MODE_MASK
> +		  | UVD_CGC_CTRL__REGS_MODE_MASK
> +		  | UVD_CGC_CTRL__RBC_MODE_MASK
> +		  | UVD_CGC_CTRL__LMI_MC_MODE_MASK
> +		  | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
> +		  | UVD_CGC_CTRL__IDCT_MODE_MASK
> +		  | UVD_CGC_CTRL__MPRD_MODE_MASK
> +		  | UVD_CGC_CTRL__MPC_MODE_MASK
> +		  | UVD_CGC_CTRL__LBSI_MODE_MASK
> +		  | UVD_CGC_CTRL__LRBBM_MODE_MASK
> +		  | UVD_CGC_CTRL__WCB_MODE_MASK
> +		  | UVD_CGC_CTRL__VCPU_MODE_MASK
> +		  | UVD_CGC_CTRL__MMSCH_MODE_MASK);
> +	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> +
> +	/* turn on */
> +	data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE);
> +	data |= (UVD_SUVD_CGC_GATE__SRE_MASK
> +		 | UVD_SUVD_CGC_GATE__SIT_MASK
> +		 | UVD_SUVD_CGC_GATE__SMP_MASK
> +		 | UVD_SUVD_CGC_GATE__SCM_MASK
> +		 | UVD_SUVD_CGC_GATE__SDB_MASK
> +		 | UVD_SUVD_CGC_GATE__SRE_H264_MASK
> +		 | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
> +		 | UVD_SUVD_CGC_GATE__SIT_H264_MASK
> +		 | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
> +		 | UVD_SUVD_CGC_GATE__SCM_H264_MASK
> +		 | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
> +		 | UVD_SUVD_CGC_GATE__SDB_H264_MASK
> +		 | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
> +		 | UVD_SUVD_CGC_GATE__SCLR_MASK
> +		 | UVD_SUVD_CGC_GATE__UVD_SC_MASK
> +		 | UVD_SUVD_CGC_GATE__ENT_MASK
> +		 | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
> +		 | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
> +		 | UVD_SUVD_CGC_GATE__SITE_MASK
> +		 | UVD_SUVD_CGC_GATE__SRE_VP9_MASK
> +		 | UVD_SUVD_CGC_GATE__SCM_VP9_MASK
> +		 | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
> +		 | UVD_SUVD_CGC_GATE__SDB_VP9_MASK
> +		 | UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
> +	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_GATE, data);
> +
> +	data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
> +	data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
> +		  | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
>   			| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
> -		WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
> -	}
> +		  | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
> +	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
>   static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
> @@ -774,65 +770,63 @@ static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
>   }
>   
>   /**
> - * vcn_v2_5_enable_clock_gating - enable VCN clock gating
> + * vcn_v2_5_enable_clock_gating_inst - enable VCN clock gating
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to enable clockgating on
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev)
> +static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i)
>   {
>   	uint32_t data = 0;
> -	int i;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		/* enable UVD CGC */
> -		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> -		if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> -			data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
> -		else
> -			data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
> -		data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
> -		data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
> -		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> -
> -		data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> -		data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_CM_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_IT_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_DB_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_MP_MODE_MASK
> -			| UVD_CGC_CTRL__SYS_MODE_MASK
> -			| UVD_CGC_CTRL__UDEC_MODE_MASK
> -			| UVD_CGC_CTRL__MPEG2_MODE_MASK
> -			| UVD_CGC_CTRL__REGS_MODE_MASK
> -			| UVD_CGC_CTRL__RBC_MODE_MASK
> -			| UVD_CGC_CTRL__LMI_MC_MODE_MASK
> -			| UVD_CGC_CTRL__LMI_UMC_MODE_MASK
> -			| UVD_CGC_CTRL__IDCT_MODE_MASK
> -			| UVD_CGC_CTRL__MPRD_MODE_MASK
> -			| UVD_CGC_CTRL__MPC_MODE_MASK
> -			| UVD_CGC_CTRL__LBSI_MODE_MASK
> -			| UVD_CGC_CTRL__LRBBM_MODE_MASK
> -			| UVD_CGC_CTRL__WCB_MODE_MASK
> -			| UVD_CGC_CTRL__VCPU_MODE_MASK);
> -		WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> -
> -		data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
> -		data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
> -			| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
> -		WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
> -	}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return;
> +	/* enable UVD CGC */
> +	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> +	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> +		data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
> +	else
> +		data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
> +	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
> +	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
> +	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> +
> +	data = RREG32_SOC15(VCN, i, mmUVD_CGC_CTRL);
> +	data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
> +		 | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
> +		 | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
> +		 | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
> +		 | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
> +		 | UVD_CGC_CTRL__SYS_MODE_MASK
> +		 | UVD_CGC_CTRL__UDEC_MODE_MASK
> +		 | UVD_CGC_CTRL__MPEG2_MODE_MASK
> +		 | UVD_CGC_CTRL__REGS_MODE_MASK
> +		 | UVD_CGC_CTRL__RBC_MODE_MASK
> +		 | UVD_CGC_CTRL__LMI_MC_MODE_MASK
> +		 | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
> +		 | UVD_CGC_CTRL__IDCT_MODE_MASK
> +		 | UVD_CGC_CTRL__MPRD_MODE_MASK
> +		 | UVD_CGC_CTRL__MPC_MODE_MASK
> +		 | UVD_CGC_CTRL__LBSI_MODE_MASK
> +		 | UVD_CGC_CTRL__LRBBM_MODE_MASK
> +		 | UVD_CGC_CTRL__WCB_MODE_MASK
> +		 | UVD_CGC_CTRL__VCPU_MODE_MASK);
> +	WREG32_SOC15(VCN, i, mmUVD_CGC_CTRL, data);
> +
> +	data = RREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL);
> +	data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
> +		 | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
> +	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
>   static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
> @@ -1006,197 +1000,185 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   	return 0;
>   }
>   
> -static int vcn_v2_5_start(struct amdgpu_device *adev)
> +static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
>   {
> +	volatile struct amdgpu_fw_shared *fw_shared =
> +		adev->vcn.inst[i].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
>   	uint32_t rb_bufsz, tmp;
> -	int i, j, k, r;
> +	int j, k, r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, true, i);
> -	}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, true, i);
>   
> -		/* disable register anti-hang mechanism */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
> -			~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		/* set uvd status busy */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
> -	}
> +	/* disable register anti-hang mechanism */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
> +		 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> +
> +	/* set uvd status busy */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>   		return 0;
>   
> -	/*SW clock gating */
> -	vcn_v2_5_disable_clock_gating(adev);
> +	/* SW clock gating */
> +	vcn_v2_5_disable_clock_gating(adev, i);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
> -			~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* setup mmUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
> -		tmp &= ~0xff;
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp | 0x8|
> -			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
> -			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		/* setup mmUVD_MPC_CNTL */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
> -		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> -		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
> -
> -		/* setup UVD_MPC_SET_MUXA0 */
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
> -			((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> -			(0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> -			(0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> -			(0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUXB0 */
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
> -			((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> -			(0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> -			(0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> -			(0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> -
> -		/* setup mmUVD_MPC_SET_MUX */
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
> -			((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> -			(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> -			(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> -	}
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
>   
> -	vcn_v2_5_mc_resume(adev);
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
> -			adev->gfx.config.gb_addr_config);
> -		WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
> -			adev->gfx.config.gb_addr_config);
> +	/* setup mmUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
> +	tmp &= ~0xff;
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp | 0x8|
> +		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	/* setup mmUVD_MPC_CNTL */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
> +	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> +	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
> +
> +	/* setup UVD_MPC_SET_MUXA0 */
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
> +		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUXB0 */
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
> +		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> +
> +	/* setup mmUVD_MPC_SET_MUX */
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
> +		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> +		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> +
> +	vcn_v2_5_mc_resume(adev, i);
>   
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
> -			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +	WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
>   
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
>   
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		for (k = 0; k < 10; ++k) {
> -			uint32_t status;
> -
> -			for (j = 0; j < 100; ++j) {
> -				status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				if (amdgpu_emu_mode == 1)
> -					msleep(500);
> -				else
> -					mdelay(10);
> -			}
> -			r = 0;
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (k = 0; k < 10; ++k) {
> +		uint32_t status;
> +
> +		for (j = 0; j < 100; ++j) {
> +			status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
>   			if (status & 2)
>   				break;
> +			if (amdgpu_emu_mode == 1)
> +				msleep(500);
> +			else
> +				mdelay(10);
> +		}
> +		r = 0;
> +		if (status & 2)
> +			break;
>   
> -			DRM_ERROR("VCN decode not responding, trying to reset the VCPU!!!\n");
> -			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> -				UVD_VCPU_CNTL__BLK_RST_MASK,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> -			mdelay(10);
> -			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> +		DRM_ERROR("VCN decode not responding, trying to reset the VCPU!!!\n");
> +		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> +			 UVD_VCPU_CNTL__BLK_RST_MASK,
> +			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +		mdelay(10);
> +		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> +			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -			mdelay(10);
> -			r = -1;
> -		}
> +		mdelay(10);
> +		r = -1;
> +	}
>   
> -		if (r) {
> -			DRM_ERROR("VCN decode not responding, giving up!!!\n");
> -			return r;
> -		}
> +	if (r) {
> +		DRM_ERROR("VCN decode not responding, giving up!!!\n");
> +		return r;
> +	}
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
> -			UVD_MASTINT_EN__VCPU_EN_MASK,
> -			~UVD_MASTINT_EN__VCPU_EN_MASK);
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
> -			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
>   
> -		ring = &adev->vcn.inst[i].ring_dec;
> -		/* force RBC into idle state */
> -		rb_bufsz = order_base_2(ring->ring_size);
> -		tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
> -		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
> +	ring = &adev->vcn.inst[i].ring_dec;
> +	/* force RBC into idle state */
> +	rb_bufsz = order_base_2(ring->ring_size);
> +	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
> +	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
>   
> -		fw_shared->multi_queue.decode_queue_mode |= FW_QUEUE_RING_RESET;
> -		/* program the RB_BASE for ring buffer */
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
> -			lower_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
> -			upper_32_bits(ring->gpu_addr));
> +	fw_shared->multi_queue.decode_queue_mode |= FW_QUEUE_RING_RESET;
> +	/* program the RB_BASE for ring buffer */
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
> +		     lower_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
> +		     upper_32_bits(ring->gpu_addr));
>   
> -		/* Initialize the ring buffer's read and write pointers */
> -		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
> +	/* Initialize the ring buffer's read and write pointers */
> +	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
>   
> -		ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
> -		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
> -				lower_32_bits(ring->wptr));
> -		fw_shared->multi_queue.decode_queue_mode &= ~FW_QUEUE_RING_RESET;
> +	ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
> +	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
> +		     lower_32_bits(ring->wptr));
> +	fw_shared->multi_queue.decode_queue_mode &= ~FW_QUEUE_RING_RESET;
>   
> -		fw_shared->multi_queue.encode_generalpurpose_queue_mode |= FW_QUEUE_RING_RESET;
> -		ring = &adev->vcn.inst[i].ring_enc[0];
> -		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
> -		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
> -		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
> -		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
> -		fw_shared->multi_queue.encode_generalpurpose_queue_mode &= ~FW_QUEUE_RING_RESET;
> -
> -		fw_shared->multi_queue.encode_lowlatency_queue_mode |= FW_QUEUE_RING_RESET;
> -		ring = &adev->vcn.inst[i].ring_enc[1];
> -		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
> -		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
> -		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
> -		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
> -		fw_shared->multi_queue.encode_lowlatency_queue_mode &= ~FW_QUEUE_RING_RESET;
> -	}
> +	fw_shared->multi_queue.encode_generalpurpose_queue_mode |= FW_QUEUE_RING_RESET;
> +	ring = &adev->vcn.inst[i].ring_enc[0];
> +	WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
> +	WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
> +	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
> +	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
> +	fw_shared->multi_queue.encode_generalpurpose_queue_mode &= ~FW_QUEUE_RING_RESET;
> +
> +	fw_shared->multi_queue.encode_lowlatency_queue_mode |= FW_QUEUE_RING_RESET;
> +	ring = &adev->vcn.inst[i].ring_enc[1];
> +	WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
> +	WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
> +	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
> +	WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
> +	fw_shared->multi_queue.encode_lowlatency_queue_mode &= ~FW_QUEUE_RING_RESET;
>   
>   	return 0;
>   }
> @@ -1425,72 +1407,66 @@ static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   	return 0;
>   }
>   
> -static int vcn_v2_5_stop(struct amdgpu_device *adev)
> +static int vcn_v2_5_stop(struct amdgpu_device *adev, int i)
>   {
>   	uint32_t tmp;
> -	int i, r = 0;
> +	int r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v2_5_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v2_5_stop_dpg_mode(adev, i);
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			return r;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		return r;
>   
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__READ_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block LMI UMC channel */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
> +	/* block LMI UMC channel */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
>   
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
> -			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
> -			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +	/* block VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> -		/* reset VCPU */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__BLK_RST_MASK,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* reset VCPU */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> -			~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
>   
> -		/* clear status */
> -		WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
> +	/* clear status */
> +	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
>   
> -		vcn_v2_5_enable_clock_gating(adev);
> +	vcn_v2_5_enable_clock_gating(adev, i);
>   
> -		/* enable register anti-hang mechanism */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS),
> -			UVD_POWER_STATUS__UVD_POWER_STATUS_MASK,
> -			~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> -	}
> +	/* enable register anti-hang mechanism */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS),
> +		 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK,
> +		 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, false, i);
> -	}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, false, i);
>   
>   	return 0;
>   }
> @@ -1811,16 +1787,19 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
>   	bool enable = (state == AMD_CG_STATE_GATE);
> +	int i;
>   
>   	if (amdgpu_sriov_vf(adev))
>   		return 0;
>   
> -	if (enable) {
> -		if (!vcn_v2_5_is_idle(adev))
> -			return -EBUSY;
> -		vcn_v2_5_enable_clock_gating(adev);
> -	} else {
> -		vcn_v2_5_disable_clock_gating(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (enable) {
> +			if (!vcn_v2_5_is_idle(adev))
> +				return -EBUSY;
> +			vcn_v2_5_enable_clock_gating(adev, i);
> +		} else {
> +			vcn_v2_5_disable_clock_gating(adev, i);
> +		}
>   	}
>   
>   	return 0;
> @@ -1830,20 +1809,22 @@ static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	if (amdgpu_sriov_vf(adev))
>   		return 0;
>   
> -	if(state == adev->vcn.cur_state)
> +	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v2_5_stop(adev);
> -	else
> -		ret = vcn_v2_5_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret |= vcn_v2_5_stop(adev, i);
> +		else
> +			ret |= vcn_v2_5_start(adev, i);
> +	}
>   
> -	if(!ret)
> +	if (!ret)
>   		adev->vcn.cur_state = state;
>   
>   	return ret;

[-- Attachment #2: Type: text/html, Size: 37827 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 02/44] drm/amdgpu/vcn3.0: split code along instances
  2025-01-31 16:56 ` [PATCH 02/44] drm/amdgpu/vcn3.0: " Alex Deucher
@ 2025-02-04 15:40   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:40 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 20148 bytes --]


On 2025-01-31 11:56, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 436 +++++++++++++-------------
>   1 file changed, 213 insertions(+), 223 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index 63ddd4cca9109..a3627700ed48d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -1134,192 +1134,186 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   	return 0;
>   }
>   
> -static int vcn_v3_0_start(struct amdgpu_device *adev)
> +static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t rb_bufsz, tmp;
> -	int i, j, k, r;
> +	int j, k, r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, true, i);
> -	}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, true, i);
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		/* disable VCN power gating */
> -		vcn_v3_0_disable_static_power_gating(adev, i);
> +	/* disable VCN power gating */
> +	vcn_v3_0_disable_static_power_gating(adev, i);
>   
> -		/* set VCN status busy */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
> +	/* set VCN status busy */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
>   
> -		/*SW clock gating */
> -		vcn_v3_0_disable_clock_gating(adev, i);
> +	/* SW clock gating */
> +	vcn_v3_0_disable_clock_gating(adev, i);
>   
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
> -			~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
> -			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> -
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
> -		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
> -
> -		/* setup mmUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp |
> -			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
> -			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		/* setup mmUVD_MPC_CNTL */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
> -		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> -		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
> -
> -		/* setup UVD_MPC_SET_MUXA0 */
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
> -			((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> -			(0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> -			(0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> -			(0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUXB0 */
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
> -			((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> -			(0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> -			(0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> -			(0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> -
> -		/* setup mmUVD_MPC_SET_MUX */
> -		WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
> -			((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> -			(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> -			(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> -
> -		vcn_v3_0_mc_resume(adev, i);
> -
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG,
> -			adev->gfx.config.gb_addr_config);
> -
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
>   
> -		for (j = 0; j < 10; ++j) {
> -			uint32_t status;
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -			for (k = 0; k < 100; ++k) {
> -				status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				mdelay(10);
> -			}
> -			r = 0;
> -			if (status & 2)
> -				break;
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
>   
> -			DRM_ERROR("VCN[%d] decode not responding, trying to reset the VCPU!!!\n", i);
> -			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> -				UVD_VCPU_CNTL__BLK_RST_MASK,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> -			mdelay(10);
> -			WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
> +	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
> +
> +	/* setup mmUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL);
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL, tmp |
> +		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	/* setup mmUVD_MPC_CNTL */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_MPC_CNTL);
> +	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> +	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_CNTL, tmp);
> +
> +	/* setup UVD_MPC_SET_MUXA0 */
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXA0,
> +		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUXB0 */
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUXB0,
> +		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> +
> +	/* setup mmUVD_MPC_SET_MUX */
> +	WREG32_SOC15(VCN, i, mmUVD_MPC_SET_MUX,
> +		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> +		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> +
> +	vcn_v3_0_mc_resume(adev, i);
> +
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (j = 0; j < 10; ++j) {
> +		uint32_t status;
> +
> +		for (k = 0; k < 100; ++k) {
> +			status = RREG32_SOC15(VCN, i, mmUVD_STATUS);
> +			if (status & 2)
> +				break;
>   			mdelay(10);
> -			r = -1;
>   		}
> +		r = 0;
> +		if (status & 2)
> +			break;
>   
> -		if (r) {
> -			DRM_ERROR("VCN[%d] decode not responding, giving up!!!\n", i);
> -			return r;
> -		}
> +		DRM_ERROR("VCN[%d] decode not responding, trying to reset the VCPU!!!\n", i);
> +		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> +			 UVD_VCPU_CNTL__BLK_RST_MASK,
> +			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +		mdelay(10);
> +		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> +			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +		mdelay(10);
> +		r = -1;
> +	}
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
> -			UVD_MASTINT_EN__VCPU_EN_MASK,
> -			~UVD_MASTINT_EN__VCPU_EN_MASK);
> +	if (r) {
> +		DRM_ERROR("VCN[%d] decode not responding, giving up!!!\n", i);
> +		return r;
> +	}
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
> -			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		ring = &adev->vcn.inst[i].ring_dec;
> -		/* force RBC into idle state */
> -		rb_bufsz = order_base_2(ring->ring_size);
> -		tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
> -		tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
> -		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_VMID, 0);
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		fw_shared->multi_queue.decode_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
> +	ring = &adev->vcn.inst[i].ring_dec;
> +	/* force RBC into idle state */
> +	rb_bufsz = order_base_2(ring->ring_size);
> +	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
> +	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
> +	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp);
>   
> -		/* programm the RB_BASE for ring buffer */
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
> -			lower_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
> -			upper_32_bits(ring->gpu_addr));
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared->multi_queue.decode_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
>   
> -		/* Initialize the ring buffer's read and write pointers */
> -		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
> +	/* programm the RB_BASE for ring buffer */
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
> +		     lower_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
> +		     upper_32_bits(ring->gpu_addr));
>   
> -		WREG32_SOC15(VCN, i, mmUVD_SCRATCH2, 0);
> -		ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
> -		WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
> -			lower_32_bits(ring->wptr));
> -		fw_shared->rb.wptr = lower_32_bits(ring->wptr);
> -		fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
> -
> -		if (amdgpu_ip_version(adev, UVD_HWIP, 0) !=
> -		    IP_VERSION(3, 0, 33)) {
> -			fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
> -			ring = &adev->vcn.inst[i].ring_enc[0];
> -			WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
> -			WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
> -			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
> -			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> -			WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
> -			fw_shared->multi_queue.encode_generalpurpose_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
> -
> -			fw_shared->multi_queue.encode_lowlatency_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
> -			ring = &adev->vcn.inst[i].ring_enc[1];
> -			WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
> -			WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
> -			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
> -			WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
> -			WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
> -			fw_shared->multi_queue.encode_lowlatency_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
> -		}
> +	/* Initialize the ring buffer's read and write pointers */
> +	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR, 0);
> +
> +	WREG32_SOC15(VCN, i, mmUVD_SCRATCH2, 0);
> +	ring->wptr = RREG32_SOC15(VCN, i, mmUVD_RBC_RB_RPTR);
> +	WREG32_SOC15(VCN, i, mmUVD_RBC_RB_WPTR,
> +		     lower_32_bits(ring->wptr));
> +	fw_shared->rb.wptr = lower_32_bits(ring->wptr);
> +	fw_shared->multi_queue.decode_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
> +
> +	if (amdgpu_ip_version(adev, UVD_HWIP, 0) !=
> +	    IP_VERSION(3, 0, 33)) {
> +		fw_shared->multi_queue.encode_generalpurpose_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
> +		ring = &adev->vcn.inst[i].ring_enc[0];
> +		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
> +		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
> +		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO, ring->gpu_addr);
> +		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE, ring->ring_size / 4);
> +		fw_shared->multi_queue.encode_generalpurpose_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
> +
> +		fw_shared->multi_queue.encode_lowlatency_queue_mode |= cpu_to_le32(FW_QUEUE_RING_RESET);
> +		ring = &adev->vcn.inst[i].ring_enc[1];
> +		WREG32_SOC15(VCN, i, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
> +		WREG32_SOC15(VCN, i, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
> +		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_LO2, ring->gpu_addr);
> +		WREG32_SOC15(VCN, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
> +		WREG32_SOC15(VCN, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
> +		fw_shared->multi_queue.encode_lowlatency_queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
>   	}
>   
>   	return 0;
> @@ -1565,79 +1559,73 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   	return 0;
>   }
>   
> -static int vcn_v3_0_stop(struct amdgpu_device *adev)
> +static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
>   {
>   	uint32_t tmp;
> -	int i, r = 0;
> +	int r = 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v3_0_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v3_0_stop_dpg_mode(adev, i);
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			return r;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		return r;
>   
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__READ_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* disable LMI UMC channel */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
> -			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	/* disable LMI UMC channel */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, i, mmUVD_LMI_CTRL2, tmp);
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK|
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
> -			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +	/* block VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> -		/* reset VCPU */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__BLK_RST_MASK,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* reset VCPU */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> -			~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
>   
> -		/* apply soft reset */
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
> -		tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
> +	/* apply soft reset */
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
> +	tmp = RREG32_SOC15(VCN, i, mmUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, mmUVD_SOFT_RESET, tmp);
>   
> -		/* clear status */
> -		WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
> +	/* clear status */
> +	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
>   
> -		/* apply HW clock gating */
> -		vcn_v3_0_enable_clock_gating(adev, i);
> +	/* apply HW clock gating */
> +	vcn_v3_0_enable_clock_gating(adev, i);
>   
> -		/* enable VCN power gating */
> -		vcn_v3_0_enable_static_power_gating(adev, i);
> -	}
> +	/* enable VCN power gating */
> +	vcn_v3_0_enable_static_power_gating(adev, i);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, false, i);
> -	}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, false, i);
>   
>   	return 0;
>   }
> @@ -2163,7 +2151,7 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
>   	 * MMSCH FW should control Power-gating and clock-gating
> @@ -2177,10 +2165,12 @@ static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v3_0_stop(adev);
> -	else
> -		ret = vcn_v3_0_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret |= vcn_v3_0_stop(adev, i);
> +		else
> +			ret |= vcn_v3_0_start(adev, i);
> +	}
>   
>   	if (!ret)
>   		adev->vcn.cur_state = state;

[-- Attachment #2: Type: text/html, Size: 20673 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 03/44] drm/amdgpu/vcn4.0: split code along instances
  2025-01-31 16:56 ` [PATCH 03/44] drm/amdgpu/vcn4.0: " Alex Deucher
@ 2025-02-04 15:50   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:50 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 18209 bytes --]


On 2025-01-31 11:56, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 436 +++++++++++++-------------
>   1 file changed, 215 insertions(+), 221 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index 00551d6f03701..c3eb4278bf465 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -1087,182 +1087,177 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>    * vcn_v4_0_start - VCN start
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to start
>    *
>    * Start VCN block
>    */
> -static int vcn_v4_0_start(struct amdgpu_device *adev)
> +static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> -	int i, j, k, r;
> +	int j, k, r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, true, i);
> -	}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, true, i);
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		/* disable VCN power gating */
> -		vcn_v4_0_disable_static_power_gating(adev, i);
> -
> -		/* set VCN status busy */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
> -
> -		/*SW clock gating */
> -		vcn_v4_0_disable_clock_gating(adev, i);
> -
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -				UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
> -				~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
> -				~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> -
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -
> -		/* setup regUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
> -		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
> -				UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> -				UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -				UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -				UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		/* setup regUVD_MPC_CNTL */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
> -		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> -		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> -		WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
> -
> -		/* setup UVD_MPC_SET_MUXA0 */
> -		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
> -				((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> -				 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> -				 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> -				 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUXB0 */
> -		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
> -				((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> -				 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> -				 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> -				 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUX */
> -		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
> -				((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> -				 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> -				 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> -
> -		vcn_v4_0_mc_resume(adev, i);
> -
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> -				adev->gfx.config.gb_addr_config);
> -
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
> -				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		for (j = 0; j < 10; ++j) {
> -			uint32_t status;
> -
> -			for (k = 0; k < 100; ++k) {
> -				status = RREG32_SOC15(VCN, i, regUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				mdelay(10);
> -				if (amdgpu_emu_mode == 1)
> -					msleep(1);
> -			}
> +	/* disable VCN power gating */
> +	vcn_v4_0_disable_static_power_gating(adev, i);
> +
> +	/* set VCN status busy */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
> +
> +	/*SW clock gating */
> +	vcn_v4_0_disable_clock_gating(adev, i);
> +
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> +
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> +
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
>   
> -			if (amdgpu_emu_mode == 1) {
> -				r = -1;
> -				if (status & 2) {
> -					r = 0;
> -					break;
> -				}
> -			} else {
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +
> +	/* setup regUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
> +	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
> +		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	/* setup regUVD_MPC_CNTL */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
> +	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> +	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> +	WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
> +
> +	/* setup UVD_MPC_SET_MUXA0 */
> +	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
> +		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUXB0 */
> +	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
> +		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUX */
> +	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
> +		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> +		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> +
> +	vcn_v4_0_mc_resume(adev, i);
> +
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (j = 0; j < 10; ++j) {
> +		uint32_t status;
> +
> +		for (k = 0; k < 100; ++k) {
> +			status = RREG32_SOC15(VCN, i, regUVD_STATUS);
> +			if (status & 2)
> +				break;
> +			mdelay(10);
> +			if (amdgpu_emu_mode == 1)
> +				msleep(1);
> +		}
> +
> +		if (amdgpu_emu_mode == 1) {
> +			r = -1;
> +			if (status & 2) {
>   				r = 0;
> -				if (status & 2)
> -					break;
> -
> -				dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -							UVD_VCPU_CNTL__BLK_RST_MASK,
> -							~UVD_VCPU_CNTL__BLK_RST_MASK);
> -				mdelay(10);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -						~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -				mdelay(10);
> -				r = -1;
> +				break;
>   			}
> +		} else {
> +			r = 0;
> +			if (status & 2)
> +				break;
> +
> +			dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +				 UVD_VCPU_CNTL__BLK_RST_MASK,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +			mdelay(10);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +			mdelay(10);
> +			r = -1;
>   		}
> +	}
>   
> -		if (r) {
> -			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> -			return r;
> -		}
> +	if (r) {
> +		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> +		return r;
> +	}
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
> -				UVD_MASTINT_EN__VCPU_EN_MASK,
> -				~UVD_MASTINT_EN__VCPU_EN_MASK);
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
> -				~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		ring = &adev->vcn.inst[i].ring_enc[0];
> -		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
> -				ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> -				VCN_RB1_DB_CTRL__EN_MASK);
> -
> -		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
> -		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
> -
> -		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> -		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> -		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> -		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
> -		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
> -
> -		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
> -		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
> -		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
> -
> -		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> -		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> -		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
> -	}
> +	ring = &adev->vcn.inst[i].ring_enc[0];
> +	WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
> +		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> +		     VCN_RB1_DB_CTRL__EN_MASK);
> +
> +	WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
> +	WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
> +
> +	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> +	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> +	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> +	WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
> +	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
> +
> +	tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
> +	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
> +	ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
> +
> +	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> +	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> +	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
>   
>   	return 0;
>   }
> @@ -1549,86 +1544,83 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>    * vcn_v4_0_stop - VCN stop
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to stop
>    *
>    * Stop VCN block
>    */
> -static int vcn_v4_0_stop(struct amdgpu_device *adev)
> +static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	uint32_t tmp;
> -	int i, r = 0;
> +	int r = 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			vcn_v4_0_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> +		vcn_v4_0_stop_dpg_mode(adev, i);
> +		return 0;
> +	}
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			return r;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		return r;
>   
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__READ_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* disable LMI UMC channel */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> -			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	/* disable LMI UMC channel */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
> -				UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +	/* block VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> -		/* reset VCPU */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -				UVD_VCPU_CNTL__BLK_RST_MASK,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* reset VCPU */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -				~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
>   
> -		/* apply soft reset */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +	/* apply soft reset */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
>   
> -		/* clear status */
> -		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
> +	/* clear status */
> +	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
>   
> -		/* apply HW clock gating */
> -		vcn_v4_0_enable_clock_gating(adev, i);
> +	/* apply HW clock gating */
> +	vcn_v4_0_enable_clock_gating(adev, i);
>   
> -		/* enable VCN power gating */
> -		vcn_v4_0_enable_static_power_gating(adev, i);
> -	}
> +	/* enable VCN power gating */
> +	vcn_v4_0_enable_static_power_gating(adev, i);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, false, i);
> -	}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, false, i);
>   
>   	return 0;
>   }
> @@ -2051,7 +2043,7 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
>   	 * MMSCH FW should control Power-gating and clock-gating
> @@ -2065,10 +2057,12 @@ static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v4_0_stop(adev);
> -	else
> -		ret = vcn_v4_0_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret |= vcn_v4_0_stop(adev, i);
> +		else
> +			ret |= vcn_v4_0_start(adev, i);
> +	}
>   
>   	if (!ret)
>   		adev->vcn.cur_state = state;

[-- Attachment #2: Type: text/html, Size: 18649 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 04/44] drm/amdgpu/vcn4.0.3: split code along instances
  2025-01-31 16:57 ` [PATCH 04/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-02-04 15:50   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:50 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 18480 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 417 ++++++++++++------------
>   1 file changed, 206 insertions(+), 211 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index f0716c10f23e4..6293d1dc02fec 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -1117,177 +1117,172 @@ static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev)
>    * vcn_v4_0_3_start - VCN start
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to start
>    *
>    * Start VCN block
>    */
> -static int vcn_v4_0_3_start(struct amdgpu_device *adev)
> +static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
> -	int i, j, k, r, vcn_inst;
> +	int j, k, r, vcn_inst;
>   	uint32_t tmp;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, true, i);
> -	}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, true, i);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		vcn_inst = GET_INST(VCN, i);
> -		/* set VCN status busy */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) |
> -		      UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
> -
> -		/*SW clock gating */
> -		vcn_v4_0_3_disable_clock_gating(adev, i);
> -
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> -			 UVD_VCPU_CNTL__CLK_EN_MASK,
> -			 ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
> -			 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
> -			 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> -
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> -		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> -
> -		/* setup regUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL,
> -			     tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> -				     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -				     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -				     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		/* setup regUVD_MPC_CNTL */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL);
> -		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> -		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp);
> -
> -		/* setup UVD_MPC_SET_MUXA0 */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0,
> -			     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> -			      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> -			      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> -			      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUXB0 */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0,
> -			     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> -			      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> -			      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> -			      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUX */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX,
> -			     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> -			      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> -			      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> -
> -		vcn_v4_0_3_mc_resume(adev, i);
> -
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
> -			     adev->gfx.config.gb_addr_config);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
> -			     adev->gfx.config.gb_addr_config);
> -
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
> -			 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> -			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	vcn_inst = GET_INST(VCN, i);
> +	/* set VCN status busy */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) |
> +		UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
>   
> -		for (j = 0; j < 10; ++j) {
> -			uint32_t status;
> +	/* SW clock gating */
> +	vcn_v4_0_3_disable_clock_gating(adev, i);
>   
> -			for (k = 0; k < 100; ++k) {
> -				status = RREG32_SOC15(VCN, vcn_inst,
> -						      regUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				mdelay(10);
> -			}
> -			r = 0;
> -			if (status & 2)
> -				break;
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK,
> +		 ~UVD_VCPU_CNTL__CLK_EN_MASK);
>   
> -			DRM_DEV_ERROR(adev->dev,
> -				"VCN decode not responding, trying to reset the VCPU!!!\n");
> -			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
> -						  regUVD_VCPU_CNTL),
> -				 UVD_VCPU_CNTL__BLK_RST_MASK,
> -				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> -			mdelay(10);
> -			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
> -						  regUVD_VCPU_CNTL),
> -				 0, ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> +
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> +
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> +	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> +
> +	/* setup regUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL,
> +		     tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	/* setup regUVD_MPC_CNTL */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL);
> +	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> +	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp);
> +
> +	/* setup UVD_MPC_SET_MUXA0 */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0,
> +		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUXB0 */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0,
> +		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUX */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX,
> +		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> +		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> +
> +	vcn_v4_0_3_mc_resume(adev, i);
> +
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
>   
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (j = 0; j < 10; ++j) {
> +		uint32_t status;
> +
> +		for (k = 0; k < 100; ++k) {
> +			status = RREG32_SOC15(VCN, vcn_inst,
> +					      regUVD_STATUS);
> +			if (status & 2)
> +				break;
>   			mdelay(10);
> -			r = -1;
>   		}
> +		r = 0;
> +		if (status & 2)
> +			break;
>   
> -		if (r) {
> -			DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n");
> -			return r;
> -		}
> +		DRM_DEV_ERROR(adev->dev,
> +			      "VCN decode not responding, trying to reset the VCPU!!!\n");
> +		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
> +					  regUVD_VCPU_CNTL),
> +			 UVD_VCPU_CNTL__BLK_RST_MASK,
> +			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +		mdelay(10);
> +		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
> +					  regUVD_VCPU_CNTL),
> +			 0, ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
> -			 UVD_MASTINT_EN__VCPU_EN_MASK,
> -			 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> +		mdelay(10);
> +		r = -1;
> +	}
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
> -			 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	if (r) {
> +		DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n");
> +		return r;
> +	}
>   
> -		ring = &adev->vcn.inst[i].ring_enc[0];
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		/* program the RB_BASE for ring buffer */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
> -			     lower_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI,
> -			     upper_32_bits(ring->gpu_addr));
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE,
> -			     ring->ring_size / sizeof(uint32_t));
> +	ring = &adev->vcn.inst[i].ring_enc[0];
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
> -		/* resetting ring, fw should not check RB ring */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> -		tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK);
> -		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
> +	/* program the RB_BASE for ring buffer */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
> +		     lower_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI,
> +		     upper_32_bits(ring->gpu_addr));
> +
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE,
> +		     ring->ring_size / sizeof(uint32_t));
> +
> +	/* resetting ring, fw should not check RB ring */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> +	tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK);
> +	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
>   
> -		/* Initialize the ring buffer's read and write pointers */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
> +	/* Initialize the ring buffer's read and write pointers */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
>   
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> -		tmp |= VCN_RB_ENABLE__RB_EN_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> +	tmp |= VCN_RB_ENABLE__RB_EN_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
>   
> -		ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
> -		fw_shared->sq.queue_mode &=
> -			cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF));
> +	ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
> +	fw_shared->sq.queue_mode &=
> +		cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF));
>   
> -	}
>   	return 0;
>   }
>   
> @@ -1327,86 +1322,84 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>    * vcn_v4_0_3_stop - VCN stop
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to stop
>    *
>    * Stop VCN block
>    */
> -static int vcn_v4_0_3_stop(struct amdgpu_device *adev)
> +static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
> -	int i, r = 0, vcn_inst;
> +	int r = 0, vcn_inst;
>   	uint32_t tmp;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		vcn_inst = GET_INST(VCN, i);
> +	vcn_inst = GET_INST(VCN, i);
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			vcn_v4_0_3_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> +		vcn_v4_0_3_stop_dpg_mode(adev, i);
> +		return 0;
> +	}
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS,
> -				       UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			goto Done;
> -
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__READ_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
> -				       tmp);
> -		if (r)
> -			goto Done;
> -
> -		/* stall UMC channel */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> -			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
> -				       tmp);
> -		if (r)
> -			goto Done;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS,
> +			       UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		goto Done;
> +
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
> +			       tmp);
> +	if (r)
> +		goto Done;
> +
> +	/* stall UMC channel */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
> +			       tmp);
> +	if (r)
> +		goto Done;
>   
> -		/* Unblock VCPU Register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
> -			 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -			 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +	/* Unblock VCPU Register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> -			 UVD_VCPU_CNTL__BLK_RST_MASK,
> -			 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> -			 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
>   
> -		/* reset LMI UMC/LMI/VCPU */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> +	/* reset LMI UMC/LMI/VCPU */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
>   
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
>   
> -		/* clear VCN status */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
> +	/* clear VCN status */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
> +
> +	/* apply HW clock gating */
> +	vcn_v4_0_3_enable_clock_gating(adev, i);
>   
> -		/* apply HW clock gating */
> -		vcn_v4_0_3_enable_clock_gating(adev, i);
> -	}
>   Done:
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, false, i);
> -	}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, false, i);
>   
>   	return 0;
>   }
> @@ -1663,7 +1656,7 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
>   	 * MMSCH FW should control Power-gating and clock-gating
> @@ -1677,10 +1670,12 @@ static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v4_0_3_stop(adev);
> -	else
> -		ret = vcn_v4_0_3_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret |= vcn_v4_0_3_stop(adev, i);
> +		else
> +			ret |= vcn_v4_0_3_start(adev, i);
> +	}
>   
>   	if (!ret)
>   		adev->vcn.cur_state = state;

[-- Attachment #2: Type: text/html, Size: 18865 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 05/44] drm/amdgpu/vcn4.0.5: split code along instances
  2025-01-31 16:57 ` [PATCH 05/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-02-04 15:51   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:51 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 18047 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 438 ++++++++++++------------
>   1 file changed, 216 insertions(+), 222 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index 23d3c16c9d9f2..bf0da0da12512 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -990,183 +990,178 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>    * vcn_v4_0_5_start - VCN start
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to start
>    *
>    * Start VCN block
>    */
> -static int vcn_v4_0_5_start(struct amdgpu_device *adev)
> +static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> -	int i, j, k, r;
> +	int j, k, r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, true, i);
> -	}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, true, i);
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		/* disable VCN power gating */
> -		vcn_v4_0_5_disable_static_power_gating(adev, i);
> -
> -		/* set VCN status busy */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
> -
> -		/*SW clock gating */
> -		vcn_v4_0_5_disable_clock_gating(adev, i);
> -
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -				UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
> -				~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
> -				~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> -
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -
> -		/* setup regUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
> -		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
> -				UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> -				UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -				UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -				UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		/* setup regUVD_MPC_CNTL */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
> -		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> -		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> -		WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
> -
> -		/* setup UVD_MPC_SET_MUXA0 */
> -		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
> -				((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> -				 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> -				 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> -				 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUXB0 */
> -		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
> -				((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> -				 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> -				 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> -				 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> -
> -		/* setup UVD_MPC_SET_MUX */
> -		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
> -				((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> -				 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> -				 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> -
> -		vcn_v4_0_5_mc_resume(adev, i);
> -
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> -				adev->gfx.config.gb_addr_config);
> -
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
> -				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		for (j = 0; j < 10; ++j) {
> -			uint32_t status;
> -
> -			for (k = 0; k < 100; ++k) {
> -				status = RREG32_SOC15(VCN, i, regUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				mdelay(10);
> -				if (amdgpu_emu_mode == 1)
> -					msleep(1);
> -			}
> +	/* disable VCN power gating */
> +	vcn_v4_0_5_disable_static_power_gating(adev, i);
> +
> +	/* set VCN status busy */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
>   
> -			if (amdgpu_emu_mode == 1) {
> -				r = -1;
> -				if (status & 2) {
> -					r = 0;
> -					break;
> -				}
> -			} else {
> +	/* SW clock gating */
> +	vcn_v4_0_5_disable_clock_gating(adev, i);
> +
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> +
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> +
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> +
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +
> +	/* setup regUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
> +	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
> +		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	/* setup regUVD_MPC_CNTL */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
> +	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
> +	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
> +	WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
> +
> +	/* setup UVD_MPC_SET_MUXA0 */
> +	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
> +		     ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUXB0 */
> +	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
> +		     ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
> +		      (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
> +		      (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
> +
> +	/* setup UVD_MPC_SET_MUX */
> +	WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
> +		     ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
> +		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
> +		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
> +
> +	vcn_v4_0_5_mc_resume(adev, i);
> +
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (j = 0; j < 10; ++j) {
> +		uint32_t status;
> +
> +		for (k = 0; k < 100; ++k) {
> +			status = RREG32_SOC15(VCN, i, regUVD_STATUS);
> +			if (status & 2)
> +				break;
> +			mdelay(10);
> +			if (amdgpu_emu_mode == 1)
> +				msleep(1);
> +		}
> +
> +		if (amdgpu_emu_mode == 1) {
> +			r = -1;
> +			if (status & 2) {
>   				r = 0;
> -				if (status & 2)
> -					break;
> -
> -				dev_err(adev->dev,
> -					"VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -							UVD_VCPU_CNTL__BLK_RST_MASK,
> -							~UVD_VCPU_CNTL__BLK_RST_MASK);
> -				mdelay(10);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -						~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -				mdelay(10);
> -				r = -1;
> +				break;
>   			}
> +		} else {
> +			r = 0;
> +			if (status & 2)
> +				break;
> +
> +			dev_err(adev->dev,
> +				"VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +				 UVD_VCPU_CNTL__BLK_RST_MASK,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +			mdelay(10);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +			mdelay(10);
> +			r = -1;
>   		}
> +	}
>   
> -		if (r) {
> -			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> -			return r;
> -		}
> +	if (r) {
> +		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> +		return r;
> +	}
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
> -				UVD_MASTINT_EN__VCPU_EN_MASK,
> -				~UVD_MASTINT_EN__VCPU_EN_MASK);
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
> -				~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		ring = &adev->vcn.inst[i].ring_enc[0];
> -		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
> -				ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> -				VCN_RB1_DB_CTRL__EN_MASK);
> -
> -		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
> -		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
> -
> -		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> -		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> -		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> -		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
> -		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
> -
> -		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
> -		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
> -		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
> -
> -		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> -		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> -		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
> -	}
> +	ring = &adev->vcn.inst[i].ring_enc[0];
> +	WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
> +		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> +		     VCN_RB1_DB_CTRL__EN_MASK);
> +
> +	WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
> +	WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
> +
> +	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> +	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> +	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> +	WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
> +	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
> +
> +	tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
> +	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
> +	ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
> +
> +	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> +	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> +	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
>   
>   	return 0;
>   }
> @@ -1203,86 +1198,83 @@ static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>    * vcn_v4_0_5_stop - VCN stop
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to stop
>    *
>    * Stop VCN block
>    */
> -static int vcn_v4_0_5_stop(struct amdgpu_device *adev)
> +static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	uint32_t tmp;
> -	int i, r = 0;
> +	int r = 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			vcn_v4_0_5_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> +		vcn_v4_0_5_stop_dpg_mode(adev, i);
> +		return 0;
> +	}
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			return r;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		return r;
>   
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__READ_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* disable LMI UMC channel */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> -			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	/* disable LMI UMC channel */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
> -				UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +	/* block VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> -		/* reset VCPU */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -				UVD_VCPU_CNTL__BLK_RST_MASK,
> -				~UVD_VCPU_CNTL__BLK_RST_MASK);
> +	/* reset VCPU */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
>   
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -				~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
>   
> -		/* apply soft reset */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +	/* apply soft reset */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
>   
> -		/* clear status */
> -		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
> +	/* clear status */
> +	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
>   
> -		/* apply HW clock gating */
> -		vcn_v4_0_5_enable_clock_gating(adev, i);
> +	/* apply HW clock gating */
> +	vcn_v4_0_5_enable_clock_gating(adev, i);
>   
> -		/* enable VCN power gating */
> -		vcn_v4_0_5_enable_static_power_gating(adev, i);
> -	}
> +	/* enable VCN power gating */
> +	vcn_v4_0_5_enable_static_power_gating(adev, i);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, false, i);
> -	}
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, false, i);
>   
>   	return 0;
>   }
> @@ -1536,15 +1528,17 @@ static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   		enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v4_0_5_stop(adev);
> -	else
> -		ret = vcn_v4_0_5_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret |= vcn_v4_0_5_stop(adev, i);
> +		else
> +			ret |= vcn_v4_0_5_start(adev, i);
> +	}
>   
>   	if (!ret)
>   		adev->vcn.cur_state = state;

[-- Attachment #2: Type: text/html, Size: 18491 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 06/44] drm/amdgpu/vcn5.0.0: split code along instances
  2025-01-31 16:57 ` [PATCH 06/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
@ 2025-02-04 15:56   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:56 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 15601 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 386 ++++++++++++------------
>   1 file changed, 190 insertions(+), 196 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index b6d78381ebfbc..6b777ed01d445 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -767,154 +767,149 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>    * vcn_v5_0_0_start - VCN start
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to start
>    *
>    * Start VCN block
>    */
> -static int vcn_v5_0_0_start(struct amdgpu_device *adev)
> +static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> -	int i, j, k, r;
> +	int j, k, r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, true, i);
> -	}
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, true, i);
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		/* disable VCN power gating */
> -		vcn_v5_0_0_disable_static_power_gating(adev, i);
> -
> -		/* set VCN status busy */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
> -
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
> -			~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
> -			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> -
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -
> -		/* setup regUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
> -		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
> -			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> -			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		vcn_v5_0_0_mc_resume(adev, i);
> -
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> -			adev->gfx.config.gb_addr_config);
> -
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		for (j = 0; j < 10; ++j) {
> -			uint32_t status;
> -
> -			for (k = 0; k < 100; ++k) {
> -				status = RREG32_SOC15(VCN, i, regUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				mdelay(10);
> -				if (amdgpu_emu_mode == 1)
> -					msleep(1);
> -			}
> +	/* disable VCN power gating */
> +	vcn_v5_0_0_disable_static_power_gating(adev, i);
> +
> +	/* set VCN status busy */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
> +
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> +
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> +
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> +
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
>   
> -			if (amdgpu_emu_mode == 1) {
> -				r = -1;
> -				if (status & 2) {
> -					r = 0;
> -					break;
> -				}
> -			} else {
> +	/* setup regUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
> +	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
> +		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	vcn_v5_0_0_mc_resume(adev, i);
> +
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (j = 0; j < 10; ++j) {
> +		uint32_t status;
> +
> +		for (k = 0; k < 100; ++k) {
> +			status = RREG32_SOC15(VCN, i, regUVD_STATUS);
> +			if (status & 2)
> +				break;
> +			mdelay(10);
> +			if (amdgpu_emu_mode == 1)
> +				msleep(1);
> +		}
> +
> +		if (amdgpu_emu_mode == 1) {
> +			r = -1;
> +			if (status & 2) {
>   				r = 0;
> -				if (status & 2)
> -					break;
> -
> -				dev_err(adev->dev,
> -					"VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -							UVD_VCPU_CNTL__BLK_RST_MASK,
> -							~UVD_VCPU_CNTL__BLK_RST_MASK);
> -				mdelay(10);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -							~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -				mdelay(10);
> -				r = -1;
> +				break;
>   			}
> +		} else {
> +			r = 0;
> +			if (status & 2)
> +				break;
> +
> +			dev_err(adev->dev,
> +				"VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +				 UVD_VCPU_CNTL__BLK_RST_MASK,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +			mdelay(10);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +			mdelay(10);
> +			r = -1;
>   		}
> +	}
>   
> -		if (r) {
> -			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> -			return r;
> -		}
> +	if (r) {
> +		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> +		return r;
> +	}
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
> -				UVD_MASTINT_EN__VCPU_EN_MASK,
> -				~UVD_MASTINT_EN__VCPU_EN_MASK);
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
> -			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		ring = &adev->vcn.inst[i].ring_enc[0];
> -		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
> -			ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> -			VCN_RB1_DB_CTRL__EN_MASK);
> -
> -		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
> -		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
> -
> -		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> -		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> -		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> -		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
> -		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
> -
> -		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
> -		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
> -		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
> -
> -		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> -		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> -		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
> -	}
> +	ring = &adev->vcn.inst[i].ring_enc[0];
> +	WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
> +		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> +		     VCN_RB1_DB_CTRL__EN_MASK);
> +
> +	WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
> +	WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
> +
> +	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> +	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> +	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> +	WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
> +	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
> +
> +	tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
> +	WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
> +	ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
> +
> +	tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
> +	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> +	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
>   
>   	return 0;
>   }
> @@ -953,83 +948,80 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>    * vcn_v5_0_0_stop - VCN stop
>    *
>    * @adev: amdgpu_device pointer
> + * @i: instance to stop
>    *
>    * Stop VCN block
>    */
> -static int vcn_v5_0_0_stop(struct amdgpu_device *adev)
> +static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
>   	uint32_t tmp;
> -	int i, r = 0;
> +	int r = 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			vcn_v5_0_0_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> +		vcn_v5_0_0_stop_dpg_mode(adev, i);
> +		return 0;
> +	}
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			return r;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		return r;
>   
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -		      UVD_LMI_STATUS__READ_CLEAN_MASK |
> -		      UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -		      UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* disable LMI UMC channel */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> -		      UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	/* disable LMI UMC channel */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
> -			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* reset VCPU */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__BLK_RST_MASK,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> -			~(UVD_VCPU_CNTL__CLK_EN_MASK));
> -
> -		/* apply soft reset */
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> -
> -		/* clear status */
> -		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
> -
> -		/* enable VCN power gating */
> -		vcn_v5_0_0_enable_static_power_gating(adev, i);
> -	}
> +	/* block VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->pm.dpm_enabled)
> -			amdgpu_dpm_enable_vcn(adev, false, i);
> -	}
> +	/* reset VCPU */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +
> +	/* apply soft reset */
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +	tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
> +
> +	/* clear status */
> +	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
> +
> +	/* enable VCN power gating */
> +	vcn_v5_0_0_enable_static_power_gating(adev, i);
> +
> +	if (adev->pm.dpm_enabled)
> +		amdgpu_dpm_enable_vcn(adev, false, i);
>   
>   	return 0;
>   }
> @@ -1279,15 +1271,17 @@ static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   		enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v5_0_0_stop(adev);
> -	else
> -		ret = vcn_v5_0_0_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret |= vcn_v5_0_0_stop(adev, i);
> +		else
> +			ret |= vcn_v5_0_0_start(adev, i);
> +	}
>   
>   	if (!ret)
>   		adev->vcn.cur_state = state;

[-- Attachment #2: Type: text/html, Size: 16015 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 07/44] drm/amdgpu/vcn5.0.1: split code along instances
  2025-01-31 16:57 ` [PATCH 07/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
@ 2025-02-04 15:57   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 15:57 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 15497 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Split the code on a per instance basis.  This will allow
> us to use the per instance functions in the future to
> handle more things per instance.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 352 ++++++++++++------------
>   1 file changed, 174 insertions(+), 178 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> index 8b463c977d08f..25abb303d6698 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -568,149 +568,145 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>    *
>    * Start VCN block
>    */
> -static int vcn_v5_0_1_start(struct amdgpu_device *adev)
> +static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> -	int i, j, k, r, vcn_inst;
> +	int j, k, r, vcn_inst;
>   
>   	if (adev->pm.dpm_enabled)
>   		amdgpu_dpm_enable_uvd(adev, true);
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			r = vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>   
> -		vcn_inst = GET_INST(VCN, i);
> +	vcn_inst = GET_INST(VCN, i);
>   
> -		/* set VCN status busy */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
> -
> -		/* enable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> -
> -		/* disable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
> -			~UVD_MASTINT_EN__VCPU_EN_MASK);
> -
> -		/* enable LMI MC and UMC channels */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
> -			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> -
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> -		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> -
> -		/* setup regUVD_LMI_CTRL */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
> -			UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> -			UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> -			UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> -			UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> -
> -		vcn_v5_0_1_mc_resume(adev, i);
> -
> -		/* VCN global tiling registers */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
> -			adev->gfx.config.gb_addr_config);
> -
> -		/* unblock VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* release VCPU reset to boot */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		for (j = 0; j < 10; ++j) {
> -			uint32_t status;
> -
> -			for (k = 0; k < 100; ++k) {
> -				status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
> -				if (status & 2)
> -					break;
> -				mdelay(100);
> -				if (amdgpu_emu_mode == 1)
> -					msleep(20);
> -			}
> +	/* set VCN status busy */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
> +
> +	/* enable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
> +
> +	/* disable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
> +
> +	/* enable LMI MC and UMC channels */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
> +		 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
> +
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> +	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> +
> +	/* setup regUVD_LMI_CTRL */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp |
> +		     UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
> +		     UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
> +		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
> +		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
> +
> +	vcn_v5_0_1_mc_resume(adev, i);
> +
> +	/* VCN global tiling registers */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
> +		     adev->gfx.config.gb_addr_config);
> +
> +	/* unblock VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	/* release VCPU reset to boot */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	for (j = 0; j < 10; ++j) {
> +		uint32_t status;
> +
> +		for (k = 0; k < 100; ++k) {
> +			status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS);
> +			if (status & 2)
> +				break;
> +			mdelay(100);
> +			if (amdgpu_emu_mode == 1)
> +				msleep(20);
> +		}
>   
> -			if (amdgpu_emu_mode == 1) {
> -				r = -1;
> -				if (status & 2) {
> -					r = 0;
> -					break;
> -				}
> -			} else {
> +		if (amdgpu_emu_mode == 1) {
> +			r = -1;
> +			if (status & 2) {
>   				r = 0;
> -				if (status & 2)
> -					break;
> -
> -				dev_err(adev->dev,
> -				    "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> -							UVD_VCPU_CNTL__BLK_RST_MASK,
> -							~UVD_VCPU_CNTL__BLK_RST_MASK);
> -				mdelay(10);
> -				WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> -							~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -				mdelay(10);
> -				r = -1;
> +				break;
>   			}
> +		} else {
> +			r = 0;
> +			if (status & 2)
> +				break;
> +
> +			dev_err(adev->dev,
> +				"VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> +				 UVD_VCPU_CNTL__BLK_RST_MASK,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +			mdelay(10);
> +			WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> +				 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +			mdelay(10);
> +			r = -1;
>   		}
> +	}
>   
> -		if (r) {
> -			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> -			return r;
> -		}
> +	if (r) {
> +		dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
> +		return r;
> +	}
>   
> -		/* enable master interrupt */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
> -				UVD_MASTINT_EN__VCPU_EN_MASK,
> -				~UVD_MASTINT_EN__VCPU_EN_MASK);
> +	/* enable master interrupt */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
> +		 UVD_MASTINT_EN__VCPU_EN_MASK,
> +		 ~UVD_MASTINT_EN__VCPU_EN_MASK);
>   
> -		/* clear the busy bit of VCN_STATUS */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
> -			~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
> +	/* clear the busy bit of VCN_STATUS */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
> +		 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
>   
> -		ring = &adev->vcn.inst[i].ring_enc[0];
> +	ring = &adev->vcn.inst[i].ring_enc[0];
>   
> -		WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
> -			ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> -			VCN_RB1_DB_CTRL__EN_MASK);
> +	WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
> +		     ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
> +		     VCN_RB1_DB_CTRL__EN_MASK);
>   
> -		/* Read DB_CTRL to flush the write DB_CTRL command. */
> -		RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
> +	/* Read DB_CTRL to flush the write DB_CTRL command. */
> +	RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL);
>   
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4);
>   
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> -		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> -		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> +	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
> +	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
>   
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
> -		ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR);
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp);
> +	ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
>   
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> -		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
> -		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
> -	}
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
> +	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
> +	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
>   
>   	return 0;
>   }
> @@ -750,71 +746,69 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>    *
>    * Stop VCN block
>    */
> -static int vcn_v5_0_1_stop(struct amdgpu_device *adev)
> +static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i)
>   {
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	uint32_t tmp;
> -	int i, r = 0, vcn_inst;
> +	int r = 0, vcn_inst;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		vcn_inst = GET_INST(VCN, i);
> +	vcn_inst = GET_INST(VCN, i);
>   
> -		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> -		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
> +	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> +	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -			vcn_v5_0_1_stop_dpg_mode(adev, i);
> -			continue;
> -		}
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> +		vcn_v5_0_1_stop_dpg_mode(adev, i);
> +		return 0;
> +	}
>   
> -		/* wait for vcn idle */
> -		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> -		if (r)
> -			return r;
> +	/* wait for vcn idle */
> +	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> +	if (r)
> +		return r;
>   
> -		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> -		      UVD_LMI_STATUS__READ_CLEAN_MASK |
> -		      UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> -		      UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__READ_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
> +		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* disable LMI UMC channel */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
> -		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
> -		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> -		      UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> -		r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
> -		if (r)
> -			return r;
> +	/* disable LMI UMC channel */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
> +	tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
> +	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
> +		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
> +	r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp);
> +	if (r)
> +		return r;
>   
> -		/* block VCPU register access */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
> -			UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> -			~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> -
> -		/* reset VCPU */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> -			UVD_VCPU_CNTL__BLK_RST_MASK,
> -			~UVD_VCPU_CNTL__BLK_RST_MASK);
> -
> -		/* disable VCPU clock */
> -		WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> -			~(UVD_VCPU_CNTL__CLK_EN_MASK));
> -
> -		/* apply soft reset */
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> -		tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> -		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> -
> -		/* clear status */
> -		WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
> -	}
> +	/* block VCPU register access */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
> +		 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
> +		 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
> +
> +	/* reset VCPU */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> +		 UVD_VCPU_CNTL__BLK_RST_MASK,
> +		 ~UVD_VCPU_CNTL__BLK_RST_MASK);
> +
> +	/* disable VCPU clock */
> +	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
> +		 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
> +
> +	/* apply soft reset */
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> +	tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
> +	tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
> +
> +	/* clear status */
> +	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
>   
>   	if (adev->pm.dpm_enabled)
>   		amdgpu_dpm_enable_uvd(adev, false);
> @@ -1010,15 +1004,17 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					    enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret;
> +	int ret = 0, i;
>   
>   	if (state == adev->vcn.cur_state)
>   		return 0;
>   
> -	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v5_0_1_stop(adev);
> -	else
> -		ret = vcn_v5_0_1_start(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		if (state == AMD_PG_STATE_GATE)
> +			ret = vcn_v5_0_1_stop(adev, i);
> +		else
> +			ret = vcn_v5_0_1_start(adev, i);
> +	}
>   
>   	if (!ret)
>   		adev->vcn.cur_state = state;

[-- Attachment #2: Type: text/html, Size: 15906 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 08/44] drm/amdgpu/vcn: switch work handler to be per instance
  2025-01-31 16:57 ` [PATCH 08/44] drm/amdgpu/vcn: switch work handler to be per instance Alex Deucher
@ 2025-02-04 20:59   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-04 20:59 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 19155 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Have a separate work handler for each VCN instance. This
> paves the way for per instance VCN power gating at runtime.
>
> v2: index instances directly on vcn1.0 and 2.0 to make
> it clear that they only support a single instance (Lijo)
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 84 +++++++++++++------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  8 ++-
>   drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c  |  2 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   | 17 ++---
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  2 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  4 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  4 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  5 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  4 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  5 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  5 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |  4 +-
>   12 files changed, 80 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 83faf6e6788a2..0c3081a198d9e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -100,6 +100,9 @@ int amdgpu_vcn_early_init(struct amdgpu_device *adev)
>   
>   	amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
>   	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		adev->vcn.inst[i].adev = adev;
> +		adev->vcn.inst[i].inst = i;
> +
>   		if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
>   			r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
>   						 AMDGPU_UCODE_REQUIRED,
> @@ -124,12 +127,13 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
>   	unsigned int fw_shared_size, log_offset;
>   	int i, r;
>   
> -	INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
> -	mutex_init(&adev->vcn.vcn_pg_lock);
>   	mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
> -	atomic_set(&adev->vcn.total_submission_cnt, 0);
> -	for (i = 0; i < adev->vcn.num_vcn_inst; i++)
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
> +		atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
> +		INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
>   		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
> +	}
>   
>   	if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
>   	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> @@ -277,10 +281,10 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
>   			amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
>   
>   		amdgpu_ucode_release(&adev->vcn.inst[j].fw);
> +		mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
>   	}
>   
>   	mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
> -	mutex_destroy(&adev->vcn.vcn_pg_lock);
>   
>   	return 0;
>   }
> @@ -331,8 +335,10 @@ int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
>   int amdgpu_vcn_suspend(struct amdgpu_device *adev)
>   {
>   	bool in_ras_intr = amdgpu_ras_intr_triggered();
> +	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
>   
>   	/* err_event_athub will corrupt VCPU buffer, so we need to
>   	 * restore fw data and clear buffer in amdgpu_vcn_resume() */
> @@ -388,46 +394,45 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
>   
>   static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>   {
> -	struct amdgpu_device *adev =
> -		container_of(work, struct amdgpu_device, vcn.idle_work.work);
> +	struct amdgpu_vcn_inst *vcn_inst =
> +		container_of(work, struct amdgpu_vcn_inst, idle_work.work);
> +	struct amdgpu_device *adev = vcn_inst->adev;
>   	unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
> -	unsigned int i, j;
> +	unsigned int i = vcn_inst->inst, j;
>   	int r = 0;
>   
> -	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
> -		if (adev->vcn.harvest_config & (1 << j))
> -			continue;
> -
> -		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> -			fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return;
>   
> -		/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
> -		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> -		    !adev->vcn.using_unified_queue) {
> -			struct dpg_pause_state new_state;
> +	for (j = 0; j < adev->vcn.num_enc_rings; ++j)
> +		fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
>   
> -			if (fence[j] ||
> -				unlikely(atomic_read(&adev->vcn.inst[j].dpg_enc_submission_cnt)))
> -				new_state.fw_based = VCN_DPG_STATE__PAUSE;
> -			else
> -				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
> +	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
> +	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> +	    !adev->vcn.using_unified_queue) {
> +		struct dpg_pause_state new_state;
>   
> -			adev->vcn.pause_dpg_mode(adev, j, &new_state);
> -		}
> +		if (fence[i] ||
> +		    unlikely(atomic_read(&vcn_inst->dpg_enc_submission_cnt)))
> +			new_state.fw_based = VCN_DPG_STATE__PAUSE;
> +		else
> +			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>   
> -		fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);
> -		fences += fence[j];
> +		adev->vcn.pause_dpg_mode(adev, i, &new_state);
>   	}
>   
> -	if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) {
> +	fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
> +	fences += fence[i];
> +
> +	if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) {
>   		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
> -		       AMD_PG_STATE_GATE);
> +						       AMD_PG_STATE_GATE);
>   		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
> -				false);
> +						    false);
>   		if (r)
>   			dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
>   	} else {
> -		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
> +		schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT);
>   	}
>   }
>   
> @@ -436,18 +441,18 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   	struct amdgpu_device *adev = ring->adev;
>   	int r = 0;
>   
> -	atomic_inc(&adev->vcn.total_submission_cnt);
> +	atomic_inc(&adev->vcn.inst[ring->me].total_submission_cnt);
>   
> -	if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) {
> +	if (!cancel_delayed_work_sync(&adev->vcn.inst[ring->me].idle_work)) {
>   		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
>   				true);
>   		if (r)
>   			dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
>   	}
>   
> -	mutex_lock(&adev->vcn.vcn_pg_lock);
> +	mutex_lock(&adev->vcn.inst[ring->me].vcn_pg_lock);
>   	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
> -	       AMD_PG_STATE_UNGATE);
> +					       AMD_PG_STATE_UNGATE);
>   
>   	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> @@ -472,7 +477,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   
>   		adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
>   	}
> -	mutex_unlock(&adev->vcn.vcn_pg_lock);
> +	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
>   }
>   
>   void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
> @@ -485,9 +490,10 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
>   	    !adev->vcn.using_unified_queue)
>   		atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
>   
> -	atomic_dec(&ring->adev->vcn.total_submission_cnt);
> +	atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
>   
> -	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
> +	schedule_delayed_work(&ring->adev->vcn.inst[ring->me].idle_work,
> +			      VCN_IDLE_TIMEOUT);
>   }
>   
>   int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index c92f683ee5958..f1685283c2f13 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -295,6 +295,8 @@ struct amdgpu_vcn_fw_shared {
>   };
>   
>   struct amdgpu_vcn_inst {
> +	struct amdgpu_device	*adev;
> +	int			inst;
>   	struct amdgpu_bo	*vcpu_bo;
>   	void			*cpu_addr;
>   	uint64_t		gpu_addr;
> @@ -316,6 +318,9 @@ struct amdgpu_vcn_inst {
>   	const struct firmware	*fw; /* VCN firmware */
>   	uint8_t			vcn_config;
>   	uint32_t		vcn_codec_disable_mask;
> +	atomic_t		total_submission_cnt;
> +	struct mutex		vcn_pg_lock;
> +	struct delayed_work	idle_work;
>   };
>   
>   struct amdgpu_vcn_ras {
> @@ -324,7 +329,6 @@ struct amdgpu_vcn_ras {
>   
>   struct amdgpu_vcn {
>   	unsigned		fw_version;
> -	struct delayed_work	idle_work;
>   	unsigned		num_enc_rings;
>   	enum amd_powergating_state cur_state;
>   	bool			indirect_sram;
> @@ -332,9 +336,7 @@ struct amdgpu_vcn {
>   	uint8_t	num_vcn_inst;
>   	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
>   	struct amdgpu_vcn_reg	 internal;
> -	struct mutex		 vcn_pg_lock;
>   	struct mutex		vcn1_jpeg1_workaround;
> -	atomic_t		 total_submission_cnt;
>   
>   	unsigned	harvest_config;
>   	int (*pause_dpg_mode)(struct amdgpu_device *adev,
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> index 03b8b7cd5229b..8031406e20ff9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> @@ -604,7 +604,7 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
>   static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
>   {
>   	struct	amdgpu_device *adev = ring->adev;
> -	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   	int		cnt = 0;
>   
>   	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index 5ea96c9835170..b90d41cd001c8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -150,7 +150,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		return r;
>   
>   	/* Override the work func */
> -	adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler;
> +	adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler;
>   
>   	amdgpu_vcn_setup_ucode(adev);
>   
> @@ -277,7 +277,7 @@ static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   
>   	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   		(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> @@ -301,7 +301,7 @@ static int vcn_v1_0_suspend(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	bool idle_work_unexecuted;
>   
> -	idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   	if (idle_work_unexecuted) {
>   		if (adev->pm.dpm_enabled)
>   			amdgpu_dpm_enable_vcn(adev, false, 0);
> @@ -1828,8 +1828,9 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   
>   static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>   {
> -	struct amdgpu_device *adev =
> -		container_of(work, struct amdgpu_device, vcn.idle_work.work);
> +	struct amdgpu_vcn_inst *vcn_inst =
> +		container_of(work, struct amdgpu_vcn_inst, idle_work.work);
> +	struct amdgpu_device *adev = vcn_inst->adev;
>   	unsigned int fences = 0, i;
>   
>   	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> @@ -1862,14 +1863,14 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>   			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
>   			       AMD_PG_STATE_GATE);
>   	} else {
> -		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
> +		schedule_delayed_work(&adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
>   	}
>   }
>   
>   static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
>   {
>   	struct	amdgpu_device *adev = ring->adev;
> -	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   
>   	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
>   
> @@ -1921,7 +1922,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
>   
>   void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
>   {
> -	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
> +	schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
>   	mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index e42cfc731ad8e..a51691c6d6110 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -313,7 +313,7 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   
>   	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   	    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index b9be304aa294b..6fb08ed093101 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -390,12 +390,12 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> +
>   		if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   		    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
>   		     RREG32_SOC15(VCN, i, mmUVD_STATUS)))
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index a3627700ed48d..70a1b85a4efae 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -422,12 +422,12 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> +
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index c3eb4278bf465..4a846c9a2b039 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -359,11 +359,12 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
> +
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> +
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 6293d1dc02fec..8343cee899c71 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -349,8 +349,10 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
>   static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
>   
>   	if (adev->vcn.cur_state != AMD_PG_STATE_GATE)
>   		vcn_v4_0_3_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index bf0da0da12512..e784f1457ee0a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -300,11 +300,12 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
> +
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> +
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index 6b777ed01d445..03c7252e28ba9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -280,11 +280,12 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
> +
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> +
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
>   				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> index 25abb303d6698..5950ec4c7f6db 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -206,8 +206,10 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block)
>   static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
> -	cancel_delayed_work_sync(&adev->vcn.idle_work);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
>   
>   	return 0;
>   }

[-- Attachment #2: Type: text/html, Size: 20091 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 09/44] drm/amdgpu/vcn: make powergating status per instance
  2025-01-31 16:57 ` [PATCH 09/44] drm/amdgpu/vcn: make powergating status " Alex Deucher
@ 2025-02-05  1:50   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05  1:50 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 27768 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Store it per instance so we can track it per instance.
>
> v2: index instances directly on vcn1.0 and 2.0 to make
> it clear that they only support a single instance (Lijo)
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h   |  2 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c     |  6 +--
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c     | 11 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c     | 43 +++++++++++-----
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c     | 49 ++++++++++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c     | 60 ++++++++++++---------
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c   | 63 ++++++++++++++---------
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c   | 48 +++++++++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c   | 48 +++++++++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c   | 40 +++++++++-----
>   drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c |  8 +--
>   11 files changed, 241 insertions(+), 137 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index f1685283c2f13..0bcf4d1c7175d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -320,6 +320,7 @@ struct amdgpu_vcn_inst {
>   	uint32_t		vcn_codec_disable_mask;
>   	atomic_t		total_submission_cnt;
>   	struct mutex		vcn_pg_lock;
> +	enum amd_powergating_state cur_state;
>   	struct delayed_work	idle_work;
>   };
>   
> @@ -330,7 +331,6 @@ struct amdgpu_vcn_ras {
>   struct amdgpu_vcn {
>   	unsigned		fw_version;
>   	unsigned		num_enc_rings;
> -	enum amd_powergating_state cur_state;
>   	bool			indirect_sram;
>   
>   	uint8_t	num_vcn_inst;
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index b90d41cd001c8..757cacf11a817 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -280,7 +280,7 @@ static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   
>   	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -		(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> +		(adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
>   		 RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
>   		vcn_v1_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
>   	}
> @@ -1813,7 +1813,7 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	int ret;
>   	struct amdgpu_device *adev = ip_block->adev;
>   
> -	if (state == adev->vcn.cur_state)
> +	if (state == adev->vcn.inst[0].cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> @@ -1822,7 +1822,7 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   		ret = vcn_v1_0_start(adev);
>   
>   	if (!ret)
> -		adev->vcn.cur_state = state;
> +		adev->vcn.inst[0].cur_state = state;
>   	return ret;
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index a51691c6d6110..e55c1f8f260e9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -316,8 +316,8 @@ static int vcn_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   
>   	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -	    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> -	      RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
> +	    (adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
> +	     RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
>   		vcn_v2_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
>   
>   	return 0;
> @@ -1810,11 +1810,11 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	struct amdgpu_device *adev = ip_block->adev;
>   
>   	if (amdgpu_sriov_vf(adev)) {
> -		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
> +		adev->vcn.inst[0].cur_state = AMD_PG_STATE_UNGATE;
>   		return 0;
>   	}
>   
> -	if (state == adev->vcn.cur_state)
> +	if (state == adev->vcn.inst[0].cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> @@ -1823,7 +1823,8 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   		ret = vcn_v2_0_start(adev);
>   
>   	if (!ret)
> -		adev->vcn.cur_state = state;
> +		adev->vcn.inst[0].cur_state = state;
> +
>   	return ret;
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index 6fb08ed093101..1d3780a2d8513 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -95,8 +95,11 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_2_5[] = {
>   static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +					       enum amd_powergating_state state,
> +					       int i);
>   static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -				enum amd_powergating_state state);
> +					  enum amd_powergating_state state);
>   static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,
>   				int inst_idx, struct dpg_pause_state *new_state);
>   static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
> @@ -397,9 +400,9 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
>   		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
>   
>   		if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -		    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> +		    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
>   		     RREG32_SOC15(VCN, i, mmUVD_STATUS)))
> -			vcn_v2_5_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +			vcn_v2_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
>   
>   		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
>   			amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0);
> @@ -1805,27 +1808,39 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> -static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -					  enum amd_powergating_state state)
> +static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +					       enum amd_powergating_state state,
> +					       int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret = 0, i;
> +	int ret;
>   
>   	if (amdgpu_sriov_vf(adev))
>   		return 0;
>   
> -	if (state == adev->vcn.cur_state)
> +	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret |= vcn_v2_5_stop(adev, i);
> -		else
> -			ret |= vcn_v2_5_start(adev, i);
> -	}
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v2_5_stop(adev, i);
> +	else
> +		ret = vcn_v2_5_start(adev, i);
>   
>   	if (!ret)
> -		adev->vcn.cur_state = state;
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
> +static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +					  enum amd_powergating_state state)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0, i;
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		ret |= vcn_v2_5_set_powergating_state_inst(ip_block,
> +							   state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index 70a1b85a4efae..13b9ed96cccda 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -105,8 +105,11 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev);
>   static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +					       enum amd_powergating_state state,
> +					       int i);
>   static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -			enum amd_powergating_state state);
> +					  enum amd_powergating_state state);
>   static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
>   			int inst_idx, struct dpg_pause_state *new_state);
>   
> @@ -430,9 +433,11 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> -				 RREG32_SOC15(VCN, i, mmUVD_STATUS))) {
> -				vcn_v3_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
> +			     RREG32_SOC15(VCN, i, mmUVD_STATUS))) {
> +				vcn_v3_0_set_powergating_state_inst(ip_block,
> +								    AMD_PG_STATE_GATE,
> +								    i);
>   			}
>   		}
>   	}
> @@ -2147,33 +2152,45 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> -static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -					  enum amd_powergating_state state)
> +static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +					       enum amd_powergating_state state,
> +					       int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret = 0, i;
> +	int ret = 0;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
>   	 * MMSCH FW should control Power-gating and clock-gating
>   	 * guest should avoid touching CGC and PG
>   	 */
>   	if (amdgpu_sriov_vf(adev)) {
> -		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
> +		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
>   		return 0;
>   	}
>   
> -	if (state == adev->vcn.cur_state)
> +	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret |= vcn_v3_0_stop(adev, i);
> -		else
> -			ret |= vcn_v3_0_start(adev, i);
> -	}
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v3_0_stop(adev, i);
> +	else
> +		ret = vcn_v3_0_start(adev, i);
>   
>   	if (!ret)
> -		adev->vcn.cur_state = state;
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
> +static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +					  enum amd_powergating_state state)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0, i;
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		ret |= vcn_v3_0_set_powergating_state_inst(ip_block,
> +							   state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index 4a846c9a2b039..dbbeeffc90726 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -96,8 +96,11 @@ static int amdgpu_ih_clientid_vcns[] = {
>   static int vcn_v4_0_start_sriov(struct amdgpu_device *adev);
>   static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +					       enum amd_powergating_state state,
> +					       int i);
>   static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -        enum amd_powergating_state state);
> +					  enum amd_powergating_state state);
>   static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev,
>           int inst_idx, struct dpg_pause_state *new_state);
>   static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
> @@ -367,9 +370,9 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> +				(adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
>   				 RREG32_SOC15(VCN, i, regUVD_STATUS))) {
> -				vcn_v4_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +				vcn_v4_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
>   			}
>   		}
>   		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
> @@ -2032,41 +2035,52 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> -/**
> - * vcn_v4_0_set_powergating_state - set VCN block powergating state
> - *
> - * @ip_block: amdgpu_ip_block pointer
> - * @state: power gating state
> - *
> - * Set VCN block powergating state
> - */
> -static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -					  enum amd_powergating_state state)
> +static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +					       enum amd_powergating_state state,
> +					       int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret = 0, i;
> +	int ret = 0;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
>   	 * MMSCH FW should control Power-gating and clock-gating
>   	 * guest should avoid touching CGC and PG
>   	 */
>   	if (amdgpu_sriov_vf(adev)) {
> -		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
> +		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
>   		return 0;
>   	}
>   
> -	if (state == adev->vcn.cur_state)
> +	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret |= vcn_v4_0_stop(adev, i);
> -		else
> -			ret |= vcn_v4_0_start(adev, i);
> -	}
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v4_0_stop(adev, i);
> +	else
> +		ret = vcn_v4_0_start(adev, i);
>   
>   	if (!ret)
> -		adev->vcn.cur_state = state;
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
> +/**
> + * vcn_v4_0_set_powergating_state - set VCN block powergating state
> + *
> + * @ip_block: amdgpu_ip_block pointer
> + * @state: power gating state
> + *
> + * Set VCN block powergating state
> + */
> +static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +					  enum amd_powergating_state state)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0, i;
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		ret |= vcn_v4_0_set_powergating_state_inst(ip_block, state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 8343cee899c71..8396ef6831b69 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -87,8 +87,11 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_3[] = {
>   static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev);
>   static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i);
>   static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -		enum amd_powergating_state state);
> +					    enum amd_powergating_state state);
>   static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev,
>   		int inst_idx, struct dpg_pause_state *new_state);
>   static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
> @@ -351,11 +354,12 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
>   
> -	if (adev->vcn.cur_state != AMD_PG_STATE_GATE)
> -		vcn_v4_0_3_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +		if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE)
> +			vcn_v4_0_3_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
> +	}
>   
>   	return 0;
>   }
> @@ -1646,41 +1650,52 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> -/**
> - * vcn_v4_0_3_set_powergating_state - set VCN block powergating state
> - *
> - * @ip_block: amdgpu_ip_block pointer
> - * @state: power gating state
> - *
> - * Set VCN block powergating state
> - */
> -static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -					  enum amd_powergating_state state)
> +static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int ret = 0, i;
> +	int ret = 0;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
>   	 * MMSCH FW should control Power-gating and clock-gating
>   	 * guest should avoid touching CGC and PG
>   	 */
>   	if (amdgpu_sriov_vf(adev)) {
> -		adev->vcn.cur_state = AMD_PG_STATE_UNGATE;
> +		adev->vcn.inst[i].cur_state = AMD_PG_STATE_UNGATE;
>   		return 0;
>   	}
>   
> -	if (state == adev->vcn.cur_state)
> +	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret |= vcn_v4_0_3_stop(adev, i);
> -		else
> -			ret |= vcn_v4_0_3_start(adev, i);
> -	}
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v4_0_3_stop(adev, i);
> +	else
> +		ret = vcn_v4_0_3_start(adev, i);
>   
>   	if (!ret)
> -		adev->vcn.cur_state = state;
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
> +/**
> + * vcn_v4_0_3_set_powergating_state - set VCN block powergating state
> + *
> + * @ip_block: amdgpu_ip_block pointer
> + * @state: power gating state
> + *
> + * Set VCN block powergating state
> + */
> +static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +					    enum amd_powergating_state state)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0, i;
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		vcn_v4_0_3_set_powergating_state_inst(ip_block, state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index e784f1457ee0a..f6b347fcdb7ed 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -95,8 +95,11 @@ static int amdgpu_ih_clientid_vcns[] = {
>   
>   static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i);
>   static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -		enum amd_powergating_state state);
> +					    enum amd_powergating_state state);
>   static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev,
>   		int inst_idx, struct dpg_pause_state *new_state);
>   static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
> @@ -308,9 +311,9 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
>   
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> -				RREG32_SOC15(VCN, i, regUVD_STATUS))) {
> -				vcn_v4_0_5_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
> +			     RREG32_SOC15(VCN, i, regUVD_STATUS))) {
> +				vcn_v4_0_5_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
>   			}
>   		}
>   	}
> @@ -1517,6 +1520,27 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> +static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0;
> +
> +	if (state == adev->vcn.inst[i].cur_state)
> +		return 0;
> +
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v4_0_5_stop(adev, i);
> +	else
> +		ret = vcn_v4_0_5_start(adev, i);
> +
> +	if (!ret)
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
>   /**
>    * vcn_v4_0_5_set_powergating_state - set VCN block powergating state
>    *
> @@ -1526,23 +1550,13 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>    * Set VCN block powergating state
>    */
>   static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -		enum amd_powergating_state state)
> +					    enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int ret = 0, i;
>   
> -	if (state == adev->vcn.cur_state)
> -		return 0;
> -
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret |= vcn_v4_0_5_stop(adev, i);
> -		else
> -			ret |= vcn_v4_0_5_start(adev, i);
> -	}
> -
> -	if (!ret)
> -		adev->vcn.cur_state = state;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		vcn_v4_0_5_set_powergating_state_inst(ip_block, state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index 03c7252e28ba9..c5d59edf3a482 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -78,8 +78,11 @@ static int amdgpu_ih_clientid_vcns[] = {
>   
>   static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i);
>   static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -		enum amd_powergating_state state);
> +					    enum amd_powergating_state state);
>   static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev,
>   		int inst_idx, struct dpg_pause_state *new_state);
>   static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
> @@ -288,9 +291,9 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   
>   		if (!amdgpu_sriov_vf(adev)) {
>   			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
> -				RREG32_SOC15(VCN, i, regUVD_STATUS))) {
> -				vcn_v5_0_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +			    (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE &&
> +			     RREG32_SOC15(VCN, i, regUVD_STATUS))) {
> +				vcn_v5_0_0_set_powergating_state_inst(ip_block, AMD_PG_STATE_GATE, i);
>   			}
>   		}
>   	}
> @@ -1260,6 +1263,27 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> +static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0;
> +
> +	if (state == adev->vcn.inst[i].cur_state)
> +		return 0;
> +
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v5_0_0_stop(adev, i);
> +	else
> +		ret = vcn_v5_0_0_start(adev, i);
> +
> +	if (!ret)
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
>   /**
>    * vcn_v5_0_0_set_powergating_state - set VCN block powergating state
>    *
> @@ -1269,23 +1293,13 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>    * Set VCN block powergating state
>    */
>   static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -		enum amd_powergating_state state)
> +					    enum amd_powergating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int ret = 0, i;
>   
> -	if (state == adev->vcn.cur_state)
> -		return 0;
> -
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret |= vcn_v5_0_0_stop(adev, i);
> -		else
> -			ret |= vcn_v5_0_0_start(adev, i);
> -	}
> -
> -	if (!ret)
> -		adev->vcn.cur_state = state;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		vcn_v5_0_0_set_powergating_state_inst(ip_block, state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> index 5950ec4c7f6db..51a2d70a65c9e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -40,8 +40,11 @@
>   
>   static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i);
>   static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -		enum amd_powergating_state state);
> +					    enum amd_powergating_state state);
>   static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   
>   /**
> @@ -994,6 +997,27 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	return 0;
>   }
>   
> +static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
> +						 enum amd_powergating_state state,
> +						 int i)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0;
> +
> +	if (state == adev->vcn.inst[i].cur_state)
> +		return 0;
> +
> +	if (state == AMD_PG_STATE_GATE)
> +		ret = vcn_v5_0_1_stop(adev, i);
> +	else
> +		ret = vcn_v5_0_1_start(adev, i);
> +
> +	if (!ret)
> +		adev->vcn.inst[i].cur_state = state;
> +
> +	return ret;
> +}
> +
>   /**
>    * vcn_v5_0_1_set_powergating_state - set VCN block powergating state
>    *
> @@ -1008,18 +1032,8 @@ static int vcn_v5_0_1_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int ret = 0, i;
>   
> -	if (state == adev->vcn.cur_state)
> -		return 0;
> -
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (state == AMD_PG_STATE_GATE)
> -			ret = vcn_v5_0_1_stop(adev, i);
> -		else
> -			ret = vcn_v5_0_1_start(adev, i);
> -	}
> -
> -	if (!ret)
> -		adev->vcn.cur_state = state;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		vcn_v5_0_1_set_powergating_state_inst(ip_block, state, i);
>   
>   	return ret;
>   }
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> index 51c2a7f4aba28..e8cf4aa6c43dd 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> @@ -2037,15 +2037,15 @@ static int smu_hw_fini(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
>   		return 0;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; i++)
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>   		smu_dpm_set_vcn_enable(smu, false, i);
> +		adev->vcn.inst[i].cur_state = AMD_PG_STATE_GATE;
> +	}
>   	smu_dpm_set_jpeg_enable(smu, false);
> +	adev->jpeg.cur_state = AMD_PG_STATE_GATE;
>   	smu_dpm_set_vpe_enable(smu, false);
>   	smu_dpm_set_umsch_mm_enable(smu, false);
>   
> -	adev->vcn.cur_state = AMD_PG_STATE_GATE;
> -	adev->jpeg.cur_state = AMD_PG_STATE_GATE;
> -
>   	if (!smu->pm_enabled)
>   		return 0;
>   

[-- Attachment #2: Type: text/html, Size: 27574 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance
  2025-01-31 16:57 ` [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance Alex Deucher
@ 2025-02-05  3:06   ` Boyuan Zhang
  2025-02-05 20:09     ` Alex Deucher
  0 siblings, 1 reply; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05  3:06 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx


On 2025-01-31 11:57, Alex Deucher wrote:
> Move more per instance data into the per instance structure.
>
> v2: index instances directly on vcn1.0 and 2.0 to make
> it clear that they only support a single instance (Lijo)
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |   2 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 196 ++++++++++++------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  17 +-
>   drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c  |   4 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   |  42 ++---
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  92 +++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  51 +++---
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  67 ++++----
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  19 ++-
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  14 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  18 ++-
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  16 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |   8 +-
>   13 files changed, 279 insertions(+), 267 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index 2c76bc5e25d92..5ee2ae66ed36b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -480,7 +480,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
>   			if (adev->vcn.harvest_config & (1 << i))
>   				continue;
>   
> -			for (j = 0; j < adev->vcn.num_enc_rings; j++)
> +			for (j = 0; j < adev->vcn.inst[i].num_enc_rings; j++)
>   				if (adev->vcn.inst[i].ring_enc[j].sched.ready)
>   					++num_rings;
>   		}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 0c3081a198d9e..9901b8e17f305 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -127,93 +127,88 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
>   	unsigned int fw_shared_size, log_offset;
>   	int i, r;
>   
> -	mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
>   	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
>   		mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
>   		atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
>   		INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
>   		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
> -	}
> -
> -	if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
> -	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> -		adev->vcn.indirect_sram = true;
> -
> -	/*
> -	 * Some Steam Deck's BIOS versions are incompatible with the
> -	 * indirect SRAM mode, leading to amdgpu being unable to get
> -	 * properly probed (and even potentially crashing the kernel).
> -	 * Hence, check for these versions here - notice this is
> -	 * restricted to Vangogh (Deck's APU).
> -	 */
> -	if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
> -		const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
> -
> -		if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
> -		     !strncmp("F7A0114", bios_ver, 7))) {
> -			adev->vcn.indirect_sram = false;
> -			dev_info(adev->dev,
> -				"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
> +		if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
> +		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> +			adev->vcn.inst[i].indirect_sram = true;
> +
> +		/*
> +		 * Some Steam Deck's BIOS versions are incompatible with the
> +		 * indirect SRAM mode, leading to amdgpu being unable to get
> +		 * properly probed (and even potentially crashing the kernel).
> +		 * Hence, check for these versions here - notice this is
> +		 * restricted to Vangogh (Deck's APU).
> +		 */
> +		if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
> +			const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
> +
> +			if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
> +					 !strncmp("F7A0114", bios_ver, 7))) {
> +				adev->vcn.inst[i].indirect_sram = false;
> +				dev_info(adev->dev,
> +					 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
> +			}
>   		}
> -	}
>   
> -	/* from vcn4 and above, only unified queue is used */
> -	adev->vcn.using_unified_queue =
> -		amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
> -
> -	hdr = (const struct common_firmware_header *)adev->vcn.inst[0].fw->data;
> -	adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
> -
> -	/* Bit 20-23, it is encode major and non-zero for new naming convention.
> -	 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
> -	 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
> -	 * is zero in old naming convention, this field is always zero so far.
> -	 * These four bits are used to tell which naming convention is present.
> -	 */
> -	fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
> -	if (fw_check) {
> -		unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
> -
> -		fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
> -		enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
> -		enc_major = fw_check;
> -		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
> -		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> -		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> -			enc_major, enc_minor, dec_ver, vep, fw_rev);
> -	} else {
> -		unsigned int version_major, version_minor, family_id;
> +		/* from vcn4 and above, only unified queue is used */
> +		adev->vcn.inst[i].using_unified_queue =
> +			amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
> +
> +		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> +		adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
> +		adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
> +
> +		/* Bit 20-23, it is encode major and non-zero for new naming convention.
> +		 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
> +		 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
> +		 * is zero in old naming convention, this field is always zero so far.
> +		 * These four bits are used to tell which naming convention is present.
> +		 */
> +		fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
> +		if (fw_check) {
> +			unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
> +
> +			fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
> +			enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
> +			enc_major = fw_check;
> +			dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
> +			vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> +			DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> +				 enc_major, enc_minor, dec_ver, vep, fw_rev);
> +		} else {
> +			unsigned int version_major, version_minor, family_id;
>   
> -		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> -		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> -		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> -		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> -			version_major, version_minor, family_id);
> -	}
> +			family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> +			version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> +			version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> +			DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> +				 version_major, version_minor, family_id);
> +		}
>   
> -	bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
> -	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
> -		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
> +		bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
> +		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
> +			bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
>   
> -	if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
> -		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
> -		log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
> -	} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
> -		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
> -		log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
> -	} else {
> -		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
> -		log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
> -	}
> -
> -	bo_size += fw_shared_size;
> +		if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
> +			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
> +			log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
> +		} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
> +			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
> +			log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
> +		} else {
> +			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
> +			log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
> +		}
>   
> -	if (amdgpu_vcnfw_log)
> -		bo_size += AMDGPU_VCNFW_LOG_SIZE;
> +		bo_size += fw_shared_size;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> +		if (amdgpu_vcnfw_log)
> +			bo_size += AMDGPU_VCNFW_LOG_SIZE;
>   
>   		r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
>   					    AMDGPU_GEM_DOMAIN_VRAM |
> @@ -239,7 +234,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
>   			adev->vcn.inst[i].fw_shared.log_offset = log_offset;
>   		}
>   
> -		if (adev->vcn.indirect_sram) {
> +		if (adev->vcn.inst[i].indirect_sram) {
>   			r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
>   					AMDGPU_GEM_DOMAIN_VRAM |
>   					AMDGPU_GEM_DOMAIN_GTT,
> @@ -277,15 +272,14 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
>   
>   		amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
>   
> -		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> +		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i)
>   			amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
>   
>   		amdgpu_ucode_release(&adev->vcn.inst[j].fw);
>   		mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
> +		mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround);
>   	}
>   
> -	mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
> -
>   	return 0;
>   }
>   
> @@ -404,12 +398,12 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>   	if (adev->vcn.harvest_config & (1 << i))
>   		return;
>   
> -	for (j = 0; j < adev->vcn.num_enc_rings; ++j)
> +	for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
>   		fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
>   
>   	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> -	    !adev->vcn.using_unified_queue) {
> +	    !adev->vcn.inst[i].using_unified_queue) {
>   		struct dpg_pause_state new_state;
>   
>   		if (fence[i] ||
> @@ -418,7 +412,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>   		else
>   			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>   
> -		adev->vcn.pause_dpg_mode(adev, i, &new_state);
> +		adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state);
>   	}
>   
>   	fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
> @@ -456,7 +450,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   
>   	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> -	    !adev->vcn.using_unified_queue) {
> +	    !adev->vcn.inst[ring->me].using_unified_queue) {
>   		struct dpg_pause_state new_state;
>   
>   		if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
> @@ -466,7 +460,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   			unsigned int fences = 0;
>   			unsigned int i;
>   
> -			for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> +			for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i)
>   				fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
>   
>   			if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
> @@ -475,7 +469,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>   		}
>   
> -		adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
> +		adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state);
>   	}
>   	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
>   }
> @@ -487,7 +481,7 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
>   	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>   	if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
>   	    ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
> -	    !adev->vcn.using_unified_queue)
> +	    !adev->vcn.inst[ring->me].using_unified_queue)
>   		atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
>   
>   	atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
> @@ -511,7 +505,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
>   	r = amdgpu_ring_alloc(ring, 3);
>   	if (r)
>   		return r;
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
>   	amdgpu_ring_write(ring, 0xDEADBEEF);
>   	amdgpu_ring_commit(ring);
>   	for (i = 0; i < adev->usec_timeout; i++) {
> @@ -576,14 +570,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
>   		goto err;
>   
>   	ib = &job->ibs[0];
> -	ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
> +	ib->ptr[0] = PACKET0(adev->vcn.inst[ring->me].internal.data0, 0);
>   	ib->ptr[1] = addr;
> -	ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
> +	ib->ptr[2] = PACKET0(adev->vcn.inst[ring->me].internal.data1, 0);
>   	ib->ptr[3] = addr >> 32;
> -	ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
> +	ib->ptr[4] = PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0);
>   	ib->ptr[5] = 0;
>   	for (i = 6; i < 16; i += 2) {
> -		ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
> +		ib->ptr[i] = PACKET0(adev->vcn.inst[ring->me].internal.nop, 0);
>   		ib->ptr[i+1] = 0;
>   	}
>   	ib->length_dw = 16;
> @@ -746,7 +740,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
>   	uint32_t ib_pack_in_dw;
>   	int i, r;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		ib_size_dw += 8;
>   
>   	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
> @@ -759,7 +753,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
>   	ib->length_dw = 0;
>   
>   	/* single queue headers */
> -	if (adev->vcn.using_unified_queue) {
> +	if (adev->vcn.inst[ring->me].using_unified_queue) {
>   		ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
>   						+ 4 + 2; /* engine info + decoding ib in dw */
>   		ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
> @@ -778,7 +772,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
>   	for (i = ib->length_dw; i < ib_size_dw; ++i)
>   		ib->ptr[i] = 0x0;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
>   
>   	r = amdgpu_job_submit_direct(job, ring, &f);
> @@ -876,7 +870,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
>   	uint64_t addr;
>   	int i, r;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		ib_size_dw += 8;
>   
>   	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
> @@ -890,7 +884,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
>   
>   	ib->length_dw = 0;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
>   
>   	ib->ptr[ib->length_dw++] = 0x00000018;
> @@ -912,7 +906,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
>   	for (i = ib->length_dw; i < ib_size_dw; ++i)
>   		ib->ptr[i] = 0x0;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
>   
>   	r = amdgpu_job_submit_direct(job, ring, &f);
> @@ -943,7 +937,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
>   	uint64_t addr;
>   	int i, r;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		ib_size_dw += 8;
>   
>   	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
> @@ -957,7 +951,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
>   
>   	ib->length_dw = 0;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
>   
>   	ib->ptr[ib->length_dw++] = 0x00000018;
> @@ -979,7 +973,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
>   	for (i = ib->length_dw; i < ib_size_dw; ++i)
>   		ib->ptr[i] = 0x0;
>   
> -	if (adev->vcn.using_unified_queue)
> +	if (adev->vcn.inst[ring->me].using_unified_queue)
>   		amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
>   
>   	r = amdgpu_job_submit_direct(job, ring, &f);
> @@ -1396,7 +1390,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
>   	struct dentry *root = minor->debugfs_root;
>   	char name[32];
>   
> -	if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.using_unified_queue)
> +	if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.inst[0].using_unified_queue)
>   		return;
>   	sprintf(name, "amdgpu_vcn_sched_mask");
>   	debugfs_create_file(name, 0600, root, adev,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index 0bcf4d1c7175d..3b059f51894b9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -322,6 +322,15 @@ struct amdgpu_vcn_inst {
>   	struct mutex		vcn_pg_lock;
>   	enum amd_powergating_state cur_state;
>   	struct delayed_work	idle_work;
> +	unsigned		fw_version;
> +	unsigned		num_enc_rings;
> +	bool			indirect_sram;
> +	struct amdgpu_vcn_reg	 internal;
> +	struct mutex		vcn1_jpeg1_workaround;
> +	int (*pause_dpg_mode)(struct amdgpu_device *adev,
> +			      int inst_idx,
> +			      struct dpg_pause_state *new_state);
> +	bool using_unified_queue;
>   };
>   
>   struct amdgpu_vcn_ras {
> @@ -330,24 +339,16 @@ struct amdgpu_vcn_ras {
>   
>   struct amdgpu_vcn {
>   	unsigned		fw_version;
> -	unsigned		num_enc_rings;
> -	bool			indirect_sram;
> -
>   	uint8_t	num_vcn_inst;
>   	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
> -	struct amdgpu_vcn_reg	 internal;
> -	struct mutex		vcn1_jpeg1_workaround;
>   
>   	unsigned	harvest_config;
> -	int (*pause_dpg_mode)(struct amdgpu_device *adev,
> -		int inst_idx, struct dpg_pause_state *new_state);
>   
>   	struct ras_common_if    *ras_if;
>   	struct amdgpu_vcn_ras   *ras;
>   
>   	uint16_t inst_mask;
>   	uint8_t	num_inst_per_aid;
> -	bool using_unified_queue;


unified_queue feature is determined by VCN IP version, so the "bool 
using_unified_queue" should be a generic value for all instances. Should 
we still need to separate it for each instance?

Boyuan


>   
>   	/* IP reg dump */
>   	uint32_t		*ip_dump;
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> index 8031406e20ff9..9e428e669ada6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> @@ -607,12 +607,12 @@ static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
>   	bool	set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   	int		cnt = 0;
>   
> -	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
> +	mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
>   
>   	if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
>   		DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
>   
> -	for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
> +	for (cnt = 0; cnt < adev->vcn.inst[0].num_enc_rings; cnt++) {
>   		if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
>   			DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
>   	}
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index 757cacf11a817..c870d9ba64c69 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -105,7 +105,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
>   
> -	adev->vcn.num_enc_rings = 2;
> +	adev->vcn.inst[0].num_enc_rings = 2;
>   
>   	vcn_v1_0_set_dec_ring_funcs(adev);
>   	vcn_v1_0_set_enc_ring_funcs(adev);
> @@ -138,7 +138,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		return r;
>   
>   	/* VCN ENC TRAP */
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_1_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
>   					&adev->vcn.inst->irq);
>   		if (r)
> @@ -166,18 +166,18 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>   	if (r)
>   		return r;
>   
> -	adev->vcn.internal.scratch9 = adev->vcn.inst->external.scratch9 =
> +	adev->vcn.inst[0].internal.scratch9 = adev->vcn.inst->external.scratch9 =
>   		SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
> -	adev->vcn.internal.data0 = adev->vcn.inst->external.data0 =
> +	adev->vcn.inst[0].internal.data0 = adev->vcn.inst->external.data0 =
>   		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
> -	adev->vcn.internal.data1 = adev->vcn.inst->external.data1 =
> +	adev->vcn.inst[0].internal.data1 = adev->vcn.inst->external.data1 =
>   		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
> -	adev->vcn.internal.cmd = adev->vcn.inst->external.cmd =
> +	adev->vcn.inst[0].internal.cmd = adev->vcn.inst->external.cmd =
>   		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
> -	adev->vcn.internal.nop = adev->vcn.inst->external.nop =
> +	adev->vcn.inst[0].internal.nop = adev->vcn.inst->external.nop =
>   		SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
>   
>   		ring = &adev->vcn.inst->ring_enc[i];
> @@ -189,7 +189,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
> +	adev->vcn.inst[0].pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
>   
>   	if (amdgpu_vcnfw_log) {
>   		volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
> @@ -253,7 +253,7 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block)
>   	if (r)
>   		return r;
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		ring = &adev->vcn.inst->ring_enc[i];
>   		r = amdgpu_ring_test_helper(ring);
>   		if (r)
> @@ -1833,7 +1833,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>   	struct amdgpu_device *adev = vcn_inst->adev;
>   	unsigned int fences = 0, i;
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>   		fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> @@ -1849,7 +1849,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>   		else
>   			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
>   
> -		adev->vcn.pause_dpg_mode(adev, 0, &new_state);
> +		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
>   	}
>   
>   	fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
> @@ -1872,7 +1872,7 @@ static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
>   	struct	amdgpu_device *adev = ring->adev;
>   	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>   
> -	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
> +	mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
>   
>   	if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec))
>   		DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
> @@ -1898,7 +1898,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
>   		struct dpg_pause_state new_state;
>   		unsigned int fences = 0, i;
>   
> -		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> +		for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>   			fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
>   
>   		if (fences)
> @@ -1916,14 +1916,14 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
>   		else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
>   			new_state.jpeg = VCN_DPG_STATE__PAUSE;
>   
> -		adev->vcn.pause_dpg_mode(adev, 0, &new_state);
> +		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
>   	}
>   }
>   
>   void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
>   {
>   	schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
> -	mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
> +	mutex_unlock(&ring->adev->vcn.inst[0].vcn1_jpeg1_workaround);
>   }
>   
>   static void vcn_v1_0_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
> @@ -2057,11 +2057,11 @@ static int vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
>   		uint32_t reg = amdgpu_ib_get_value(ib, i);
>   		uint32_t val = amdgpu_ib_get_value(ib, i + 1);
>   
> -		if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
> +		if (reg == PACKET0(p->adev->vcn.inst[0].internal.data0, 0)) {
>   			msg_lo = val;
> -		} else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
> +		} else if (reg == PACKET0(p->adev->vcn.inst[0].internal.data1, 0)) {
>   			msg_hi = val;
> -		} else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0)) {
> +		} else if (reg == PACKET0(p->adev->vcn.inst[0].internal.cmd, 0)) {
>   			r = vcn_v1_0_validate_bo(p, job,
>   						 ((u64)msg_hi) << 32 | msg_lo);
>   			if (r)
> @@ -2146,7 +2146,7 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
>   {
>   	int i;
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>   		adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
>   }
>   
> @@ -2157,7 +2157,7 @@ static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
>   
>   static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev)
>   {
> -	adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2;
> +	adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 2;
>   	adev->vcn.inst->irq.funcs = &vcn_v1_0_irq_funcs;
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index e55c1f8f260e9..b0a957664250c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -110,9 +110,9 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   
>   	if (amdgpu_sriov_vf(adev))
> -		adev->vcn.num_enc_rings = 1;
> +		adev->vcn.inst[0].num_enc_rings = 1;
>   	else
> -		adev->vcn.num_enc_rings = 2;
> +		adev->vcn.inst[0].num_enc_rings = 2;
>   
>   	vcn_v2_0_set_dec_ring_funcs(adev);
>   	vcn_v2_0_set_enc_ring_funcs(adev);
> @@ -145,7 +145,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		return r;
>   
>   	/* VCN ENC TRAP */
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
>   				      i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
>   				      &adev->vcn.inst->irq);
> @@ -175,25 +175,25 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>   	if (r)
>   		return r;
>   
> -	adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> -	adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> -	adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> -	adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> -	adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> -	adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>   
> -	adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>   	adev->vcn.inst->external.scratch9 = SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
> -	adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>   	adev->vcn.inst->external.data0 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
> -	adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>   	adev->vcn.inst->external.data1 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
> -	adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>   	adev->vcn.inst->external.cmd = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
> -	adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> +	adev->vcn.inst[0].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>   	adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
>   
>   		ring = &adev->vcn.inst->ring_enc[i];
> @@ -210,7 +210,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	adev->vcn.pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
> +	adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
>   
>   	r = amdgpu_virt_alloc_mm_table(adev);
>   	if (r)
> @@ -292,7 +292,7 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev))
>   		ring->sched.ready = false;
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		ring = &adev->vcn.inst->ring_enc[i];
>   		r = amdgpu_ring_test_helper(ring);
>   		if (r)
> @@ -981,7 +981,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
>   		amdgpu_dpm_enable_vcn(adev, true, 0);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram);
> +		return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram);
>   
>   	vcn_v2_0_disable_static_power_gating(adev);
>   
> @@ -1421,9 +1421,9 @@ void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
>   {
>   	struct amdgpu_device *adev = ring->adev;
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>   	amdgpu_ring_write(ring, 0);
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
>   }
>   
> @@ -1438,7 +1438,7 @@ void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
>   {
>   	struct amdgpu_device *adev = ring->adev;
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[0].internal.cmd, 0));
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
>   }
>   
> @@ -1458,7 +1458,7 @@ void vcn_v2_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
>   	WARN_ON(ring->wptr % 2 || count % 2);
>   
>   	for (i = 0; i < count / 2; i++) {
> -		amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.nop, 0));
> +		amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.nop, 0));
>   		amdgpu_ring_write(ring, 0);
>   	}
>   }
> @@ -1479,25 +1479,25 @@ void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
>   	struct amdgpu_device *adev = ring->adev;
>   
>   	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.context_id, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.context_id, 0));
>   	amdgpu_ring_write(ring, seq);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>   	amdgpu_ring_write(ring, addr & 0xffffffff);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>   	amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>   	amdgpu_ring_write(ring, 0);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>   	amdgpu_ring_write(ring, 0);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>   
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
>   }
> @@ -1520,14 +1520,14 @@ void vcn_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
>   	struct amdgpu_device *adev = ring->adev;
>   	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_vmid, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_vmid, 0));
>   	amdgpu_ring_write(ring, vmid);
>   
> -	amdgpu_ring_write(ring,	PACKET0(adev->vcn.internal.ib_bar_low, 0));
> +	amdgpu_ring_write(ring,	PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_low, 0));
>   	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
> -	amdgpu_ring_write(ring,	PACKET0(adev->vcn.internal.ib_bar_high, 0));
> +	amdgpu_ring_write(ring,	PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_high, 0));
>   	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
> -	amdgpu_ring_write(ring,	PACKET0(adev->vcn.internal.ib_size, 0));
> +	amdgpu_ring_write(ring,	PACKET0(adev->vcn.inst[ring->me].internal.ib_size, 0));
>   	amdgpu_ring_write(ring, ib->length_dw);
>   }
>   
> @@ -1536,16 +1536,16 @@ void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
>   {
>   	struct amdgpu_device *adev = ring->adev;
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>   	amdgpu_ring_write(ring, reg << 2);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>   	amdgpu_ring_write(ring, val);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.gp_scratch8, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.gp_scratch8, 0));
>   	amdgpu_ring_write(ring, mask);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>   
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
>   }
> @@ -1570,13 +1570,13 @@ void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
>   {
>   	struct amdgpu_device *adev = ring->adev;
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>   	amdgpu_ring_write(ring, reg << 2);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>   	amdgpu_ring_write(ring, val);
>   
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>   
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
>   }
> @@ -1777,9 +1777,9 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
>   	r = amdgpu_ring_alloc(ring, 4);
>   	if (r)
>   		return r;
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>   	amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
> -	amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
> +	amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
>   	amdgpu_ring_write(ring, 0xDEADBEEF);
>   	amdgpu_ring_commit(ring);
>   	for (i = 0; i < adev->usec_timeout; i++) {
> @@ -1863,7 +1863,7 @@ static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev,
>   	adev->vcn.inst->ring_dec.wptr_old = 0;
>   	vcn_v2_0_dec_ring_set_wptr(&adev->vcn.inst->ring_dec);
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>   		adev->vcn.inst->ring_enc[i].wptr = 0;
>   		adev->vcn.inst->ring_enc[i].wptr_old = 0;
>   		vcn_v2_0_enc_ring_set_wptr(&adev->vcn.inst->ring_enc[i]);
> @@ -1989,7 +1989,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev)
>   			SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2),
>   			AMDGPU_VCN_CONTEXT_SIZE);
>   
> -		for (r = 0; r < adev->vcn.num_enc_rings; ++r) {
> +		for (r = 0; r < adev->vcn.inst[0].num_enc_rings; ++r) {
>   			ring = &adev->vcn.inst->ring_enc[r];
>   			ring->wptr = 0;
>   			MMSCH_V2_0_INSERT_DIRECT_WT(
> @@ -2178,7 +2178,7 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
>   {
>   	int i;
>   
> -	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> +	for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>   		adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs;
>   }
>   
> @@ -2189,7 +2189,7 @@ static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
>   
>   static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev)
>   {
> -	adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 1;
> +	adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 1;
>   	adev->vcn.inst->irq.funcs = &vcn_v2_0_irq_funcs;
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index 1d3780a2d8513..a3bac39e4c9db 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -121,11 +121,13 @@ static int amdgpu_ih_clientid_vcns[] = {
>   static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
>   	if (amdgpu_sriov_vf(adev)) {
>   		adev->vcn.num_vcn_inst = 2;
>   		adev->vcn.harvest_config = 0;
> -		adev->vcn.num_enc_rings = 1;
> +		for (i = 0; i < adev->vcn.num_vcn_inst; i++)
> +			adev->vcn.inst[i].num_enc_rings = 1;
>   	} else {
>   		u32 harvest;
>   		int i;
> @@ -134,13 +136,12 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>   			harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING);
>   			if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
>   				adev->vcn.harvest_config |= 1 << i;
> +			adev->vcn.inst[i].num_enc_rings = 2;
>   		}
>   		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
>   					AMDGPU_VCN_HARVEST_VCN1))
>   			/* both instances are harvested, disable the block */
>   			return -ENOENT;
> -
> -		adev->vcn.num_enc_rings = 2;
>   	}
>   
>   	vcn_v2_5_set_dec_ring_funcs(adev);
> @@ -176,7 +177,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   
>   		/* VCN ENC TRAP */
> -		for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>   			r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j],
>   				i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[j].irq);
>   			if (r)
> @@ -205,22 +206,22 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   
>   		if (adev->vcn.harvest_config & (1 << j))
>   			continue;
> -		adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> -		adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> -
> -		adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> +
> +		adev->vcn.inst[j].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].external.scratch9 = SOC15_REG_OFFSET(VCN, j, mmUVD_SCRATCH9);
> -		adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].external.data0 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA0);
> -		adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].external.data1 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA1);
> -		adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].external.cmd = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_CMD);
> -		adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> +		adev->vcn.inst[j].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].external.nop = SOC15_REG_OFFSET(VCN, j, mmUVD_NO_OP);
>   
>   		ring = &adev->vcn.inst[j].ring_dec;
> @@ -240,7 +241,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   		if (r)
>   			return r;
>   
> -		for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>   			enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
>   
>   			ring = &adev->vcn.inst[j].ring_enc[i];
> @@ -268,6 +269,9 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   
>   		if (amdgpu_vcnfw_log)
>   			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> +
> +		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +			adev->vcn.inst[i].pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
>   	}
>   
>   	if (amdgpu_sriov_vf(adev)) {
> @@ -276,9 +280,6 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
> -
>   	r = amdgpu_vcn_ras_sw_init(adev);
>   	if (r)
>   		return r;
> @@ -369,7 +370,7 @@ static int vcn_v2_5_hw_init(struct amdgpu_ip_block *ip_block)
>   			if (r)
>   				return r;
>   
> -			for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +			for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>   				ring = &adev->vcn.inst[j].ring_enc[i];
>   				r = amdgpu_ring_test_helper(ring);
>   				if (r)
> @@ -1018,7 +1019,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
>   		amdgpu_dpm_enable_vcn(adev, true, i);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable register anti-hang mechanism */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
> @@ -1746,7 +1747,7 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
>   	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
>   		if (adev->vcn.harvest_config & (1 << j))
>   			continue;
> -		for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> +		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>   			adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs;
>   			adev->vcn.inst[j].ring_enc[i].me = j;
>   		}
> @@ -1917,10 +1918,10 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
> -		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs;
>   
> -		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs;
>   	}
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index 13b9ed96cccda..fabe4d75a7f6b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -127,11 +127,13 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
>   	if (amdgpu_sriov_vf(adev)) {
>   		adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
>   		adev->vcn.harvest_config = 0;
> -		adev->vcn.num_enc_rings = 1;
> +		for (i = 0; i < adev->vcn.num_vcn_inst; i++)
> +			adev->vcn.inst[i].num_enc_rings = 1;
>   
>   	} else {
>   		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
> @@ -139,11 +141,13 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
>   			/* both instances are harvested, disable the block */
>   			return -ENOENT;
>   
> -		if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
> -		    IP_VERSION(3, 0, 33))
> -			adev->vcn.num_enc_rings = 0;
> -		else
> -			adev->vcn.num_enc_rings = 2;
> +		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +			if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
> +			    IP_VERSION(3, 0, 33))
> +				adev->vcn.inst[i].num_enc_rings = 0;
> +			else
> +				adev->vcn.inst[i].num_enc_rings = 2;
> +		}
>   	}
>   
>   	vcn_v3_0_set_dec_ring_funcs(adev);
> @@ -198,22 +202,22 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> -		adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> -		adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> -		adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>   
> -		adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].external.scratch9 = SOC15_REG_OFFSET(VCN, i, mmUVD_SCRATCH9);
> -		adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].external.data0 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA0);
> -		adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].external.data1 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA1);
> -		adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].external.cmd = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_CMD);
> -		adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> +		adev->vcn.inst[i].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].external.nop = SOC15_REG_OFFSET(VCN, i, mmUVD_NO_OP);
>   
>   		/* VCN DEC TRAP */
> @@ -227,7 +231,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		ring = &adev->vcn.inst[i].ring_dec;
>   		ring->use_doorbell = true;
>   		if (amdgpu_sriov_vf(adev)) {
> -			ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1);
> +			ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1);
>   		} else {
>   			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i;
>   		}
> @@ -239,7 +243,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		if (r)
>   			return r;
>   
> -		for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> +		for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>   			enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(j);
>   
>   			/* VCN ENC TRAP */
> @@ -251,7 +255,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			ring = &adev->vcn.inst[i].ring_enc[j];
>   			ring->use_doorbell = true;
>   			if (amdgpu_sriov_vf(adev)) {
> -				ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1) + 1 + j;
> +				ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1) + 1 + j;
>   			} else {
>   				ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i;
>   			}
> @@ -277,6 +281,9 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   
>   		if (amdgpu_vcnfw_log)
>   			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> +
> +		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +			adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
>   	}
>   
>   	if (amdgpu_sriov_vf(adev)) {
> @@ -284,8 +291,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		if (r)
>   			return r;
>   	}
> -	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		adev->vcn.pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
>   
>   	/* Allocate memory for VCN IP Dump buffer */
>   	ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
> @@ -373,7 +378,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
>   				ring->sched.ready = true;
>   			}
>   
> -			for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> +			for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>   				ring = &adev->vcn.inst[i].ring_enc[j];
>   				if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) {
>   					ring->sched.ready = false;
> @@ -401,7 +406,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
>   			if (r)
>   				return r;
>   
> -			for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> +			for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>   				ring = &adev->vcn.inst[i].ring_enc[j];
>   				r = amdgpu_ring_test_helper(ring);
>   				if (r)
> @@ -1153,7 +1158,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
>   		amdgpu_dpm_enable_vcn(adev, true, i);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
>   	vcn_v3_0_disable_static_power_gating(adev, i);
> @@ -1433,7 +1438,7 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
>   			mmUVD_VCPU_CACHE_SIZE2),
>   			AMDGPU_VCN_CONTEXT_SIZE);
>   
> -		for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> +		for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>   			ring = &adev->vcn.inst[i].ring_enc[j];
>   			ring->wptr = 0;
>   			rb_addr = ring->gpu_addr;
> @@ -1921,11 +1926,11 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
>   		uint32_t reg = amdgpu_ib_get_value(ib, i);
>   		uint32_t val = amdgpu_ib_get_value(ib, i + 1);
>   
> -		if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
> +		if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data0, 0)) {
>   			msg_lo = val;
> -		} else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
> +		} else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data1, 0)) {
>   			msg_hi = val;
> -		} else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0) &&
> +		} else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.cmd, 0) &&
>   			   val == 0) {
>   			r = vcn_v3_0_dec_msg(p, job,
>   					     ((u64)msg_hi) << 32 | msg_lo);
> @@ -2089,7 +2094,7 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> -		for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> +		for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>   			adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs;
>   			adev->vcn.inst[i].ring_enc[j].me = i;
>   		}
> @@ -2255,7 +2260,7 @@ static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> -		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].irq.funcs = &vcn_v3_0_irq_funcs;
>   	}
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index dbbeeffc90726..ee87594fafa60 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -129,8 +129,9 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
>   		}
>   	}
>   
> -	/* re-use enc ring as unified ring */
> -	adev->vcn.num_enc_rings = 1;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		/* re-use enc ring as unified ring */
> +		adev->vcn.inst[i].num_enc_rings = 1;
>   
>   	vcn_v4_0_set_unified_ring_funcs(adev);
>   	vcn_v4_0_set_irq_funcs(adev);
> @@ -214,7 +215,8 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		ring = &adev->vcn.inst[i].ring_enc[0];
>   		ring->use_doorbell = true;
>   		if (amdgpu_sriov_vf(adev))
> -			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * (adev->vcn.num_enc_rings + 1) + 1;
> +			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i *
> +				(adev->vcn.inst[i].num_enc_rings + 1) + 1;
>   		else
>   			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;
>   		ring->vm_hub = AMDGPU_MMHUB0(0);
> @@ -226,6 +228,9 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   
>   		vcn_v4_0_fw_shared_init(adev, i);
> +
> +		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +			adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
>   	}
>   
>   	/* TODO: Add queue reset mask when FW fully supports it */
> @@ -238,8 +243,6 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
>   
>   	r = amdgpu_vcn_ras_sw_init(adev);
>   	if (r)
> @@ -1111,7 +1114,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
>   	vcn_v4_0_disable_static_power_gating(adev, i);
> @@ -2172,10 +2175,10 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> -		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs;
>   
> -		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs;
>   	}
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 8396ef6831b69..35854e074d142 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -114,9 +114,11 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
>   static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
> -	/* re-use enc ring as unified ring */
> -	adev->vcn.num_enc_rings = 1;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		/* re-use enc ring as unified ring */
> +		adev->vcn.inst[i].num_enc_rings = 1;
>   
>   	vcn_v4_0_3_set_unified_ring_funcs(adev);
>   	vcn_v4_0_3_set_irq_funcs(adev);
> @@ -194,6 +196,9 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   
>   		vcn_v4_0_3_fw_shared_init(adev, i);
> +
> +		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +			adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
>   	}
>   
>   	/* TODO: Add queue reset mask when FW fully supports it */
> @@ -206,9 +211,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		adev->vcn.pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
> -
>   	if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
>   		r = amdgpu_vcn_ras_sw_init(adev);
>   		if (r) {
> @@ -1138,7 +1140,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>   		amdgpu_dpm_enable_vcn(adev, true, i);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	vcn_inst = GET_INST(VCN, i);
>   	/* set VCN status busy */
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index f6b347fcdb7ed..0700a5f96084c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -115,9 +115,11 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
> -	/* re-use enc ring as unified ring */
> -	adev->vcn.num_enc_rings = 1;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		/* re-use enc ring as unified ring */
> +		adev->vcn.inst[i].num_enc_rings = 1;
>   	vcn_v4_0_5_set_unified_ring_funcs(adev);
>   	vcn_v4_0_5_set_irq_funcs(adev);
>   
> @@ -173,7 +175,7 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>   		ring->use_doorbell = true;
>   		if (amdgpu_sriov_vf(adev))
>   			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
> -						i * (adev->vcn.num_enc_rings + 1) + 1;
> +						i * (adev->vcn.inst[i].num_enc_rings + 1) + 1;
>   		else
>   			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
>   						2 + 8 * i;
> @@ -198,6 +200,9 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>   
>   		if (amdgpu_vcnfw_log)
>   			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> +
> +		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +			adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
>   	}
>   
>   	if (amdgpu_sriov_vf(adev)) {
> @@ -206,9 +211,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
> -
>   	/* Allocate memory for VCN IP Dump buffer */
>   	ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
>   	if (!ptr) {
> @@ -1014,7 +1016,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
>   	vcn_v4_0_5_disable_static_power_gating(adev, i);
> @@ -1624,7 +1626,7 @@ static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> -		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs;
>   	}
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index c5d59edf3a482..eeb3c9875ad50 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -98,9 +98,11 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
> -	/* re-use enc ring as unified ring */
> -	adev->vcn.num_enc_rings = 1;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		/* re-use enc ring as unified ring */
> +		adev->vcn.inst[i].num_enc_rings = 1;
>   
>   	vcn_v5_0_0_set_unified_ring_funcs(adev);
>   	vcn_v5_0_0_set_irq_funcs(adev);
> @@ -184,15 +186,15 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
>   
>   		if (amdgpu_vcnfw_log)
>   			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> +
> +		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> +			adev->vcn.inst[i].pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
>   	}
>   
>   	/* TODO: Add queue reset mask when FW fully supports it */
>   	adev->vcn.supported_reset =
>   		amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
>   
> -	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
> -
>   	vcn_v5_0_0_alloc_ip_dump(adev);
>   
>   	r = amdgpu_vcn_sysfs_reset_mask_init(adev);
> @@ -791,7 +793,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
>   	vcn_v5_0_0_disable_static_power_gating(adev, i);
> @@ -1367,7 +1369,7 @@ static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> -		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> +		adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>   		adev->vcn.inst[i].irq.funcs = &vcn_v5_0_0_irq_funcs;
>   	}
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> index 51a2d70a65c9e..f428d23eb2857 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -58,9 +58,11 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	int i;
>   
> -	/* re-use enc ring as unified ring */
> -	adev->vcn.num_enc_rings = 1;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> +		/* re-use enc ring as unified ring */
> +		adev->vcn.inst[i].num_enc_rings = 1;
>   
>   	vcn_v5_0_1_set_unified_ring_funcs(adev);
>   	vcn_v5_0_1_set_irq_funcs(adev);
> @@ -586,7 +588,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> +		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>   
>   	vcn_inst = GET_INST(VCN, i);
>   

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 11/44] drm/amdgpu/vcn: switch vcn helpers to be instance based
  2025-01-31 16:57 ` [PATCH 11/44] drm/amdgpu/vcn: switch vcn helpers to be instance based Alex Deucher
@ 2025-02-05 13:23   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 13:23 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 51816 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the instance to the helpers.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 437 ++++++++++++------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  12 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   |  16 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  16 +-
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  71 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  65 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  69 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  70 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  63 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  67 ++--
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |  64 ++--
>   11 files changed, 541 insertions(+), 409 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 9901b8e17f305..010cc64a950a4 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -93,192 +93,186 @@ MODULE_FIRMWARE(FIRMWARE_VCN5_0_1);
>   
>   static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
>   
> -int amdgpu_vcn_early_init(struct amdgpu_device *adev)
> +int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i)
>   {
>   	char ucode_prefix[25];
> -	int r, i;
> +	int r;
>   
> +	adev->vcn.inst[i].adev = adev;
> +	adev->vcn.inst[i].inst = i;
>   	amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
> -	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> -		adev->vcn.inst[i].adev = adev;
> -		adev->vcn.inst[i].inst = i;
> -
> -		if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
> -			r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
> -						 AMDGPU_UCODE_REQUIRED,
> -						 "amdgpu/%s_%d.bin", ucode_prefix, i);
> -		else
> -			r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
> -						 AMDGPU_UCODE_REQUIRED,
> -						 "amdgpu/%s.bin", ucode_prefix);
> -		if (r) {
> -			amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> -			return r;
> -		}
> +
> +	if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
> +		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
> +					 AMDGPU_UCODE_REQUIRED,
> +					 "amdgpu/%s_%d.bin", ucode_prefix, i);
> +	else
> +		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
> +					 AMDGPU_UCODE_REQUIRED,
> +					 "amdgpu/%s.bin", ucode_prefix);
> +	if (r) {
> +		amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> +		return r;
>   	}
>   	return r;
>   }
>   
> -int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
> +int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
>   {
>   	unsigned long bo_size;
>   	const struct common_firmware_header *hdr;
>   	unsigned char fw_check;
>   	unsigned int fw_shared_size, log_offset;
> -	int i, r;
> +	int r;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> -		mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
> -		mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
> -		atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
> -		INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
> -		atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
> -		if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
> -		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> -			adev->vcn.inst[i].indirect_sram = true;
> -
> -		/*
> -		 * Some Steam Deck's BIOS versions are incompatible with the
> -		 * indirect SRAM mode, leading to amdgpu being unable to get
> -		 * properly probed (and even potentially crashing the kernel).
> -		 * Hence, check for these versions here - notice this is
> -		 * restricted to Vangogh (Deck's APU).
> -		 */
> -		if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
> -			const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
> -
> -			if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
> -					 !strncmp("F7A0114", bios_ver, 7))) {
> -				adev->vcn.inst[i].indirect_sram = false;
> -				dev_info(adev->dev,
> -					 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
> -			}
> +	mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
> +	mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
> +	atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
> +	INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
> +	atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
> +	if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
> +	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> +		adev->vcn.inst[i].indirect_sram = true;
> +
> +	/*
> +	 * Some Steam Deck's BIOS versions are incompatible with the
> +	 * indirect SRAM mode, leading to amdgpu being unable to get
> +	 * properly probed (and even potentially crashing the kernel).
> +	 * Hence, check for these versions here - notice this is
> +	 * restricted to Vangogh (Deck's APU).
> +	 */
> +	if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
> +		const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
> +
> +		if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
> +				 !strncmp("F7A0114", bios_ver, 7))) {
> +			adev->vcn.inst[i].indirect_sram = false;
> +			dev_info(adev->dev,
> +				 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
>   		}
> +	}
>   
> -		/* from vcn4 and above, only unified queue is used */
> -		adev->vcn.inst[i].using_unified_queue =
> -			amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
> +	/* from vcn4 and above, only unified queue is used */
> +	adev->vcn.inst[i].using_unified_queue =
> +		amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
> +
> +	hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> +	adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
> +	adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
> +
> +	/* Bit 20-23, it is encode major and non-zero for new naming convention.
> +	 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
> +	 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
> +	 * is zero in old naming convention, this field is always zero so far.
> +	 * These four bits are used to tell which naming convention is present.
> +	 */
> +	fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
> +	if (fw_check) {
> +		unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
> +
> +		fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
> +		enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
> +		enc_major = fw_check;
> +		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
> +		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> +		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> +			 enc_major, enc_minor, dec_ver, vep, fw_rev);
> +	} else {
> +		unsigned int version_major, version_minor, family_id;
>   
> -		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> -		adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
> -		adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
> -
> -		/* Bit 20-23, it is encode major and non-zero for new naming convention.
> -		 * This field is part of version minor and DRM_DISABLED_FLAG in old naming
> -		 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
> -		 * is zero in old naming convention, this field is always zero so far.
> -		 * These four bits are used to tell which naming convention is present.
> -		 */
> -		fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
> -		if (fw_check) {
> -			unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
> -
> -			fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
> -			enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
> -			enc_major = fw_check;
> -			dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
> -			vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> -			DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> -				 enc_major, enc_minor, dec_ver, vep, fw_rev);
> -		} else {
> -			unsigned int version_major, version_minor, family_id;
> +		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> +		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> +		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> +		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> +			 version_major, version_minor, family_id);
> +	}
>   
> -			family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> -			version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> -			version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> -			DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> -				 version_major, version_minor, family_id);
> -		}
> +	bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
> +	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
> +		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
>   
> -		bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
> -		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
> -			bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
> +	if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
> +		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
> +		log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
> +	} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
> +		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
> +		log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
> +	} else {
> +		fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
> +		log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
> +	}
>   
> -		if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
> -			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
> -			log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
> -		} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
> -			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
> -			log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
> -		} else {
> -			fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
> -			log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
> -		}
> +	bo_size += fw_shared_size;
> +
> +	if (amdgpu_vcnfw_log)
> +		bo_size += AMDGPU_VCNFW_LOG_SIZE;
> +
> +	r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
> +				    AMDGPU_GEM_DOMAIN_VRAM |
> +				    AMDGPU_GEM_DOMAIN_GTT,
> +				    &adev->vcn.inst[i].vcpu_bo,
> +				    &adev->vcn.inst[i].gpu_addr,
> +				    &adev->vcn.inst[i].cpu_addr);
> +	if (r) {
> +		dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
> +		return r;
> +	}
>   
> -		bo_size += fw_shared_size;
> +	adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +
> +		bo_size - fw_shared_size;
> +	adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +
> +		bo_size - fw_shared_size;
>   
> -		if (amdgpu_vcnfw_log)
> -			bo_size += AMDGPU_VCNFW_LOG_SIZE;
> +	adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;
>   
> -		r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
> +	if (amdgpu_vcnfw_log) {
> +		adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
> +		adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
> +		adev->vcn.inst[i].fw_shared.log_offset = log_offset;
> +	}
> +
> +	if (adev->vcn.inst[i].indirect_sram) {
> +		r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
>   					    AMDGPU_GEM_DOMAIN_VRAM |
>   					    AMDGPU_GEM_DOMAIN_GTT,
> -					    &adev->vcn.inst[i].vcpu_bo,
> -					    &adev->vcn.inst[i].gpu_addr,
> -					    &adev->vcn.inst[i].cpu_addr);
> +					    &adev->vcn.inst[i].dpg_sram_bo,
> +					    &adev->vcn.inst[i].dpg_sram_gpu_addr,
> +					    &adev->vcn.inst[i].dpg_sram_cpu_addr);
>   		if (r) {
> -			dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
> +			dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
>   			return r;
>   		}
> -
> -		adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +
> -				bo_size - fw_shared_size;
> -		adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +
> -				bo_size - fw_shared_size;
> -
> -		adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;
> -
> -		if (amdgpu_vcnfw_log) {
> -			adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
> -			adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
> -			adev->vcn.inst[i].fw_shared.log_offset = log_offset;
> -		}
> -
> -		if (adev->vcn.inst[i].indirect_sram) {
> -			r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
> -					AMDGPU_GEM_DOMAIN_VRAM |
> -					AMDGPU_GEM_DOMAIN_GTT,
> -					&adev->vcn.inst[i].dpg_sram_bo,
> -					&adev->vcn.inst[i].dpg_sram_gpu_addr,
> -					&adev->vcn.inst[i].dpg_sram_cpu_addr);
> -			if (r) {
> -				dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
> -				return r;
> -			}
> -		}
>   	}
>   
>   	return 0;
>   }
>   
> -int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
> +int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i)
>   {
> -	int i, j;
> +	int j;
>   
> -	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
> -		if (adev->vcn.harvest_config & (1 << j))
> -			continue;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
>   
> -		amdgpu_bo_free_kernel(
> -			&adev->vcn.inst[j].dpg_sram_bo,
> -			&adev->vcn.inst[j].dpg_sram_gpu_addr,
> -			(void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);
> +	amdgpu_bo_free_kernel(
> +		&adev->vcn.inst[i].dpg_sram_bo,
> +		&adev->vcn.inst[i].dpg_sram_gpu_addr,
> +		(void **)&adev->vcn.inst[i].dpg_sram_cpu_addr);
>   
> -		kvfree(adev->vcn.inst[j].saved_bo);
> +	kvfree(adev->vcn.inst[i].saved_bo);
>   
> -		amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,
> -					  &adev->vcn.inst[j].gpu_addr,
> -					  (void **)&adev->vcn.inst[j].cpu_addr);
> +	amdgpu_bo_free_kernel(&adev->vcn.inst[i].vcpu_bo,
> +			      &adev->vcn.inst[i].gpu_addr,
> +			      (void **)&adev->vcn.inst[i].cpu_addr);
>   
> -		amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
> +	amdgpu_ring_fini(&adev->vcn.inst[i].ring_dec);
>   
> -		for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i)
> -			amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
> +	for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
> +		amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]);
>   
> -		amdgpu_ucode_release(&adev->vcn.inst[j].fw);
> -		mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
> -		mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround);
> -	}
> +	amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> +	mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock);
> +	mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
>   
>   	return 0;
>   }
> @@ -298,91 +292,102 @@ bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type t
>   	return ret;
>   }
>   
> -int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
> +static int amdgpu_vcn_save_vcpu_bo_inst(struct amdgpu_device *adev, int i)
>   {
>   	unsigned int size;
>   	void *ptr;
> -	int i, idx;
> +	int idx;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		if (adev->vcn.inst[i].vcpu_bo == NULL)
> -			return 0;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
> +	if (adev->vcn.inst[i].vcpu_bo == NULL)
> +		return 0;
>   
> -		size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
> -		ptr = adev->vcn.inst[i].cpu_addr;
> +	size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
> +	ptr = adev->vcn.inst[i].cpu_addr;
>   
> -		adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
> -		if (!adev->vcn.inst[i].saved_bo)
> -			return -ENOMEM;
> +	adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
> +	if (!adev->vcn.inst[i].saved_bo)
> +		return -ENOMEM;
>   
> -		if (drm_dev_enter(adev_to_drm(adev), &idx)) {
> -			memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
> -			drm_dev_exit(idx);
> -		}
> +	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
> +		memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
> +		drm_dev_exit(idx);
> +	}
> +
> +	return 0;
> +}
> +
> +int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
> +{
> +	int ret, i;
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		ret = amdgpu_vcn_save_vcpu_bo_inst(adev, i);
> +		if (ret)
> +			return ret;
>   	}
>   
>   	return 0;
>   }
>   
> -int amdgpu_vcn_suspend(struct amdgpu_device *adev)
> +int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i)
>   {
>   	bool in_ras_intr = amdgpu_ras_intr_triggered();
> -	int i;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> -		cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
> +
> +	cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
>   
>   	/* err_event_athub will corrupt VCPU buffer, so we need to
>   	 * restore fw data and clear buffer in amdgpu_vcn_resume() */
>   	if (in_ras_intr)
>   		return 0;
>   
> -	return amdgpu_vcn_save_vcpu_bo(adev);
> +	return amdgpu_vcn_save_vcpu_bo_inst(adev, i);
>   }
>   
> -int amdgpu_vcn_resume(struct amdgpu_device *adev)
> +int amdgpu_vcn_resume(struct amdgpu_device *adev, int i)
>   {
>   	unsigned int size;
>   	void *ptr;
> -	int i, idx;
> +	int idx;
>   
> -	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> -		if (adev->vcn.harvest_config & (1 << i))
> -			continue;
> -		if (adev->vcn.inst[i].vcpu_bo == NULL)
> -			return -EINVAL;
> +	if (adev->vcn.harvest_config & (1 << i))
> +		return 0;
> +	if (adev->vcn.inst[i].vcpu_bo == NULL)
> +		return -EINVAL;
> +
> +	size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
> +	ptr = adev->vcn.inst[i].cpu_addr;
>   
> -		size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
> -		ptr = adev->vcn.inst[i].cpu_addr;
> +	if (adev->vcn.inst[i].saved_bo != NULL) {
> +		if (drm_dev_enter(adev_to_drm(adev), &idx)) {
> +			memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
> +			drm_dev_exit(idx);
> +		}
> +		kvfree(adev->vcn.inst[i].saved_bo);
> +		adev->vcn.inst[i].saved_bo = NULL;
> +	} else {
> +		const struct common_firmware_header *hdr;
> +		unsigned int offset;
>   
> -		if (adev->vcn.inst[i].saved_bo != NULL) {
> +		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> +		if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
> +			offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
>   			if (drm_dev_enter(adev_to_drm(adev), &idx)) {
> -				memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
> +				memcpy_toio(adev->vcn.inst[i].cpu_addr,
> +					    adev->vcn.inst[i].fw->data + offset,
> +					    le32_to_cpu(hdr->ucode_size_bytes));
>   				drm_dev_exit(idx);
>   			}
> -			kvfree(adev->vcn.inst[i].saved_bo);
> -			adev->vcn.inst[i].saved_bo = NULL;
> -		} else {
> -			const struct common_firmware_header *hdr;
> -			unsigned int offset;
> -
> -			hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> -			if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
> -				offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
> -				if (drm_dev_enter(adev_to_drm(adev), &idx)) {
> -					memcpy_toio(adev->vcn.inst[i].cpu_addr,
> -						    adev->vcn.inst[i].fw->data + offset,
> -						    le32_to_cpu(hdr->ucode_size_bytes));
> -					drm_dev_exit(idx);
> -				}
> -				size -= le32_to_cpu(hdr->ucode_size_bytes);
> -				ptr += le32_to_cpu(hdr->ucode_size_bytes);
> -			}
> -			memset_io(ptr, 0, size);
> +			size -= le32_to_cpu(hdr->ucode_size_bytes);
> +			ptr += le32_to_cpu(hdr->ucode_size_bytes);
>   		}
> +		memset_io(ptr, 0, size);
>   	}
> +
>   	return 0;
>   }
>   
> @@ -1058,36 +1063,32 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
>   	}
>   }
>   
> -void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
> +void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i)
>   {
> -	int i;
>   	unsigned int idx;
>   
>   	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
>   		const struct common_firmware_header *hdr;
>   
> -		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> -			if (adev->vcn.harvest_config & (1 << i))
> -				continue;
> +		if (adev->vcn.harvest_config & (1 << i))
> +			return;
>   
> -			hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> -			/* currently only support 2 FW instances */
> -			if (i >= 2) {
> -				dev_info(adev->dev, "More then 2 VCN FW instances!\n");
> -				break;
> -			}
> -			idx = AMDGPU_UCODE_ID_VCN + i;
> -			adev->firmware.ucode[idx].ucode_id = idx;
> -			adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw;
> -			adev->firmware.fw_size +=
> -				ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
> -
> -			if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
> -			    IP_VERSION(4, 0, 3) ||
> -			    amdgpu_ip_version(adev, UVD_HWIP, 0) ==
> -			    IP_VERSION(5, 0, 1))
> -				break;
> +		if ((amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 3) ||
> +		     amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 1))
> +		    && (i > 0))
> +			return;
> +
> +		hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> +		/* currently only support 2 FW instances */
> +		if (i >= 2) {
> +			dev_info(adev->dev, "More then 2 VCN FW instances!\n");
> +			return;
>   		}
> +		idx = AMDGPU_UCODE_ID_VCN + i;
> +		adev->firmware.ucode[idx].ucode_id = idx;
> +		adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw;
> +		adev->firmware.fw_size +=
> +			ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
>   	}
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index 3b059f51894b9..5f92cf28cc752 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -503,11 +503,11 @@ enum vcn_ring_type {
>   	VCN_UNIFIED_RING,
>   };
>   
> -int amdgpu_vcn_early_init(struct amdgpu_device *adev);
> -int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
> -int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
> -int amdgpu_vcn_suspend(struct amdgpu_device *adev);
> -int amdgpu_vcn_resume(struct amdgpu_device *adev);
> +int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i);
> +int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i);
> +int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i);
> +int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i);
> +int amdgpu_vcn_resume(struct amdgpu_device *adev, int i);
>   void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring);
>   void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring);
>   
> @@ -525,7 +525,7 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
>   
>   enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring);
>   
> -void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev);
> +void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i);
>   
>   void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn);
>   void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index c870d9ba64c69..f74767843e85d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -113,7 +113,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
>   
>   	jpeg_v1_0_early_init(ip_block);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	return amdgpu_vcn_early_init(adev, 0);
>   }
>   
>   /**
> @@ -145,16 +145,16 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	r = amdgpu_vcn_sw_init(adev);
> +	r = amdgpu_vcn_sw_init(adev, 0);
>   	if (r)
>   		return r;
>   
>   	/* Override the work func */
>   	adev->vcn.inst[0].idle_work.work.func = vcn_v1_0_idle_work_handler;
>   
> -	amdgpu_vcn_setup_ucode(adev);
> +	amdgpu_vcn_setup_ucode(adev, 0);
>   
> -	r = amdgpu_vcn_resume(adev);
> +	r = amdgpu_vcn_resume(adev, 0);
>   	if (r)
>   		return r;
>   
> @@ -223,13 +223,13 @@ static int vcn_v1_0_sw_fini(struct amdgpu_ip_block *ip_block)
>   	int r;
>   	struct amdgpu_device *adev = ip_block->adev;
>   
> -	r = amdgpu_vcn_suspend(adev);
> +	r = amdgpu_vcn_suspend(adev, 0);
>   	if (r)
>   		return r;
>   
>   	jpeg_v1_0_sw_fini(ip_block);
>   
> -	r = amdgpu_vcn_sw_fini(adev);
> +	r = amdgpu_vcn_sw_fini(adev, 0);
>   
>   	kfree(adev->vcn.ip_dump);
>   
> @@ -311,7 +311,7 @@ static int vcn_v1_0_suspend(struct amdgpu_ip_block *ip_block)
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(adev);
> +	r = amdgpu_vcn_suspend(adev, 0);
>   
>   	return r;
>   }
> @@ -327,7 +327,7 @@ static int vcn_v1_0_resume(struct amdgpu_ip_block *ip_block)
>   {
>   	int r;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> +	r = amdgpu_vcn_resume(ip_block->adev, 0);
>   	if (r)
>   		return r;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index b0a957664250c..8ff5a9d67cbd2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -118,7 +118,7 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v2_0_set_enc_ring_funcs(adev);
>   	vcn_v2_0_set_irq_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	return amdgpu_vcn_early_init(adev, 0);
>   }
>   
>   /**
> @@ -153,13 +153,13 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>   			return r;
>   	}
>   
> -	r = amdgpu_vcn_sw_init(adev);
> +	r = amdgpu_vcn_sw_init(adev, 0);
>   	if (r)
>   		return r;
>   
> -	amdgpu_vcn_setup_ucode(adev);
> +	amdgpu_vcn_setup_ucode(adev, 0);
>   
> -	r = amdgpu_vcn_resume(adev);
> +	r = amdgpu_vcn_resume(adev, 0);
>   	if (r)
>   		return r;
>   
> @@ -254,11 +254,11 @@ static int vcn_v2_0_sw_fini(struct amdgpu_ip_block *ip_block)
>   
>   	amdgpu_virt_free_mm_table(adev);
>   
> -	r = amdgpu_vcn_suspend(adev);
> +	r = amdgpu_vcn_suspend(adev, 0);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_sw_fini(adev);
> +	r = amdgpu_vcn_sw_fini(adev, 0);
>   
>   	kfree(adev->vcn.ip_dump);
>   
> @@ -338,7 +338,7 @@ static int vcn_v2_0_suspend(struct amdgpu_ip_block *ip_block)
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	r = amdgpu_vcn_suspend(ip_block->adev, 0);
>   
>   	return r;
>   }
> @@ -354,7 +354,7 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block)
>   {
>   	int r;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> +	r = amdgpu_vcn_resume(ip_block->adev, 0);
>   	if (r)
>   		return r;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index a3bac39e4c9db..4f9f3de023ffd 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -121,7 +121,7 @@ static int amdgpu_ih_clientid_vcns[] = {
>   static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	if (amdgpu_sriov_vf(adev)) {
>   		adev->vcn.num_vcn_inst = 2;
> @@ -139,7 +139,7 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>   			adev->vcn.inst[i].num_enc_rings = 2;
>   		}
>   		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
> -					AMDGPU_VCN_HARVEST_VCN1))
> +						 AMDGPU_VCN_HARVEST_VCN1))
>   			/* both instances are harvested, disable the block */
>   			return -ENOENT;
>   	}
> @@ -149,7 +149,13 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v2_5_set_irq_funcs(adev);
>   	vcn_v2_5_set_ras_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
>   }
>   
>   /**
> @@ -168,6 +174,8 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   
>   	for (j = 0; j < adev->vcn.num_vcn_inst; j++) {
> +		volatile struct amdgpu_fw_shared *fw_shared;
> +
>   		if (adev->vcn.harvest_config & (1 << j))
>   			continue;
>   		/* VCN DEC TRAP */
> @@ -189,23 +197,17 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>   			VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].ras_poison_irq);
>   		if (r)
>   			return r;
> -	}
> -
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
>   
> -	amdgpu_vcn_setup_ucode(adev);
> +		r = amdgpu_vcn_sw_init(adev, j);
> +		if (r)
> +			return r;
>   
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> +		amdgpu_vcn_setup_ucode(adev, j);
>   
> -	for (j = 0; j < adev->vcn.num_vcn_inst; j++) {
> -		volatile struct amdgpu_fw_shared *fw_shared;
> +		r = amdgpu_vcn_resume(adev, j);
> +		if (r)
> +			return r;
>   
> -		if (adev->vcn.harvest_config & (1 << j))
> -			continue;
>   		adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>   		adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> @@ -323,15 +325,18 @@ static int vcn_v2_5_sw_fini(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev))
>   		amdgpu_virt_free_mm_table(adev);
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> -
> -	r = amdgpu_vcn_sw_fini(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	kfree(adev->vcn.ip_dump);
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -421,15 +426,20 @@ static int vcn_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v2_5_suspend(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
>   	r = vcn_v2_5_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -441,11 +451,14 @@ static int vcn_v2_5_suspend(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v2_5_hw_init(ip_block);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index fabe4d75a7f6b..724f36467b068 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -127,7 +127,7 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	if (amdgpu_sriov_vf(adev)) {
>   		adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
> @@ -154,7 +154,12 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v3_0_set_enc_ring_funcs(adev);
>   	vcn_v3_0_set_irq_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +	return 0;
>   }
>   
>   /**
> @@ -173,16 +178,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   	uint32_t *ptr;
>   	struct amdgpu_device *adev = ip_block->adev;
>   
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
> -
> -	amdgpu_vcn_setup_ucode(adev);
> -
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> -
>   	/*
>   	 * Note: doorbell assignment is fixed for SRIOV multiple VCN engines
>   	 * Formula:
> @@ -202,6 +197,16 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> +		r = amdgpu_vcn_sw_init(adev, i);
> +		if (r)
> +			return r;
> +
> +		amdgpu_vcn_setup_ucode(adev, i);
> +
> +		r = amdgpu_vcn_resume(adev, i);
> +		if (r)
> +			return r;
> +
>   		adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>   		adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> @@ -333,14 +338,18 @@ static int vcn_v3_0_sw_fini(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev))
>   		amdgpu_virt_free_mm_table(adev);
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
>   
> -	r = amdgpu_vcn_sw_fini(adev);
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	kfree(adev->vcn.ip_dump);
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -459,15 +468,20 @@ static int vcn_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v3_0_suspend(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
>   	r = vcn_v3_0_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -479,11 +493,14 @@ static int vcn_v3_0_suspend(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v3_0_resume(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v3_0_hw_init(ip_block);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index ee87594fafa60..1200815b3eee8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -117,7 +117,7 @@ static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev);
>   static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	if (amdgpu_sriov_vf(adev)) {
>   		adev->vcn.harvest_config = VCN_HARVEST_MMSCH;
> @@ -137,7 +137,13 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v4_0_set_irq_funcs(adev);
>   	vcn_v4_0_set_ras_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
>   }
>   
>   static int vcn_v4_0_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
> @@ -180,20 +186,20 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>   	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0);
>   	uint32_t *ptr;
>   
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
> -
> -	amdgpu_vcn_setup_ucode(adev);
> -
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> +		r = amdgpu_vcn_sw_init(adev, i);
> +		if (r)
> +			return r;
> +
> +		amdgpu_vcn_setup_ucode(adev, i);
> +
> +		r = amdgpu_vcn_resume(adev, i);
> +		if (r)
> +			return r;
> +
>   		/* Init instance 0 sched_score to 1, so it's scheduled after other instances */
>   		if (i == 0)
>   			atomic_set(&adev->vcn.inst[i].sched_score, 1);
> @@ -294,16 +300,23 @@ static int vcn_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev))
>   		amdgpu_virt_free_mm_table(adev);
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	amdgpu_vcn_sysfs_reset_mask_fini(adev);
> -	r = amdgpu_vcn_sw_fini(adev);
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	kfree(adev->vcn.ip_dump);
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -394,15 +407,20 @@ static int vcn_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v4_0_suspend(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
>   	r = vcn_v4_0_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -414,11 +432,14 @@ static int vcn_v4_0_suspend(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v4_0_resume(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v4_0_hw_init(ip_block);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 35854e074d142..1407cb4b553b7 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -114,7 +114,7 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
>   static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>   		/* re-use enc ring as unified ring */
> @@ -124,7 +124,13 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v4_0_3_set_irq_funcs(adev);
>   	vcn_v4_0_3_set_ras_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
>   }
>   
>   static int vcn_v4_0_3_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
> @@ -156,16 +162,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
>   	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_3);
>   	uint32_t *ptr;
>   
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
> -
> -	amdgpu_vcn_setup_ucode(adev);
> -
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> -
>   	/* VCN DEC TRAP */
>   	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
>   		VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
> @@ -173,6 +169,17 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
>   		return r;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +
> +		r = amdgpu_vcn_sw_init(adev, i);
> +		if (r)
> +			return r;
> +
> +		amdgpu_vcn_setup_ucode(adev, i);
> +
> +		r = amdgpu_vcn_resume(adev, i);
> +		if (r)
> +			return r;
> +
>   		vcn_inst = GET_INST(VCN, i);
>   
>   		ring = &adev->vcn.inst[i].ring_enc[0];
> @@ -261,16 +268,23 @@ static int vcn_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev))
>   		amdgpu_virt_free_mm_table(adev);
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	amdgpu_vcn_sysfs_reset_mask_fini(adev);
> -	r = amdgpu_vcn_sw_fini(adev);
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	kfree(adev->vcn.ip_dump);
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -375,15 +389,20 @@ static int vcn_v4_0_3_hw_fini(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v4_0_3_suspend(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
>   	r = vcn_v4_0_3_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -395,11 +414,14 @@ static int vcn_v4_0_3_suspend(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v4_0_3_resume(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v4_0_3_hw_init(ip_block);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index 0700a5f96084c..c3a2826a59631 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -115,7 +115,7 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>   		/* re-use enc ring as unified ring */
> @@ -123,7 +123,13 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v4_0_5_set_unified_ring_funcs(adev);
>   	vcn_v4_0_5_set_irq_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
>   }
>   
>   /**
> @@ -141,15 +147,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>   	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_5);
>   	uint32_t *ptr;
>   
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
> -
> -	amdgpu_vcn_setup_ucode(adev);
> -
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>   		volatile struct amdgpu_vcn4_fw_shared *fw_shared;
> @@ -157,6 +154,16 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> +		r = amdgpu_vcn_sw_init(adev, i);
> +		if (r)
> +			return r;
> +
> +		amdgpu_vcn_setup_ucode(adev, i);
> +
> +		r = amdgpu_vcn_resume(adev, i);
> +		if (r)
> +			return r;
> +
>   		atomic_set(&adev->vcn.inst[i].sched_score, 0);
>   
>   		/* VCN UNIFIED TRAP */
> @@ -252,15 +259,19 @@ static int vcn_v4_0_5_sw_fini(struct amdgpu_ip_block *ip_block)
>   	if (amdgpu_sriov_vf(adev))
>   		amdgpu_virt_free_mm_table(adev);
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
>   
> -	r = amdgpu_vcn_sw_fini(adev);
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	kfree(adev->vcn.ip_dump);
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -332,13 +343,18 @@ static int vcn_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v4_0_5_suspend(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
>   	r = vcn_v4_0_5_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	return r;
>   }
> @@ -352,11 +368,14 @@ static int vcn_v4_0_5_suspend(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v4_0_5_resume(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v4_0_5_hw_init(ip_block);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index eeb3c9875ad50..d3e4d02c12a06 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -98,7 +98,7 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>   		/* re-use enc ring as unified ring */
> @@ -107,7 +107,13 @@ static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v5_0_0_set_unified_ring_funcs(adev);
>   	vcn_v5_0_0_set_irq_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
>   }
>   
>   void vcn_v5_0_0_alloc_ip_dump(struct amdgpu_device *adev)
> @@ -138,22 +144,22 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i, r;
>   
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
> -
> -	amdgpu_vcn_setup_ucode(adev);
> -
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> -
>   	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>   		volatile struct amdgpu_vcn5_fw_shared *fw_shared;
>   
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
> +		r = amdgpu_vcn_sw_init(adev, i);
> +		if (r)
> +			return r;
> +
> +		amdgpu_vcn_setup_ucode(adev, i);
> +
> +		r = amdgpu_vcn_resume(adev, i);
> +		if (r)
> +			return r;
> +
>   		atomic_set(&adev->vcn.inst[i].sched_score, 0);
>   
>   		/* VCN UNIFIED TRAP */
> @@ -231,16 +237,23 @@ static int vcn_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
>   		drm_dev_exit(idx);
>   	}
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	amdgpu_vcn_sysfs_reset_mask_fini(adev);
> -	r = amdgpu_vcn_sw_fini(adev);
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	kfree(adev->vcn.ip_dump);
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -312,13 +325,18 @@ static int vcn_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v5_0_0_suspend(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
>   	r = vcn_v5_0_0_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(ip_block->adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	return r;
>   }
> @@ -332,11 +350,14 @@ static int vcn_v5_0_0_suspend(struct amdgpu_ip_block *ip_block)
>    */
>   static int vcn_v5_0_0_resume(struct amdgpu_ip_block *ip_block)
>   {
> -	int r;
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(ip_block->adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v5_0_0_hw_init(ip_block);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> index f428d23eb2857..f49fdf2bb6e33 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -58,7 +58,7 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int i;
> +	int i, r;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>   		/* re-use enc ring as unified ring */
> @@ -67,7 +67,13 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
>   	vcn_v5_0_1_set_unified_ring_funcs(adev);
>   	vcn_v5_0_1_set_irq_funcs(adev);
>   
> -	return amdgpu_vcn_early_init(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		r = amdgpu_vcn_early_init(adev, i);
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
>   }
>   
>   /**
> @@ -83,16 +89,6 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_ring *ring;
>   	int i, r, vcn_inst;
>   
> -	r = amdgpu_vcn_sw_init(adev);
> -	if (r)
> -		return r;
> -
> -	amdgpu_vcn_setup_ucode(adev);
> -
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> -
>   	/* VCN UNIFIED TRAP */
>   	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
>   		VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
> @@ -104,6 +100,16 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block)
>   
>   		vcn_inst = GET_INST(VCN, i);
>   
> +		r = amdgpu_vcn_sw_init(adev, i);
> +		if (r)
> +			return r;
> +
> +		amdgpu_vcn_setup_ucode(adev, i);
> +
> +		r = amdgpu_vcn_resume(adev, i);
> +		if (r)
> +			return r;
> +
>   		ring = &adev->vcn.inst[i].ring_enc[0];
>   		ring->use_doorbell = true;
>   		ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 9 * vcn_inst;
> @@ -157,17 +163,23 @@ static int vcn_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block)
>   		drm_dev_exit(idx);
>   	}
>   
> -	r = amdgpu_vcn_suspend(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
> -	r = amdgpu_vcn_sw_fini(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_sw_fini(adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	amdgpu_vcn_sysfs_reset_mask_fini(adev);
>   
>   	kfree(adev->vcn.ip_dump);
>   
> -	return r;
> +	return 0;
>   }
>   
>   /**
> @@ -229,13 +241,17 @@ static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block)
>   static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int r;
> +	int r, i;
>   
>   	r = vcn_v5_0_1_hw_fini(ip_block);
>   	if (r)
>   		return r;
>   
> -	r = amdgpu_vcn_suspend(adev);
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_suspend(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	return r;
>   }
> @@ -250,11 +266,13 @@ static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block)
>   static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> -	int r;
> +	int r, i;
>   
> -	r = amdgpu_vcn_resume(adev);
> -	if (r)
> -		return r;
> +	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> +		r = amdgpu_vcn_resume(ip_block->adev, i);
> +		if (r)
> +			return r;
> +	}
>   
>   	r = vcn_v5_0_1_hw_init(ip_block);
>   

[-- Attachment #2: Type: text/html, Size: 51049 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 12/44] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 12/44] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst Alex Deucher
@ 2025-02-05 15:00   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:00 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 10585 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 79 ++++++++++++++++++---------
>   1 file changed, 52 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index 724f36467b068..f6f4f04d74339 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -510,13 +510,14 @@ static int vcn_v3_0_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v3_0_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst)
> +static void vcn_v3_0_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -565,8 +566,11 @@ static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst)
>   		AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
>   }
>   
> -static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst_idx].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -661,8 +665,10 @@ static void vcn_v3_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
>   		UVD, inst_idx, mmUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
>   }
>   
> -static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v3_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data = 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -712,8 +718,10 @@ static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int
>   	WREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS, data);
>   }
>   
> -static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v3_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -765,8 +773,10 @@ static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v3_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	/* VCN disable CGC */
> @@ -893,9 +903,12 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
>   	WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
> -		uint8_t sram_sel, int inst_idx, uint8_t indirect)
> +static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					   uint8_t sram_sel,
> +					   uint8_t indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   
>   	/* enable sw clock gating control */
> @@ -949,8 +962,10 @@ static void vcn_v3_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v3_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	/* enable VCN CGC */
> @@ -1009,8 +1024,10 @@ static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
>   	WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v3_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
>   	uint32_t rb_bufsz, tmp;
> @@ -1028,7 +1045,7 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   		adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
>   
>   	/* enable clock gating */
> -	vcn_v3_0_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
> +	vcn_v3_0_clock_gating_dpg_mode(vinst, 0, indirect);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -1077,7 +1094,7 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
>   
> -	vcn_v3_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v3_0_mc_resume_dpg_mode(vinst, indirect);
>   
>   	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
>   		VCN, inst_idx, mmUVD_REG_XX_MASK), 0x10, 0, indirect);
> @@ -1161,8 +1178,10 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   	return 0;
>   }
>   
> -static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
> +static int vcn_v3_0_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t rb_bufsz, tmp;
> @@ -1175,17 +1194,17 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
>   		amdgpu_dpm_enable_vcn(adev, true, i);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v3_0_start_dpg_mode(vinst, vinst->indirect_sram);
>   
>   	/* disable VCN power gating */
> -	vcn_v3_0_disable_static_power_gating(adev, i);
> +	vcn_v3_0_disable_static_power_gating(vinst);
>   
>   	/* set VCN status busy */
>   	tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
>   	WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
>   
>   	/* SW clock gating */
> -	vcn_v3_0_disable_clock_gating(adev, i);
> +	vcn_v3_0_disable_clock_gating(vinst);
>   
>   	/* enable VCPU clock */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> @@ -1238,7 +1257,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
>   		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v3_0_mc_resume(adev, i);
> +	vcn_v3_0_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, i, mmUVD_GFX10_ADDR_CONFIG,
> @@ -1555,8 +1574,10 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
>   	return 0;
>   }
>   
> -static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static int vcn_v3_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> @@ -1586,8 +1607,10 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   	return 0;
>   }
>   
> -static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v3_0_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	uint32_t tmp;
>   	int r = 0;
>   
> @@ -1595,7 +1618,7 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
>   		return 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v3_0_stop_dpg_mode(adev, i);
> +		return vcn_v3_0_stop_dpg_mode(vinst);
>   
>   	/* wait for vcn idle */
>   	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> @@ -1646,10 +1669,10 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
>   
>   	/* apply HW clock gating */
> -	vcn_v3_0_enable_clock_gating(adev, i);
> +	vcn_v3_0_enable_clock_gating(vinst);
>   
>   	/* enable VCN power gating */
> -	vcn_v3_0_enable_static_power_gating(adev, i);
> +	vcn_v3_0_enable_static_power_gating(vinst);
>   
>   	if (adev->pm.dpm_enabled)
>   		amdgpu_dpm_enable_vcn(adev, false, i);
> @@ -2159,15 +2182,16 @@ static int vcn_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	int i;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
>   		if (enable) {
>   			if (RREG32_SOC15(VCN, i, mmUVD_STATUS) != UVD_STATUS__IDLE)
>   				return -EBUSY;
> -			vcn_v3_0_enable_clock_gating(adev, i);
> +			vcn_v3_0_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v3_0_disable_clock_gating(adev, i);
> +			vcn_v3_0_disable_clock_gating(vinst);
>   		}
>   	}
>   
> @@ -2179,6 +2203,7 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   					       int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret = 0;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
> @@ -2194,9 +2219,9 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v3_0_stop(adev, i);
> +		ret = vcn_v3_0_stop(vinst);
>   	else
> -		ret = vcn_v3_0_start(adev, i);
> +		ret = vcn_v3_0_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 11128 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 13/44] drm/amdgpu/vcn1.0: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 13/44] drm/amdgpu/vcn1.0: " Alex Deucher
@ 2025-02-05 15:01   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:01 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 11559 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 85 ++++++++++++++++-----------
>   1 file changed, 51 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index f74767843e85d..613f17be9d829 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -81,7 +81,7 @@ static const struct amdgpu_hwip_reg_entry vcn_reg_list_1_0[] = {
>   	SOC15_REG_ENTRY_STR(VCN, 0, mmUVD_DPG_PAUSE)
>   };
>   
> -static int vcn_v1_0_stop(struct amdgpu_device *adev);
> +static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst);
>   static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
> @@ -339,12 +339,13 @@ static int vcn_v1_0_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v1_0_mc_resume_spg_mode - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
> +static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -410,8 +411,9 @@ static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
>   			adev->gfx.config.gb_addr_config);
>   }
>   
> -static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
> +static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -485,12 +487,13 @@ static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
>   /**
>    * vcn_v1_0_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev)
> +static void vcn_v1_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data;
>   
>   	/* JPEG disable CGC */
> @@ -615,8 +618,9 @@ static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev)
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev)
> +static void vcn_v1_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data = 0;
>   
>   	/* enable JPEG CGC */
> @@ -680,8 +684,10 @@ static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev)
>   	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel)
> +static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					   uint8_t sram_sel)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t reg_data = 0;
>   
>   	/* disable JPEG CGC */
> @@ -734,8 +740,9 @@ static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t s
>   	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SUVD_CGC_CTRL, 0, 0xFFFFFFFF, sram_sel);
>   }
>   
> -static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev)
> +static void vcn_1_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data = 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -779,8 +786,9 @@ static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev)
>   	WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
>   }
>   
> -static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev)
> +static void vcn_1_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data = 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -823,12 +831,13 @@ static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev)
>   /**
>    * vcn_v1_0_start_spg_mode - start VCN block
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Setup and start the VCN block
>    */
> -static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
> +static int vcn_v1_0_start_spg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
>   	uint32_t rb_bufsz, tmp;
>   	uint32_t lmi_swap_cntl;
> @@ -837,13 +846,13 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
>   	/* disable byte swapping */
>   	lmi_swap_cntl = 0;
>   
> -	vcn_1_0_disable_static_power_gating(adev);
> +	vcn_1_0_disable_static_power_gating(vinst);
>   
>   	tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
>   	WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp);
>   
>   	/* disable clock gating */
> -	vcn_v1_0_disable_clock_gating(adev);
> +	vcn_v1_0_disable_clock_gating(vinst);
>   
>   	/* disable interupt */
>   	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), 0,
> @@ -885,7 +894,7 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
>   		(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v1_0_mc_resume_spg_mode(adev);
> +	vcn_v1_0_mc_resume_spg_mode(vinst);
>   
>   	WREG32_SOC15(UVD, 0, mmUVD_REG_XX_MASK_1_0, 0x10);
>   	WREG32_SOC15(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK_1_0,
> @@ -1001,8 +1010,9 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
>   	return 0;
>   }
>   
> -static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
> +static int vcn_v1_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
>   	uint32_t rb_bufsz, tmp;
>   	uint32_t lmi_swap_cntl;
> @@ -1010,7 +1020,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
>   	/* disable byte swapping */
>   	lmi_swap_cntl = 0;
>   
> -	vcn_1_0_enable_static_power_gating(adev);
> +	vcn_1_0_enable_static_power_gating(vinst);
>   
>   	/* enable dynamic power gating mode */
>   	tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
> @@ -1019,7 +1029,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
>   	WREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS, tmp);
>   
>   	/* enable clock gating */
> -	vcn_v1_0_clock_gating_dpg_mode(adev, 0);
> +	vcn_v1_0_clock_gating_dpg_mode(vinst, 0);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -1068,7 +1078,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0xFFFFFFFF, 0);
>   
> -	vcn_v1_0_mc_resume_dpg_mode(adev);
> +	vcn_v1_0_mc_resume_dpg_mode(vinst);
>   
>   	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_REG_XX_MASK, 0x10, 0xFFFFFFFF, 0);
>   	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK, 0x3, 0xFFFFFFFF, 0);
> @@ -1085,7 +1095,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
>   	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MASTINT_EN,
>   			UVD_MASTINT_EN__VCPU_EN_MASK, UVD_MASTINT_EN__VCPU_EN_MASK, 0);
>   
> -	vcn_v1_0_clock_gating_dpg_mode(adev, 1);
> +	vcn_v1_0_clock_gating_dpg_mode(vinst, 1);
>   	/* setup mmUVD_LMI_CTRL */
>   	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_CTRL,
>   		(8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
> @@ -1145,21 +1155,24 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
>   	return 0;
>   }
>   
> -static int vcn_v1_0_start(struct amdgpu_device *adev)
> +static int vcn_v1_0_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +
>   	return (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ?
> -		vcn_v1_0_start_dpg_mode(adev) : vcn_v1_0_start_spg_mode(adev);
> +		vcn_v1_0_start_dpg_mode(vinst) : vcn_v1_0_start_spg_mode(vinst);
>   }
>   
>   /**
>    * vcn_v1_0_stop_spg_mode - stop VCN block
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * stop the VCN block
>    */
> -static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev)
> +static int vcn_v1_0_stop_spg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	int tmp;
>   
>   	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> @@ -1199,13 +1212,14 @@ static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev)
>   
>   	WREG32_SOC15(UVD, 0, mmUVD_STATUS, 0);
>   
> -	vcn_v1_0_enable_clock_gating(adev);
> -	vcn_1_0_enable_static_power_gating(adev);
> +	vcn_v1_0_enable_clock_gating(vinst);
> +	vcn_1_0_enable_static_power_gating(vinst);
>   	return 0;
>   }
>   
> -static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev)
> +static int vcn_v1_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t tmp;
>   
>   	/* Wait for power status to be UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF */
> @@ -1237,14 +1251,15 @@ static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev)
>   	return 0;
>   }
>   
> -static int vcn_v1_0_stop(struct amdgpu_device *adev)
> +static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	int r;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		r = vcn_v1_0_stop_dpg_mode(adev);
> +		r = vcn_v1_0_stop_dpg_mode(vinst);
>   	else
> -		r = vcn_v1_0_stop_spg_mode(adev);
> +		r = vcn_v1_0_stop_spg_mode(vinst);
>   
>   	return r;
>   }
> @@ -1399,16 +1414,17 @@ static int vcn_v1_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_clockgating_state state)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
>   	bool enable = (state == AMD_CG_STATE_GATE);
>   
>   	if (enable) {
>   		/* wait for STATUS to clear */
>   		if (!vcn_v1_0_is_idle(adev))
>   			return -EBUSY;
> -		vcn_v1_0_enable_clock_gating(adev);
> +		vcn_v1_0_enable_clock_gating(vinst);
>   	} else {
>   		/* disable HW gating and enable Sw gating */
> -		vcn_v1_0_disable_clock_gating(adev);
> +		vcn_v1_0_disable_clock_gating(vinst);
>   	}
>   	return 0;
>   }
> @@ -1812,14 +1828,15 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	 */
>   	int ret;
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
>   
>   	if (state == adev->vcn.inst[0].cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v1_0_stop(adev);
> +		ret = vcn_v1_0_stop(vinst);
>   	else
> -		ret = vcn_v1_0_start(adev);
> +		ret = vcn_v1_0_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[0].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 11955 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 14/44] drm/amdgpu/vcn2.0: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 14/44] drm/amdgpu/vcn2.0: " Alex Deucher
@ 2025-02-05 15:01   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:01 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 9603 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> v2: index instances directly on vcn1.0 and 2.0 to make
> it clear that they only support a single instance (Lijo)
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 66 ++++++++++++++++-----------
>   1 file changed, 39 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index 8ff5a9d67cbd2..aa61d3b54f8c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -370,8 +370,9 @@ static int vcn_v2_0_resume(struct amdgpu_ip_block *ip_block)
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
> +static void vcn_v2_0_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -426,8 +427,10 @@ static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
>   	WREG32_SOC15(UVD, 0, mmUVD_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
>   }
>   
> -static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirect)
> +static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[0].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -525,12 +528,13 @@ static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirec
>   /**
>    * vcn_v2_0_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v2_0_disable_clock_gating(struct amdgpu_device *adev)
> +static void vcn_v2_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data;
>   
>   	if (amdgpu_sriov_vf(adev))
> @@ -634,9 +638,10 @@ static void vcn_v2_0_disable_clock_gating(struct amdgpu_device *adev)
>   	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
> +static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
>   		uint8_t sram_sel, uint8_t indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t reg_data = 0;
>   
>   	/* enable sw clock gating control */
> @@ -685,12 +690,13 @@ static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
>   /**
>    * vcn_v2_0_enable_clock_gating - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v2_0_enable_clock_gating(struct amdgpu_device *adev)
> +static void vcn_v2_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data = 0;
>   
>   	if (amdgpu_sriov_vf(adev))
> @@ -743,8 +749,9 @@ static void vcn_v2_0_enable_clock_gating(struct amdgpu_device *adev)
>   	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v2_0_disable_static_power_gating(struct amdgpu_device *adev)
> +static void vcn_v2_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data = 0;
>   
>   	if (amdgpu_sriov_vf(adev))
> @@ -792,8 +799,9 @@ static void vcn_v2_0_disable_static_power_gating(struct amdgpu_device *adev)
>   	WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
>   }
>   
> -static void vcn_v2_0_enable_static_power_gating(struct amdgpu_device *adev)
> +static void vcn_v2_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t data = 0;
>   
>   	if (amdgpu_sriov_vf(adev))
> @@ -834,13 +842,14 @@ static void vcn_v2_0_enable_static_power_gating(struct amdgpu_device *adev)
>   	}
>   }
>   
> -static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
> +static int vcn_v2_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
>   	uint32_t rb_bufsz, tmp;
>   
> -	vcn_v2_0_enable_static_power_gating(adev);
> +	vcn_v2_0_enable_static_power_gating(vinst);
>   
>   	/* enable dynamic power gating mode */
>   	tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
> @@ -852,7 +861,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
>   		adev->vcn.inst->dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst->dpg_sram_cpu_addr;
>   
>   	/* enable clock gating */
> -	vcn_v2_0_clock_gating_dpg_mode(adev, 0, indirect);
> +	vcn_v2_0_clock_gating_dpg_mode(vinst, 0, indirect);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -901,7 +910,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
>   
> -	vcn_v2_0_mc_resume_dpg_mode(adev, indirect);
> +	vcn_v2_0_mc_resume_dpg_mode(vinst, indirect);
>   
>   	WREG32_SOC15_DPG_MODE(0, SOC15_DPG_MODE_OFFSET(
>   		UVD, 0, mmUVD_REG_XX_MASK), 0x10, 0, indirect);
> @@ -969,8 +978,9 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect)
>   	return 0;
>   }
>   
> -static int vcn_v2_0_start(struct amdgpu_device *adev)
> +static int vcn_v2_0_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
>   	uint32_t rb_bufsz, tmp;
> @@ -981,16 +991,16 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
>   		amdgpu_dpm_enable_vcn(adev, true, 0);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram);
> +		return vcn_v2_0_start_dpg_mode(vinst, adev->vcn.inst->indirect_sram);
>   
> -	vcn_v2_0_disable_static_power_gating(adev);
> +	vcn_v2_0_disable_static_power_gating(vinst);
>   
>   	/* set uvd status busy */
>   	tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
>   	WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp);
>   
>   	/*SW clock gating */
> -	vcn_v2_0_disable_clock_gating(adev);
> +	vcn_v2_0_disable_clock_gating(vinst);
>   
>   	/* enable VCPU clock */
>   	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CNTL),
> @@ -1034,7 +1044,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
>   		(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v2_0_mc_resume(adev);
> +	vcn_v2_0_mc_resume(vinst);
>   
>   	/* release VCPU reset to boot */
>   	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0,
> @@ -1142,8 +1152,9 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
>   	return 0;
>   }
>   
> -static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev)
> +static int vcn_v2_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> @@ -1172,13 +1183,14 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev)
>   	return 0;
>   }
>   
> -static int vcn_v2_0_stop(struct amdgpu_device *adev)
> +static int vcn_v2_0_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
>   	uint32_t tmp;
>   	int r;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -		r = vcn_v2_0_stop_dpg_mode(adev);
> +		r = vcn_v2_0_stop_dpg_mode(vinst);
>   		if (r)
>   			return r;
>   		goto power_off;
> @@ -1230,8 +1242,8 @@ static int vcn_v2_0_stop(struct amdgpu_device *adev)
>   	/* clear status */
>   	WREG32_SOC15(VCN, 0, mmUVD_STATUS, 0);
>   
> -	vcn_v2_0_enable_clock_gating(adev);
> -	vcn_v2_0_enable_static_power_gating(adev);
> +	vcn_v2_0_enable_clock_gating(vinst);
> +	vcn_v2_0_enable_static_power_gating(vinst);
>   
>   power_off:
>   	if (adev->pm.dpm_enabled)
> @@ -1348,10 +1360,10 @@ static int vcn_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   		/* wait for STATUS to clear */
>   		if (!vcn_v2_0_is_idle(adev))
>   			return -EBUSY;
> -		vcn_v2_0_enable_clock_gating(adev);
> +		vcn_v2_0_enable_clock_gating(&adev->vcn.inst[0]);
>   	} else {
>   		/* disable HW gating and enable Sw gating */
> -		vcn_v2_0_disable_clock_gating(adev);
> +		vcn_v2_0_disable_clock_gating(&adev->vcn.inst[0]);
>   	}
>   	return 0;
>   }
> @@ -1818,9 +1830,9 @@ static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v2_0_stop(adev);
> +		ret = vcn_v2_0_stop(adev->vcn.inst);
>   	else
> -		ret = vcn_v2_0_start(adev);
> +		ret = vcn_v2_0_start(adev->vcn.inst);
>   
>   	if (!ret)
>   		adev->vcn.inst[0].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 10173 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 15/44] drm/amdgpu/vcn2.5: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 15/44] drm/amdgpu/vcn2.5: " Alex Deucher
@ 2025-02-05 15:02   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:02 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 10426 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 79 +++++++++++++++++----------
>   1 file changed, 50 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index 4f9f3de023ffd..69cf42a4a3f18 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -468,13 +468,14 @@ static int vcn_v2_5_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v2_5_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to resume
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i)
> +static void vcn_v2_5_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	uint32_t size;
>   	uint32_t offset;
>   
> @@ -527,8 +528,11 @@ static void vcn_v2_5_mc_resume(struct amdgpu_device *adev, int i)
>   		     AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared)));
>   }
>   
> -static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.inst[inst_idx].fw->size + 4);
>   	uint32_t offset;
>   
> @@ -626,13 +630,14 @@ static void vcn_v2_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
>   /**
>    * vcn_v2_5_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to disable clockgating on
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i)
> +static void vcn_v2_5_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->vcn.harvest_config & (1 << i))
> @@ -738,9 +743,11 @@ static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
> -		uint8_t sram_sel, int inst_idx, uint8_t indirect)
> +static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +		uint8_t sram_sel, uint8_t indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   
>   	/* enable sw clock gating control */
> @@ -789,13 +796,14 @@ static void vcn_v2_5_clock_gating_dpg_mode(struct amdgpu_device *adev,
>   /**
>    * vcn_v2_5_enable_clock_gating_inst - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to enable clockgating on
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i)
> +static void vcn_v2_5_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	uint32_t data = 0;
>   
>   	if (adev->vcn.harvest_config & (1 << i))
> @@ -846,9 +854,11 @@ static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, i, mmUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
> +static void vcn_v2_6_enable_ras(struct amdgpu_vcn_inst *vinst,
>   				bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t tmp;
>   
>   	if (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(2, 6, 0))
> @@ -873,8 +883,10 @@ static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
>   			      tmp, 0, indirect);
>   }
>   
> -static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v2_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
>   	uint32_t rb_bufsz, tmp;
> @@ -892,7 +904,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   		adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
>   
>   	/* enable clock gating */
> -	vcn_v2_5_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
> +	vcn_v2_5_clock_gating_dpg_mode(vinst, 0, indirect);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -941,7 +953,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
>   
> -	vcn_v2_5_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v2_5_mc_resume_dpg_mode(vinst, indirect);
>   
>   	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
>   		VCN, 0, mmUVD_REG_XX_MASK), 0x10, 0, indirect);
> @@ -952,7 +964,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
>   		VCN, 0, mmUVD_LMI_CTRL2), 0, 0, indirect);
>   
> -	vcn_v2_6_enable_ras(adev, inst_idx, indirect);
> +	vcn_v2_6_enable_ras(vinst, indirect);
>   
>   	/* unblock VCPU register access */
>   	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
> @@ -1017,8 +1029,10 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   	return 0;
>   }
>   
> -static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
> +static int vcn_v2_5_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_fw_shared *fw_shared =
>   		adev->vcn.inst[i].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
> @@ -1032,7 +1046,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
>   		amdgpu_dpm_enable_vcn(adev, true, i);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v2_5_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable register anti-hang mechanism */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
> @@ -1046,7 +1060,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
>   		return 0;
>   
>   	/* SW clock gating */
> -	vcn_v2_5_disable_clock_gating(adev, i);
> +	vcn_v2_5_disable_clock_gating(vinst);
>   
>   	/* enable VCPU clock */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
> @@ -1091,7 +1105,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
>   		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v2_5_mc_resume(adev, i);
> +	vcn_v2_5_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, i, mmUVD_GFX8_ADDR_CONFIG,
> @@ -1396,8 +1410,10 @@ static int vcn_v2_5_sriov_start(struct amdgpu_device *adev)
>   	return vcn_v2_5_mmsch_start(adev, &adev->virt.mm_table);
>   }
>   
> -static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static int vcn_v2_5_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t tmp;
>   
>   	/* Wait for power status to be 1 */
> @@ -1424,15 +1440,17 @@ static int vcn_v2_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   	return 0;
>   }
>   
> -static int vcn_v2_5_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v2_5_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	uint32_t tmp;
>   	int r;
>   
>   	if (adev->vcn.harvest_config & (1 << i))
>   		return 0;
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v2_5_stop_dpg_mode(adev, i);
> +		return vcn_v2_5_stop_dpg_mode(vinst);
>   
>   	/* wait for vcn idle */
>   	r = SOC15_WAIT_ON_RREG(VCN, i, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
> @@ -1475,7 +1493,7 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev, int i)
>   	/* clear status */
>   	WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
>   
> -	vcn_v2_5_enable_clock_gating(adev, i);
> +	vcn_v2_5_enable_clock_gating(vinst);
>   
>   	/* enable register anti-hang mechanism */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS),
> @@ -1810,12 +1828,14 @@ static int vcn_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   		return 0;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
>   		if (enable) {
>   			if (!vcn_v2_5_is_idle(adev))
>   				return -EBUSY;
> -			vcn_v2_5_enable_clock_gating(adev, i);
> +			vcn_v2_5_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v2_5_disable_clock_gating(adev, i);
> +			vcn_v2_5_disable_clock_gating(vinst);
>   		}
>   	}
>   
> @@ -1827,6 +1847,7 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   					       int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret;
>   
>   	if (amdgpu_sriov_vf(adev))
> @@ -1836,9 +1857,9 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v2_5_stop(adev, i);
> +		ret = vcn_v2_5_stop(vinst);
>   	else
> -		ret = vcn_v2_5_start(adev, i);
> +		ret = vcn_v2_5_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 10976 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 16/44] drm/amdgpu/vcn4.0: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 16/44] drm/amdgpu/vcn4.0: " Alex Deucher
@ 2025-02-05 15:03   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:03 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 13517 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 116 +++++++++++++++-----------
>   1 file changed, 67 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index 1200815b3eee8..3d70e2cc81982 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -449,13 +449,14 @@ static int vcn_v4_0_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v4_0_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -509,14 +510,16 @@ static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v4_0_mc_resume_dpg_mode - memory controller programming for dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Let the VCN memory controller know it's offsets with dpg mode
>    */
> -static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   	hdr = (const struct common_firmware_header *)adev->vcn.inst[inst_idx].fw->data;
> @@ -616,13 +619,14 @@ static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx
>   /**
>    * vcn_v4_0_disable_static_power_gating - disable VCN static power gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable static power gating for VCN block
>    */
> -static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data = 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -681,13 +685,14 @@ static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int
>   /**
>    * vcn_v4_0_enable_static_power_gating - enable VCN static power gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable static power gating for VCN block
>    */
> -static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -736,13 +741,14 @@ static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int
>   /**
>    * vcn_v4_0_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -847,16 +853,18 @@ static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v4_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    * @sram_sel: sram select
> - * @inst_idx: instance number index
>    * @indirect: indirectly write sram
>    *
>    * Disable clock gating for VCN block with dpg mode
>    */
> -static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
> -      int inst_idx, uint8_t indirect)
> +static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +						   uint8_t sram_sel,
> +						   uint8_t indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -904,13 +912,14 @@ static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, u
>   /**
>    * vcn_v4_0_enable_clock_gating - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -960,9 +969,11 @@ static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
>   	WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
>   }
>   
> -static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx,
> +static void vcn_v4_0_enable_ras(struct amdgpu_vcn_inst *vinst,
>   				bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t tmp;
>   
>   	if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
> @@ -985,14 +996,15 @@ static void vcn_v4_0_enable_ras(struct amdgpu_device *adev, int inst_idx,
>   /**
>    * vcn_v4_0_start_dpg_mode - VCN start with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Start VCN block with dpg mode
>    */
> -static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v4_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst, bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -1010,7 +1022,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   		adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
>   
>   	/* enable clock gating */
> -	vcn_v4_0_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
> +	vcn_v4_0_disable_clock_gating_dpg_mode(vinst, 0, indirect);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -1058,7 +1070,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
>   
> -	vcn_v4_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v4_0_mc_resume_dpg_mode(vinst, indirect);
>   
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
>   	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
> @@ -1070,7 +1082,7 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
>   		VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);
>   
> -	vcn_v4_0_enable_ras(adev, inst_idx, indirect);
> +	vcn_v4_0_enable_ras(vinst, indirect);
>   
>   	/* enable master interrupt */
>   	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
> @@ -1114,13 +1126,14 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
>   /**
>    * vcn_v4_0_start - VCN start
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to start
> + * @vinst: VCN instance
>    *
>    * Start VCN block
>    */
> -static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
> +static int vcn_v4_0_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -1135,17 +1148,17 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v4_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
> -	vcn_v4_0_disable_static_power_gating(adev, i);
> +	vcn_v4_0_disable_static_power_gating(vinst);
>   
>   	/* set VCN status busy */
>   	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
>   	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
>   
>   	/*SW clock gating */
> -	vcn_v4_0_disable_clock_gating(adev, i);
> +	vcn_v4_0_disable_clock_gating(vinst);
>   
>   	/* enable VCPU clock */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> @@ -1198,7 +1211,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
>   		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v4_0_mc_resume(adev, i);
> +	vcn_v4_0_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> @@ -1541,13 +1554,14 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev)
>   /**
>    * vcn_v4_0_stop_dpg_mode - VCN stop with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    *
>    * Stop VCN block with dpg mode
>    */
> -static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v4_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> @@ -1571,13 +1585,14 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   /**
>    * vcn_v4_0_stop - VCN stop
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to stop
> + * @vinst: VCN instance
>    *
>    * Stop VCN block
>    */
> -static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v4_0_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	uint32_t tmp;
>   	int r = 0;
> @@ -1589,7 +1604,7 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
>   	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -		vcn_v4_0_stop_dpg_mode(adev, i);
> +		vcn_v4_0_stop_dpg_mode(vinst);
>   		return 0;
>   	}
>   
> @@ -1642,10 +1657,10 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
>   
>   	/* apply HW clock gating */
> -	vcn_v4_0_enable_clock_gating(adev, i);
> +	vcn_v4_0_enable_clock_gating(vinst);
>   
>   	/* enable VCN power gating */
> -	vcn_v4_0_enable_static_power_gating(adev, i);
> +	vcn_v4_0_enable_static_power_gating(vinst);
>   
>   	if (adev->pm.dpm_enabled)
>   		amdgpu_dpm_enable_vcn(adev, false, i);
> @@ -2044,15 +2059,17 @@ static int vcn_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	int i;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
>   		if (enable) {
>   			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
>   				return -EBUSY;
> -			vcn_v4_0_enable_clock_gating(adev, i);
> +			vcn_v4_0_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v4_0_disable_clock_gating(adev, i);
> +			vcn_v4_0_disable_clock_gating(vinst);
>   		}
>   	}
>   
> @@ -2064,6 +2081,7 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   					       int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret = 0;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
> @@ -2079,9 +2097,9 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v4_0_stop(adev, i);
> +		ret = vcn_v4_0_stop(vinst);
>   	else
> -		ret = vcn_v4_0_start(adev, i);
> +		ret = vcn_v4_0_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 13868 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 17/44] drm/amdgpu/vcn4.0.3: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 17/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-02-05 15:03   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:03 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 10823 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 93 ++++++++++++++-----------
>   1 file changed, 54 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 1407cb4b553b7..a3fbfaac76603 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -431,13 +431,14 @@ static int vcn_v4_0_3_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v4_0_3_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v4_0_3_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t offset, size, vcn_inst;
>   	const struct common_firmware_header *hdr;
>   
> @@ -505,14 +506,16 @@ static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx)
>   /**
>    * vcn_v4_0_3_mc_resume_dpg_mode - memory controller programming for dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Let the VCN memory controller know it's offsets with dpg mode
>    */
> -static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					  bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -619,13 +622,14 @@ static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
>   /**
>    * vcn_v4_0_3_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t data;
>   	int vcn_inst;
>   
> @@ -712,16 +716,18 @@ static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst
>   /**
>    * vcn_v4_0_3_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    * @sram_sel: sram select
> - * @inst_idx: instance number index
>    * @indirect: indirectly write sram
>    *
>    * Disable clock gating for VCN block with dpg mode
>    */
> -static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
> -				int inst_idx, uint8_t indirect)
> +static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +						     uint8_t sram_sel,
> +						     uint8_t indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -763,13 +769,14 @@ static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev,
>   /**
>    * vcn_v4_0_3_enable_clock_gating - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t data;
>   	int vcn_inst;
>   
> @@ -814,14 +821,16 @@ static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_
>   /**
>    * vcn_v4_0_3_start_dpg_mode - VCN start with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Start VCN block with dpg mode
>    */
> -static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared =
>   						adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
> @@ -849,7 +858,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   	}
>   
>   	/* enable clock gating */
> -	vcn_v4_0_3_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
> +	vcn_v4_0_3_disable_clock_gating_dpg_mode(vinst, 0, indirect);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -899,7 +908,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
>   
> -	vcn_v4_0_3_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v4_0_3_mc_resume_dpg_mode(vinst, indirect);
>   
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
>   	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
> @@ -1146,13 +1155,14 @@ static int vcn_v4_0_3_start_sriov(struct amdgpu_device *adev)
>   /**
>    * vcn_v4_0_3_start - VCN start
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to start
> + * @vinst: VCN instance
>    *
>    * Start VCN block
>    */
> -static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
> +static int vcn_v4_0_3_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	int j, k, r, vcn_inst;
> @@ -1162,7 +1172,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>   		amdgpu_dpm_enable_vcn(adev, true, i);
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
>   
>   	vcn_inst = GET_INST(VCN, i);
>   	/* set VCN status busy */
> @@ -1171,7 +1181,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
>   
>   	/* SW clock gating */
> -	vcn_v4_0_3_disable_clock_gating(adev, i);
> +	vcn_v4_0_3_disable_clock_gating(vinst);
>   
>   	/* enable VCPU clock */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
> @@ -1225,7 +1235,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>   		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v4_0_3_mc_resume(adev, i);
> +	vcn_v4_0_3_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
> @@ -1319,13 +1329,14 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>   /**
>    * vcn_v4_0_3_stop_dpg_mode - VCN stop with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    *
>    * Stop VCN block with dpg mode
>    */
> -static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t tmp;
>   	int vcn_inst;
>   
> @@ -1351,13 +1362,14 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   /**
>    * vcn_v4_0_3_stop - VCN stop
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to stop
> + * @vinst: VCN instance
>    *
>    * Stop VCN block
>    */
> -static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	int r = 0, vcn_inst;
>   	uint32_t tmp;
> @@ -1368,7 +1380,7 @@ static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
>   	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -		vcn_v4_0_3_stop_dpg_mode(adev, i);
> +		vcn_v4_0_3_stop_dpg_mode(vinst);
>   		return 0;
>   	}
>   
> @@ -1425,7 +1437,7 @@ static int vcn_v4_0_3_stop(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
>   
>   	/* apply HW clock gating */
> -	vcn_v4_0_3_enable_clock_gating(adev, i);
> +	vcn_v4_0_3_enable_clock_gating(vinst);
>   
>   Done:
>   	if (adev->pm.dpm_enabled)
> @@ -1662,13 +1674,15 @@ static int vcn_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	int i;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
>   		if (enable) {
>   			if (RREG32_SOC15(VCN, GET_INST(VCN, i),
>   					 regUVD_STATUS) != UVD_STATUS__IDLE)
>   				return -EBUSY;
> -			vcn_v4_0_3_enable_clock_gating(adev, i);
> +			vcn_v4_0_3_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v4_0_3_disable_clock_gating(adev, i);
> +			vcn_v4_0_3_disable_clock_gating(vinst);
>   		}
>   	}
>   	return 0;
> @@ -1679,6 +1693,7 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret = 0;
>   
>   	/* for SRIOV, guest should not control VCN Power-gating
> @@ -1694,9 +1709,9 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v4_0_3_stop(adev, i);
> +		ret = vcn_v4_0_3_stop(vinst);
>   	else
> -		ret = vcn_v4_0_3_start(adev, i);
> +		ret = vcn_v4_0_3_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 11272 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 18/44] drm/amdgpu/vcn4.0.5: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 18/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-02-05 15:04   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:04 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 12473 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 111 ++++++++++++++----------
>   1 file changed, 64 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index c3a2826a59631..295f39b2222d5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -385,13 +385,14 @@ static int vcn_v4_0_5_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v4_0_5_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_5_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -445,14 +446,16 @@ static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v4_0_5_mc_resume_dpg_mode - memory controller programming for dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Let the VCN memory controller know it's offsets with dpg mode
>    */
> -static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					  bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -559,13 +562,14 @@ static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
>   /**
>    * vcn_v4_0_5_disable_static_power_gating - disable VCN static power gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable static power gating for VCN block
>    */
> -static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data = 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -618,13 +622,14 @@ static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, i
>   /**
>    * vcn_v4_0_5_enable_static_power_gating - enable VCN static power gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable static power gating for VCN block
>    */
> -static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -660,13 +665,14 @@ static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, in
>   /**
>    * vcn_v4_0_5_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -771,16 +777,18 @@ static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst
>   /**
>    * vcn_v4_0_5_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    * @sram_sel: sram select
> - * @inst_idx: instance number index
>    * @indirect: indirectly write sram
>    *
>    * Disable clock gating for VCN block with dpg mode
>    */
> -static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
> -		int inst_idx, uint8_t indirect)
> +static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +						     uint8_t sram_sel,
> +						     uint8_t indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -828,13 +836,14 @@ static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev,
>   /**
>    * vcn_v4_0_5_enable_clock_gating - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
> @@ -887,14 +896,16 @@ static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v4_0_5_start_dpg_mode - VCN start with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Start VCN block with dpg mode
>    */
> -static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -913,7 +924,7 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   					(uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
>   
>   	/* enable clock gating */
> -	vcn_v4_0_5_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
> +	vcn_v4_0_5_disable_clock_gating_dpg_mode(vinst, 0, indirect);
>   
>   	/* enable VCPU clock */
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
> @@ -961,7 +972,7 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
>   
> -	vcn_v4_0_5_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v4_0_5_mc_resume_dpg_mode(vinst, indirect);
>   
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
>   	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
> @@ -1014,13 +1025,14 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   /**
>    * vcn_v4_0_5_start - VCN start
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to start
> + * @vinst: VCN instance
>    *
>    * Start VCN block
>    */
> -static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
> +static int vcn_v4_0_5_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -1035,17 +1047,17 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v4_0_5_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
> -	vcn_v4_0_5_disable_static_power_gating(adev, i);
> +	vcn_v4_0_5_disable_static_power_gating(vinst);
>   
>   	/* set VCN status busy */
>   	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
>   	WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
>   
>   	/* SW clock gating */
> -	vcn_v4_0_5_disable_clock_gating(adev, i);
> +	vcn_v4_0_5_disable_clock_gating(vinst);
>   
>   	/* enable VCPU clock */
>   	WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
> @@ -1098,7 +1110,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
>   		      (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
>   		      (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
>   
> -	vcn_v4_0_5_mc_resume(adev, i);
> +	vcn_v4_0_5_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> @@ -1194,13 +1206,14 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
>   /**
>    * vcn_v4_0_5_stop_dpg_mode - VCN stop with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    *
>    * Stop VCN block with dpg mode
>    */
> -static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t tmp;
>   
>   	/* Wait for power status to be 1 */
> @@ -1222,13 +1235,14 @@ static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   /**
>    * vcn_v4_0_5_stop - VCN stop
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to stop
> + * @vinst: VCN instance
>    *
>    * Stop VCN block
>    */
> -static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v4_0_5_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	uint32_t tmp;
>   	int r = 0;
> @@ -1240,7 +1254,7 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
>   	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -		vcn_v4_0_5_stop_dpg_mode(adev, i);
> +		vcn_v4_0_5_stop_dpg_mode(vinst);
>   		return 0;
>   	}
>   
> @@ -1293,10 +1307,10 @@ static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
>   
>   	/* apply HW clock gating */
> -	vcn_v4_0_5_enable_clock_gating(adev, i);
> +	vcn_v4_0_5_enable_clock_gating(vinst);
>   
>   	/* enable VCN power gating */
> -	vcn_v4_0_5_enable_static_power_gating(adev, i);
> +	vcn_v4_0_5_enable_static_power_gating(vinst);
>   
>   	if (adev->pm.dpm_enabled)
>   		amdgpu_dpm_enable_vcn(adev, false, i);
> @@ -1526,15 +1540,17 @@ static int vcn_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	int i;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
>   		if (enable) {
>   			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
>   				return -EBUSY;
> -			vcn_v4_0_5_enable_clock_gating(adev, i);
> +			vcn_v4_0_5_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v4_0_5_disable_clock_gating(adev, i);
> +			vcn_v4_0_5_disable_clock_gating(vinst);
>   		}
>   	}
>   
> @@ -1546,15 +1562,16 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret = 0;
>   
>   	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v4_0_5_stop(adev, i);
> +		ret = vcn_v4_0_5_stop(vinst);
>   	else
> -		ret = vcn_v4_0_5_start(adev, i);
> +		ret = vcn_v4_0_5_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 12870 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 19/44] drm/amdgpu/vcn5.0.0: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 19/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
@ 2025-02-05 15:05   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:05 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 11267 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 99 ++++++++++++++-----------
>   1 file changed, 55 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index d3e4d02c12a06..a71960d899e38 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -367,13 +367,14 @@ static int vcn_v5_0_0_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v5_0_0_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_0_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -427,14 +428,16 @@ static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v5_0_0_mc_resume_dpg_mode - memory controller programming for dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Let the VCN memory controller know it's offsets with dpg mode
>    */
> -static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					  bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -537,13 +540,14 @@ static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
>   /**
>    * vcn_v5_0_0_disable_static_power_gating - disable VCN static power gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable static power gating for VCN block
>    */
> -static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data = 0;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -604,13 +608,14 @@ static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, i
>   /**
>    * vcn_v5_0_0_enable_static_power_gating - enable VCN static power gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable static power gating for VCN block
>    */
> -static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t data;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
> @@ -650,12 +655,11 @@ static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, in
>   /**
>    * vcn_v5_0_0_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
>   	return;
>   }
> @@ -664,15 +668,15 @@ static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst
>   /**
>    * vcn_v5_0_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    * @sram_sel: sram select
> - * @inst_idx: instance number index
>    * @indirect: indirectly write sram
>    *
>    * Disable clock gating for VCN block with dpg mode
>    */
> -static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
> -	int inst_idx, uint8_t indirect)
> +static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +						     uint8_t sram_sel,
> +						     uint8_t indirect)
>   {
>   	return;
>   }
> @@ -681,12 +685,11 @@ static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev,
>   /**
>    * vcn_v5_0_0_enable_clock_gating - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
>   	return;
>   }
> @@ -694,14 +697,16 @@ static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v5_0_0_start_dpg_mode - VCN start with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Start VCN block with dpg mode
>    */
> -static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_vcn5_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -741,7 +746,7 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   	WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
>   		VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect);
>   
> -	vcn_v5_0_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v5_0_0_mc_resume_dpg_mode(vinst, indirect);
>   
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
>   	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
> @@ -793,13 +798,14 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   /**
>    * vcn_v5_0_0_start - VCN start
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to start
> + * @vinst: VCN instance
>    *
>    * Start VCN block
>    */
> -static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
> +static int vcn_v5_0_0_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -814,10 +820,10 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v5_0_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
>   
>   	/* disable VCN power gating */
> -	vcn_v5_0_0_disable_static_power_gating(adev, i);
> +	vcn_v5_0_0_disable_static_power_gating(vinst);
>   
>   	/* set VCN status busy */
>   	tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
> @@ -848,7 +854,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
>   		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
>   		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
>   
> -	vcn_v5_0_0_mc_resume(adev, i);
> +	vcn_v5_0_0_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
> @@ -944,13 +950,14 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
>   /**
>    * vcn_v5_0_0_stop_dpg_mode - VCN stop with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    *
>    * Stop VCN block with dpg mode
>    */
> -static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> @@ -974,13 +981,14 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   /**
>    * vcn_v5_0_0_stop - VCN stop
>    *
> - * @adev: amdgpu_device pointer
> - * @i: instance to stop
> + * @vinst: VCN instance
>    *
>    * Stop VCN block
>    */
> -static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v5_0_0_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn5_fw_shared *fw_shared;
>   	uint32_t tmp;
>   	int r = 0;
> @@ -992,7 +1000,7 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
>   	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -		vcn_v5_0_0_stop_dpg_mode(adev, i);
> +		vcn_v5_0_0_stop_dpg_mode(vinst);
>   		return 0;
>   	}
>   
> @@ -1045,7 +1053,7 @@ static int vcn_v5_0_0_stop(struct amdgpu_device *adev, int i)
>   	WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
>   
>   	/* enable VCN power gating */
> -	vcn_v5_0_0_enable_static_power_gating(adev, i);
> +	vcn_v5_0_0_enable_static_power_gating(vinst);
>   
>   	if (adev->pm.dpm_enabled)
>   		amdgpu_dpm_enable_vcn(adev, false, i);
> @@ -1271,15 +1279,17 @@ static int vcn_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	int i;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
>   		if (adev->vcn.harvest_config & (1 << i))
>   			continue;
>   
>   		if (enable) {
>   			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
>   				return -EBUSY;
> -			vcn_v5_0_0_enable_clock_gating(adev, i);
> +			vcn_v5_0_0_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v5_0_0_disable_clock_gating(adev, i);
> +			vcn_v5_0_0_disable_clock_gating(vinst);
>   		}
>   	}
>   
> @@ -1291,15 +1301,16 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret = 0;
>   
>   	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v5_0_0_stop(adev, i);
> +		ret = vcn_v5_0_0_stop(vinst);
>   	else
> -		ret = vcn_v5_0_0_start(adev, i);
> +		ret = vcn_v5_0_0_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 11669 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 20/44] drm/amdgpu/vcn5.0.1: convert internal functions to use vcn_inst
  2025-01-31 16:57 ` [PATCH 20/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
@ 2025-02-05 15:05   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-05 15:05 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 8190 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Pass the vcn instance structure to these functions rather
> than adev and the instance number.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 71 ++++++++++++++-----------
>   1 file changed, 41 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> index f49fdf2bb6e33..8eccb45b04d2c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> @@ -282,13 +282,14 @@ static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block)
>   /**
>    * vcn_v5_0_1_mc_resume - memory controller programming
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Let the VCN memory controller know it's offsets
>    */
> -static void vcn_v5_0_1_mc_resume(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_1_mc_resume(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst = vinst->inst;
>   	uint32_t offset, size, vcn_inst;
>   	const struct common_firmware_header *hdr;
>   
> @@ -344,14 +345,16 @@ static void vcn_v5_0_1_mc_resume(struct amdgpu_device *adev, int inst)
>   /**
>    * vcn_v5_0_1_mc_resume_dpg_mode - memory controller programming for dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Let the VCN memory controller know it's offsets with dpg mode
>    */
> -static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +					  bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t offset, size;
>   	const struct common_firmware_header *hdr;
>   
> @@ -456,38 +459,38 @@ static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i
>   /**
>    * vcn_v5_0_1_disable_clock_gating - disable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Disable clock gating for VCN block
>    */
> -static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
>   }
>   
>   /**
>    * vcn_v5_0_1_enable_clock_gating - enable VCN clock gating
>    *
> - * @adev: amdgpu_device pointer
> - * @inst: instance number
> + * @vinst: VCN instance
>    *
>    * Enable clock gating for VCN block
>    */
> -static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_device *adev, int inst)
> +static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_vcn_inst *vinst)
>   {
>   }
>   
>   /**
>    * vcn_v5_0_1_start_dpg_mode - VCN start with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @indirect: indirectly write sram
>    *
>    * Start VCN block with dpg mode
>    */
> -static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
> +static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     bool indirect)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared =
>   		adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
>   	struct amdgpu_ring *ring;
> @@ -535,7 +538,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   	WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(
>   		VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect);
>   
> -	vcn_v5_0_1_mc_resume_dpg_mode(adev, inst_idx, indirect);
> +	vcn_v5_0_1_mc_resume_dpg_mode(vinst, indirect);
>   
>   	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
>   	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
> @@ -589,12 +592,14 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b
>   /**
>    * vcn_v5_0_1_start - VCN start
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Start VCN block
>    */
> -static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
> +static int vcn_v5_0_1_start(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t tmp;
> @@ -606,7 +611,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
>   	fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> -		return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> +		return vcn_v5_0_1_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);
>   
>   	vcn_inst = GET_INST(VCN, i);
>   
> @@ -639,7 +644,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
>   		     UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
>   		     UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
>   
> -	vcn_v5_0_1_mc_resume(adev, i);
> +	vcn_v5_0_1_mc_resume(vinst);
>   
>   	/* VCN global tiling registers */
>   	WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
> @@ -739,13 +744,14 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
>   /**
>    * vcn_v5_0_1_stop_dpg_mode - VCN stop with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    *
>    * Stop VCN block with dpg mode
>    */
> -static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
> +static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t tmp;
>   	int vcn_inst;
>   
> @@ -767,12 +773,14 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
>   /**
>    * vcn_v5_0_1_stop - VCN stop
>    *
> - * @adev: amdgpu_device pointer
> + * @vinst: VCN instance
>    *
>    * Stop VCN block
>    */
> -static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i)
> +static int vcn_v5_0_1_stop(struct amdgpu_vcn_inst *vinst)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int i = vinst->inst;
>   	volatile struct amdgpu_vcn4_fw_shared *fw_shared;
>   	uint32_t tmp;
>   	int r = 0, vcn_inst;
> @@ -783,7 +791,7 @@ static int vcn_v5_0_1_stop(struct amdgpu_device *adev, int i)
>   	fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
>   
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> -		vcn_v5_0_1_stop_dpg_mode(adev, i);
> +		vcn_v5_0_1_stop_dpg_mode(vinst);
>   		return 0;
>   	}
>   
> @@ -1005,12 +1013,14 @@ static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
>   	int i;
>   
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
>   		if (enable) {
>   			if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE)
>   				return -EBUSY;
> -			vcn_v5_0_1_enable_clock_gating(adev, i);
> +			vcn_v5_0_1_enable_clock_gating(vinst);
>   		} else {
> -			vcn_v5_0_1_disable_clock_gating(adev, i);
> +			vcn_v5_0_1_disable_clock_gating(vinst);
>   		}
>   	}
>   
> @@ -1022,15 +1032,16 @@ static int vcn_v5_0_1_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
>   	int ret = 0;
>   
>   	if (state == adev->vcn.inst[i].cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> -		ret = vcn_v5_0_1_stop(adev, i);
> +		ret = vcn_v5_0_1_stop(vinst);
>   	else
> -		ret = vcn_v5_0_1_start(adev, i);
> +		ret = vcn_v5_0_1_start(vinst);
>   
>   	if (!ret)
>   		adev->vcn.inst[i].cur_state = state;

[-- Attachment #2: Type: text/html, Size: 8744 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance
  2025-02-05  3:06   ` Boyuan Zhang
@ 2025-02-05 20:09     ` Alex Deucher
  2025-02-06 13:39       ` Boyuan Zhang
  0 siblings, 1 reply; 74+ messages in thread
From: Alex Deucher @ 2025-02-05 20:09 UTC (permalink / raw)
  To: Boyuan Zhang; +Cc: Alex Deucher, amd-gfx

On Tue, Feb 4, 2025 at 10:42 PM Boyuan Zhang <Boyuan.Zhang@amd.com> wrote:
>
>
> On 2025-01-31 11:57, Alex Deucher wrote:
> > Move more per instance data into the per instance structure.
> >
> > v2: index instances directly on vcn1.0 and 2.0 to make
> > it clear that they only support a single instance (Lijo)
> >
> > Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> > ---
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |   2 +-
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 196 ++++++++++++------------
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  17 +-
> >   drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c  |   4 +-
> >   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   |  42 ++---
> >   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  92 +++++------
> >   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  51 +++---
> >   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  67 ++++----
> >   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  19 ++-
> >   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  14 +-
> >   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  18 ++-
> >   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  16 +-
> >   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |   8 +-
> >   13 files changed, 279 insertions(+), 267 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> > index 2c76bc5e25d92..5ee2ae66ed36b 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> > @@ -480,7 +480,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
> >                       if (adev->vcn.harvest_config & (1 << i))
> >                               continue;
> >
> > -                     for (j = 0; j < adev->vcn.num_enc_rings; j++)
> > +                     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; j++)
> >                               if (adev->vcn.inst[i].ring_enc[j].sched.ready)
> >                                       ++num_rings;
> >               }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> > index 0c3081a198d9e..9901b8e17f305 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> > @@ -127,93 +127,88 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
> >       unsigned int fw_shared_size, log_offset;
> >       int i, r;
> >
> > -     mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
> >       for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> > +             mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
> >               mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
> >               atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
> >               INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
> >               atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
> > -     }
> > -
> > -     if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
> > -         (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> > -             adev->vcn.indirect_sram = true;
> > -
> > -     /*
> > -      * Some Steam Deck's BIOS versions are incompatible with the
> > -      * indirect SRAM mode, leading to amdgpu being unable to get
> > -      * properly probed (and even potentially crashing the kernel).
> > -      * Hence, check for these versions here - notice this is
> > -      * restricted to Vangogh (Deck's APU).
> > -      */
> > -     if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
> > -             const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
> > -
> > -             if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
> > -                  !strncmp("F7A0114", bios_ver, 7))) {
> > -                     adev->vcn.indirect_sram = false;
> > -                     dev_info(adev->dev,
> > -                             "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
> > +             if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
> > +                 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
> > +                     adev->vcn.inst[i].indirect_sram = true;
> > +
> > +             /*
> > +              * Some Steam Deck's BIOS versions are incompatible with the
> > +              * indirect SRAM mode, leading to amdgpu being unable to get
> > +              * properly probed (and even potentially crashing the kernel).
> > +              * Hence, check for these versions here - notice this is
> > +              * restricted to Vangogh (Deck's APU).
> > +              */
> > +             if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
> > +                     const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
> > +
> > +                     if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
> > +                                      !strncmp("F7A0114", bios_ver, 7))) {
> > +                             adev->vcn.inst[i].indirect_sram = false;
> > +                             dev_info(adev->dev,
> > +                                      "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
> > +                     }
> >               }
> > -     }
> >
> > -     /* from vcn4 and above, only unified queue is used */
> > -     adev->vcn.using_unified_queue =
> > -             amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
> > -
> > -     hdr = (const struct common_firmware_header *)adev->vcn.inst[0].fw->data;
> > -     adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
> > -
> > -     /* Bit 20-23, it is encode major and non-zero for new naming convention.
> > -      * This field is part of version minor and DRM_DISABLED_FLAG in old naming
> > -      * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
> > -      * is zero in old naming convention, this field is always zero so far.
> > -      * These four bits are used to tell which naming convention is present.
> > -      */
> > -     fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
> > -     if (fw_check) {
> > -             unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
> > -
> > -             fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
> > -             enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
> > -             enc_major = fw_check;
> > -             dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
> > -             vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> > -             DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> > -                     enc_major, enc_minor, dec_ver, vep, fw_rev);
> > -     } else {
> > -             unsigned int version_major, version_minor, family_id;
> > +             /* from vcn4 and above, only unified queue is used */
> > +             adev->vcn.inst[i].using_unified_queue =
> > +                     amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
> > +
> > +             hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
> > +             adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
> > +             adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
> > +
> > +             /* Bit 20-23, it is encode major and non-zero for new naming convention.
> > +              * This field is part of version minor and DRM_DISABLED_FLAG in old naming
> > +              * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
> > +              * is zero in old naming convention, this field is always zero so far.
> > +              * These four bits are used to tell which naming convention is present.
> > +              */
> > +             fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
> > +             if (fw_check) {
> > +                     unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
> > +
> > +                     fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
> > +                     enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
> > +                     enc_major = fw_check;
> > +                     dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
> > +                     vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> > +                     DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> > +                              enc_major, enc_minor, dec_ver, vep, fw_rev);
> > +             } else {
> > +                     unsigned int version_major, version_minor, family_id;
> >
> > -             family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> > -             version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> > -             version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> > -             DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> > -                     version_major, version_minor, family_id);
> > -     }
> > +                     family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> > +                     version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> > +                     version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> > +                     DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> > +                              version_major, version_minor, family_id);
> > +             }
> >
> > -     bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
> > -     if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
> > -             bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
> > +             bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
> > +             if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
> > +                     bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
> >
> > -     if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
> > -             fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
> > -             log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
> > -     } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
> > -             fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
> > -             log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
> > -     } else {
> > -             fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
> > -             log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
> > -     }
> > -
> > -     bo_size += fw_shared_size;
> > +             if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
> > +                     fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
> > +                     log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
> > +             } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
> > +                     fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
> > +                     log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
> > +             } else {
> > +                     fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
> > +                     log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
> > +             }
> >
> > -     if (amdgpu_vcnfw_log)
> > -             bo_size += AMDGPU_VCNFW_LOG_SIZE;
> > +             bo_size += fw_shared_size;
> >
> > -     for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> > -             if (adev->vcn.harvest_config & (1 << i))
> > -                     continue;
> > +             if (amdgpu_vcnfw_log)
> > +                     bo_size += AMDGPU_VCNFW_LOG_SIZE;
> >
> >               r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
> >                                           AMDGPU_GEM_DOMAIN_VRAM |
> > @@ -239,7 +234,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
> >                       adev->vcn.inst[i].fw_shared.log_offset = log_offset;
> >               }
> >
> > -             if (adev->vcn.indirect_sram) {
> > +             if (adev->vcn.inst[i].indirect_sram) {
> >                       r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
> >                                       AMDGPU_GEM_DOMAIN_VRAM |
> >                                       AMDGPU_GEM_DOMAIN_GTT,
> > @@ -277,15 +272,14 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
> >
> >               amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
> >
> > -             for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> > +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i)
> >                       amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
> >
> >               amdgpu_ucode_release(&adev->vcn.inst[j].fw);
> >               mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
> > +             mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround);
> >       }
> >
> > -     mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
> > -
> >       return 0;
> >   }
> >
> > @@ -404,12 +398,12 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
> >       if (adev->vcn.harvest_config & (1 << i))
> >               return;
> >
> > -     for (j = 0; j < adev->vcn.num_enc_rings; ++j)
> > +     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
> >               fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
> >
> >       /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> > -         !adev->vcn.using_unified_queue) {
> > +         !adev->vcn.inst[i].using_unified_queue) {
> >               struct dpg_pause_state new_state;
> >
> >               if (fence[i] ||
> > @@ -418,7 +412,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
> >               else
> >                       new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
> >
> > -             adev->vcn.pause_dpg_mode(adev, i, &new_state);
> > +             adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state);
> >       }
> >
> >       fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
> > @@ -456,7 +450,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
> >
> >       /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> > -         !adev->vcn.using_unified_queue) {
> > +         !adev->vcn.inst[ring->me].using_unified_queue) {
> >               struct dpg_pause_state new_state;
> >
> >               if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
> > @@ -466,7 +460,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
> >                       unsigned int fences = 0;
> >                       unsigned int i;
> >
> > -                     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> > +                     for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i)
> >                               fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
> >
> >                       if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
> > @@ -475,7 +469,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
> >                               new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
> >               }
> >
> > -             adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
> > +             adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state);
> >       }
> >       mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
> >   }
> > @@ -487,7 +481,7 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
> >       /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
> >       if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> >           ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
> > -         !adev->vcn.using_unified_queue)
> > +         !adev->vcn.inst[ring->me].using_unified_queue)
> >               atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
> >
> >       atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
> > @@ -511,7 +505,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
> >       r = amdgpu_ring_alloc(ring, 3);
> >       if (r)
> >               return r;
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
> >       amdgpu_ring_write(ring, 0xDEADBEEF);
> >       amdgpu_ring_commit(ring);
> >       for (i = 0; i < adev->usec_timeout; i++) {
> > @@ -576,14 +570,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
> >               goto err;
> >
> >       ib = &job->ibs[0];
> > -     ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
> > +     ib->ptr[0] = PACKET0(adev->vcn.inst[ring->me].internal.data0, 0);
> >       ib->ptr[1] = addr;
> > -     ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
> > +     ib->ptr[2] = PACKET0(adev->vcn.inst[ring->me].internal.data1, 0);
> >       ib->ptr[3] = addr >> 32;
> > -     ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
> > +     ib->ptr[4] = PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0);
> >       ib->ptr[5] = 0;
> >       for (i = 6; i < 16; i += 2) {
> > -             ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
> > +             ib->ptr[i] = PACKET0(adev->vcn.inst[ring->me].internal.nop, 0);
> >               ib->ptr[i+1] = 0;
> >       }
> >       ib->length_dw = 16;
> > @@ -746,7 +740,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
> >       uint32_t ib_pack_in_dw;
> >       int i, r;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               ib_size_dw += 8;
> >
> >       r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
> > @@ -759,7 +753,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
> >       ib->length_dw = 0;
> >
> >       /* single queue headers */
> > -     if (adev->vcn.using_unified_queue) {
> > +     if (adev->vcn.inst[ring->me].using_unified_queue) {
> >               ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
> >                                               + 4 + 2; /* engine info + decoding ib in dw */
> >               ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
> > @@ -778,7 +772,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
> >       for (i = ib->length_dw; i < ib_size_dw; ++i)
> >               ib->ptr[i] = 0x0;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
> >
> >       r = amdgpu_job_submit_direct(job, ring, &f);
> > @@ -876,7 +870,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
> >       uint64_t addr;
> >       int i, r;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               ib_size_dw += 8;
> >
> >       r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
> > @@ -890,7 +884,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
> >
> >       ib->length_dw = 0;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
> >
> >       ib->ptr[ib->length_dw++] = 0x00000018;
> > @@ -912,7 +906,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
> >       for (i = ib->length_dw; i < ib_size_dw; ++i)
> >               ib->ptr[i] = 0x0;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
> >
> >       r = amdgpu_job_submit_direct(job, ring, &f);
> > @@ -943,7 +937,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
> >       uint64_t addr;
> >       int i, r;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               ib_size_dw += 8;
> >
> >       r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
> > @@ -957,7 +951,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
> >
> >       ib->length_dw = 0;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
> >
> >       ib->ptr[ib->length_dw++] = 0x00000018;
> > @@ -979,7 +973,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
> >       for (i = ib->length_dw; i < ib_size_dw; ++i)
> >               ib->ptr[i] = 0x0;
> >
> > -     if (adev->vcn.using_unified_queue)
> > +     if (adev->vcn.inst[ring->me].using_unified_queue)
> >               amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
> >
> >       r = amdgpu_job_submit_direct(job, ring, &f);
> > @@ -1396,7 +1390,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
> >       struct dentry *root = minor->debugfs_root;
> >       char name[32];
> >
> > -     if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.using_unified_queue)
> > +     if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.inst[0].using_unified_queue)
> >               return;
> >       sprintf(name, "amdgpu_vcn_sched_mask");
> >       debugfs_create_file(name, 0600, root, adev,
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> > index 0bcf4d1c7175d..3b059f51894b9 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> > @@ -322,6 +322,15 @@ struct amdgpu_vcn_inst {
> >       struct mutex            vcn_pg_lock;
> >       enum amd_powergating_state cur_state;
> >       struct delayed_work     idle_work;
> > +     unsigned                fw_version;
> > +     unsigned                num_enc_rings;
> > +     bool                    indirect_sram;
> > +     struct amdgpu_vcn_reg    internal;
> > +     struct mutex            vcn1_jpeg1_workaround;
> > +     int (*pause_dpg_mode)(struct amdgpu_device *adev,
> > +                           int inst_idx,
> > +                           struct dpg_pause_state *new_state);
> > +     bool using_unified_queue;
> >   };
> >
> >   struct amdgpu_vcn_ras {
> > @@ -330,24 +339,16 @@ struct amdgpu_vcn_ras {
> >
> >   struct amdgpu_vcn {
> >       unsigned                fw_version;
> > -     unsigned                num_enc_rings;
> > -     bool                    indirect_sram;
> > -
> >       uint8_t num_vcn_inst;
> >       struct amdgpu_vcn_inst   inst[AMDGPU_MAX_VCN_INSTANCES];
> > -     struct amdgpu_vcn_reg    internal;
> > -     struct mutex            vcn1_jpeg1_workaround;
> >
> >       unsigned        harvest_config;
> > -     int (*pause_dpg_mode)(struct amdgpu_device *adev,
> > -             int inst_idx, struct dpg_pause_state *new_state);
> >
> >       struct ras_common_if    *ras_if;
> >       struct amdgpu_vcn_ras   *ras;
> >
> >       uint16_t inst_mask;
> >       uint8_t num_inst_per_aid;
> > -     bool using_unified_queue;
>
>
> unified_queue feature is determined by VCN IP version, so the "bool
> using_unified_queue" should be a generic value for all instances. Should
> we still need to separate it for each instance?

Well, you could in theory have two different VCN instances each with a
different version on an SoC.  We already have that today (e.g., navi31
contains two instances, one is 4.0.0 and the other is 4.0.1), but it
just so happens that both versions support unified queues.

Alex

>
> Boyuan
>
>
> >
> >       /* IP reg dump */
> >       uint32_t                *ip_dump;
> > diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> > index 8031406e20ff9..9e428e669ada6 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
> > @@ -607,12 +607,12 @@ static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
> >       bool    set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
> >       int             cnt = 0;
> >
> > -     mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
> > +     mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
> >
> >       if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
> >               DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
> >
> > -     for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
> > +     for (cnt = 0; cnt < adev->vcn.inst[0].num_enc_rings; cnt++) {
> >               if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
> >                       DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
> >       }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> > index 757cacf11a817..c870d9ba64c69 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> > @@ -105,7 +105,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> >
> > -     adev->vcn.num_enc_rings = 2;
> > +     adev->vcn.inst[0].num_enc_rings = 2;
> >
> >       vcn_v1_0_set_dec_ring_funcs(adev);
> >       vcn_v1_0_set_enc_ring_funcs(adev);
> > @@ -138,7 +138,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               return r;
> >
> >       /* VCN ENC TRAP */
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_1_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
> >                                       &adev->vcn.inst->irq);
> >               if (r)
> > @@ -166,18 +166,18 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
> >       if (r)
> >               return r;
> >
> > -     adev->vcn.internal.scratch9 = adev->vcn.inst->external.scratch9 =
> > +     adev->vcn.inst[0].internal.scratch9 = adev->vcn.inst->external.scratch9 =
> >               SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
> > -     adev->vcn.internal.data0 = adev->vcn.inst->external.data0 =
> > +     adev->vcn.inst[0].internal.data0 = adev->vcn.inst->external.data0 =
> >               SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
> > -     adev->vcn.internal.data1 = adev->vcn.inst->external.data1 =
> > +     adev->vcn.inst[0].internal.data1 = adev->vcn.inst->external.data1 =
> >               SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
> > -     adev->vcn.internal.cmd = adev->vcn.inst->external.cmd =
> > +     adev->vcn.inst[0].internal.cmd = adev->vcn.inst->external.cmd =
> >               SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
> > -     adev->vcn.internal.nop = adev->vcn.inst->external.nop =
> > +     adev->vcn.inst[0].internal.nop = adev->vcn.inst->external.nop =
> >               SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
> >
> >               ring = &adev->vcn.inst->ring_enc[i];
> > @@ -189,7 +189,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >       }
> >
> > -     adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
> > +     adev->vcn.inst[0].pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
> >
> >       if (amdgpu_vcnfw_log) {
> >               volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
> > @@ -253,7 +253,7 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block)
> >       if (r)
> >               return r;
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               ring = &adev->vcn.inst->ring_enc[i];
> >               r = amdgpu_ring_test_helper(ring);
> >               if (r)
> > @@ -1833,7 +1833,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
> >       struct amdgpu_device *adev = vcn_inst->adev;
> >       unsigned int fences = 0, i;
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
> >               fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
> > @@ -1849,7 +1849,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
> >               else
> >                       new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
> >
> > -             adev->vcn.pause_dpg_mode(adev, 0, &new_state);
> > +             adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
> >       }
> >
> >       fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
> > @@ -1872,7 +1872,7 @@ static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
> >       struct  amdgpu_device *adev = ring->adev;
> >       bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
> >
> > -     mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
> > +     mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
> >
> >       if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec))
> >               DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
> > @@ -1898,7 +1898,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
> >               struct dpg_pause_state new_state;
> >               unsigned int fences = 0, i;
> >
> > -             for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> > +             for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
> >                       fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
> >
> >               if (fences)
> > @@ -1916,14 +1916,14 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
> >               else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
> >                       new_state.jpeg = VCN_DPG_STATE__PAUSE;
> >
> > -             adev->vcn.pause_dpg_mode(adev, 0, &new_state);
> > +             adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
> >       }
> >   }
> >
> >   void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
> >   {
> >       schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
> > -     mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
> > +     mutex_unlock(&ring->adev->vcn.inst[0].vcn1_jpeg1_workaround);
> >   }
> >
> >   static void vcn_v1_0_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
> > @@ -2057,11 +2057,11 @@ static int vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
> >               uint32_t reg = amdgpu_ib_get_value(ib, i);
> >               uint32_t val = amdgpu_ib_get_value(ib, i + 1);
> >
> > -             if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
> > +             if (reg == PACKET0(p->adev->vcn.inst[0].internal.data0, 0)) {
> >                       msg_lo = val;
> > -             } else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
> > +             } else if (reg == PACKET0(p->adev->vcn.inst[0].internal.data1, 0)) {
> >                       msg_hi = val;
> > -             } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0)) {
> > +             } else if (reg == PACKET0(p->adev->vcn.inst[0].internal.cmd, 0)) {
> >                       r = vcn_v1_0_validate_bo(p, job,
> >                                                ((u64)msg_hi) << 32 | msg_lo);
> >                       if (r)
> > @@ -2146,7 +2146,7 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
> >   {
> >       int i;
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
> >               adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
> >   }
> >
> > @@ -2157,7 +2157,7 @@ static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
> >
> >   static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev)
> >   {
> > -     adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2;
> > +     adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 2;
> >       adev->vcn.inst->irq.funcs = &vcn_v1_0_irq_funcs;
> >   }
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> > index e55c1f8f260e9..b0a957664250c 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> > @@ -110,9 +110,9 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
> >       struct amdgpu_device *adev = ip_block->adev;
> >
> >       if (amdgpu_sriov_vf(adev))
> > -             adev->vcn.num_enc_rings = 1;
> > +             adev->vcn.inst[0].num_enc_rings = 1;
> >       else
> > -             adev->vcn.num_enc_rings = 2;
> > +             adev->vcn.inst[0].num_enc_rings = 2;
> >
> >       vcn_v2_0_set_dec_ring_funcs(adev);
> >       vcn_v2_0_set_enc_ring_funcs(adev);
> > @@ -145,7 +145,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               return r;
> >
> >       /* VCN ENC TRAP */
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
> >                                     i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
> >                                     &adev->vcn.inst->irq);
> > @@ -175,25 +175,25 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
> >       if (r)
> >               return r;
> >
> > -     adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> > -     adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> > -     adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> > -     adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> > -     adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> > -     adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> >
> > -     adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> >       adev->vcn.inst->external.scratch9 = SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
> > -     adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> >       adev->vcn.inst->external.data0 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
> > -     adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> >       adev->vcn.inst->external.data1 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
> > -     adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> >       adev->vcn.inst->external.cmd = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
> > -     adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> > +     adev->vcn.inst[0].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> >       adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
> >
> >               ring = &adev->vcn.inst->ring_enc[i];
> > @@ -210,7 +210,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >       }
> >
> > -     adev->vcn.pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
> > +     adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
> >
> >       r = amdgpu_virt_alloc_mm_table(adev);
> >       if (r)
> > @@ -292,7 +292,7 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
> >       if (amdgpu_sriov_vf(adev))
> >               ring->sched.ready = false;
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               ring = &adev->vcn.inst->ring_enc[i];
> >               r = amdgpu_ring_test_helper(ring);
> >               if (r)
> > @@ -981,7 +981,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
> >               amdgpu_dpm_enable_vcn(adev, true, 0);
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram);
> > +             return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram);
> >
> >       vcn_v2_0_disable_static_power_gating(adev);
> >
> > @@ -1421,9 +1421,9 @@ void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
> >   {
> >       struct amdgpu_device *adev = ring->adev;
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
> >       amdgpu_ring_write(ring, 0);
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
> >   }
> >
> > @@ -1438,7 +1438,7 @@ void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
> >   {
> >       struct amdgpu_device *adev = ring->adev;
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[0].internal.cmd, 0));
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
> >   }
> >
> > @@ -1458,7 +1458,7 @@ void vcn_v2_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
> >       WARN_ON(ring->wptr % 2 || count % 2);
> >
> >       for (i = 0; i < count / 2; i++) {
> > -             amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.nop, 0));
> > +             amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.nop, 0));
> >               amdgpu_ring_write(ring, 0);
> >       }
> >   }
> > @@ -1479,25 +1479,25 @@ void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
> >       struct amdgpu_device *adev = ring->adev;
> >
> >       WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.context_id, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.context_id, 0));
> >       amdgpu_ring_write(ring, seq);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
> >       amdgpu_ring_write(ring, addr & 0xffffffff);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
> >       amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
> >       amdgpu_ring_write(ring, 0);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
> >       amdgpu_ring_write(ring, 0);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
> >
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
> >   }
> > @@ -1520,14 +1520,14 @@ void vcn_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
> >       struct amdgpu_device *adev = ring->adev;
> >       unsigned vmid = AMDGPU_JOB_GET_VMID(job);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_vmid, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_vmid, 0));
> >       amdgpu_ring_write(ring, vmid);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_bar_low, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_low, 0));
> >       amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_bar_high, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_high, 0));
> >       amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_size, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_size, 0));
> >       amdgpu_ring_write(ring, ib->length_dw);
> >   }
> >
> > @@ -1536,16 +1536,16 @@ void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
> >   {
> >       struct amdgpu_device *adev = ring->adev;
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
> >       amdgpu_ring_write(ring, reg << 2);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
> >       amdgpu_ring_write(ring, val);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.gp_scratch8, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.gp_scratch8, 0));
> >       amdgpu_ring_write(ring, mask);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
> >
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
> >   }
> > @@ -1570,13 +1570,13 @@ void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
> >   {
> >       struct amdgpu_device *adev = ring->adev;
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
> >       amdgpu_ring_write(ring, reg << 2);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
> >       amdgpu_ring_write(ring, val);
> >
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
> >
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
> >   }
> > @@ -1777,9 +1777,9 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
> >       r = amdgpu_ring_alloc(ring, 4);
> >       if (r)
> >               return r;
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
> >       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
> > -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
> > +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
> >       amdgpu_ring_write(ring, 0xDEADBEEF);
> >       amdgpu_ring_commit(ring);
> >       for (i = 0; i < adev->usec_timeout; i++) {
> > @@ -1863,7 +1863,7 @@ static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev,
> >       adev->vcn.inst->ring_dec.wptr_old = 0;
> >       vcn_v2_0_dec_ring_set_wptr(&adev->vcn.inst->ring_dec);
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
> >               adev->vcn.inst->ring_enc[i].wptr = 0;
> >               adev->vcn.inst->ring_enc[i].wptr_old = 0;
> >               vcn_v2_0_enc_ring_set_wptr(&adev->vcn.inst->ring_enc[i]);
> > @@ -1989,7 +1989,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev)
> >                       SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2),
> >                       AMDGPU_VCN_CONTEXT_SIZE);
> >
> > -             for (r = 0; r < adev->vcn.num_enc_rings; ++r) {
> > +             for (r = 0; r < adev->vcn.inst[0].num_enc_rings; ++r) {
> >                       ring = &adev->vcn.inst->ring_enc[r];
> >                       ring->wptr = 0;
> >                       MMSCH_V2_0_INSERT_DIRECT_WT(
> > @@ -2178,7 +2178,7 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
> >   {
> >       int i;
> >
> > -     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
> > +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
> >               adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs;
> >   }
> >
> > @@ -2189,7 +2189,7 @@ static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
> >
> >   static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev)
> >   {
> > -     adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 1;
> > +     adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 1;
> >       adev->vcn.inst->irq.funcs = &vcn_v2_0_irq_funcs;
> >   }
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> > index 1d3780a2d8513..a3bac39e4c9db 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> > @@ -121,11 +121,13 @@ static int amdgpu_ih_clientid_vcns[] = {
> >   static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> > +     int i;
> >
> >       if (amdgpu_sriov_vf(adev)) {
> >               adev->vcn.num_vcn_inst = 2;
> >               adev->vcn.harvest_config = 0;
> > -             adev->vcn.num_enc_rings = 1;
> > +             for (i = 0; i < adev->vcn.num_vcn_inst; i++)
> > +                     adev->vcn.inst[i].num_enc_rings = 1;
> >       } else {
> >               u32 harvest;
> >               int i;
> > @@ -134,13 +136,12 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
> >                       harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING);
> >                       if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
> >                               adev->vcn.harvest_config |= 1 << i;
> > +                     adev->vcn.inst[i].num_enc_rings = 2;
> >               }
> >               if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
> >                                       AMDGPU_VCN_HARVEST_VCN1))
> >                       /* both instances are harvested, disable the block */
> >                       return -ENOENT;
> > -
> > -             adev->vcn.num_enc_rings = 2;
> >       }
> >
> >       vcn_v2_5_set_dec_ring_funcs(adev);
> > @@ -176,7 +177,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >
> >               /* VCN ENC TRAP */
> > -             for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
> >                       r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j],
> >                               i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[j].irq);
> >                       if (r)
> > @@ -205,22 +206,22 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
> >
> >               if (adev->vcn.harvest_config & (1 << j))
> >                       continue;
> > -             adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> > -             adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> > -
> > -             adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> > +
> > +             adev->vcn.inst[j].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> >               adev->vcn.inst[j].external.scratch9 = SOC15_REG_OFFSET(VCN, j, mmUVD_SCRATCH9);
> > -             adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> >               adev->vcn.inst[j].external.data0 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA0);
> > -             adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> >               adev->vcn.inst[j].external.data1 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA1);
> > -             adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> >               adev->vcn.inst[j].external.cmd = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_CMD);
> > -             adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> > +             adev->vcn.inst[j].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> >               adev->vcn.inst[j].external.nop = SOC15_REG_OFFSET(VCN, j, mmUVD_NO_OP);
> >
> >               ring = &adev->vcn.inst[j].ring_dec;
> > @@ -240,7 +241,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
> >               if (r)
> >                       return r;
> >
> > -             for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
> >                       enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
> >
> >                       ring = &adev->vcn.inst[j].ring_enc[i];
> > @@ -268,6 +269,9 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
> >
> >               if (amdgpu_vcnfw_log)
> >                       amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> > +
> > +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
> >       }
> >
> >       if (amdgpu_sriov_vf(adev)) {
> > @@ -276,9 +280,6 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >       }
> >
> > -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
> > -
> >       r = amdgpu_vcn_ras_sw_init(adev);
> >       if (r)
> >               return r;
> > @@ -369,7 +370,7 @@ static int vcn_v2_5_hw_init(struct amdgpu_ip_block *ip_block)
> >                       if (r)
> >                               return r;
> >
> > -                     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +                     for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
> >                               ring = &adev->vcn.inst[j].ring_enc[i];
> >                               r = amdgpu_ring_test_helper(ring);
> >                               if (r)
> > @@ -1018,7 +1019,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
> >               amdgpu_dpm_enable_vcn(adev, true, i);
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       /* disable register anti-hang mechanism */
> >       WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
> > @@ -1746,7 +1747,7 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
> >       for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
> >               if (adev->vcn.harvest_config & (1 << j))
> >                       continue;
> > -             for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
> > +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
> >                       adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs;
> >                       adev->vcn.inst[j].ring_enc[i].me = j;
> >               }
> > @@ -1917,10 +1918,10 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
> >       for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> > -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs;
> >
> > -             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs;
> >       }
> >   }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> > index 13b9ed96cccda..fabe4d75a7f6b 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> > @@ -127,11 +127,13 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
> >   static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> > +     int i;
> >
> >       if (amdgpu_sriov_vf(adev)) {
> >               adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
> >               adev->vcn.harvest_config = 0;
> > -             adev->vcn.num_enc_rings = 1;
> > +             for (i = 0; i < adev->vcn.num_vcn_inst; i++)
> > +                     adev->vcn.inst[i].num_enc_rings = 1;
> >
> >       } else {
> >               if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
> > @@ -139,11 +141,13 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
> >                       /* both instances are harvested, disable the block */
> >                       return -ENOENT;
> >
> > -             if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
> > -                 IP_VERSION(3, 0, 33))
> > -                     adev->vcn.num_enc_rings = 0;
> > -             else
> > -                     adev->vcn.num_enc_rings = 2;
> > +             for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> > +                     if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
> > +                         IP_VERSION(3, 0, 33))
> > +                             adev->vcn.inst[i].num_enc_rings = 0;
> > +                     else
> > +                             adev->vcn.inst[i].num_enc_rings = 2;
> > +             }
> >       }
> >
> >       vcn_v3_0_set_dec_ring_funcs(adev);
> > @@ -198,22 +202,22 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> >
> > -             adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> > -             adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> > -             adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
> >
> > -             adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
> >               adev->vcn.inst[i].external.scratch9 = SOC15_REG_OFFSET(VCN, i, mmUVD_SCRATCH9);
> > -             adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
> >               adev->vcn.inst[i].external.data0 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA0);
> > -             adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
> >               adev->vcn.inst[i].external.data1 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA1);
> > -             adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
> >               adev->vcn.inst[i].external.cmd = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_CMD);
> > -             adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> > +             adev->vcn.inst[i].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
> >               adev->vcn.inst[i].external.nop = SOC15_REG_OFFSET(VCN, i, mmUVD_NO_OP);
> >
> >               /* VCN DEC TRAP */
> > @@ -227,7 +231,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               ring = &adev->vcn.inst[i].ring_dec;
> >               ring->use_doorbell = true;
> >               if (amdgpu_sriov_vf(adev)) {
> > -                     ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1);
> > +                     ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1);
> >               } else {
> >                       ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i;
> >               }
> > @@ -239,7 +243,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               if (r)
> >                       return r;
> >
> > -             for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> > +             for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
> >                       enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(j);
> >
> >                       /* VCN ENC TRAP */
> > @@ -251,7 +255,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
> >                       ring = &adev->vcn.inst[i].ring_enc[j];
> >                       ring->use_doorbell = true;
> >                       if (amdgpu_sriov_vf(adev)) {
> > -                             ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1) + 1 + j;
> > +                             ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1) + 1 + j;
> >                       } else {
> >                               ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i;
> >                       }
> > @@ -277,6 +281,9 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
> >
> >               if (amdgpu_vcnfw_log)
> >                       amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> > +
> > +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
> >       }
> >
> >       if (amdgpu_sriov_vf(adev)) {
> > @@ -284,8 +291,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               if (r)
> >                       return r;
> >       }
> > -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             adev->vcn.pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
> >
> >       /* Allocate memory for VCN IP Dump buffer */
> >       ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
> > @@ -373,7 +378,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
> >                               ring->sched.ready = true;
> >                       }
> >
> > -                     for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> > +                     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
> >                               ring = &adev->vcn.inst[i].ring_enc[j];
> >                               if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) {
> >                                       ring->sched.ready = false;
> > @@ -401,7 +406,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
> >                       if (r)
> >                               return r;
> >
> > -                     for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> > +                     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
> >                               ring = &adev->vcn.inst[i].ring_enc[j];
> >                               r = amdgpu_ring_test_helper(ring);
> >                               if (r)
> > @@ -1153,7 +1158,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
> >               amdgpu_dpm_enable_vcn(adev, true, i);
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       /* disable VCN power gating */
> >       vcn_v3_0_disable_static_power_gating(adev, i);
> > @@ -1433,7 +1438,7 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
> >                       mmUVD_VCPU_CACHE_SIZE2),
> >                       AMDGPU_VCN_CONTEXT_SIZE);
> >
> > -             for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> > +             for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
> >                       ring = &adev->vcn.inst[i].ring_enc[j];
> >                       ring->wptr = 0;
> >                       rb_addr = ring->gpu_addr;
> > @@ -1921,11 +1926,11 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
> >               uint32_t reg = amdgpu_ib_get_value(ib, i);
> >               uint32_t val = amdgpu_ib_get_value(ib, i + 1);
> >
> > -             if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
> > +             if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data0, 0)) {
> >                       msg_lo = val;
> > -             } else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
> > +             } else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data1, 0)) {
> >                       msg_hi = val;
> > -             } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0) &&
> > +             } else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.cmd, 0) &&
> >                          val == 0) {
> >                       r = vcn_v3_0_dec_msg(p, job,
> >                                            ((u64)msg_hi) << 32 | msg_lo);
> > @@ -2089,7 +2094,7 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> >
> > -             for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
> > +             for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
> >                       adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs;
> >                       adev->vcn.inst[i].ring_enc[j].me = i;
> >               }
> > @@ -2255,7 +2260,7 @@ static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev)
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> >
> > -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].irq.funcs = &vcn_v3_0_irq_funcs;
> >       }
> >   }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> > index dbbeeffc90726..ee87594fafa60 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> > @@ -129,8 +129,9 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
> >               }
> >       }
> >
> > -     /* re-use enc ring as unified ring */
> > -     adev->vcn.num_enc_rings = 1;
> > +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> > +             /* re-use enc ring as unified ring */
> > +             adev->vcn.inst[i].num_enc_rings = 1;
> >
> >       vcn_v4_0_set_unified_ring_funcs(adev);
> >       vcn_v4_0_set_irq_funcs(adev);
> > @@ -214,7 +215,8 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
> >               ring = &adev->vcn.inst[i].ring_enc[0];
> >               ring->use_doorbell = true;
> >               if (amdgpu_sriov_vf(adev))
> > -                     ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * (adev->vcn.num_enc_rings + 1) + 1;
> > +                     ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i *
> > +                             (adev->vcn.inst[i].num_enc_rings + 1) + 1;
> >               else
> >                       ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;
> >               ring->vm_hub = AMDGPU_MMHUB0(0);
> > @@ -226,6 +228,9 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >
> >               vcn_v4_0_fw_shared_init(adev, i);
> > +
> > +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
> >       }
> >
> >       /* TODO: Add queue reset mask when FW fully supports it */
> > @@ -238,8 +243,6 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >       }
> >
> > -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
> >
> >       r = amdgpu_vcn_ras_sw_init(adev);
> >       if (r)
> > @@ -1111,7 +1114,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
> >       fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       /* disable VCN power gating */
> >       vcn_v4_0_disable_static_power_gating(adev, i);
> > @@ -2172,10 +2175,10 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev)
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> >
> > -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs;
> >
> > -             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs;
> >       }
> >   }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> > index 8396ef6831b69..35854e074d142 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> > @@ -114,9 +114,11 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
> >   static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> > +     int i;
> >
> > -     /* re-use enc ring as unified ring */
> > -     adev->vcn.num_enc_rings = 1;
> > +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> > +             /* re-use enc ring as unified ring */
> > +             adev->vcn.inst[i].num_enc_rings = 1;
> >
> >       vcn_v4_0_3_set_unified_ring_funcs(adev);
> >       vcn_v4_0_3_set_irq_funcs(adev);
> > @@ -194,6 +196,9 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >
> >               vcn_v4_0_3_fw_shared_init(adev, i);
> > +
> > +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
> >       }
> >
> >       /* TODO: Add queue reset mask when FW fully supports it */
> > @@ -206,9 +211,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >       }
> >
> > -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             adev->vcn.pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
> > -
> >       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
> >               r = amdgpu_vcn_ras_sw_init(adev);
> >               if (r) {
> > @@ -1138,7 +1140,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
> >               amdgpu_dpm_enable_vcn(adev, true, i);
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       vcn_inst = GET_INST(VCN, i);
> >       /* set VCN status busy */
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> > index f6b347fcdb7ed..0700a5f96084c 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> > @@ -115,9 +115,11 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
> >   static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> > +     int i;
> >
> > -     /* re-use enc ring as unified ring */
> > -     adev->vcn.num_enc_rings = 1;
> > +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> > +             /* re-use enc ring as unified ring */
> > +             adev->vcn.inst[i].num_enc_rings = 1;
> >       vcn_v4_0_5_set_unified_ring_funcs(adev);
> >       vcn_v4_0_5_set_irq_funcs(adev);
> >
> > @@ -173,7 +175,7 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
> >               ring->use_doorbell = true;
> >               if (amdgpu_sriov_vf(adev))
> >                       ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
> > -                                             i * (adev->vcn.num_enc_rings + 1) + 1;
> > +                                             i * (adev->vcn.inst[i].num_enc_rings + 1) + 1;
> >               else
> >                       ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
> >                                               2 + 8 * i;
> > @@ -198,6 +200,9 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
> >
> >               if (amdgpu_vcnfw_log)
> >                       amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> > +
> > +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
> >       }
> >
> >       if (amdgpu_sriov_vf(adev)) {
> > @@ -206,9 +211,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
> >                       return r;
> >       }
> >
> > -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
> > -
> >       /* Allocate memory for VCN IP Dump buffer */
> >       ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
> >       if (!ptr) {
> > @@ -1014,7 +1016,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
> >       fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       /* disable VCN power gating */
> >       vcn_v4_0_5_disable_static_power_gating(adev, i);
> > @@ -1624,7 +1626,7 @@ static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> >
> > -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs;
> >       }
> >   }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> > index c5d59edf3a482..eeb3c9875ad50 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> > @@ -98,9 +98,11 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
> >   static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> > +     int i;
> >
> > -     /* re-use enc ring as unified ring */
> > -     adev->vcn.num_enc_rings = 1;
> > +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> > +             /* re-use enc ring as unified ring */
> > +             adev->vcn.inst[i].num_enc_rings = 1;
> >
> >       vcn_v5_0_0_set_unified_ring_funcs(adev);
> >       vcn_v5_0_0_set_irq_funcs(adev);
> > @@ -184,15 +186,15 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
> >
> >               if (amdgpu_vcnfw_log)
> >                       amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
> > +
> > +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
> >       }
> >
> >       /* TODO: Add queue reset mask when FW fully supports it */
> >       adev->vcn.supported_reset =
> >               amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
> >
> > -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
> > -
> >       vcn_v5_0_0_alloc_ip_dump(adev);
> >
> >       r = amdgpu_vcn_sysfs_reset_mask_init(adev);
> > @@ -791,7 +793,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
> >       fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       /* disable VCN power gating */
> >       vcn_v5_0_0_disable_static_power_gating(adev, i);
> > @@ -1367,7 +1369,7 @@ static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev)
> >               if (adev->vcn.harvest_config & (1 << i))
> >                       continue;
> >
> > -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
> > +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
> >               adev->vcn.inst[i].irq.funcs = &vcn_v5_0_0_irq_funcs;
> >       }
> >   }
> > diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> > index 51a2d70a65c9e..f428d23eb2857 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
> > @@ -58,9 +58,11 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
> >   static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
> >   {
> >       struct amdgpu_device *adev = ip_block->adev;
> > +     int i;
> >
> > -     /* re-use enc ring as unified ring */
> > -     adev->vcn.num_enc_rings = 1;
> > +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
> > +             /* re-use enc ring as unified ring */
> > +             adev->vcn.inst[i].num_enc_rings = 1;
> >
> >       vcn_v5_0_1_set_unified_ring_funcs(adev);
> >       vcn_v5_0_1_set_irq_funcs(adev);
> > @@ -586,7 +588,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
> >       fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
> >
> >       if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
> > -             return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
> > +             return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
> >
> >       vcn_inst = GET_INST(VCN, i);
> >

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance
  2025-02-05 20:09     ` Alex Deucher
@ 2025-02-06 13:39       ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 13:39 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 79507 bytes --]


On 2025-02-05 15:09, Alex Deucher wrote:
> On Tue, Feb 4, 2025 at 10:42 PM Boyuan Zhang<Boyuan.Zhang@amd.com>  wrote:
>>
>> On 2025-01-31 11:57, Alex Deucher wrote:
>>> Move more per instance data into the per instance structure.
>>>
>>> v2: index instances directly on vcn1.0 and 2.0 to make
>>> it clear that they only support a single instance (Lijo)
>>>
>>> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>
>>> ---
>>>    drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |   2 +-
>>>    drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 196 ++++++++++++------------
>>>    drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  17 +-
>>>    drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c  |   4 +-
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   |  42 ++---
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   |  92 +++++------
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   |  51 +++---
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   |  67 ++++----
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   |  19 ++-
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c |  14 +-
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  18 ++-
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c |  16 +-
>>>    drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c |   8 +-
>>>    13 files changed, 279 insertions(+), 267 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>>> index 2c76bc5e25d92..5ee2ae66ed36b 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>>> @@ -480,7 +480,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
>>>                        if (adev->vcn.harvest_config & (1 << i))
>>>                                continue;
>>>
>>> -                     for (j = 0; j < adev->vcn.num_enc_rings; j++)
>>> +                     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; j++)
>>>                                if (adev->vcn.inst[i].ring_enc[j].sched.ready)
>>>                                        ++num_rings;
>>>                }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
>>> index 0c3081a198d9e..9901b8e17f305 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
>>> @@ -127,93 +127,88 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
>>>        unsigned int fw_shared_size, log_offset;
>>>        int i, r;
>>>
>>> -     mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
>>>        for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>>> +             mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
>>>                mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
>>>                atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
>>>                INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
>>>                atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
>>> -     }
>>> -
>>> -     if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
>>> -         (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
>>> -             adev->vcn.indirect_sram = true;
>>> -
>>> -     /*
>>> -      * Some Steam Deck's BIOS versions are incompatible with the
>>> -      * indirect SRAM mode, leading to amdgpu being unable to get
>>> -      * properly probed (and even potentially crashing the kernel).
>>> -      * Hence, check for these versions here - notice this is
>>> -      * restricted to Vangogh (Deck's APU).
>>> -      */
>>> -     if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
>>> -             const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
>>> -
>>> -             if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
>>> -                  !strncmp("F7A0114", bios_ver, 7))) {
>>> -                     adev->vcn.indirect_sram = false;
>>> -                     dev_info(adev->dev,
>>> -                             "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
>>> +             if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
>>> +                 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
>>> +                     adev->vcn.inst[i].indirect_sram = true;
>>> +
>>> +             /*
>>> +              * Some Steam Deck's BIOS versions are incompatible with the
>>> +              * indirect SRAM mode, leading to amdgpu being unable to get
>>> +              * properly probed (and even potentially crashing the kernel).
>>> +              * Hence, check for these versions here - notice this is
>>> +              * restricted to Vangogh (Deck's APU).
>>> +              */
>>> +             if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {
>>> +                     const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
>>> +
>>> +                     if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
>>> +                                      !strncmp("F7A0114", bios_ver, 7))) {
>>> +                             adev->vcn.inst[i].indirect_sram = false;
>>> +                             dev_info(adev->dev,
>>> +                                      "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
>>> +                     }
>>>                }
>>> -     }
>>>
>>> -     /* from vcn4 and above, only unified queue is used */
>>> -     adev->vcn.using_unified_queue =
>>> -             amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
>>> -
>>> -     hdr = (const struct common_firmware_header *)adev->vcn.inst[0].fw->data;
>>> -     adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
>>> -
>>> -     /* Bit 20-23, it is encode major and non-zero for new naming convention.
>>> -      * This field is part of version minor and DRM_DISABLED_FLAG in old naming
>>> -      * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
>>> -      * is zero in old naming convention, this field is always zero so far.
>>> -      * These four bits are used to tell which naming convention is present.
>>> -      */
>>> -     fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
>>> -     if (fw_check) {
>>> -             unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
>>> -
>>> -             fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
>>> -             enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
>>> -             enc_major = fw_check;
>>> -             dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
>>> -             vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
>>> -             DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
>>> -                     enc_major, enc_minor, dec_ver, vep, fw_rev);
>>> -     } else {
>>> -             unsigned int version_major, version_minor, family_id;
>>> +             /* from vcn4 and above, only unified queue is used */
>>> +             adev->vcn.inst[i].using_unified_queue =
>>> +                     amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
>>> +
>>> +             hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
>>> +             adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
>>> +             adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
>>> +
>>> +             /* Bit 20-23, it is encode major and non-zero for new naming convention.
>>> +              * This field is part of version minor and DRM_DISABLED_FLAG in old naming
>>> +              * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
>>> +              * is zero in old naming convention, this field is always zero so far.
>>> +              * These four bits are used to tell which naming convention is present.
>>> +              */
>>> +             fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
>>> +             if (fw_check) {
>>> +                     unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
>>> +
>>> +                     fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
>>> +                     enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
>>> +                     enc_major = fw_check;
>>> +                     dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
>>> +                     vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
>>> +                     DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
>>> +                              enc_major, enc_minor, dec_ver, vep, fw_rev);
>>> +             } else {
>>> +                     unsigned int version_major, version_minor, family_id;
>>>
>>> -             family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
>>> -             version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
>>> -             version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
>>> -             DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
>>> -                     version_major, version_minor, family_id);
>>> -     }
>>> +                     family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
>>> +                     version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
>>> +                     version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
>>> +                     DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
>>> +                              version_major, version_minor, family_id);
>>> +             }
>>>
>>> -     bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
>>> -     if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
>>> -             bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
>>> +             bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
>>> +             if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
>>> +                     bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
>>>
>>> -     if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
>>> -             fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
>>> -             log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
>>> -     } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
>>> -             fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
>>> -             log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
>>> -     } else {
>>> -             fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
>>> -             log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
>>> -     }
>>> -
>>> -     bo_size += fw_shared_size;
>>> +             if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
>>> +                     fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
>>> +                     log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
>>> +             } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
>>> +                     fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
>>> +                     log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
>>> +             } else {
>>> +                     fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
>>> +                     log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
>>> +             }
>>>
>>> -     if (amdgpu_vcnfw_log)
>>> -             bo_size += AMDGPU_VCNFW_LOG_SIZE;
>>> +             bo_size += fw_shared_size;
>>>
>>> -     for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>>> -             if (adev->vcn.harvest_config & (1 << i))
>>> -                     continue;
>>> +             if (amdgpu_vcnfw_log)
>>> +                     bo_size += AMDGPU_VCNFW_LOG_SIZE;
>>>
>>>                r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
>>>                                            AMDGPU_GEM_DOMAIN_VRAM |
>>> @@ -239,7 +234,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
>>>                        adev->vcn.inst[i].fw_shared.log_offset = log_offset;
>>>                }
>>>
>>> -             if (adev->vcn.indirect_sram) {
>>> +             if (adev->vcn.inst[i].indirect_sram) {
>>>                        r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
>>>                                        AMDGPU_GEM_DOMAIN_VRAM |
>>>                                        AMDGPU_GEM_DOMAIN_GTT,
>>> @@ -277,15 +272,14 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
>>>
>>>                amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
>>>
>>> -             for (i = 0; i < adev->vcn.num_enc_rings; ++i)
>>> +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i)
>>>                        amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
>>>
>>>                amdgpu_ucode_release(&adev->vcn.inst[j].fw);
>>>                mutex_destroy(&adev->vcn.inst[j].vcn_pg_lock);
>>> +             mutex_destroy(&adev->vcn.inst[j].vcn1_jpeg1_workaround);
>>>        }
>>>
>>> -     mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
>>> -
>>>        return 0;
>>>    }
>>>
>>> @@ -404,12 +398,12 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>>>        if (adev->vcn.harvest_config & (1 << i))
>>>                return;
>>>
>>> -     for (j = 0; j < adev->vcn.num_enc_rings; ++j)
>>> +     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
>>>                fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
>>>
>>>        /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
>>> -         !adev->vcn.using_unified_queue) {
>>> +         !adev->vcn.inst[i].using_unified_queue) {
>>>                struct dpg_pause_state new_state;
>>>
>>>                if (fence[i] ||
>>> @@ -418,7 +412,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>>>                else
>>>                        new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>>>
>>> -             adev->vcn.pause_dpg_mode(adev, i, &new_state);
>>> +             adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state);
>>>        }
>>>
>>>        fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
>>> @@ -456,7 +450,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>>>
>>>        /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
>>> -         !adev->vcn.using_unified_queue) {
>>> +         !adev->vcn.inst[ring->me].using_unified_queue) {
>>>                struct dpg_pause_state new_state;
>>>
>>>                if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
>>> @@ -466,7 +460,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>>>                        unsigned int fences = 0;
>>>                        unsigned int i;
>>>
>>> -                     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
>>> +                     for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i)
>>>                                fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
>>>
>>>                        if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
>>> @@ -475,7 +469,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>>>                                new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>>>                }
>>>
>>> -             adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
>>> +             adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state);
>>>        }
>>>        mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
>>>    }
>>> @@ -487,7 +481,7 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
>>>        /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>>>        if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
>>>            ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
>>> -         !adev->vcn.using_unified_queue)
>>> +         !adev->vcn.inst[ring->me].using_unified_queue)
>>>                atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
>>>
>>>        atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
>>> @@ -511,7 +505,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
>>>        r = amdgpu_ring_alloc(ring, 3);
>>>        if (r)
>>>                return r;
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
>>>        amdgpu_ring_write(ring, 0xDEADBEEF);
>>>        amdgpu_ring_commit(ring);
>>>        for (i = 0; i < adev->usec_timeout; i++) {
>>> @@ -576,14 +570,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
>>>                goto err;
>>>
>>>        ib = &job->ibs[0];
>>> -     ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
>>> +     ib->ptr[0] = PACKET0(adev->vcn.inst[ring->me].internal.data0, 0);
>>>        ib->ptr[1] = addr;
>>> -     ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
>>> +     ib->ptr[2] = PACKET0(adev->vcn.inst[ring->me].internal.data1, 0);
>>>        ib->ptr[3] = addr >> 32;
>>> -     ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
>>> +     ib->ptr[4] = PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0);
>>>        ib->ptr[5] = 0;
>>>        for (i = 6; i < 16; i += 2) {
>>> -             ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
>>> +             ib->ptr[i] = PACKET0(adev->vcn.inst[ring->me].internal.nop, 0);
>>>                ib->ptr[i+1] = 0;
>>>        }
>>>        ib->length_dw = 16;
>>> @@ -746,7 +740,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
>>>        uint32_t ib_pack_in_dw;
>>>        int i, r;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                ib_size_dw += 8;
>>>
>>>        r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
>>> @@ -759,7 +753,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
>>>        ib->length_dw = 0;
>>>
>>>        /* single queue headers */
>>> -     if (adev->vcn.using_unified_queue) {
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue) {
>>>                ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
>>>                                                + 4 + 2; /* engine info + decoding ib in dw */
>>>                ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
>>> @@ -778,7 +772,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
>>>        for (i = ib->length_dw; i < ib_size_dw; ++i)
>>>                ib->ptr[i] = 0x0;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
>>>
>>>        r = amdgpu_job_submit_direct(job, ring, &f);
>>> @@ -876,7 +870,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
>>>        uint64_t addr;
>>>        int i, r;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                ib_size_dw += 8;
>>>
>>>        r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
>>> @@ -890,7 +884,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
>>>
>>>        ib->length_dw = 0;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
>>>
>>>        ib->ptr[ib->length_dw++] = 0x00000018;
>>> @@ -912,7 +906,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
>>>        for (i = ib->length_dw; i < ib_size_dw; ++i)
>>>                ib->ptr[i] = 0x0;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
>>>
>>>        r = amdgpu_job_submit_direct(job, ring, &f);
>>> @@ -943,7 +937,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
>>>        uint64_t addr;
>>>        int i, r;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                ib_size_dw += 8;
>>>
>>>        r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
>>> @@ -957,7 +951,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
>>>
>>>        ib->length_dw = 0;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
>>>
>>>        ib->ptr[ib->length_dw++] = 0x00000018;
>>> @@ -979,7 +973,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
>>>        for (i = ib->length_dw; i < ib_size_dw; ++i)
>>>                ib->ptr[i] = 0x0;
>>>
>>> -     if (adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.inst[ring->me].using_unified_queue)
>>>                amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
>>>
>>>        r = amdgpu_job_submit_direct(job, ring, &f);
>>> @@ -1396,7 +1390,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
>>>        struct dentry *root = minor->debugfs_root;
>>>        char name[32];
>>>
>>> -     if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.using_unified_queue)
>>> +     if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.inst[0].using_unified_queue)
>>>                return;
>>>        sprintf(name, "amdgpu_vcn_sched_mask");
>>>        debugfs_create_file(name, 0600, root, adev,
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
>>> index 0bcf4d1c7175d..3b059f51894b9 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
>>> @@ -322,6 +322,15 @@ struct amdgpu_vcn_inst {
>>>        struct mutex            vcn_pg_lock;
>>>        enum amd_powergating_state cur_state;
>>>        struct delayed_work     idle_work;
>>> +     unsigned                fw_version;
>>> +     unsigned                num_enc_rings;
>>> +     bool                    indirect_sram;
>>> +     struct amdgpu_vcn_reg    internal;
>>> +     struct mutex            vcn1_jpeg1_workaround;
>>> +     int (*pause_dpg_mode)(struct amdgpu_device *adev,
>>> +                           int inst_idx,
>>> +                           struct dpg_pause_state *new_state);
>>> +     bool using_unified_queue;
>>>    };
>>>
>>>    struct amdgpu_vcn_ras {
>>> @@ -330,24 +339,16 @@ struct amdgpu_vcn_ras {
>>>
>>>    struct amdgpu_vcn {
>>>        unsigned                fw_version;
>>> -     unsigned                num_enc_rings;
>>> -     bool                    indirect_sram;
>>> -
>>>        uint8_t num_vcn_inst;
>>>        struct amdgpu_vcn_inst   inst[AMDGPU_MAX_VCN_INSTANCES];
>>> -     struct amdgpu_vcn_reg    internal;
>>> -     struct mutex            vcn1_jpeg1_workaround;
>>>
>>>        unsigned        harvest_config;
>>> -     int (*pause_dpg_mode)(struct amdgpu_device *adev,
>>> -             int inst_idx, struct dpg_pause_state *new_state);
>>>
>>>        struct ras_common_if    *ras_if;
>>>        struct amdgpu_vcn_ras   *ras;
>>>
>>>        uint16_t inst_mask;
>>>        uint8_t num_inst_per_aid;
>>> -     bool using_unified_queue;
>>
>> unified_queue feature is determined by VCN IP version, so the "bool
>> using_unified_queue" should be a generic value for all instances. Should
>> we still need to separate it for each instance?
> Well, you could in theory have two different VCN instances each with a
> different version on an SoC.  We already have that today (e.g., navi31
> contains two instances, one is 4.0.0 and the other is 4.0.1), but it
> just so happens that both versions support unified queues.


yea make sense.

Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


>
> Alex
>
>> Boyuan
>>
>>
>>>        /* IP reg dump */
>>>        uint32_t                *ip_dump;
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
>>> index 8031406e20ff9..9e428e669ada6 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
>>> @@ -607,12 +607,12 @@ static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
>>>        bool    set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>>>        int             cnt = 0;
>>>
>>> -     mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
>>> +     mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
>>>
>>>        if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
>>>                DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
>>>
>>> -     for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
>>> +     for (cnt = 0; cnt < adev->vcn.inst[0].num_enc_rings; cnt++) {
>>>                if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
>>>                        DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
>>>        }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
>>> index 757cacf11a817..c870d9ba64c69 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
>>> @@ -105,7 +105,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>>
>>> -     adev->vcn.num_enc_rings = 2;
>>> +     adev->vcn.inst[0].num_enc_rings = 2;
>>>
>>>        vcn_v1_0_set_dec_ring_funcs(adev);
>>>        vcn_v1_0_set_enc_ring_funcs(adev);
>>> @@ -138,7 +138,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                return r;
>>>
>>>        /* VCN ENC TRAP */
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_1_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
>>>                                        &adev->vcn.inst->irq);
>>>                if (r)
>>> @@ -166,18 +166,18 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>        if (r)
>>>                return r;
>>>
>>> -     adev->vcn.internal.scratch9 = adev->vcn.inst->external.scratch9 =
>>> +     adev->vcn.inst[0].internal.scratch9 = adev->vcn.inst->external.scratch9 =
>>>                SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
>>> -     adev->vcn.internal.data0 = adev->vcn.inst->external.data0 =
>>> +     adev->vcn.inst[0].internal.data0 = adev->vcn.inst->external.data0 =
>>>                SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
>>> -     adev->vcn.internal.data1 = adev->vcn.inst->external.data1 =
>>> +     adev->vcn.inst[0].internal.data1 = adev->vcn.inst->external.data1 =
>>>                SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
>>> -     adev->vcn.internal.cmd = adev->vcn.inst->external.cmd =
>>> +     adev->vcn.inst[0].internal.cmd = adev->vcn.inst->external.cmd =
>>>                SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
>>> -     adev->vcn.internal.nop = adev->vcn.inst->external.nop =
>>> +     adev->vcn.inst[0].internal.nop = adev->vcn.inst->external.nop =
>>>                SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
>>>
>>>                ring = &adev->vcn.inst->ring_enc[i];
>>> @@ -189,7 +189,7 @@ static int vcn_v1_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>        }
>>>
>>> -     adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
>>> +     adev->vcn.inst[0].pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
>>>
>>>        if (amdgpu_vcnfw_log) {
>>>                volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
>>> @@ -253,7 +253,7 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block)
>>>        if (r)
>>>                return r;
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                ring = &adev->vcn.inst->ring_enc[i];
>>>                r = amdgpu_ring_test_helper(ring);
>>>                if (r)
>>> @@ -1833,7 +1833,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>>>        struct amdgpu_device *adev = vcn_inst->adev;
>>>        unsigned int fences = 0, i;
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>>>                fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
>>> @@ -1849,7 +1849,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>>>                else
>>>                        new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
>>>
>>> -             adev->vcn.pause_dpg_mode(adev, 0, &new_state);
>>> +             adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
>>>        }
>>>
>>>        fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
>>> @@ -1872,7 +1872,7 @@ static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
>>>        struct  amdgpu_device *adev = ring->adev;
>>>        bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
>>>
>>> -     mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
>>> +     mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
>>>
>>>        if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec))
>>>                DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
>>> @@ -1898,7 +1898,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
>>>                struct dpg_pause_state new_state;
>>>                unsigned int fences = 0, i;
>>>
>>> -             for (i = 0; i < adev->vcn.num_enc_rings; ++i)
>>> +             for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>>>                        fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
>>>
>>>                if (fences)
>>> @@ -1916,14 +1916,14 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
>>>                else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
>>>                        new_state.jpeg = VCN_DPG_STATE__PAUSE;
>>>
>>> -             adev->vcn.pause_dpg_mode(adev, 0, &new_state);
>>> +             adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
>>>        }
>>>    }
>>>
>>>    void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
>>>    {
>>>        schedule_delayed_work(&ring->adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
>>> -     mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
>>> +     mutex_unlock(&ring->adev->vcn.inst[0].vcn1_jpeg1_workaround);
>>>    }
>>>
>>>    static void vcn_v1_0_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
>>> @@ -2057,11 +2057,11 @@ static int vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
>>>                uint32_t reg = amdgpu_ib_get_value(ib, i);
>>>                uint32_t val = amdgpu_ib_get_value(ib, i + 1);
>>>
>>> -             if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
>>> +             if (reg == PACKET0(p->adev->vcn.inst[0].internal.data0, 0)) {
>>>                        msg_lo = val;
>>> -             } else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
>>> +             } else if (reg == PACKET0(p->adev->vcn.inst[0].internal.data1, 0)) {
>>>                        msg_hi = val;
>>> -             } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0)) {
>>> +             } else if (reg == PACKET0(p->adev->vcn.inst[0].internal.cmd, 0)) {
>>>                        r = vcn_v1_0_validate_bo(p, job,
>>>                                                 ((u64)msg_hi) << 32 | msg_lo);
>>>                        if (r)
>>> @@ -2146,7 +2146,7 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
>>>    {
>>>        int i;
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>>>                adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
>>>    }
>>>
>>> @@ -2157,7 +2157,7 @@ static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
>>>
>>>    static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev)
>>>    {
>>> -     adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2;
>>> +     adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 2;
>>>        adev->vcn.inst->irq.funcs = &vcn_v1_0_irq_funcs;
>>>    }
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
>>> index e55c1f8f260e9..b0a957664250c 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
>>> @@ -110,9 +110,9 @@ static int vcn_v2_0_early_init(struct amdgpu_ip_block *ip_block)
>>>        struct amdgpu_device *adev = ip_block->adev;
>>>
>>>        if (amdgpu_sriov_vf(adev))
>>> -             adev->vcn.num_enc_rings = 1;
>>> +             adev->vcn.inst[0].num_enc_rings = 1;
>>>        else
>>> -             adev->vcn.num_enc_rings = 2;
>>> +             adev->vcn.inst[0].num_enc_rings = 2;
>>>
>>>        vcn_v2_0_set_dec_ring_funcs(adev);
>>>        vcn_v2_0_set_enc_ring_funcs(adev);
>>> @@ -145,7 +145,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                return r;
>>>
>>>        /* VCN ENC TRAP */
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
>>>                                      i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
>>>                                      &adev->vcn.inst->irq);
>>> @@ -175,25 +175,25 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>        if (r)
>>>                return r;
>>>
>>> -     adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>>> -     adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>>> -     adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
>>> -     adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
>>> -     adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
>>> -     adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>>>
>>> -     adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>>>        adev->vcn.inst->external.scratch9 = SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
>>> -     adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>>>        adev->vcn.inst->external.data0 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
>>> -     adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>>>        adev->vcn.inst->external.data1 = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
>>> -     adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>>>        adev->vcn.inst->external.cmd = SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
>>> -     adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>>> +     adev->vcn.inst[0].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>>>        adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
>>>
>>>                ring = &adev->vcn.inst->ring_enc[i];
>>> @@ -210,7 +210,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>        }
>>>
>>> -     adev->vcn.pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
>>> +     adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
>>>
>>>        r = amdgpu_virt_alloc_mm_table(adev);
>>>        if (r)
>>> @@ -292,7 +292,7 @@ static int vcn_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
>>>        if (amdgpu_sriov_vf(adev))
>>>                ring->sched.ready = false;
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                ring = &adev->vcn.inst->ring_enc[i];
>>>                r = amdgpu_ring_test_helper(ring);
>>>                if (r)
>>> @@ -981,7 +981,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
>>>                amdgpu_dpm_enable_vcn(adev, true, 0);
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram);
>>> +             return vcn_v2_0_start_dpg_mode(adev, adev->vcn.inst->indirect_sram);
>>>
>>>        vcn_v2_0_disable_static_power_gating(adev);
>>>
>>> @@ -1421,9 +1421,9 @@ void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
>>>    {
>>>        struct amdgpu_device *adev = ring->adev;
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>>>        amdgpu_ring_write(ring, 0);
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
>>>    }
>>>
>>> @@ -1438,7 +1438,7 @@ void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
>>>    {
>>>        struct amdgpu_device *adev = ring->adev;
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[0].internal.cmd, 0));
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
>>>    }
>>>
>>> @@ -1458,7 +1458,7 @@ void vcn_v2_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
>>>        WARN_ON(ring->wptr % 2 || count % 2);
>>>
>>>        for (i = 0; i < count / 2; i++) {
>>> -             amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.nop, 0));
>>> +             amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.nop, 0));
>>>                amdgpu_ring_write(ring, 0);
>>>        }
>>>    }
>>> @@ -1479,25 +1479,25 @@ void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
>>>        struct amdgpu_device *adev = ring->adev;
>>>
>>>        WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.context_id, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.context_id, 0));
>>>        amdgpu_ring_write(ring, seq);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>>>        amdgpu_ring_write(ring, addr & 0xffffffff);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>>>        amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>>>        amdgpu_ring_write(ring, 0);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>>>        amdgpu_ring_write(ring, 0);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>>>
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
>>>    }
>>> @@ -1520,14 +1520,14 @@ void vcn_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
>>>        struct amdgpu_device *adev = ring->adev;
>>>        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_vmid, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_vmid, 0));
>>>        amdgpu_ring_write(ring, vmid);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_bar_low, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_low, 0));
>>>        amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_bar_high, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_bar_high, 0));
>>>        amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.ib_size, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.ib_size, 0));
>>>        amdgpu_ring_write(ring, ib->length_dw);
>>>    }
>>>
>>> @@ -1536,16 +1536,16 @@ void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
>>>    {
>>>        struct amdgpu_device *adev = ring->adev;
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>>>        amdgpu_ring_write(ring, reg << 2);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>>>        amdgpu_ring_write(ring, val);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.gp_scratch8, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.gp_scratch8, 0));
>>>        amdgpu_ring_write(ring, mask);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>>>
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
>>>    }
>>> @@ -1570,13 +1570,13 @@ void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
>>>    {
>>>        struct amdgpu_device *adev = ring->adev;
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data0, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data0, 0));
>>>        amdgpu_ring_write(ring, reg << 2);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.data1, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.data1, 0));
>>>        amdgpu_ring_write(ring, val);
>>>
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>>>
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
>>>    }
>>> @@ -1777,9 +1777,9 @@ int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
>>>        r = amdgpu_ring_alloc(ring, 4);
>>>        if (r)
>>>                return r;
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.cmd, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0));
>>>        amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
>>> -     amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
>>> +     amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
>>>        amdgpu_ring_write(ring, 0xDEADBEEF);
>>>        amdgpu_ring_commit(ring);
>>>        for (i = 0; i < adev->usec_timeout; i++) {
>>> @@ -1863,7 +1863,7 @@ static int vcn_v2_0_start_mmsch(struct amdgpu_device *adev,
>>>        adev->vcn.inst->ring_dec.wptr_old = 0;
>>>        vcn_v2_0_dec_ring_set_wptr(&adev->vcn.inst->ring_dec);
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i) {
>>>                adev->vcn.inst->ring_enc[i].wptr = 0;
>>>                adev->vcn.inst->ring_enc[i].wptr_old = 0;
>>>                vcn_v2_0_enc_ring_set_wptr(&adev->vcn.inst->ring_enc[i]);
>>> @@ -1989,7 +1989,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev)
>>>                        SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2),
>>>                        AMDGPU_VCN_CONTEXT_SIZE);
>>>
>>> -             for (r = 0; r < adev->vcn.num_enc_rings; ++r) {
>>> +             for (r = 0; r < adev->vcn.inst[0].num_enc_rings; ++r) {
>>>                        ring = &adev->vcn.inst->ring_enc[r];
>>>                        ring->wptr = 0;
>>>                        MMSCH_V2_0_INSERT_DIRECT_WT(
>>> @@ -2178,7 +2178,7 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
>>>    {
>>>        int i;
>>>
>>> -     for (i = 0; i < adev->vcn.num_enc_rings; ++i)
>>> +     for (i = 0; i < adev->vcn.inst[0].num_enc_rings; ++i)
>>>                adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs;
>>>    }
>>>
>>> @@ -2189,7 +2189,7 @@ static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
>>>
>>>    static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev)
>>>    {
>>> -     adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +     adev->vcn.inst->irq.num_types = adev->vcn.inst[0].num_enc_rings + 1;
>>>        adev->vcn.inst->irq.funcs = &vcn_v2_0_irq_funcs;
>>>    }
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
>>> index 1d3780a2d8513..a3bac39e4c9db 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
>>> @@ -121,11 +121,13 @@ static int amdgpu_ih_clientid_vcns[] = {
>>>    static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>> +     int i;
>>>
>>>        if (amdgpu_sriov_vf(adev)) {
>>>                adev->vcn.num_vcn_inst = 2;
>>>                adev->vcn.harvest_config = 0;
>>> -             adev->vcn.num_enc_rings = 1;
>>> +             for (i = 0; i < adev->vcn.num_vcn_inst; i++)
>>> +                     adev->vcn.inst[i].num_enc_rings = 1;
>>>        } else {
>>>                u32 harvest;
>>>                int i;
>>> @@ -134,13 +136,12 @@ static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
>>>                        harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING);
>>>                        if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
>>>                                adev->vcn.harvest_config |= 1 << i;
>>> +                     adev->vcn.inst[i].num_enc_rings = 2;
>>>                }
>>>                if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
>>>                                        AMDGPU_VCN_HARVEST_VCN1))
>>>                        /* both instances are harvested, disable the block */
>>>                        return -ENOENT;
>>> -
>>> -             adev->vcn.num_enc_rings = 2;
>>>        }
>>>
>>>        vcn_v2_5_set_dec_ring_funcs(adev);
>>> @@ -176,7 +177,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>
>>>                /* VCN ENC TRAP */
>>> -             for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>>>                        r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j],
>>>                                i + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[j].irq);
>>>                        if (r)
>>> @@ -205,22 +206,22 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>
>>>                if (adev->vcn.harvest_config & (1 << j))
>>>                        continue;
>>> -             adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>>> -
>>> -             adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>>> +
>>> +             adev->vcn.inst[j].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>>>                adev->vcn.inst[j].external.scratch9 = SOC15_REG_OFFSET(VCN, j, mmUVD_SCRATCH9);
>>> -             adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>>>                adev->vcn.inst[j].external.data0 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA0);
>>> -             adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>>>                adev->vcn.inst[j].external.data1 = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_DATA1);
>>> -             adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>>>                adev->vcn.inst[j].external.cmd = SOC15_REG_OFFSET(VCN, j, mmUVD_GPCOM_VCPU_CMD);
>>> -             adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[j].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>>>                adev->vcn.inst[j].external.nop = SOC15_REG_OFFSET(VCN, j, mmUVD_NO_OP);
>>>
>>>                ring = &adev->vcn.inst[j].ring_dec;
>>> @@ -240,7 +241,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>                if (r)
>>>                        return r;
>>>
>>> -             for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>>>                        enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
>>>
>>>                        ring = &adev->vcn.inst[j].ring_enc[i];
>>> @@ -268,6 +269,9 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>
>>>                if (amdgpu_vcnfw_log)
>>>                        amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
>>> +
>>> +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
>>>        }
>>>
>>>        if (amdgpu_sriov_vf(adev)) {
>>> @@ -276,9 +280,6 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>        }
>>>
>>> -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
>>> -
>>>        r = amdgpu_vcn_ras_sw_init(adev);
>>>        if (r)
>>>                return r;
>>> @@ -369,7 +370,7 @@ static int vcn_v2_5_hw_init(struct amdgpu_ip_block *ip_block)
>>>                        if (r)
>>>                                return r;
>>>
>>> -                     for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +                     for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>>>                                ring = &adev->vcn.inst[j].ring_enc[i];
>>>                                r = amdgpu_ring_test_helper(ring);
>>>                                if (r)
>>> @@ -1018,7 +1019,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev, int i)
>>>                amdgpu_dpm_enable_vcn(adev, true, i);
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v2_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        /* disable register anti-hang mechanism */
>>>        WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_POWER_STATUS), 0,
>>> @@ -1746,7 +1747,7 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
>>>        for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
>>>                if (adev->vcn.harvest_config & (1 << j))
>>>                        continue;
>>> -             for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>>> +             for (i = 0; i < adev->vcn.inst[j].num_enc_rings; ++i) {
>>>                        adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs;
>>>                        adev->vcn.inst[j].ring_enc[i].me = j;
>>>                }
>>> @@ -1917,10 +1918,10 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
>>>        for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>> -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs;
>>>
>>> -             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs;
>>>        }
>>>    }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
>>> index 13b9ed96cccda..fabe4d75a7f6b 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
>>> @@ -127,11 +127,13 @@ static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
>>>    static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>> +     int i;
>>>
>>>        if (amdgpu_sriov_vf(adev)) {
>>>                adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
>>>                adev->vcn.harvest_config = 0;
>>> -             adev->vcn.num_enc_rings = 1;
>>> +             for (i = 0; i < adev->vcn.num_vcn_inst; i++)
>>> +                     adev->vcn.inst[i].num_enc_rings = 1;
>>>
>>>        } else {
>>>                if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
>>> @@ -139,11 +141,13 @@ static int vcn_v3_0_early_init(struct amdgpu_ip_block *ip_block)
>>>                        /* both instances are harvested, disable the block */
>>>                        return -ENOENT;
>>>
>>> -             if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
>>> -                 IP_VERSION(3, 0, 33))
>>> -                     adev->vcn.num_enc_rings = 0;
>>> -             else
>>> -                     adev->vcn.num_enc_rings = 2;
>>> +             for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
>>> +                     if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
>>> +                         IP_VERSION(3, 0, 33))
>>> +                             adev->vcn.inst[i].num_enc_rings = 0;
>>> +                     else
>>> +                             adev->vcn.inst[i].num_enc_rings = 2;
>>> +             }
>>>        }
>>>
>>>        vcn_v3_0_set_dec_ring_funcs(adev);
>>> @@ -198,22 +202,22 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>>
>>> -             adev->vcn.internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
>>> -             adev->vcn.internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.context_id = mmUVD_CONTEXT_ID_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.ib_vmid = mmUVD_LMI_RBC_IB_VMID_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.ib_bar_low = mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.ib_bar_high = mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.ib_size = mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.gp_scratch8 = mmUVD_GP_SCRATCH8_INTERNAL_OFFSET;
>>>
>>> -             adev->vcn.internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.scratch9 = mmUVD_SCRATCH9_INTERNAL_OFFSET;
>>>                adev->vcn.inst[i].external.scratch9 = SOC15_REG_OFFSET(VCN, i, mmUVD_SCRATCH9);
>>> -             adev->vcn.internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.data0 = mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET;
>>>                adev->vcn.inst[i].external.data0 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA0);
>>> -             adev->vcn.internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.data1 = mmUVD_GPCOM_VCPU_DATA1_INTERNAL_OFFSET;
>>>                adev->vcn.inst[i].external.data1 = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_DATA1);
>>> -             adev->vcn.internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.cmd = mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET;
>>>                adev->vcn.inst[i].external.cmd = SOC15_REG_OFFSET(VCN, i, mmUVD_GPCOM_VCPU_CMD);
>>> -             adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>>> +             adev->vcn.inst[i].internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
>>>                adev->vcn.inst[i].external.nop = SOC15_REG_OFFSET(VCN, i, mmUVD_NO_OP);
>>>
>>>                /* VCN DEC TRAP */
>>> @@ -227,7 +231,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                ring = &adev->vcn.inst[i].ring_dec;
>>>                ring->use_doorbell = true;
>>>                if (amdgpu_sriov_vf(adev)) {
>>> -                     ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1);
>>> +                     ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1);
>>>                } else {
>>>                        ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i;
>>>                }
>>> @@ -239,7 +243,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                if (r)
>>>                        return r;
>>>
>>> -             for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
>>> +             for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>>>                        enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(j);
>>>
>>>                        /* VCN ENC TRAP */
>>> @@ -251,7 +255,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        ring = &adev->vcn.inst[i].ring_enc[j];
>>>                        ring->use_doorbell = true;
>>>                        if (amdgpu_sriov_vf(adev)) {
>>> -                             ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.num_enc_rings + 1) + 1 + j;
>>> +                             ring->doorbell_index = vcn_doorbell_index + i * (adev->vcn.inst[i].num_enc_rings + 1) + 1 + j;
>>>                        } else {
>>>                                ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i;
>>>                        }
>>> @@ -277,6 +281,9 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>
>>>                if (amdgpu_vcnfw_log)
>>>                        amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
>>> +
>>> +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
>>>        }
>>>
>>>        if (amdgpu_sriov_vf(adev)) {
>>> @@ -284,8 +291,6 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                if (r)
>>>                        return r;
>>>        }
>>> -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             adev->vcn.pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
>>>
>>>        /* Allocate memory for VCN IP Dump buffer */
>>>        ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
>>> @@ -373,7 +378,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
>>>                                ring->sched.ready = true;
>>>                        }
>>>
>>> -                     for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
>>> +                     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>>>                                ring = &adev->vcn.inst[i].ring_enc[j];
>>>                                if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) {
>>>                                        ring->sched.ready = false;
>>> @@ -401,7 +406,7 @@ static int vcn_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
>>>                        if (r)
>>>                                return r;
>>>
>>> -                     for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
>>> +                     for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>>>                                ring = &adev->vcn.inst[i].ring_enc[j];
>>>                                r = amdgpu_ring_test_helper(ring);
>>>                                if (r)
>>> @@ -1153,7 +1158,7 @@ static int vcn_v3_0_start(struct amdgpu_device *adev, int i)
>>>                amdgpu_dpm_enable_vcn(adev, true, i);
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v3_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        /* disable VCN power gating */
>>>        vcn_v3_0_disable_static_power_gating(adev, i);
>>> @@ -1433,7 +1438,7 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
>>>                        mmUVD_VCPU_CACHE_SIZE2),
>>>                        AMDGPU_VCN_CONTEXT_SIZE);
>>>
>>> -             for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
>>> +             for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>>>                        ring = &adev->vcn.inst[i].ring_enc[j];
>>>                        ring->wptr = 0;
>>>                        rb_addr = ring->gpu_addr;
>>> @@ -1921,11 +1926,11 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
>>>                uint32_t reg = amdgpu_ib_get_value(ib, i);
>>>                uint32_t val = amdgpu_ib_get_value(ib, i + 1);
>>>
>>> -             if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
>>> +             if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data0, 0)) {
>>>                        msg_lo = val;
>>> -             } else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
>>> +             } else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.data1, 0)) {
>>>                        msg_hi = val;
>>> -             } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0) &&
>>> +             } else if (reg == PACKET0(p->adev->vcn.inst[ring->me].internal.cmd, 0) &&
>>>                           val == 0) {
>>>                        r = vcn_v3_0_dec_msg(p, job,
>>>                                             ((u64)msg_hi) << 32 | msg_lo);
>>> @@ -2089,7 +2094,7 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>>
>>> -             for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
>>> +             for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j) {
>>>                        adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs;
>>>                        adev->vcn.inst[i].ring_enc[j].me = i;
>>>                }
>>> @@ -2255,7 +2260,7 @@ static void vcn_v3_0_set_irq_funcs(struct amdgpu_device *adev)
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>>
>>> -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].irq.funcs = &vcn_v3_0_irq_funcs;
>>>        }
>>>    }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
>>> index dbbeeffc90726..ee87594fafa60 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
>>> @@ -129,8 +129,9 @@ static int vcn_v4_0_early_init(struct amdgpu_ip_block *ip_block)
>>>                }
>>>        }
>>>
>>> -     /* re-use enc ring as unified ring */
>>> -     adev->vcn.num_enc_rings = 1;
>>> +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>>> +             /* re-use enc ring as unified ring */
>>> +             adev->vcn.inst[i].num_enc_rings = 1;
>>>
>>>        vcn_v4_0_set_unified_ring_funcs(adev);
>>>        vcn_v4_0_set_irq_funcs(adev);
>>> @@ -214,7 +215,8 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                ring = &adev->vcn.inst[i].ring_enc[0];
>>>                ring->use_doorbell = true;
>>>                if (amdgpu_sriov_vf(adev))
>>> -                     ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * (adev->vcn.num_enc_rings + 1) + 1;
>>> +                     ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i *
>>> +                             (adev->vcn.inst[i].num_enc_rings + 1) + 1;
>>>                else
>>>                        ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;
>>>                ring->vm_hub = AMDGPU_MMHUB0(0);
>>> @@ -226,6 +228,9 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>
>>>                vcn_v4_0_fw_shared_init(adev, i);
>>> +
>>> +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
>>>        }
>>>
>>>        /* TODO: Add queue reset mask when FW fully supports it */
>>> @@ -238,8 +243,6 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>        }
>>>
>>> -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
>>>
>>>        r = amdgpu_vcn_ras_sw_init(adev);
>>>        if (r)
>>> @@ -1111,7 +1114,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev, int i)
>>>        fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        /* disable VCN power gating */
>>>        vcn_v4_0_disable_static_power_gating(adev, i);
>>> @@ -2172,10 +2175,10 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev)
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>>
>>> -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs;
>>>
>>> -             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs;
>>>        }
>>>    }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
>>> index 8396ef6831b69..35854e074d142 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
>>> @@ -114,9 +114,11 @@ static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
>>>    static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>> +     int i;
>>>
>>> -     /* re-use enc ring as unified ring */
>>> -     adev->vcn.num_enc_rings = 1;
>>> +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>>> +             /* re-use enc ring as unified ring */
>>> +             adev->vcn.inst[i].num_enc_rings = 1;
>>>
>>>        vcn_v4_0_3_set_unified_ring_funcs(adev);
>>>        vcn_v4_0_3_set_irq_funcs(adev);
>>> @@ -194,6 +196,9 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>
>>>                vcn_v4_0_3_fw_shared_init(adev, i);
>>> +
>>> +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
>>>        }
>>>
>>>        /* TODO: Add queue reset mask when FW fully supports it */
>>> @@ -206,9 +211,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>        }
>>>
>>> -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             adev->vcn.pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
>>> -
>>>        if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
>>>                r = amdgpu_vcn_ras_sw_init(adev);
>>>                if (r) {
>>> @@ -1138,7 +1140,7 @@ static int vcn_v4_0_3_start(struct amdgpu_device *adev, int i)
>>>                amdgpu_dpm_enable_vcn(adev, true, i);
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        vcn_inst = GET_INST(VCN, i);
>>>        /* set VCN status busy */
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
>>> index f6b347fcdb7ed..0700a5f96084c 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
>>> @@ -115,9 +115,11 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
>>>    static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>> +     int i;
>>>
>>> -     /* re-use enc ring as unified ring */
>>> -     adev->vcn.num_enc_rings = 1;
>>> +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>>> +             /* re-use enc ring as unified ring */
>>> +             adev->vcn.inst[i].num_enc_rings = 1;
>>>        vcn_v4_0_5_set_unified_ring_funcs(adev);
>>>        vcn_v4_0_5_set_irq_funcs(adev);
>>>
>>> @@ -173,7 +175,7 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>                ring->use_doorbell = true;
>>>                if (amdgpu_sriov_vf(adev))
>>>                        ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
>>> -                                             i * (adev->vcn.num_enc_rings + 1) + 1;
>>> +                                             i * (adev->vcn.inst[i].num_enc_rings + 1) + 1;
>>>                else
>>>                        ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
>>>                                                2 + 8 * i;
>>> @@ -198,6 +200,9 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>
>>>                if (amdgpu_vcnfw_log)
>>>                        amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
>>> +
>>> +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
>>>        }
>>>
>>>        if (amdgpu_sriov_vf(adev)) {
>>> @@ -206,9 +211,6 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
>>>                        return r;
>>>        }
>>>
>>> -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;
>>> -
>>>        /* Allocate memory for VCN IP Dump buffer */
>>>        ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);
>>>        if (!ptr) {
>>> @@ -1014,7 +1016,7 @@ static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
>>>        fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        /* disable VCN power gating */
>>>        vcn_v4_0_5_disable_static_power_gating(adev, i);
>>> @@ -1624,7 +1626,7 @@ static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>>
>>> -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs;
>>>        }
>>>    }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
>>> index c5d59edf3a482..eeb3c9875ad50 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
>>> @@ -98,9 +98,11 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
>>>    static int vcn_v5_0_0_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>> +     int i;
>>>
>>> -     /* re-use enc ring as unified ring */
>>> -     adev->vcn.num_enc_rings = 1;
>>> +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>>> +             /* re-use enc ring as unified ring */
>>> +             adev->vcn.inst[i].num_enc_rings = 1;
>>>
>>>        vcn_v5_0_0_set_unified_ring_funcs(adev);
>>>        vcn_v5_0_0_set_irq_funcs(adev);
>>> @@ -184,15 +186,15 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
>>>
>>>                if (amdgpu_vcnfw_log)
>>>                        amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
>>> +
>>> +             if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> +                     adev->vcn.inst[i].pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
>>>        }
>>>
>>>        /* TODO: Add queue reset mask when FW fully supports it */
>>>        adev->vcn.supported_reset =
>>>                amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
>>>
>>> -     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
>>> -
>>>        vcn_v5_0_0_alloc_ip_dump(adev);
>>>
>>>        r = amdgpu_vcn_sysfs_reset_mask_init(adev);
>>> @@ -791,7 +793,7 @@ static int vcn_v5_0_0_start(struct amdgpu_device *adev, int i)
>>>        fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        /* disable VCN power gating */
>>>        vcn_v5_0_0_disable_static_power_gating(adev, i);
>>> @@ -1367,7 +1369,7 @@ static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev)
>>>                if (adev->vcn.harvest_config & (1 << i))
>>>                        continue;
>>>
>>> -             adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
>>> +             adev->vcn.inst[i].irq.num_types = adev->vcn.inst[i].num_enc_rings + 1;
>>>                adev->vcn.inst[i].irq.funcs = &vcn_v5_0_0_irq_funcs;
>>>        }
>>>    }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
>>> index 51a2d70a65c9e..f428d23eb2857 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
>>> @@ -58,9 +58,11 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring);
>>>    static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block)
>>>    {
>>>        struct amdgpu_device *adev = ip_block->adev;
>>> +     int i;
>>>
>>> -     /* re-use enc ring as unified ring */
>>> -     adev->vcn.num_enc_rings = 1;
>>> +     for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>>> +             /* re-use enc ring as unified ring */
>>> +             adev->vcn.inst[i].num_enc_rings = 1;
>>>
>>>        vcn_v5_0_1_set_unified_ring_funcs(adev);
>>>        vcn_v5_0_1_set_irq_funcs(adev);
>>> @@ -586,7 +588,7 @@ static int vcn_v5_0_1_start(struct amdgpu_device *adev, int i)
>>>        fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
>>>
>>>        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
>>> -             return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
>>> +             return vcn_v5_0_1_start_dpg_mode(adev, i, adev->vcn.inst[i].indirect_sram);
>>>
>>>        vcn_inst = GET_INST(VCN, i);
>>>

[-- Attachment #2: Type: text/html, Size: 78404 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 21/44] drm/amdgpu/vcn: adjust pause_dpg_mode function signature
  2025-01-31 16:57 ` [PATCH 21/44] drm/amdgpu/vcn: adjust pause_dpg_mode function signature Alex Deucher
@ 2025-02-06 13:40   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 13:40 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 16787 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Change it to take a vcn instance rather than adev to align
> with the vcn instance changes.
>
> TODO: clean up the function internals to use the vinst state
> directly rather than accessing it indirectly via adev->vcn.inst[].
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c |  4 ++--
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  3 +--
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c   | 14 ++++++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c   | 12 +++++++-----
>   drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c   | 10 ++++++----
>   drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c   | 12 +++++++-----
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c   | 15 ++++++++-------
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 11 +++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 13 +++++++------
>   drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 15 ++++++++-------
>   10 files changed, 59 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 010cc64a950a4..a2250747a7c81 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -417,7 +417,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>   		else
>   			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>   
> -		adev->vcn.inst[i].pause_dpg_mode(adev, i, &new_state);
> +		adev->vcn.inst[i].pause_dpg_mode(vcn_inst, &new_state);
>   	}
>   
>   	fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
> @@ -474,7 +474,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>   		}
>   
> -		adev->vcn.inst[ring->me].pause_dpg_mode(adev, ring->me, &new_state);
> +		adev->vcn.inst[ring->me].pause_dpg_mode(&adev->vcn.inst[ring->me], &new_state);
>   	}
>   	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
>   }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index 5f92cf28cc752..8d34e3814ab19 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -327,8 +327,7 @@ struct amdgpu_vcn_inst {
>   	bool			indirect_sram;
>   	struct amdgpu_vcn_reg	 internal;
>   	struct mutex		vcn1_jpeg1_workaround;
> -	int (*pause_dpg_mode)(struct amdgpu_device *adev,
> -			      int inst_idx,
> +	int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst,
>   			      struct dpg_pause_state *new_state);
>   	bool using_unified_queue;
>   };
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index 613f17be9d829..3d56660fd90a9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -87,8 +87,8 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
>   static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   				enum amd_powergating_state state);
> -static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
> -				int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state);
>   
>   static void vcn_v1_0_idle_work_handler(struct work_struct *work);
>   static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);
> @@ -1264,9 +1264,11 @@ static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst)
>   	return r;
>   }
>   
> -static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
> -				int inst_idx, struct dpg_pause_state *new_state)
> +static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	int ret_code;
>   	uint32_t reg_data = 0;
>   	uint32_t reg_data2 = 0;
> @@ -1866,7 +1868,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>   		else
>   			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
>   
> -		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
> +		adev->vcn.inst->pause_dpg_mode(vcn_inst, &new_state);
>   	}
>   
>   	fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
> @@ -1933,7 +1935,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
>   		else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
>   			new_state.jpeg = VCN_DPG_STATE__PAUSE;
>   
> -		adev->vcn.inst[0].pause_dpg_mode(adev, 0, &new_state);
> +		adev->vcn.inst->pause_dpg_mode(adev->vcn.inst, &new_state);
>   	}
>   }
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> index aa61d3b54f8c2..e4305687749a8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
> @@ -94,8 +94,8 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev);
>   static int vcn_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   				enum amd_powergating_state state);
> -static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,
> -				int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state);
>   static int vcn_v2_0_start_sriov(struct amdgpu_device *adev);
>   /**
>    * vcn_v2_0_early_init - set function pointers and load microcode
> @@ -1158,7 +1158,7 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> -	vcn_v2_0_pause_dpg_mode(adev, 0, &state);
> +	vcn_v2_0_pause_dpg_mode(vinst, &state);
>   	/* Wait for power status to be 1 */
>   	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS, 1,
>   		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> @@ -1252,9 +1252,11 @@ static int vcn_v2_0_stop(struct amdgpu_vcn_inst *vinst)
>   	return 0;
>   }
>   
> -static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,
> -				int inst_idx, struct dpg_pause_state *new_state)
> +static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	struct amdgpu_ring *ring;
>   	uint32_t reg_data = 0;
>   	int ret_code;
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index 69cf42a4a3f18..d5921a954948e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -100,8 +100,8 @@ static int vcn_v2_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   					       int i);
>   static int vcn_v2_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state);
> -static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,
> -				int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state);
>   static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
>   static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev);
>   
> @@ -1506,9 +1506,11 @@ static int vcn_v2_5_stop(struct amdgpu_vcn_inst *vinst)
>   	return 0;
>   }
>   
> -static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,
> -				int inst_idx, struct dpg_pause_state *new_state)
> +static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	struct amdgpu_ring *ring;
>   	uint32_t reg_data = 0;
>   	int ret_code = 0;
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> index f6f4f04d74339..2a17a7e108001 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
> @@ -110,8 +110,8 @@ static int vcn_v3_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   					       int i);
>   static int vcn_v3_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state);
> -static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
> -			int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state);
>   
>   static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring);
>   static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
> @@ -1581,7 +1581,7 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> -	vcn_v3_0_pause_dpg_mode(adev, inst_idx, &state);
> +	vcn_v3_0_pause_dpg_mode(vinst, &state);
>   
>   	/* Wait for power status to be 1 */
>   	SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS, 1,
> @@ -1680,9 +1680,11 @@ static int vcn_v3_0_stop(struct amdgpu_vcn_inst *vinst)
>   	return 0;
>   }
>   
> -static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
> -		   int inst_idx, struct dpg_pause_state *new_state)
> +static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	volatile struct amdgpu_fw_shared *fw_shared;
>   	struct amdgpu_ring *ring;
>   	uint32_t reg_data = 0;
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index 3d70e2cc81982..2ad217470c8c6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -101,8 +101,8 @@ static int vcn_v4_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_block,
>   					       int i);
>   static int vcn_v4_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					  enum amd_powergating_state state);
> -static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev,
> -        int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state);
>   static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev);
>   
> @@ -1565,7 +1565,7 @@ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> -	vcn_v4_0_pause_dpg_mode(adev, inst_idx, &state);
> +	vcn_v4_0_pause_dpg_mode(vinst, &state);
>   	/* Wait for power status to be 1 */
>   	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
>   		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
> @@ -1671,15 +1671,16 @@ static int vcn_v4_0_stop(struct amdgpu_vcn_inst *vinst)
>   /**
>    * vcn_v4_0_pause_dpg_mode - VCN pause with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @new_state: pause state
>    *
>    * Pause dpg mode for VCN block
>    */
> -static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
> -      struct dpg_pause_state *new_state)
> +static int vcn_v4_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				   struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   	int ret_code;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index a3fbfaac76603..ae7733c0d032e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -92,8 +92,8 @@ static int vcn_v4_0_3_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i);
>   static int vcn_v4_0_3_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					    enum amd_powergating_state state);
> -static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev,
> -		int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     struct dpg_pause_state *new_state);
>   static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   static void vcn_v4_0_3_set_ras_funcs(struct amdgpu_device *adev);
>   static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev,
> @@ -1449,14 +1449,13 @@ static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst *vinst)
>   /**
>    * vcn_v4_0_3_pause_dpg_mode - VCN pause with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @new_state: pause state
>    *
>    * Pause dpg mode for VCN block
>    */
> -static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
> -				struct dpg_pause_state *new_state)
> +static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     struct dpg_pause_state *new_state)
>   {
>   
>   	return 0;
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index 295f39b2222d5..a00c74d287a69 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -100,8 +100,8 @@ static int vcn_v4_0_5_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i);
>   static int vcn_v4_0_5_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					    enum amd_powergating_state state);
> -static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev,
> -		int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     struct dpg_pause_state *new_state);
>   static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   
>   /**
> @@ -1321,15 +1321,16 @@ static int vcn_v4_0_5_stop(struct amdgpu_vcn_inst *vinst)
>   /**
>    * vcn_v4_0_5_pause_dpg_mode - VCN pause with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @new_state: pause state
>    *
>    * Pause dpg mode for VCN block
>    */
> -static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
> -		struct dpg_pause_state *new_state)
> +static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   	int ret_code;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index a71960d899e38..91b57b86dc58a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -83,8 +83,8 @@ static int vcn_v5_0_0_set_powergating_state_inst(struct amdgpu_ip_block *ip_bloc
>   						 int i);
>   static int vcn_v5_0_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   					    enum amd_powergating_state state);
> -static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev,
> -		int inst_idx, struct dpg_pause_state *new_state);
> +static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     struct dpg_pause_state *new_state);
>   static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
>   
>   /**
> @@ -961,7 +961,7 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
>   	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
>   	uint32_t tmp;
>   
> -	vcn_v5_0_0_pause_dpg_mode(adev, inst_idx, &state);
> +	vcn_v5_0_0_pause_dpg_mode(vinst, &state);
>   
>   	/* Wait for power status to be 1 */
>   	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
> @@ -1064,15 +1064,16 @@ static int vcn_v5_0_0_stop(struct amdgpu_vcn_inst *vinst)
>   /**
>    * vcn_v5_0_0_pause_dpg_mode - VCN pause with dpg mode
>    *
> - * @adev: amdgpu_device pointer
> - * @inst_idx: instance number index
> + * @vinst: VCN instance
>    * @new_state: pause state
>    *
>    * Pause dpg mode for VCN block
>    */
> -static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
> -	struct dpg_pause_state *new_state)
> +static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> +				     struct dpg_pause_state *new_state)
>   {
> +	struct amdgpu_device *adev = vinst->adev;
> +	int inst_idx = vinst->inst;
>   	uint32_t reg_data = 0;
>   	int ret_code;
>   

[-- Attachment #2: Type: text/html, Size: 17089 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 22/44] drm/amdgpu/vcn: add new per instance callback for powergating
  2025-01-31 16:57 ` [PATCH 22/44] drm/amdgpu/vcn: add new per instance callback for powergating Alex Deucher
@ 2025-02-06 13:40   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 13:40 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 916 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> This is per instance so add a new function pointer for it.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index 8d34e3814ab19..508fa022df78c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -329,6 +329,8 @@ struct amdgpu_vcn_inst {
>   	struct mutex		vcn1_jpeg1_workaround;
>   	int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst,
>   			      struct dpg_pause_state *new_state);
> +	int (*set_pg_state)(struct amdgpu_vcn_inst *vinst,
> +			    enum amd_powergating_state state);
>   	bool using_unified_queue;
>   };
>   

[-- Attachment #2: Type: text/html, Size: 1897 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 23/44] drm/amdgpu/vcn1.0: add set_pg_state callback
  2025-01-31 16:57 ` [PATCH 23/44] drm/amdgpu/vcn1.0: add set_pg_state callback Alex Deucher
@ 2025-02-06 13:46   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 13:46 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 3856 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Rework the code as a vcn instance callback.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Patches 23-32 are

Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 32 ++++++++++++++++++---------
>   1 file changed, 22 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> index 3d56660fd90a9..fdb954c7377eb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
> @@ -85,6 +85,8 @@ static int vcn_v1_0_stop(struct amdgpu_vcn_inst *vinst);
>   static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
>   static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
> +static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
> +				 enum amd_powergating_state state);
>   static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   				enum amd_powergating_state state);
>   static int vcn_v1_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
> @@ -106,6 +108,7 @@ static int vcn_v1_0_early_init(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   
>   	adev->vcn.inst[0].num_enc_rings = 2;
> +	adev->vcn.inst[0].set_pg_state = vcn_v1_0_set_pg_state;
>   
>   	vcn_v1_0_set_dec_ring_funcs(adev);
>   	vcn_v1_0_set_enc_ring_funcs(adev);
> @@ -276,13 +279,14 @@ static int vcn_v1_0_hw_init(struct amdgpu_ip_block *ip_block)
>   static int vcn_v1_0_hw_fini(struct amdgpu_ip_block *ip_block)
>   {
>   	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
>   
> -	cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
> +	cancel_delayed_work_sync(&vinst->idle_work);
>   
>   	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
> -		(adev->vcn.inst[0].cur_state != AMD_PG_STATE_GATE &&
> -		 RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
> -		vcn_v1_0_set_powergating_state(ip_block, AMD_PG_STATE_GATE);
> +	    (vinst->cur_state != AMD_PG_STATE_GATE &&
> +	     RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
> +		vinst->set_pg_state(vinst, AMD_PG_STATE_GATE);
>   	}
>   
>   	return 0;
> @@ -1818,8 +1822,8 @@ static void vcn_v1_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t coun
>   	}
>   }
>   
> -static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> -					  enum amd_powergating_state state)
> +static int vcn_v1_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
> +				 enum amd_powergating_state state)
>   {
>   	/* This doesn't actually powergate the VCN block.
>   	 * That's done in the dpm code via the SMC.  This
> @@ -1829,10 +1833,8 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   	 * the smc and the hw blocks
>   	 */
>   	int ret;
> -	struct amdgpu_device *adev = ip_block->adev;
> -	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
>   
> -	if (state == adev->vcn.inst[0].cur_state)
> +	if (state == vinst->cur_state)
>   		return 0;
>   
>   	if (state == AMD_PG_STATE_GATE)
> @@ -1841,10 +1843,20 @@ static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
>   		ret = vcn_v1_0_start(vinst);
>   
>   	if (!ret)
> -		adev->vcn.inst[0].cur_state = state;
> +		vinst->cur_state = state;
> +
>   	return ret;
>   }
>   
> +static int vcn_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +					  enum amd_powergating_state state)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	struct amdgpu_vcn_inst *vinst = adev->vcn.inst;
> +
> +	return vinst->set_pg_state(vinst, state);
> +}
> +
>   static void vcn_v1_0_idle_work_handler(struct work_struct *work)
>   {
>   	struct amdgpu_vcn_inst *vcn_inst =

[-- Attachment #2: Type: text/html, Size: 4752 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 32/44] drm/amdgpu/vcn: use per instance callbacks for idle work handler
  2025-01-31 16:57 ` [PATCH 32/44] drm/amdgpu/vcn: use per instance callbacks for idle work handler Alex Deucher
@ 2025-02-06 13:53   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 13:53 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 3673 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> Use the vcn instance power gating callbacks rather than
> the IP powergating callback.  This limits power gating to
> only the instance in use rather than all of the instances.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 27 ++++++++++++-------------
>   1 file changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index a2250747a7c81..81bfd8a9d8268 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -424,8 +424,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>   	fences += fence[i];
>   
>   	if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) {
> -		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
> -						       AMD_PG_STATE_GATE);
> +		vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE);
>   		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
>   						    false);
>   		if (r)
> @@ -438,45 +437,45 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
>   void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>   {
>   	struct amdgpu_device *adev = ring->adev;
> +	struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me];
>   	int r = 0;
>   
> -	atomic_inc(&adev->vcn.inst[ring->me].total_submission_cnt);
> +	atomic_inc(&vcn_inst->total_submission_cnt);
>   
> -	if (!cancel_delayed_work_sync(&adev->vcn.inst[ring->me].idle_work)) {
> +	if (!cancel_delayed_work_sync(&vcn_inst->idle_work)) {
>   		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
>   				true);
>   		if (r)
>   			dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
>   	}
>   
> -	mutex_lock(&adev->vcn.inst[ring->me].vcn_pg_lock);
> -	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
> -					       AMD_PG_STATE_UNGATE);
> +	mutex_lock(&vcn_inst->vcn_pg_lock);
> +	vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE);
>   
>   	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
>   	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
> -	    !adev->vcn.inst[ring->me].using_unified_queue) {
> +	    !vcn_inst->using_unified_queue) {
>   		struct dpg_pause_state new_state;
>   
>   		if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
> -			atomic_inc(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
> +			atomic_inc(&vcn_inst->dpg_enc_submission_cnt);
>   			new_state.fw_based = VCN_DPG_STATE__PAUSE;
>   		} else {
>   			unsigned int fences = 0;
>   			unsigned int i;
>   
> -			for (i = 0; i < adev->vcn.inst[ring->me].num_enc_rings; ++i)
> -				fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
> +			for (i = 0; i < vcn_inst->num_enc_rings; ++i)
> +				fences += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[i]);
>   
> -			if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
> +			if (fences || atomic_read(&vcn_inst->dpg_enc_submission_cnt))
>   				new_state.fw_based = VCN_DPG_STATE__PAUSE;
>   			else
>   				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
>   		}
>   
> -		adev->vcn.inst[ring->me].pause_dpg_mode(&adev->vcn.inst[ring->me], &new_state);
> +		vcn_inst->pause_dpg_mode(vcn_inst, &new_state);
>   	}
> -	mutex_unlock(&adev->vcn.inst[ring->me].vcn_pg_lock);
> +	mutex_unlock(&vcn_inst->vcn_pg_lock);
>   }
>   
>   void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)

[-- Attachment #2: Type: text/html, Size: 4737 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 33/44] drm/amdgpu/vcn: add a generic helper for set_power_gating_state
  2025-01-31 16:57 ` [PATCH 33/44] drm/amdgpu/vcn: add a generic helper for set_power_gating_state Alex Deucher
@ 2025-02-06 13:54   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 13:54 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 1999 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> It's common for all VCN variants.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Patches 33-42 are

Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 23 +++++++++++++++++++++++
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  3 +++
>   2 files changed, 26 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 81bfd8a9d8268..e4ef0fb970b29 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -1397,3 +1397,26 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
>   			    &amdgpu_debugfs_vcn_sched_mask_fops);
>   #endif
>   }
> +
> +/**
> + * vcn_set_powergating_state - set VCN block powergating state
> + *
> + * @ip_block: amdgpu_ip_block pointer
> + * @state: power gating state
> + *
> + * Set VCN block powergating state
> + */
> +int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +			      enum amd_powergating_state state)
> +{
> +	struct amdgpu_device *adev = ip_block->adev;
> +	int ret = 0, i;
> +
> +	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> +		struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
> +
> +		ret |= vinst->set_pg_state(vinst, state);
> +	}
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index 508fa022df78c..a023f46ec904a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -546,4 +546,7 @@ int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev);
>   void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev);
>   void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev);
>   
> +int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
> +			      enum amd_powergating_state state);
> +
>   #endif

[-- Attachment #2: Type: text/html, Size: 2949 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 43/44] drm/amdgpu/vcn: optimize firmware storage
  2025-01-31 16:57 ` [PATCH 43/44] drm/amdgpu/vcn: optimize firmware storage Alex Deucher
@ 2025-02-06 14:48   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 14:48 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 3713 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> If each instance uses the same fw image, only store one
> copy in the driver.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Acked-by: Boyuan Zhang <Boyuan.Zhang@amd.com> <mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 30 +++++++++++++++++--------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h |  4 +++-
>   drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  3 +++
>   3 files changed, 27 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index e4ef0fb970b29..edbcb11c382a2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -102,18 +102,25 @@ int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i)
>   	adev->vcn.inst[i].inst = i;
>   	amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
>   
> -	if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) ==  IP_VERSION(4, 0, 6))
> +	if (i != 0 && adev->vcn.per_inst_fw) {
>   		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
>   					 AMDGPU_UCODE_REQUIRED,
>   					 "amdgpu/%s_%d.bin", ucode_prefix, i);
> -	else
> -		r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
> -					 AMDGPU_UCODE_REQUIRED,
> -					 "amdgpu/%s.bin", ucode_prefix);
> -	if (r) {
> -		amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> -		return r;
> +		if (r)
> +			amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> +	} else {
> +		if (!adev->vcn.inst[0].fw) {
> +			r = amdgpu_ucode_request(adev, &adev->vcn.inst[0].fw,
> +						 AMDGPU_UCODE_REQUIRED,
> +						 "amdgpu/%s.bin", ucode_prefix);
> +			if (r)
> +				amdgpu_ucode_release(&adev->vcn.inst[0].fw);
> +		} else {
> +			r = 0;
> +		}
> +		adev->vcn.inst[i].fw = adev->vcn.inst[0].fw;
>   	}
> +
>   	return r;
>   }
>   
> @@ -270,7 +277,12 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i)
>   	for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
>   		amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]);
>   
> -	amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> +	if (adev->vcn.per_inst_fw) {
> +		amdgpu_ucode_release(&adev->vcn.inst[i].fw);
> +	} else {
> +		amdgpu_ucode_release(&adev->vcn.inst[0].fw);
> +		adev->vcn.inst[i].fw = NULL;
> +	}
>   	mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock);
>   	mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index a023f46ec904a..26c9c2d90f455 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -339,7 +339,6 @@ struct amdgpu_vcn_ras {
>   };
>   
>   struct amdgpu_vcn {
> -	unsigned		fw_version;
>   	uint8_t	num_vcn_inst;
>   	struct amdgpu_vcn_inst	 inst[AMDGPU_MAX_VCN_INSTANCES];
>   
> @@ -356,6 +355,9 @@ struct amdgpu_vcn {
>   
>   	uint32_t		supported_reset;
>   	uint32_t		caps;
> +
> +	bool			per_inst_fw;
> +	unsigned		fw_version;
>   };
>   
>   struct amdgpu_fw_shared_rb_ptrs_struct {
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index 0d6a97c4bf8f6..347a2c40c32d0 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -114,6 +114,9 @@ static int vcn_v4_0_5_early_init(struct amdgpu_ip_block *ip_block)
>   	struct amdgpu_device *adev = ip_block->adev;
>   	int i, r;
>   
> +	if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6))
> +		adev->vcn.per_inst_fw = true;
> +
>   	for (i = 0; i < adev->vcn.num_vcn_inst; ++i)
>   		/* re-use enc ring as unified ring */
>   		adev->vcn.inst[i].num_enc_rings = 1;

[-- Attachment #2: Type: text/html, Size: 4681 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 44/44] drm/amdgpu/vcn: use dev_info() for firmware information
  2025-01-31 16:57 ` [PATCH 44/44] drm/amdgpu/vcn: use dev_info() for firmware information Alex Deucher
@ 2025-02-06 14:49   ` Boyuan Zhang
  0 siblings, 0 replies; 74+ messages in thread
From: Boyuan Zhang @ 2025-02-06 14:49 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx

[-- Attachment #1: Type: text/plain, Size: 1602 bytes --]


On 2025-01-31 11:57, Alex Deucher wrote:
> To properly handle multiple GPUs.
>
> Signed-off-by: Alex Deucher<alexander.deucher@amd.com>


Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> 
<mailto:Boyuan.Zhang@amd.com>


> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index edbcb11c382a2..8d8b39e6d197a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -182,7 +182,8 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
>   		enc_major = fw_check;
>   		dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
>   		vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
> -		DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
> +		dev_info(adev->dev,
> +			 "Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
>   			 enc_major, enc_minor, dec_ver, vep, fw_rev);
>   	} else {
>   		unsigned int version_major, version_minor, family_id;
> @@ -190,7 +191,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
>   		family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
>   		version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
>   		version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> -		DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
> +		dev_info(adev->dev, "Found VCN firmware Version: %u.%u Family ID: %u\n",
>   			 version_major, version_minor, family_id);
>   	}
>   

[-- Attachment #2: Type: text/html, Size: 2662 bytes --]

^ permalink raw reply	[flat|nested] 74+ messages in thread

end of thread, other threads:[~2025-02-06 14:50 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-31 16:56 [PATCH V3 00/44] VCN instance rework Alex Deucher
2025-01-31 16:56 ` [PATCH 01/44] drm/amdgpu/vcn2.5: split code along instances Alex Deucher
2025-02-04 15:35   ` Boyuan Zhang
2025-01-31 16:56 ` [PATCH 02/44] drm/amdgpu/vcn3.0: " Alex Deucher
2025-02-04 15:40   ` Boyuan Zhang
2025-01-31 16:56 ` [PATCH 03/44] drm/amdgpu/vcn4.0: " Alex Deucher
2025-02-04 15:50   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 04/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
2025-02-04 15:50   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 05/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
2025-02-04 15:51   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 06/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
2025-02-04 15:56   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 07/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
2025-02-04 15:57   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 08/44] drm/amdgpu/vcn: switch work handler to be per instance Alex Deucher
2025-02-04 20:59   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 09/44] drm/amdgpu/vcn: make powergating status " Alex Deucher
2025-02-05  1:50   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 10/44] drm/amdgpu/vcn: move more instanced data to vcn_instance Alex Deucher
2025-02-05  3:06   ` Boyuan Zhang
2025-02-05 20:09     ` Alex Deucher
2025-02-06 13:39       ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 11/44] drm/amdgpu/vcn: switch vcn helpers to be instance based Alex Deucher
2025-02-05 13:23   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 12/44] drm/amdgpu/vcn3.0: convert internal functions to use vcn_inst Alex Deucher
2025-02-05 15:00   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 13/44] drm/amdgpu/vcn1.0: " Alex Deucher
2025-02-05 15:01   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 14/44] drm/amdgpu/vcn2.0: " Alex Deucher
2025-02-05 15:01   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 15/44] drm/amdgpu/vcn2.5: " Alex Deucher
2025-02-05 15:02   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 16/44] drm/amdgpu/vcn4.0: " Alex Deucher
2025-02-05 15:03   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 17/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
2025-02-05 15:03   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 18/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
2025-02-05 15:04   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 19/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
2025-02-05 15:05   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 20/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
2025-02-05 15:05   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 21/44] drm/amdgpu/vcn: adjust pause_dpg_mode function signature Alex Deucher
2025-02-06 13:40   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 22/44] drm/amdgpu/vcn: add new per instance callback for powergating Alex Deucher
2025-02-06 13:40   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 23/44] drm/amdgpu/vcn1.0: add set_pg_state callback Alex Deucher
2025-02-06 13:46   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 24/44] drm/amdgpu/vcn2.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 25/44] drm/amdgpu/vcn2.5: " Alex Deucher
2025-01-31 16:57 ` [PATCH 26/44] drm/amdgpu/vcn3.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 27/44] drm/amdgpu/vcn4.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 28/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
2025-01-31 16:57 ` [PATCH 29/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
2025-01-31 16:57 ` [PATCH 30/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 31/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
2025-01-31 16:57 ` [PATCH 32/44] drm/amdgpu/vcn: use per instance callbacks for idle work handler Alex Deucher
2025-02-06 13:53   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 33/44] drm/amdgpu/vcn: add a generic helper for set_power_gating_state Alex Deucher
2025-02-06 13:54   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 34/44] drm/amdgpu/vcn1.0: use generic set_power_gating_state helper Alex Deucher
2025-01-31 16:57 ` [PATCH 35/44] drm/amdgpu/vcn2.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 36/44] drm/amdgpu/vcn2.5: " Alex Deucher
2025-01-31 16:57 ` [PATCH 37/44] drm/amdgpu/vcn3.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 38/44] drm/amdgpu/vcn4.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 39/44] drm/amdgpu/vcn4.0.3: " Alex Deucher
2025-01-31 16:57 ` [PATCH 40/44] drm/amdgpu/vcn4.0.5: " Alex Deucher
2025-01-31 16:57 ` [PATCH 41/44] drm/amdgpu/vcn5.0.0: " Alex Deucher
2025-01-31 16:57 ` [PATCH 42/44] drm/amdgpu/vcn5.0.1: " Alex Deucher
2025-01-31 16:57 ` [PATCH 43/44] drm/amdgpu/vcn: optimize firmware storage Alex Deucher
2025-02-06 14:48   ` Boyuan Zhang
2025-01-31 16:57 ` [PATCH 44/44] drm/amdgpu/vcn: use dev_info() for firmware information Alex Deucher
2025-02-06 14:49   ` Boyuan Zhang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.