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" 37aaa36a97SAlex Deucher 38aaa36a97SAlex Deucher static void vce_v3_0_mc_resume(struct amdgpu_device *adev); 39aaa36a97SAlex Deucher static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev); 40aaa36a97SAlex Deucher static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev); 41aaa36a97SAlex Deucher 42aaa36a97SAlex Deucher /** 43aaa36a97SAlex Deucher * vce_v3_0_ring_get_rptr - get read pointer 44aaa36a97SAlex Deucher * 45aaa36a97SAlex Deucher * @ring: amdgpu_ring pointer 46aaa36a97SAlex Deucher * 47aaa36a97SAlex Deucher * Returns the current hardware read pointer 48aaa36a97SAlex Deucher */ 49aaa36a97SAlex Deucher static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) 50aaa36a97SAlex Deucher { 51aaa36a97SAlex Deucher struct amdgpu_device *adev = ring->adev; 52aaa36a97SAlex Deucher 53aaa36a97SAlex Deucher if (ring == &adev->vce.ring[0]) 54aaa36a97SAlex Deucher return RREG32(mmVCE_RB_RPTR); 55aaa36a97SAlex Deucher else 56aaa36a97SAlex Deucher return RREG32(mmVCE_RB_RPTR2); 57aaa36a97SAlex Deucher } 58aaa36a97SAlex Deucher 59aaa36a97SAlex Deucher /** 60aaa36a97SAlex Deucher * vce_v3_0_ring_get_wptr - get write pointer 61aaa36a97SAlex Deucher * 62aaa36a97SAlex Deucher * @ring: amdgpu_ring pointer 63aaa36a97SAlex Deucher * 64aaa36a97SAlex Deucher * Returns the current hardware write pointer 65aaa36a97SAlex Deucher */ 66aaa36a97SAlex Deucher static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring) 67aaa36a97SAlex Deucher { 68aaa36a97SAlex Deucher struct amdgpu_device *adev = ring->adev; 69aaa36a97SAlex Deucher 70aaa36a97SAlex Deucher if (ring == &adev->vce.ring[0]) 71aaa36a97SAlex Deucher return RREG32(mmVCE_RB_WPTR); 72aaa36a97SAlex Deucher else 73aaa36a97SAlex Deucher return RREG32(mmVCE_RB_WPTR2); 74aaa36a97SAlex Deucher } 75aaa36a97SAlex Deucher 76aaa36a97SAlex Deucher /** 77aaa36a97SAlex Deucher * vce_v3_0_ring_set_wptr - set write pointer 78aaa36a97SAlex Deucher * 79aaa36a97SAlex Deucher * @ring: amdgpu_ring pointer 80aaa36a97SAlex Deucher * 81aaa36a97SAlex Deucher * Commits the write pointer to the hardware 82aaa36a97SAlex Deucher */ 83aaa36a97SAlex Deucher static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) 84aaa36a97SAlex Deucher { 85aaa36a97SAlex Deucher struct amdgpu_device *adev = ring->adev; 86aaa36a97SAlex Deucher 87aaa36a97SAlex Deucher if (ring == &adev->vce.ring[0]) 88aaa36a97SAlex Deucher WREG32(mmVCE_RB_WPTR, ring->wptr); 89aaa36a97SAlex Deucher else 90aaa36a97SAlex Deucher WREG32(mmVCE_RB_WPTR2, ring->wptr); 91aaa36a97SAlex Deucher } 92aaa36a97SAlex Deucher 93aaa36a97SAlex Deucher /** 94aaa36a97SAlex Deucher * vce_v3_0_start - start VCE block 95aaa36a97SAlex Deucher * 96aaa36a97SAlex Deucher * @adev: amdgpu_device pointer 97aaa36a97SAlex Deucher * 98aaa36a97SAlex Deucher * Setup and start the VCE block 99aaa36a97SAlex Deucher */ 100aaa36a97SAlex Deucher static int vce_v3_0_start(struct amdgpu_device *adev) 101aaa36a97SAlex Deucher { 102aaa36a97SAlex Deucher struct amdgpu_ring *ring; 103aaa36a97SAlex Deucher int i, j, r; 104aaa36a97SAlex Deucher 105aaa36a97SAlex Deucher vce_v3_0_mc_resume(adev); 106aaa36a97SAlex Deucher 107aaa36a97SAlex Deucher /* set BUSY flag */ 108aaa36a97SAlex Deucher WREG32_P(mmVCE_STATUS, 1, ~1); 109aaa36a97SAlex Deucher 110aaa36a97SAlex Deucher ring = &adev->vce.ring[0]; 111aaa36a97SAlex Deucher WREG32(mmVCE_RB_RPTR, ring->wptr); 112aaa36a97SAlex Deucher WREG32(mmVCE_RB_WPTR, ring->wptr); 113aaa36a97SAlex Deucher WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); 114aaa36a97SAlex Deucher WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 115aaa36a97SAlex Deucher WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); 116aaa36a97SAlex Deucher 117aaa36a97SAlex Deucher ring = &adev->vce.ring[1]; 118aaa36a97SAlex Deucher WREG32(mmVCE_RB_RPTR2, ring->wptr); 119aaa36a97SAlex Deucher WREG32(mmVCE_RB_WPTR2, ring->wptr); 120aaa36a97SAlex Deucher WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); 121aaa36a97SAlex Deucher WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 122aaa36a97SAlex Deucher WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); 123aaa36a97SAlex Deucher 124aaa36a97SAlex Deucher WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK); 125aaa36a97SAlex Deucher 126aaa36a97SAlex Deucher WREG32_P(mmVCE_SOFT_RESET, 127aaa36a97SAlex Deucher VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 128aaa36a97SAlex Deucher ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 129aaa36a97SAlex Deucher 130aaa36a97SAlex Deucher mdelay(100); 131aaa36a97SAlex Deucher 132aaa36a97SAlex Deucher WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 133aaa36a97SAlex Deucher 134aaa36a97SAlex Deucher for (i = 0; i < 10; ++i) { 135aaa36a97SAlex Deucher uint32_t status; 136aaa36a97SAlex Deucher for (j = 0; j < 100; ++j) { 137aaa36a97SAlex Deucher status = RREG32(mmVCE_STATUS); 138aaa36a97SAlex Deucher if (status & 2) 139aaa36a97SAlex Deucher break; 140aaa36a97SAlex Deucher mdelay(10); 141aaa36a97SAlex Deucher } 142aaa36a97SAlex Deucher r = 0; 143aaa36a97SAlex Deucher if (status & 2) 144aaa36a97SAlex Deucher break; 145aaa36a97SAlex Deucher 146aaa36a97SAlex Deucher DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); 147aaa36a97SAlex Deucher WREG32_P(mmVCE_SOFT_RESET, VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 148aaa36a97SAlex Deucher ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 149aaa36a97SAlex Deucher mdelay(10); 150aaa36a97SAlex Deucher WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 151aaa36a97SAlex Deucher mdelay(10); 152aaa36a97SAlex Deucher r = -1; 153aaa36a97SAlex Deucher } 154aaa36a97SAlex Deucher 155aaa36a97SAlex Deucher /* clear BUSY flag */ 156aaa36a97SAlex Deucher WREG32_P(mmVCE_STATUS, 0, ~1); 157aaa36a97SAlex Deucher 158aaa36a97SAlex Deucher if (r) { 159aaa36a97SAlex Deucher DRM_ERROR("VCE not responding, giving up!!!\n"); 160aaa36a97SAlex Deucher return r; 161aaa36a97SAlex Deucher } 162aaa36a97SAlex Deucher 163aaa36a97SAlex Deucher return 0; 164aaa36a97SAlex Deucher } 165aaa36a97SAlex Deucher 166aaa36a97SAlex Deucher static int vce_v3_0_early_init(struct amdgpu_device *adev) 167aaa36a97SAlex Deucher { 168aaa36a97SAlex Deucher vce_v3_0_set_ring_funcs(adev); 169aaa36a97SAlex Deucher vce_v3_0_set_irq_funcs(adev); 170aaa36a97SAlex Deucher 171aaa36a97SAlex Deucher return 0; 172aaa36a97SAlex Deucher } 173aaa36a97SAlex Deucher 174aaa36a97SAlex Deucher static int vce_v3_0_sw_init(struct amdgpu_device *adev) 175aaa36a97SAlex Deucher { 176aaa36a97SAlex Deucher struct amdgpu_ring *ring; 177aaa36a97SAlex Deucher int r; 178aaa36a97SAlex Deucher 179aaa36a97SAlex Deucher /* VCE */ 180aaa36a97SAlex Deucher r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq); 181aaa36a97SAlex Deucher if (r) 182aaa36a97SAlex Deucher return r; 183aaa36a97SAlex Deucher 184aaa36a97SAlex Deucher r = amdgpu_vce_sw_init(adev); 185aaa36a97SAlex Deucher if (r) 186aaa36a97SAlex Deucher return r; 187aaa36a97SAlex Deucher 188aaa36a97SAlex Deucher r = amdgpu_vce_resume(adev); 189aaa36a97SAlex Deucher if (r) 190aaa36a97SAlex Deucher return r; 191aaa36a97SAlex Deucher 192aaa36a97SAlex Deucher ring = &adev->vce.ring[0]; 193aaa36a97SAlex Deucher sprintf(ring->name, "vce0"); 194aaa36a97SAlex Deucher r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf, 195aaa36a97SAlex Deucher &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); 196aaa36a97SAlex Deucher if (r) 197aaa36a97SAlex Deucher return r; 198aaa36a97SAlex Deucher 199aaa36a97SAlex Deucher ring = &adev->vce.ring[1]; 200aaa36a97SAlex Deucher sprintf(ring->name, "vce1"); 201aaa36a97SAlex Deucher r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf, 202aaa36a97SAlex Deucher &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); 203aaa36a97SAlex Deucher if (r) 204aaa36a97SAlex Deucher return r; 205aaa36a97SAlex Deucher 206aaa36a97SAlex Deucher return r; 207aaa36a97SAlex Deucher } 208aaa36a97SAlex Deucher 209aaa36a97SAlex Deucher static int vce_v3_0_sw_fini(struct amdgpu_device *adev) 210aaa36a97SAlex Deucher { 211aaa36a97SAlex Deucher int r; 212aaa36a97SAlex Deucher 213aaa36a97SAlex Deucher r = amdgpu_vce_suspend(adev); 214aaa36a97SAlex Deucher if (r) 215aaa36a97SAlex Deucher return r; 216aaa36a97SAlex Deucher 217aaa36a97SAlex Deucher r = amdgpu_vce_sw_fini(adev); 218aaa36a97SAlex Deucher if (r) 219aaa36a97SAlex Deucher return r; 220aaa36a97SAlex Deucher 221aaa36a97SAlex Deucher return r; 222aaa36a97SAlex Deucher } 223aaa36a97SAlex Deucher 224aaa36a97SAlex Deucher static int vce_v3_0_hw_init(struct amdgpu_device *adev) 225aaa36a97SAlex Deucher { 226aaa36a97SAlex Deucher struct amdgpu_ring *ring; 227aaa36a97SAlex Deucher int r; 228aaa36a97SAlex Deucher 229aaa36a97SAlex Deucher r = vce_v3_0_start(adev); 230aaa36a97SAlex Deucher if (r) 231aaa36a97SAlex Deucher return r; 232aaa36a97SAlex Deucher 233aaa36a97SAlex Deucher ring = &adev->vce.ring[0]; 234aaa36a97SAlex Deucher ring->ready = true; 235aaa36a97SAlex Deucher r = amdgpu_ring_test_ring(ring); 236aaa36a97SAlex Deucher if (r) { 237aaa36a97SAlex Deucher ring->ready = false; 238aaa36a97SAlex Deucher return r; 239aaa36a97SAlex Deucher } 240aaa36a97SAlex Deucher 241aaa36a97SAlex Deucher ring = &adev->vce.ring[1]; 242aaa36a97SAlex Deucher ring->ready = true; 243aaa36a97SAlex Deucher r = amdgpu_ring_test_ring(ring); 244aaa36a97SAlex Deucher if (r) { 245aaa36a97SAlex Deucher ring->ready = false; 246aaa36a97SAlex Deucher return r; 247aaa36a97SAlex Deucher } 248aaa36a97SAlex Deucher 249aaa36a97SAlex Deucher DRM_INFO("VCE initialized successfully.\n"); 250aaa36a97SAlex Deucher 251aaa36a97SAlex Deucher return 0; 252aaa36a97SAlex Deucher } 253aaa36a97SAlex Deucher 254aaa36a97SAlex Deucher static int vce_v3_0_hw_fini(struct amdgpu_device *adev) 255aaa36a97SAlex Deucher { 256aaa36a97SAlex Deucher // TODO 257aaa36a97SAlex Deucher return 0; 258aaa36a97SAlex Deucher } 259aaa36a97SAlex Deucher 260aaa36a97SAlex Deucher static int vce_v3_0_suspend(struct amdgpu_device *adev) 261aaa36a97SAlex Deucher { 262aaa36a97SAlex Deucher int r; 263aaa36a97SAlex Deucher 264aaa36a97SAlex Deucher r = vce_v3_0_hw_fini(adev); 265aaa36a97SAlex Deucher if (r) 266aaa36a97SAlex Deucher return r; 267aaa36a97SAlex Deucher 268aaa36a97SAlex Deucher r = amdgpu_vce_suspend(adev); 269aaa36a97SAlex Deucher if (r) 270aaa36a97SAlex Deucher return r; 271aaa36a97SAlex Deucher 272aaa36a97SAlex Deucher return r; 273aaa36a97SAlex Deucher } 274aaa36a97SAlex Deucher 275aaa36a97SAlex Deucher static int vce_v3_0_resume(struct amdgpu_device *adev) 276aaa36a97SAlex Deucher { 277aaa36a97SAlex Deucher int r; 278aaa36a97SAlex Deucher 279aaa36a97SAlex Deucher r = amdgpu_vce_resume(adev); 280aaa36a97SAlex Deucher if (r) 281aaa36a97SAlex Deucher return r; 282aaa36a97SAlex Deucher 283aaa36a97SAlex Deucher r = vce_v3_0_hw_init(adev); 284aaa36a97SAlex Deucher if (r) 285aaa36a97SAlex Deucher return r; 286aaa36a97SAlex Deucher 287aaa36a97SAlex Deucher return r; 288aaa36a97SAlex Deucher } 289aaa36a97SAlex Deucher 290aaa36a97SAlex Deucher static void vce_v3_0_mc_resume(struct amdgpu_device *adev) 291aaa36a97SAlex Deucher { 292aaa36a97SAlex Deucher uint32_t offset, size; 293aaa36a97SAlex Deucher 294aaa36a97SAlex Deucher WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16)); 295aaa36a97SAlex Deucher WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 296aaa36a97SAlex Deucher WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 297aaa36a97SAlex Deucher WREG32(mmVCE_CLOCK_GATING_B, 0xf7); 298aaa36a97SAlex Deucher 299aaa36a97SAlex Deucher WREG32(mmVCE_LMI_CTRL, 0x00398000); 300aaa36a97SAlex Deucher WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1); 301aaa36a97SAlex Deucher WREG32(mmVCE_LMI_SWAP_CNTL, 0); 302aaa36a97SAlex Deucher WREG32(mmVCE_LMI_SWAP_CNTL1, 0); 303aaa36a97SAlex Deucher WREG32(mmVCE_LMI_VM_CTRL, 0); 304aaa36a97SAlex Deucher 305aaa36a97SAlex Deucher WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8)); 306aaa36a97SAlex Deucher offset = AMDGPU_VCE_FIRMWARE_OFFSET; 307aaa36a97SAlex Deucher size = AMDGPU_GPU_PAGE_ALIGN(adev->vce.fw->size); 308aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff); 309aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_SIZE0, size); 310aaa36a97SAlex Deucher 311aaa36a97SAlex Deucher offset += size; 312aaa36a97SAlex Deucher size = AMDGPU_VCE_STACK_SIZE; 313aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff); 314aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 315aaa36a97SAlex Deucher 316aaa36a97SAlex Deucher offset += size; 317aaa36a97SAlex Deucher size = AMDGPU_VCE_HEAP_SIZE; 318aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff); 319aaa36a97SAlex Deucher WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 320aaa36a97SAlex Deucher 321aaa36a97SAlex Deucher WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); 322aaa36a97SAlex Deucher 323aaa36a97SAlex Deucher WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK, 324aaa36a97SAlex Deucher ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 325aaa36a97SAlex Deucher } 326aaa36a97SAlex Deucher 327aaa36a97SAlex Deucher static bool vce_v3_0_is_idle(struct amdgpu_device *adev) 328aaa36a97SAlex Deucher { 329aaa36a97SAlex Deucher return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK); 330aaa36a97SAlex Deucher } 331aaa36a97SAlex Deucher 332aaa36a97SAlex Deucher static int vce_v3_0_wait_for_idle(struct amdgpu_device *adev) 333aaa36a97SAlex Deucher { 334aaa36a97SAlex Deucher unsigned i; 335aaa36a97SAlex Deucher 336aaa36a97SAlex Deucher for (i = 0; i < adev->usec_timeout; i++) { 337aaa36a97SAlex Deucher if (!(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK)) 338aaa36a97SAlex Deucher return 0; 339aaa36a97SAlex Deucher } 340aaa36a97SAlex Deucher return -ETIMEDOUT; 341aaa36a97SAlex Deucher } 342aaa36a97SAlex Deucher 343aaa36a97SAlex Deucher static int vce_v3_0_soft_reset(struct amdgpu_device *adev) 344aaa36a97SAlex Deucher { 345aaa36a97SAlex Deucher WREG32_P(mmSRBM_SOFT_RESET, SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK, 346aaa36a97SAlex Deucher ~SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK); 347aaa36a97SAlex Deucher mdelay(5); 348aaa36a97SAlex Deucher 349aaa36a97SAlex Deucher return vce_v3_0_start(adev); 350aaa36a97SAlex Deucher } 351aaa36a97SAlex Deucher 352aaa36a97SAlex Deucher static void vce_v3_0_print_status(struct amdgpu_device *adev) 353aaa36a97SAlex Deucher { 354aaa36a97SAlex Deucher dev_info(adev->dev, "VCE 3.0 registers\n"); 355aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_STATUS=0x%08X\n", 356aaa36a97SAlex Deucher RREG32(mmVCE_STATUS)); 357aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CNTL=0x%08X\n", 358aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CNTL)); 359aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET0=0x%08X\n", 360aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_OFFSET0)); 361aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE0=0x%08X\n", 362aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_SIZE0)); 363aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET1=0x%08X\n", 364aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_OFFSET1)); 365aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE1=0x%08X\n", 366aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_SIZE1)); 367aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET2=0x%08X\n", 368aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_OFFSET2)); 369aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE2=0x%08X\n", 370aaa36a97SAlex Deucher RREG32(mmVCE_VCPU_CACHE_SIZE2)); 371aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_SOFT_RESET=0x%08X\n", 372aaa36a97SAlex Deucher RREG32(mmVCE_SOFT_RESET)); 373aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_LO2=0x%08X\n", 374aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_LO2)); 375aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_HI2=0x%08X\n", 376aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_HI2)); 377aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_SIZE2=0x%08X\n", 378aaa36a97SAlex Deucher RREG32(mmVCE_RB_SIZE2)); 379aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_RPTR2=0x%08X\n", 380aaa36a97SAlex Deucher RREG32(mmVCE_RB_RPTR2)); 381aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_WPTR2=0x%08X\n", 382aaa36a97SAlex Deucher RREG32(mmVCE_RB_WPTR2)); 383aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_LO=0x%08X\n", 384aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_LO)); 385aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_BASE_HI=0x%08X\n", 386aaa36a97SAlex Deucher RREG32(mmVCE_RB_BASE_HI)); 387aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_SIZE=0x%08X\n", 388aaa36a97SAlex Deucher RREG32(mmVCE_RB_SIZE)); 389aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_RPTR=0x%08X\n", 390aaa36a97SAlex Deucher RREG32(mmVCE_RB_RPTR)); 391aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_RB_WPTR=0x%08X\n", 392aaa36a97SAlex Deucher RREG32(mmVCE_RB_WPTR)); 393aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_CLOCK_GATING_A=0x%08X\n", 394aaa36a97SAlex Deucher RREG32(mmVCE_CLOCK_GATING_A)); 395aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_CLOCK_GATING_B=0x%08X\n", 396aaa36a97SAlex Deucher RREG32(mmVCE_CLOCK_GATING_B)); 397aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_UENC_CLOCK_GATING=0x%08X\n", 398aaa36a97SAlex Deucher RREG32(mmVCE_UENC_CLOCK_GATING)); 399aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_UENC_REG_CLOCK_GATING=0x%08X\n", 400aaa36a97SAlex Deucher RREG32(mmVCE_UENC_REG_CLOCK_GATING)); 401aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_SYS_INT_EN=0x%08X\n", 402aaa36a97SAlex Deucher RREG32(mmVCE_SYS_INT_EN)); 403aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_CTRL2=0x%08X\n", 404aaa36a97SAlex Deucher RREG32(mmVCE_LMI_CTRL2)); 405aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_CTRL=0x%08X\n", 406aaa36a97SAlex Deucher RREG32(mmVCE_LMI_CTRL)); 407aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_VM_CTRL=0x%08X\n", 408aaa36a97SAlex Deucher RREG32(mmVCE_LMI_VM_CTRL)); 409aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_SWAP_CNTL=0x%08X\n", 410aaa36a97SAlex Deucher RREG32(mmVCE_LMI_SWAP_CNTL)); 411aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_SWAP_CNTL1=0x%08X\n", 412aaa36a97SAlex Deucher RREG32(mmVCE_LMI_SWAP_CNTL1)); 413aaa36a97SAlex Deucher dev_info(adev->dev, " VCE_LMI_CACHE_CTRL=0x%08X\n", 414aaa36a97SAlex Deucher RREG32(mmVCE_LMI_CACHE_CTRL)); 415aaa36a97SAlex Deucher } 416aaa36a97SAlex Deucher 417aaa36a97SAlex Deucher static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev, 418aaa36a97SAlex Deucher struct amdgpu_irq_src *source, 419aaa36a97SAlex Deucher unsigned type, 420aaa36a97SAlex Deucher enum amdgpu_interrupt_state state) 421aaa36a97SAlex Deucher { 422aaa36a97SAlex Deucher uint32_t val = 0; 423aaa36a97SAlex Deucher 424aaa36a97SAlex Deucher if (state == AMDGPU_IRQ_STATE_ENABLE) 425aaa36a97SAlex Deucher val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK; 426aaa36a97SAlex Deucher 427aaa36a97SAlex Deucher WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 428aaa36a97SAlex Deucher return 0; 429aaa36a97SAlex Deucher } 430aaa36a97SAlex Deucher 431aaa36a97SAlex Deucher static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, 432aaa36a97SAlex Deucher struct amdgpu_irq_src *source, 433aaa36a97SAlex Deucher struct amdgpu_iv_entry *entry) 434aaa36a97SAlex Deucher { 435aaa36a97SAlex Deucher DRM_DEBUG("IH: VCE\n"); 436aaa36a97SAlex Deucher switch (entry->src_data) { 437aaa36a97SAlex Deucher case 0: 438aaa36a97SAlex Deucher amdgpu_fence_process(&adev->vce.ring[0]); 439aaa36a97SAlex Deucher break; 440aaa36a97SAlex Deucher case 1: 441aaa36a97SAlex Deucher amdgpu_fence_process(&adev->vce.ring[1]); 442aaa36a97SAlex Deucher break; 443aaa36a97SAlex Deucher default: 444aaa36a97SAlex Deucher DRM_ERROR("Unhandled interrupt: %d %d\n", 445aaa36a97SAlex Deucher entry->src_id, entry->src_data); 446aaa36a97SAlex Deucher break; 447aaa36a97SAlex Deucher } 448aaa36a97SAlex Deucher 449aaa36a97SAlex Deucher return 0; 450aaa36a97SAlex Deucher } 451aaa36a97SAlex Deucher 452aaa36a97SAlex Deucher static int vce_v3_0_set_clockgating_state(struct amdgpu_device *adev, 453aaa36a97SAlex Deucher enum amdgpu_clockgating_state state) 454aaa36a97SAlex Deucher { 455aaa36a97SAlex Deucher //TODO 456aaa36a97SAlex Deucher return 0; 457aaa36a97SAlex Deucher } 458aaa36a97SAlex Deucher 459aaa36a97SAlex Deucher static int vce_v3_0_set_powergating_state(struct amdgpu_device *adev, 460aaa36a97SAlex Deucher enum amdgpu_powergating_state state) 461aaa36a97SAlex Deucher { 462aaa36a97SAlex Deucher /* This doesn't actually powergate the VCE block. 463aaa36a97SAlex Deucher * That's done in the dpm code via the SMC. This 464aaa36a97SAlex Deucher * just re-inits the block as necessary. The actual 465aaa36a97SAlex Deucher * gating still happens in the dpm code. We should 466aaa36a97SAlex Deucher * revisit this when there is a cleaner line between 467aaa36a97SAlex Deucher * the smc and the hw blocks 468aaa36a97SAlex Deucher */ 469aaa36a97SAlex Deucher if (state == AMDGPU_PG_STATE_GATE) 470aaa36a97SAlex Deucher /* XXX do we need a vce_v3_0_stop()? */ 471aaa36a97SAlex Deucher return 0; 472aaa36a97SAlex Deucher else 473aaa36a97SAlex Deucher return vce_v3_0_start(adev); 474aaa36a97SAlex Deucher } 475aaa36a97SAlex Deucher 476aaa36a97SAlex Deucher const struct amdgpu_ip_funcs vce_v3_0_ip_funcs = { 477aaa36a97SAlex Deucher .early_init = vce_v3_0_early_init, 478aaa36a97SAlex Deucher .late_init = NULL, 479aaa36a97SAlex Deucher .sw_init = vce_v3_0_sw_init, 480aaa36a97SAlex Deucher .sw_fini = vce_v3_0_sw_fini, 481aaa36a97SAlex Deucher .hw_init = vce_v3_0_hw_init, 482aaa36a97SAlex Deucher .hw_fini = vce_v3_0_hw_fini, 483aaa36a97SAlex Deucher .suspend = vce_v3_0_suspend, 484aaa36a97SAlex Deucher .resume = vce_v3_0_resume, 485aaa36a97SAlex Deucher .is_idle = vce_v3_0_is_idle, 486aaa36a97SAlex Deucher .wait_for_idle = vce_v3_0_wait_for_idle, 487aaa36a97SAlex Deucher .soft_reset = vce_v3_0_soft_reset, 488aaa36a97SAlex Deucher .print_status = vce_v3_0_print_status, 489aaa36a97SAlex Deucher .set_clockgating_state = vce_v3_0_set_clockgating_state, 490aaa36a97SAlex Deucher .set_powergating_state = vce_v3_0_set_powergating_state, 491aaa36a97SAlex Deucher }; 492aaa36a97SAlex Deucher 493aaa36a97SAlex Deucher static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { 494aaa36a97SAlex Deucher .get_rptr = vce_v3_0_ring_get_rptr, 495aaa36a97SAlex Deucher .get_wptr = vce_v3_0_ring_get_wptr, 496aaa36a97SAlex Deucher .set_wptr = vce_v3_0_ring_set_wptr, 497aaa36a97SAlex Deucher .parse_cs = amdgpu_vce_ring_parse_cs, 498aaa36a97SAlex Deucher .emit_ib = amdgpu_vce_ring_emit_ib, 499aaa36a97SAlex Deucher .emit_fence = amdgpu_vce_ring_emit_fence, 500aaa36a97SAlex Deucher .emit_semaphore = amdgpu_vce_ring_emit_semaphore, 501aaa36a97SAlex Deucher .test_ring = amdgpu_vce_ring_test_ring, 502aaa36a97SAlex Deucher .test_ib = amdgpu_vce_ring_test_ib, 503aaa36a97SAlex Deucher .is_lockup = amdgpu_ring_test_lockup, 504aaa36a97SAlex Deucher }; 505aaa36a97SAlex Deucher 506aaa36a97SAlex Deucher static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) 507aaa36a97SAlex Deucher { 508aaa36a97SAlex Deucher adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs; 509aaa36a97SAlex Deucher adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs; 510aaa36a97SAlex Deucher } 511aaa36a97SAlex Deucher 512aaa36a97SAlex Deucher static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = { 513aaa36a97SAlex Deucher .set = vce_v3_0_set_interrupt_state, 514aaa36a97SAlex Deucher .process = vce_v3_0_process_interrupt, 515aaa36a97SAlex Deucher }; 516aaa36a97SAlex Deucher 517aaa36a97SAlex Deucher static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev) 518aaa36a97SAlex Deucher { 519aaa36a97SAlex Deucher adev->vce.irq.num_types = 1; 520aaa36a97SAlex Deucher adev->vce.irq.funcs = &vce_v3_0_irq_funcs; 521aaa36a97SAlex Deucher }; 522