diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0423-drm-amdgpu-Add-DPG-pause-mode-support.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0423-drm-amdgpu-Add-DPG-pause-mode-support.patch | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0423-drm-amdgpu-Add-DPG-pause-mode-support.patch b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0423-drm-amdgpu-Add-DPG-pause-mode-support.patch new file mode 100644 index 00000000..189b501b --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0423-drm-amdgpu-Add-DPG-pause-mode-support.patch @@ -0,0 +1,217 @@ +From 28a2f3cb0b96a181b0597fc6056baa1b68ad24e5 Mon Sep 17 00:00:00 2001 +From: James Zhu <James.Zhu@amd.com> +Date: Fri, 21 Sep 2018 14:43:18 -0400 +Subject: [PATCH 0423/2940] drm/amdgpu:Add DPG pause mode support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add functions to support VCN DPG pause mode. + +Signed-off-by: James Zhu <James.Zhu@amd.com> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Reviewed-by: Huang Rui <ray.huang@amd.com> +Acked-by: Christian König <christian.koenig@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 ec28969d09e6..5616cf21ea7d 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_VCN_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_VCN_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.17.1 + |