1aaa36a97SAlex Deucher /* 2aaa36a97SAlex Deucher * Copyright 2014 Advanced Micro Devices, Inc. 3aaa36a97SAlex Deucher * All Rights Reserved. 4aaa36a97SAlex Deucher * 5aaa36a97SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a 6aaa36a97SAlex Deucher * copy of this software and associated documentation files (the 7aaa36a97SAlex Deucher * "Software"), to deal in the Software without restriction, including 8aaa36a97SAlex Deucher * without limitation the rights to use, copy, modify, merge, publish, 9aaa36a97SAlex Deucher * distribute, sub license, and/or sell copies of the Software, and to 10aaa36a97SAlex Deucher * permit persons to whom the Software is furnished to do so, subject to 11aaa36a97SAlex Deucher * the following conditions: 12aaa36a97SAlex Deucher * 13aaa36a97SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14aaa36a97SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15aaa36a97SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16aaa36a97SAlex Deucher * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17aaa36a97SAlex Deucher * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18aaa36a97SAlex Deucher * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19aaa36a97SAlex Deucher * USE OR OTHER DEALINGS IN THE SOFTWARE. 20aaa36a97SAlex Deucher * 21aaa36a97SAlex Deucher * The above copyright notice and this permission notice (including the 22aaa36a97SAlex Deucher * next paragraph) shall be included in all copies or substantial portions 23aaa36a97SAlex Deucher * of the Software. 24aaa36a97SAlex Deucher * 25aaa36a97SAlex Deucher * Authors: Christian König <christian.koenig@amd.com> 26aaa36a97SAlex Deucher */ 27aaa36a97SAlex Deucher 28aaa36a97SAlex Deucher #include <linux/firmware.h> 29aaa36a97SAlex Deucher #include <drm/drmP.h> 30aaa36a97SAlex Deucher #include "amdgpu.h" 31aaa36a97SAlex Deucher #include "amdgpu_vce.h" 32aaa36a97SAlex Deucher #include "vid.h" 33aaa36a97SAlex Deucher #include "vce/vce_3_0_d.h" 34aaa36a97SAlex Deucher #include "vce/vce_3_0_sh_mask.h" 35aaa36a97SAlex Deucher #include "oss/oss_2_0_d.h" 36aaa36a97SAlex Deucher #include "oss/oss_2_0_sh_mask.h" 375bbc553aSLeo Liu #include "gca/gfx_8_0_d.h" 385bbc553aSLeo Liu 395bbc553aSLeo Liu #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04 405bbc553aSLeo Liu #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10 41aaa36a97SAlex Deucher 42e9822622SLeo Liu #define VCE_V3_0_FW_SIZE (384 * 1024) 43e9822622SLeo Liu #define VCE_V3_0_STACK_SIZE (64 * 1024) 44e9822622SLeo Liu #define VCE_V3_0_DATA_SIZE ((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024)) 45e9822622SLeo Liu 465bbc553aSLeo Liu static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx); 47aaa36a97SAlex Deucher static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev); 48aaa36a97SAlex Deucher static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev); 49aaa36a97SAlex Deucher 50aaa36a97SAlex Deucher /** 51aaa36a97SAlex Deucher * vce_v3_0_ring_get_rptr - get read pointer 52aaa36a97SAlex Deucher * 53aaa36a97SAlex Deucher * @ring: amdgpu_ring pointer 54aaa36a97SAlex Deucher * 55aaa36a97SAlex Deucher * Returns the current hardware read pointer 56aaa36a97SAlex Deucher */ 57aaa36a97SAlex Deucher static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) 58aaa36a97SAlex Deucher { 59aaa36a97SAlex Deucher struct amdgpu_device *adev = ring->adev; 60aaa36a97SAlex Deucher 61aaa36a97SAlex Deucher if (ring == &adev->vce.ring[0]) 62aaa36a97SAlex Deucher return RREG32(mmVCE_RB_RPTR); 63aaa36a97SAlex Deucher else 64aaa36a97SAlex Deucher return RREG32(mmVCE_RB_RPTR2); 65aaa36a97SAlex Deucher } 66aaa36a97SAlex Deucher 67aaa36a97SAlex Deucher /** 68aaa36a97SAlex Deucher * vce_v3_0_ring_get_wptr - get write pointer 69aaa36a97SAlex Deucher * 70aaa36a97SAlex Deucher * @ring: amdgpu_ring pointer 71aaa36a97SAlex Deucher * 72aaa36a97SAlex Deucher * Returns the current hardware write pointer 73aaa36a97SAlex Deucher */ 74aaa36a97SAlex Deucher static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring) 75aaa36a97SAlex Deucher { 76aaa36a97SAlex Deucher struct amdgpu_device *adev = ring->adev; 77aaa36a97SAlex Deucher 78aaa36a97SAlex Deucher if (ring == &adev->vce.ring[0]) 79aaa36a97SAlex Deucher return RREG32(mmVCE_RB_WPTR); 80aaa36a97SAlex Deucher else 81aaa36a97SAlex Deucher return RREG32(mmVCE_RB_WPTR2); 82aaa36a97SAlex Deucher } 83aaa36a97SAlex Deucher 84aaa36a97SAlex Deucher /** 85aaa36a97SAlex Deucher * vce_v3_0_ring_set_wptr - set write pointer 86aaa36a97SAlex Deucher * 87aaa36a97SAlex Deucher * @ring: amdgpu_ring pointer 88aaa36a97SAlex Deucher * 89aaa36a97SAlex Deucher * Commits the write pointer to the hardware 90aaa36a97SAlex Deucher */ 91aaa36a97SAlex Deucher static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) 92aaa36a97SAlex Deucher { 93aaa36a97SAlex Deucher struct amdgpu_device *adev = ring->adev; 94aaa36a97SAlex Deucher 95aaa36a97SAlex Deucher if (ring == &adev->vce.ring[0]) 96aaa36a97SAlex Deucher WREG32(mmVCE_RB_WPTR, ring->wptr); 97aaa36a97SAlex Deucher else 98aaa36a97SAlex Deucher WREG32(mmVCE_RB_WPTR2, ring->wptr); 99aaa36a97SAlex Deucher } 100aaa36a97SAlex Deucher 101aaa36a97SAlex Deucher /** 102aaa36a97SAlex Deucher * vce_v3_0_start - start VCE block 103aaa36a97SAlex Deucher * 104aaa36a97SAlex Deucher * @adev: amdgpu_device pointer 105aaa36a97SAlex Deucher * 106aaa36a97SAlex Deucher * Setup and start the VCE block 107aaa36a97SAlex Deucher */ 108aaa36a97SAlex Deucher static int vce_v3_0_start(struct amdgpu_device *adev) 109aaa36a97SAlex Deucher { 110aaa36a97SAlex Deucher struct amdgpu_ring *ring; 1115bbc553aSLeo Liu int idx, i, j, r; 112aaa36a97SAlex Deucher 1135bbc553aSLeo Liu mutex_lock(&adev->grbm_idx_mutex); 1145bbc553aSLeo Liu for (idx = 0; idx < 2; ++idx) { 1155bbc553aSLeo Liu if(idx == 0) 1165bbc553aSLeo Liu WREG32_P(mmGRBM_GFX_INDEX, 0, 1175bbc553aSLeo Liu ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 1185bbc553aSLeo Liu else 1195bbc553aSLeo Liu WREG32_P(mmGRBM_GFX_INDEX, 1205bbc553aSLeo Liu GRBM_GFX_INDEX__VCE_INSTANCE_MASK, 1215bbc553aSLeo Liu ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 1225bbc553aSLeo Liu 1235bbc553aSLeo Liu vce_v3_0_mc_resume(adev, idx); 124aaa36a97SAlex Deucher 125aaa36a97SAlex Deucher /* set BUSY flag */ 126aaa36a97SAlex Deucher WREG32_P(mmVCE_STATUS, 1, ~1); 127aaa36a97SAlex Deucher 1285bbc553aSLeo Liu WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, 1295bbc553aSLeo Liu ~VCE_VCPU_CNTL__CLK_EN_MASK); 130aaa36a97SAlex Deucher 131aaa36a97SAlex Deucher WREG32_P(mmVCE_SOFT_RESET, 132aaa36a97SAlex Deucher VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 133aaa36a97SAlex Deucher ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 134aaa36a97SAlex Deucher 135aaa36a97SAlex Deucher mdelay(100); 136aaa36a97SAlex Deucher 1375bbc553aSLeo Liu WREG32_P(mmVCE_SOFT_RESET, 0, 1385bbc553aSLeo Liu ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 139aaa36a97SAlex Deucher 140aaa36a97SAlex Deucher for (i = 0; i < 10; ++i) { 141aaa36a97SAlex Deucher uint32_t status; 142aaa36a97SAlex Deucher for (j = 0; j < 100; ++j) { 143aaa36a97SAlex Deucher status = RREG32(mmVCE_STATUS); 144aaa36a97SAlex Deucher if (status & 2) 145aaa36a97SAlex Deucher break; 146aaa36a97SAlex Deucher mdelay(10); 147aaa36a97SAlex Deucher } 148aaa36a97SAlex Deucher r = 0; 149aaa36a97SAlex Deucher if (status & 2) 150aaa36a97SAlex Deucher break; 151aaa36a97SAlex Deucher 152aaa36a97SAlex Deucher DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); 1535bbc553aSLeo Liu WREG32_P(mmVCE_SOFT_RESET, 1545bbc553aSLeo Liu VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 155aaa36a97SAlex Deucher ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 156aaa36a97SAlex Deucher mdelay(10); 1575bbc553aSLeo Liu WREG32_P(mmVCE_SOFT_RESET, 0, 1585bbc553aSLeo Liu ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 159aaa36a97SAlex Deucher mdelay(10); 160aaa36a97SAlex Deucher r = -1; 161aaa36a97SAlex Deucher } 162aaa36a97SAlex Deucher 163aaa36a97SAlex Deucher /* clear BUSY flag */ 164aaa36a97SAlex Deucher WREG32_P(mmVCE_STATUS, 0, ~1); 165aaa36a97SAlex Deucher 166aaa36a97SAlex Deucher if (r) { 167aaa36a97SAlex Deucher DRM_ERROR("VCE not responding, giving up!!!\n"); 1685bbc553aSLeo Liu mutex_unlock(&adev->grbm_idx_mutex); 169aaa36a97SAlex Deucher return r; 170aaa36a97SAlex Deucher } 1715bbc553aSLeo Liu } 1725bbc553aSLeo Liu 1735bbc553aSLeo Liu WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 1745bbc553aSLeo Liu mutex_unlock(&adev->grbm_idx_mutex); 1755bbc553aSLeo Liu 1765bbc553aSLeo Liu ring = &adev->vce.ring[0]; 1775bbc553aSLeo Liu WREG32(mmVCE_RB_RPTR, ring->wptr); 1785bbc553aSLeo Liu WREG32(mmVCE_RB_WPTR, ring->wptr); 1795bbc553aSLeo Liu WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); 1805bbc553aSLeo Liu WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 1815bbc553aSLeo Liu WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); 1825bbc553aSLeo Liu 1835bbc553aSLeo Liu ring = &adev->vce.ring[1]; 1845bbc553aSLeo Liu WREG32(mmVCE_RB_RPTR2, ring->wptr); 1855bbc553aSLeo Liu WREG32(mmVCE_RB_WPTR2, ring->wptr); 1865bbc553aSLeo Liu WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); 1875bbc553aSLeo Liu WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 1885bbc553aSLeo Liu WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); 189aaa36a97SAlex Deucher 190aaa36a97SAlex Deucher return 0; 191aaa36a97SAlex Deucher } 192aaa36a97SAlex Deucher 1935fc3aeebSyanyang1 static int vce_v3_0_early_init(void *handle) 194aaa36a97SAlex Deucher { 1955fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1965fc3aeebSyanyang1 197aaa36a97SAlex Deucher vce_v3_0_set_ring_funcs(adev); 198aaa36a97SAlex Deucher vce_v3_0_set_irq_funcs(adev); 199aaa36a97SAlex Deucher 200aaa36a97SAlex Deucher return 0; 201aaa36a97SAlex Deucher } 202aaa36a97SAlex Deucher 2035fc3aeebSyanyang1 static int vce_v3_0_sw_init(void *handle) 204aaa36a97SAlex Deucher { 2055fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 206aaa36a97SAlex Deucher struct amdgpu_ring *ring; 207aaa36a97SAlex Deucher int r; 208aaa36a97SAlex Deucher 209aaa36a97SAlex Deucher /* VCE */ 210aaa36a97SAlex Deucher r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq); 211aaa36a97SAlex Deucher if (r) 212aaa36a97SAlex Deucher return r; 213aaa36a97SAlex Deucher 214e9822622SLeo Liu r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE + 215e9822622SLeo Liu (VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2); 216aaa36a97SAlex Deucher if (r) 217aaa36a97SAlex Deucher return r; 218aaa36a97SAlex Deucher 219aaa36a97SAlex Deucher r = amdgpu_vce_resume(adev); 220aaa36a97SAlex Deucher if (r) 221aaa36a97SAlex Deucher return r; 222aaa36a97SAlex Deucher 223aaa36a97SAlex Deucher ring = &adev->vce.ring[0]; 224aaa36a97SAlex Deucher sprintf(ring->name, "vce0"); 225aaa36a97SAlex Deucher r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf, 226aaa36a97SAlex Deucher &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); 227aaa36a97SAlex Deucher if (r) 228aaa36a97SAlex Deucher return r; 229aaa36a97SAlex Deucher 230aaa36a97SAlex Deucher ring = &adev->vce.ring[1]; 231aaa36a97SAlex Deucher sprintf(ring->name, "vce1"); 232aaa36a97SAlex Deucher r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf, 233aaa36a97SAlex Deucher &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); 234aaa36a97SAlex Deucher if (r) 235aaa36a97SAlex Deucher return r; 236aaa36a97SAlex Deucher 237aaa36a97SAlex Deucher return r; 238aaa36a97SAlex Deucher } 239aaa36a97SAlex Deucher 2405fc3aeebSyanyang1 static int vce_v3_0_sw_fini(void *handle) 241aaa36a97SAlex Deucher { 242aaa36a97SAlex Deucher int r; 2435fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 244aaa36a97SAlex Deucher 245aaa36a97SAlex Deucher r = amdgpu_vce_suspend(adev); 246aaa36a97SAlex Deucher if (r) 247aaa36a97SAlex Deucher return r; 248aaa36a97SAlex Deucher 249aaa36a97SAlex Deucher r = amdgpu_vce_sw_fini(adev); 250aaa36a97SAlex Deucher if (r) 251aaa36a97SAlex Deucher return r; 252aaa36a97SAlex Deucher 253aaa36a97SAlex Deucher return r; 254aaa36a97SAlex Deucher } 255aaa36a97SAlex Deucher 2565fc3aeebSyanyang1 static int vce_v3_0_hw_init(void *handle) 257aaa36a97SAlex Deucher { 258aaa36a97SAlex Deucher struct amdgpu_ring *ring; 259aaa36a97SAlex Deucher int r; 2605fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 261aaa36a97SAlex Deucher 262aaa36a97SAlex Deucher r = vce_v3_0_start(adev); 263aaa36a97SAlex Deucher if (r) 264aaa36a97SAlex Deucher return r; 265aaa36a97SAlex Deucher 266aaa36a97SAlex Deucher ring = &adev->vce.ring[0]; 267aaa36a97SAlex Deucher ring->ready = true; 268aaa36a97SAlex Deucher r = amdgpu_ring_test_ring(ring); 269aaa36a97SAlex Deucher if (r) { 270aaa36a97SAlex Deucher ring->ready = false; 271aaa36a97SAlex Deucher return r; 272aaa36a97SAlex Deucher } 273aaa36a97SAlex Deucher 274aaa36a97SAlex Deucher ring = &adev->vce.ring[1]; 275aaa36a97SAlex Deucher ring->ready = true; 276aaa36a97SAlex Deucher r = amdgpu_ring_test_ring(ring); 277aaa36a97SAlex Deucher if (r) { 278aaa36a97SAlex Deucher ring->ready = false; 279aaa36a97SAlex Deucher return r; 280aaa36a97SAlex Deucher } 281aaa36a97SAlex Deucher 282aaa36a97SAlex Deucher DRM_INFO("VCE initialized successfully.\n"); 283aaa36a97SAlex Deucher 284aaa36a97SAlex Deucher return 0; 285aaa36a97SAlex Deucher } 286aaa36a97SAlex Deucher 2875fc3aeebSyanyang1 static int vce_v3_0_hw_fini(void *handle) 288aaa36a97SAlex Deucher { 289aaa36a97SAlex Deucher return 0; 290aaa36a97SAlex Deucher } 291aaa36a97SAlex Deucher 2925fc3aeebSyanyang1 static int vce_v3_0_suspend(void *handle) 293aaa36a97SAlex Deucher { 294aaa36a97SAlex Deucher int r; 2955fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 296aaa36a97SAlex Deucher 297aaa36a97SAlex Deucher r = vce_v3_0_hw_fini(adev); 298aaa36a97SAlex Deucher if (r) 299aaa36a97SAlex Deucher return r; 300aaa36a97SAlex Deucher 301aaa36a97SAlex Deucher r = amdgpu_vce_suspend(adev); 302aaa36a97SAlex Deucher if (r) 303aaa36a97SAlex Deucher return r; 304aaa36a97SAlex Deucher 305aaa36a97SAlex Deucher return r; 306aaa36a97SAlex Deucher } 307aaa36a97SAlex Deucher 3085fc3aeebSyanyang1 static int vce_v3_0_resume(void *handle) 309aaa36a97SAlex Deucher { 310aaa36a97SAlex Deucher int r; 3115fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 312aaa36a97SAlex Deucher 313aaa36a97SAlex Deucher r = amdgpu_vce_resume(adev); 314aaa36a97SAlex Deucher if (r) 315aaa36a97SAlex Deucher return r; 316aaa36a97SAlex Deucher 317aaa36a97SAlex Deucher r = vce_v3_0_hw_init(adev); 318aaa36a97SAlex Deucher if (r) 319aaa36a97SAlex Deucher return r; 320aaa36a97SAlex Deucher 321aaa36a97SAlex Deucher return r; 322aaa36a97SAlex Deucher } 323aaa36a97SAlex Deucher 3245bbc553aSLeo Liu static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx) 325aaa36a97SAlex Deucher { 326aaa36a97SAlex Deucher uint32_t offset, size; 327aaa36a97SAlex Deucher 328aaa36a97SAlex Deucher WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16)); 329aaa36a97SAlex Deucher WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 330aaa36a97SAlex Deucher WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 331aaa36a97SAlex Deucher WREG32(mmVCE_CLOCK_GATING_B, 0xf7); 332aaa36a97SAlex Deucher 333aaa36a97SAlex Deucher WREG32(mmVCE_LMI_CTRL, 0x00398000); 334aaa36a97SAlex Deucher WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1); 335aaa36a97SAlex Deucher WREG32(mmVCE_LMI_SWAP_CNTL, 0); 336aaa36a97SAlex Deucher WREG32(mmVCE_LMI_SWAP_CNTL1, 0); 337aaa36a97SAlex Deucher WREG32(mmVCE_LMI_VM_CTRL, 0); 338aaa36a97SAlex Deucher 339aaa36a97SAlex Deucher WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8)); 340aaa36a97SAlex Deucher offset = AMDGPU_VCE_FIRMWARE_OFFSET; 341e9822622SLeo Liu size = VCE_V3_0_FW_SIZE; 342aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff); 343aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_SIZE0, size); 344aaa36a97SAlex Deucher 3455bbc553aSLeo Liu if (idx == 0) { 346aaa36a97SAlex Deucher offset += size; 347e9822622SLeo Liu size = VCE_V3_0_STACK_SIZE; 348aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff); 349aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 350aaa36a97SAlex Deucher offset += size; 351e9822622SLeo Liu size = VCE_V3_0_DATA_SIZE; 352aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff); 353aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 3545bbc553aSLeo Liu } else { 3555bbc553aSLeo Liu offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE; 3565bbc553aSLeo Liu size = VCE_V3_0_STACK_SIZE; 3575bbc553aSLeo Liu WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff); 3585bbc553aSLeo Liu WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 3595bbc553aSLeo Liu offset += size; 3605bbc553aSLeo Liu size = VCE_V3_0_DATA_SIZE; 3615bbc553aSLeo Liu WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff); 3625bbc553aSLeo Liu WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 3635bbc553aSLeo Liu } 364aaa36a97SAlex Deucher 365aaa36a97SAlex Deucher WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); 366aaa36a97SAlex Deucher 367aaa36a97SAlex Deucher WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK, 368aaa36a97SAlex Deucher ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 369aaa36a97SAlex Deucher } 370aaa36a97SAlex Deucher 3715fc3aeebSyanyang1 static bool vce_v3_0_is_idle(void *handle) 372aaa36a97SAlex Deucher { 3735fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 3745fc3aeebSyanyang1 375aaa36a97SAlex Deucher return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK); 376aaa36a97SAlex Deucher } 377aaa36a97SAlex Deucher 3785fc3aeebSyanyang1 static int vce_v3_0_wait_for_idle(void *handle) 379aaa36a97SAlex Deucher { 380aaa36a97SAlex Deucher unsigned i; 3815fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 382aaa36a97SAlex Deucher 383aaa36a97SAlex Deucher for (i = 0; i < adev->usec_timeout; i++) { 384aaa36a97SAlex Deucher if (!(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK)) 385aaa36a97SAlex Deucher return 0; 386aaa36a97SAlex Deucher } 387aaa36a97SAlex Deucher return -ETIMEDOUT; 388aaa36a97SAlex Deucher } 389aaa36a97SAlex Deucher 3905fc3aeebSyanyang1 static int vce_v3_0_soft_reset(void *handle) 391aaa36a97SAlex Deucher { 3925fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 3935fc3aeebSyanyang1 394aaa36a97SAlex Deucher WREG32_P(mmSRBM_SOFT_RESET, SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK, 395aaa36a97SAlex Deucher ~SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK); 396aaa36a97SAlex Deucher mdelay(5); 397aaa36a97SAlex Deucher 398aaa36a97SAlex Deucher return vce_v3_0_start(adev); 399aaa36a97SAlex Deucher } 400aaa36a97SAlex Deucher 4015fc3aeebSyanyang1 static void vce_v3_0_print_status(void *handle) 402aaa36a97SAlex Deucher { 4035fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 4045fc3aeebSyanyang1 405aaa36a97SAlex Deucher dev_info(adev->dev, "VCE 3.0 registers\n"); 406aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_STATUS=0x%08X\n", 407aaa36a97SAlex Deucher RREG32(mmVCE_STATUS)); 408aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CNTL=0x%08X\n", 409aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CNTL)); 410aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET0=0x%08X\n", 411aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_OFFSET0)); 412aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE0=0x%08X\n", 413aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_SIZE0)); 414aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET1=0x%08X\n", 415aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_OFFSET1)); 416aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE1=0x%08X\n", 417aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_SIZE1)); 418aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET2=0x%08X\n", 419aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_OFFSET2)); 420aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE2=0x%08X\n", 421aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_SIZE2)); 422aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_SOFT_RESET=0x%08X\n", 423aaa36a97SAlex Deucher RREG32(mmVCE_SOFT_RESET)); 424aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_LO2=0x%08X\n", 425aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_LO2)); 426aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_HI2=0x%08X\n", 427aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_HI2)); 428aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_SIZE2=0x%08X\n", 429aaa36a97SAlex Deucher RREG32(mmVCE_RB_SIZE2)); 430aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_RPTR2=0x%08X\n", 431aaa36a97SAlex Deucher RREG32(mmVCE_RB_RPTR2)); 432aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_WPTR2=0x%08X\n", 433aaa36a97SAlex Deucher RREG32(mmVCE_RB_WPTR2)); 434aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_LO=0x%08X\n", 435aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_LO)); 436aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_HI=0x%08X\n", 437aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_HI)); 438aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_SIZE=0x%08X\n", 439aaa36a97SAlex Deucher RREG32(mmVCE_RB_SIZE)); 440aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_RPTR=0x%08X\n", 441aaa36a97SAlex Deucher RREG32(mmVCE_RB_RPTR)); 442aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_WPTR=0x%08X\n", 443aaa36a97SAlex Deucher RREG32(mmVCE_RB_WPTR)); 444aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_CLOCK_GATING_A=0x%08X\n", 445aaa36a97SAlex Deucher RREG32(mmVCE_CLOCK_GATING_A)); 446aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_CLOCK_GATING_B=0x%08X\n", 447aaa36a97SAlex Deucher RREG32(mmVCE_CLOCK_GATING_B)); 448aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_UENC_CLOCK_GATING=0x%08X\n", 449aaa36a97SAlex Deucher RREG32(mmVCE_UENC_CLOCK_GATING)); 450aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_UENC_REG_CLOCK_GATING=0x%08X\n", 451aaa36a97SAlex Deucher RREG32(mmVCE_UENC_REG_CLOCK_GATING)); 452aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_SYS_INT_EN=0x%08X\n", 453aaa36a97SAlex Deucher RREG32(mmVCE_SYS_INT_EN)); 454aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_CTRL2=0x%08X\n", 455aaa36a97SAlex Deucher RREG32(mmVCE_LMI_CTRL2)); 456aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_CTRL=0x%08X\n", 457aaa36a97SAlex Deucher RREG32(mmVCE_LMI_CTRL)); 458aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_VM_CTRL=0x%08X\n", 459aaa36a97SAlex Deucher RREG32(mmVCE_LMI_VM_CTRL)); 460aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_SWAP_CNTL=0x%08X\n", 461aaa36a97SAlex Deucher RREG32(mmVCE_LMI_SWAP_CNTL)); 462aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_SWAP_CNTL1=0x%08X\n", 463aaa36a97SAlex Deucher RREG32(mmVCE_LMI_SWAP_CNTL1)); 464aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_CACHE_CTRL=0x%08X\n", 465aaa36a97SAlex Deucher RREG32(mmVCE_LMI_CACHE_CTRL)); 466aaa36a97SAlex Deucher } 467aaa36a97SAlex Deucher 468aaa36a97SAlex Deucher static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev, 469aaa36a97SAlex Deucher struct amdgpu_irq_src *source, 470aaa36a97SAlex Deucher unsigned type, 471aaa36a97SAlex Deucher enum amdgpu_interrupt_state state) 472aaa36a97SAlex Deucher { 473aaa36a97SAlex Deucher uint32_t val = 0; 474aaa36a97SAlex Deucher 475aaa36a97SAlex Deucher if (state == AMDGPU_IRQ_STATE_ENABLE) 476aaa36a97SAlex Deucher val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK; 477aaa36a97SAlex Deucher 478aaa36a97SAlex Deucher WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 479aaa36a97SAlex Deucher return 0; 480aaa36a97SAlex Deucher } 481aaa36a97SAlex Deucher 482aaa36a97SAlex Deucher static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, 483aaa36a97SAlex Deucher struct amdgpu_irq_src *source, 484aaa36a97SAlex Deucher struct amdgpu_iv_entry *entry) 485aaa36a97SAlex Deucher { 486aaa36a97SAlex Deucher DRM_DEBUG("IH: VCE\n"); 487aaa36a97SAlex Deucher switch (entry->src_data) { 488aaa36a97SAlex Deucher case 0: 489aaa36a97SAlex Deucher amdgpu_fence_process(&adev->vce.ring[0]); 490aaa36a97SAlex Deucher break; 491aaa36a97SAlex Deucher case 1: 492aaa36a97SAlex Deucher amdgpu_fence_process(&adev->vce.ring[1]); 493aaa36a97SAlex Deucher break; 494aaa36a97SAlex Deucher default: 495aaa36a97SAlex Deucher DRM_ERROR("Unhandled interrupt: %d %d\n", 496aaa36a97SAlex Deucher entry->src_id, entry->src_data); 497aaa36a97SAlex Deucher break; 498aaa36a97SAlex Deucher } 499aaa36a97SAlex Deucher 500aaa36a97SAlex Deucher return 0; 501aaa36a97SAlex Deucher } 502aaa36a97SAlex Deucher 5035fc3aeebSyanyang1 static int vce_v3_0_set_clockgating_state(void *handle, 5045fc3aeebSyanyang1 enum amd_clockgating_state state) 505aaa36a97SAlex Deucher { 506aaa36a97SAlex Deucher return 0; 507aaa36a97SAlex Deucher } 508aaa36a97SAlex Deucher 5095fc3aeebSyanyang1 static int vce_v3_0_set_powergating_state(void *handle, 5105fc3aeebSyanyang1 enum amd_powergating_state state) 511aaa36a97SAlex Deucher { 512aaa36a97SAlex Deucher /* This doesn't actually powergate the VCE block. 513aaa36a97SAlex Deucher * That's done in the dpm code via the SMC. This 514aaa36a97SAlex Deucher * just re-inits the block as necessary. The actual 515aaa36a97SAlex Deucher * gating still happens in the dpm code. We should 516aaa36a97SAlex Deucher * revisit this when there is a cleaner line between 517aaa36a97SAlex Deucher * the smc and the hw blocks 518aaa36a97SAlex Deucher */ 5195fc3aeebSyanyang1 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 5205fc3aeebSyanyang1 5215fc3aeebSyanyang1 if (state == AMD_PG_STATE_GATE) 522aaa36a97SAlex Deucher /* XXX do we need a vce_v3_0_stop()? */ 523aaa36a97SAlex Deucher return 0; 524aaa36a97SAlex Deucher else 525aaa36a97SAlex Deucher return vce_v3_0_start(adev); 526aaa36a97SAlex Deucher } 527aaa36a97SAlex Deucher 5285fc3aeebSyanyang1 const struct amd_ip_funcs vce_v3_0_ip_funcs = { 529aaa36a97SAlex Deucher .early_init = vce_v3_0_early_init, 530aaa36a97SAlex Deucher .late_init = NULL, 531aaa36a97SAlex Deucher .sw_init = vce_v3_0_sw_init, 532aaa36a97SAlex Deucher .sw_fini = vce_v3_0_sw_fini, 533aaa36a97SAlex Deucher .hw_init = vce_v3_0_hw_init, 534aaa36a97SAlex Deucher .hw_fini = vce_v3_0_hw_fini, 535aaa36a97SAlex Deucher .suspend = vce_v3_0_suspend, 536aaa36a97SAlex Deucher .resume = vce_v3_0_resume, 537aaa36a97SAlex Deucher .is_idle = vce_v3_0_is_idle, 538aaa36a97SAlex Deucher .wait_for_idle = vce_v3_0_wait_for_idle, 539aaa36a97SAlex Deucher .soft_reset = vce_v3_0_soft_reset, 540aaa36a97SAlex Deucher .print_status = vce_v3_0_print_status, 541aaa36a97SAlex Deucher .set_clockgating_state = vce_v3_0_set_clockgating_state, 542aaa36a97SAlex Deucher .set_powergating_state = vce_v3_0_set_powergating_state, 543aaa36a97SAlex Deucher }; 544aaa36a97SAlex Deucher 545aaa36a97SAlex Deucher static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { 546aaa36a97SAlex Deucher .get_rptr = vce_v3_0_ring_get_rptr, 547aaa36a97SAlex Deucher .get_wptr = vce_v3_0_ring_get_wptr, 548aaa36a97SAlex Deucher .set_wptr = vce_v3_0_ring_set_wptr, 549aaa36a97SAlex Deucher .parse_cs = amdgpu_vce_ring_parse_cs, 550aaa36a97SAlex Deucher .emit_ib = amdgpu_vce_ring_emit_ib, 551aaa36a97SAlex Deucher .emit_fence = amdgpu_vce_ring_emit_fence, 552aaa36a97SAlex Deucher .emit_semaphore = amdgpu_vce_ring_emit_semaphore, 553aaa36a97SAlex Deucher .test_ring = amdgpu_vce_ring_test_ring, 554aaa36a97SAlex Deucher .test_ib = amdgpu_vce_ring_test_ib, 555aaa36a97SAlex Deucher .is_lockup = amdgpu_ring_test_lockup, 556aaa36a97SAlex Deucher }; 557aaa36a97SAlex Deucher 558aaa36a97SAlex Deucher static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) 559aaa36a97SAlex Deucher { 560aaa36a97SAlex Deucher adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs; 561aaa36a97SAlex Deucher adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs; 562aaa36a97SAlex Deucher } 563aaa36a97SAlex Deucher 564aaa36a97SAlex Deucher static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = { 565aaa36a97SAlex Deucher .set = vce_v3_0_set_interrupt_state, 566aaa36a97SAlex Deucher .process = vce_v3_0_process_interrupt, 567aaa36a97SAlex Deucher }; 568aaa36a97SAlex Deucher 569aaa36a97SAlex Deucher static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev) 570aaa36a97SAlex Deucher { 571aaa36a97SAlex Deucher adev->vce.irq.num_types = 1; 572aaa36a97SAlex Deucher adev->vce.irq.funcs = &vce_v3_0_irq_funcs; 573aaa36a97SAlex Deucher }; 574