[PATCH 7/8] drm/amdgpu:Add DPG pause mode support

Alex Deucher alexdeucher at gmail.com
Tue Sep 25 20:12:08 UTC 2018


On Tue, Sep 25, 2018 at 4:04 PM James Zhu <jzhums at gmail.com> wrote:
>
> Add fucntions to support VCN DPG pause mode.

fucntions -> functions
With that fixed:
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

>
> Signed-off-by: James Zhu <James.Zhu at amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 161 +++++++++++++++++++++++++++++++-
>  1 file changed, 159 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 27262a8..9d59cd2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -36,6 +36,7 @@
>  #include "soc15_common.h"
>
>  #include "vcn/vcn_1_0_offset.h"
> +#include "vcn/vcn_1_0_sh_mask.h"
>
>  /* 1 second timeout */
>  #define VCN_IDLE_TIMEOUT       msecs_to_jiffies(1000)
> @@ -212,18 +213,158 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
>         return 0;
>  }
>
> +static int amdgpu_vcn_pause_dpg_mode(struct amdgpu_device *adev,
> +                                                                                               struct dpg_pause_state *new_state)
> +{
> +       int ret_code;
> +       uint32_t reg_data = 0;
> +       uint32_t reg_data2 = 0;
> +       struct amdgpu_ring *ring;
> +
> +       /* pause/unpause if state is changed */
> +       if (adev->vcn.pause_state.fw_based != new_state->fw_based) {
> +               DRM_DEBUG("dpg pause state changed %d:%d -> %d:%d",
> +                       adev->vcn.pause_state.fw_based, adev->vcn.pause_state.jpeg,
> +                       new_state->fw_based, new_state->jpeg);
> +
> +               reg_data = RREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE) &
> +                                               (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
> +
> +               if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
> +                       ret_code = 0;
> +
> +                       if (!(reg_data & UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK))
> +                               SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
> +                                               UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
> +                                               UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
> +
> +                       if (!ret_code) {
> +                               /* pause DPG non-jpeg */
> +                               reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
> +                               WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
> +                               SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_DPG_PAUSE,
> +                                                       UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
> +                                                       UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, ret_code);
> +
> +                               /* Restore */
> +                               ring = &adev->vcn.ring_enc[0];
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO, ring->gpu_addr);
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE, ring->ring_size / 4);
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR,     lower_32_bits(ring->wptr));
> +
> +                               ring = &adev->vcn.ring_enc[1];
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO2, ring->gpu_addr);
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE2, ring->ring_size / 4);
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
> +                               WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
> +
> +                               ring = &adev->vcn.ring_dec;
> +                               WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
> +                                                                       lower_32_bits(ring->wptr) | 0x80000000);
> +                               SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
> +                                                                               UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
> +                                                                               UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
> +                       }
> +               } else {
> +                       /* unpause dpg non-jpeg, no need to wait */
> +                       reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
> +                       WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
> +               }
> +               adev->vcn.pause_state.fw_based = new_state->fw_based;
> +       }
> +
> +       /* pause/unpause if state is changed */
> +       if (adev->vcn.pause_state.jpeg != new_state->jpeg) {
> +               DRM_DEBUG("dpg pause state changed %d:%d -> %d:%d",
> +                       adev->vcn.pause_state.fw_based, adev->vcn.pause_state.jpeg,
> +                       new_state->fw_based, new_state->jpeg);
> +
> +               reg_data = RREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE) &
> +                                               (~UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK);
> +
> +               if (new_state->jpeg == VCN_DPG_STATE__PAUSE) {
> +                       ret_code = 0;
> +
> +                       if (!(reg_data & UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK))
> +                               SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
> +                                               UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
> +                                               UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
> +
> +                       if (!ret_code) {
> +                               /* Make sure JPRG Snoop is disabled before sending the pause */
> +                               reg_data2 = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
> +                               reg_data2 |= UVD_POWER_STATUS__JRBC_SNOOP_DIS_MASK;
> +                               WREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS, reg_data2);
> +
> +                               /* pause DPG jpeg */
> +                               reg_data |= UVD_DPG_PAUSE__JPEG_PAUSE_DPG_REQ_MASK;
> +                               WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
> +                               SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_DPG_PAUSE,
> +                                                       UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK,
> +                                                       UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK, ret_code);
> +
> +                               /* Restore */
> +                               ring = &adev->vcn.ring_jpeg;
> +                               WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
> +                               WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, 0x00000001L | 0x00000002L);
> +                               WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
> +                                                                                       lower_32_bits(ring->gpu_addr));
> +                               WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
> +                                                                                       upper_32_bits(ring->gpu_addr));
> +                               WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR, ring->wptr);
> +                               WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, ring->wptr);
> +                               WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L);
> +
> +                               ring = &adev->vcn.ring_dec;
> +                               WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
> +                                                                       lower_32_bits(ring->wptr) | 0x80000000);
> +                               SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
> +                                                                               UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
> +                                                                               UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
> +                       }
> +               } else {
> +                       /* unpause dpg jpeg, no need to wait */
> +                       reg_data &= ~UVD_DPG_PAUSE__JPEG_PAUSE_DPG_REQ_MASK;
> +                       WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
> +               }
> +               adev->vcn.pause_state.jpeg = new_state->jpeg;
> +       }
> +
> +       return 0;
> +}
> +
>  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);
> -       unsigned fences = amdgpu_fence_count_emitted(&adev->vcn.ring_dec);
> -       unsigned i;
> +       unsigned int fences = 0;
> +       unsigned int i;
>
>         for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
>                 fences += amdgpu_fence_count_emitted(&adev->vcn.ring_enc[i]);
>         }
>
> +       if (adev->pg_flags & AMD_PG_SUPPORT_DPG)        {
> +               struct dpg_pause_state new_state;
> +
> +               if (fences)
> +                       new_state.fw_based = VCN_DPG_STATE__PAUSE;
> +               else
> +                       new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
> +
> +               if (amdgpu_fence_count_emitted(&adev->vcn.ring_jpeg))
> +                       new_state.jpeg = VCN_DPG_STATE__PAUSE;
> +               else
> +                       new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
> +
> +               amdgpu_vcn_pause_dpg_mode(adev, &new_state);
> +       }
> +
>         fences += amdgpu_fence_count_emitted(&adev->vcn.ring_jpeg);
> +       fences += amdgpu_fence_count_emitted(&adev->vcn.ring_dec);
>
>         if (fences == 0) {
>                 amdgpu_gfx_off_ctrl(adev, true);
> @@ -250,6 +391,22 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
>                         amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
>                                                                AMD_PG_STATE_UNGATE);
>         }
> +
> +       if (adev->pg_flags & AMD_PG_SUPPORT_DPG)        {
> +               struct dpg_pause_state new_state;
> +
> +               if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
> +                       new_state.fw_based = VCN_DPG_STATE__PAUSE;
> +               else
> +                       new_state.fw_based = adev->vcn.pause_state.fw_based;
> +
> +               if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
> +                       new_state.jpeg = VCN_DPG_STATE__PAUSE;
> +               else
> +                       new_state.jpeg = adev->vcn.pause_state.jpeg;
> +
> +               amdgpu_vcn_pause_dpg_mode(adev, &new_state);
> +       }
>  }
>
>  void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
> --
> 2.7.4
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list