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
>

Reply via email to