On Mon, Jan 19, 2026 at 12:52 AM Jesse.Zhang <[email protected]> wrote: > > For MI projects, when Dynamic Power Gating (DPG) is enabled, > VCN reset operations should be performed with DPG in pause mode. > Otherwise, the hardware may perform undesirable reset operations > > Signed-off-by: Jesse Zhang <[email protected]>
This patch should probably come first in the series. You could also merge patches 1 and 2 into one patch. Same with 4 and 5. Either way, the series is: Reviewed-by: Alex Deucher <[email protected]> > --- > drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 41 +++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > > 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 78c13724a7ba..dd247abce1ab 100644 > --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c > +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c > @@ -847,6 +847,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct > amdgpu_vcn_inst *vinst, > int inst_idx = vinst->inst; > struct amdgpu_vcn4_fw_shared *fw_shared = > > adev->vcn.inst[inst_idx].fw_shared.cpu_addr; > + struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE}; > struct amdgpu_ring *ring; > int vcn_inst, ret; > uint32_t tmp; > @@ -951,6 +952,9 @@ static int vcn_v4_0_3_start_dpg_mode(struct > amdgpu_vcn_inst *vinst, > > ring = &adev->vcn.inst[inst_idx].ring_enc[0]; > > + /* Pause dpg */ > + vcn_v4_0_3_pause_dpg_mode(vinst, &state); > + > /* program the RB_BASE for ring buffer */ > WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, > lower_32_bits(ring->gpu_addr)); > @@ -1360,9 +1364,13 @@ static int vcn_v4_0_3_stop_dpg_mode(struct > amdgpu_vcn_inst *vinst) > int inst_idx = vinst->inst; > uint32_t tmp; > int vcn_inst; > + struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; > > vcn_inst = GET_INST(VCN, inst_idx); > > + /* Unpause dpg */ > + vcn_v4_0_3_pause_dpg_mode(vinst, &state); > + > /* Wait for power status to be 1 */ > SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1, > UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); > @@ -1486,6 +1494,39 @@ static int vcn_v4_0_3_stop(struct amdgpu_vcn_inst > *vinst) > static int vcn_v4_0_3_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; > + > + /* pause/unpause if state is changed */ > + if (adev->vcn.inst[inst_idx].pause_state.fw_based != > new_state->fw_based) { > + DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d", > + adev->vcn.inst[inst_idx].pause_state.fw_based, > new_state->fw_based); > + reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) & > + (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); > + > + if (new_state->fw_based == VCN_DPG_STATE__PAUSE) { > + ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, > regUVD_POWER_STATUS, 0x1, > + UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); > + > + if (!ret_code) { > + /* pause DPG */ > + reg_data |= > UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; > + WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, > reg_data); > + > + /* wait for ACK */ > + SOC15_WAIT_ON_RREG(VCN, inst_idx, > regUVD_DPG_PAUSE, > + UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, > + UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); > + } > + } else { > + /* unpause dpg, no need to wait */ > + reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; > + WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, > reg_data); > + } > + adev->vcn.inst[inst_idx].pause_state.fw_based = > new_state->fw_based; > + } > > return 0; > } > -- > 2.49.0 >
