1*855e3e19SSonny Jiang // SPDX-License-Identifier: GPL-2.0 OR MIT 2*855e3e19SSonny Jiang /* 3*855e3e19SSonny Jiang * Copyright 2025-2026 Advanced Micro Devices, Inc. All rights reserved. 4*855e3e19SSonny Jiang * 5*855e3e19SSonny Jiang * Permission is hereby granted, free of charge, to any person obtaining a 6*855e3e19SSonny Jiang * copy of this software and associated documentation files (the "Software"), 7*855e3e19SSonny Jiang * to deal in the Software without restriction, including without limitation 8*855e3e19SSonny Jiang * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9*855e3e19SSonny Jiang * and/or sell copies of the Software, and to permit persons to whom the 10*855e3e19SSonny Jiang * Software is furnished to do so, subject to the following conditions: 11*855e3e19SSonny Jiang * 12*855e3e19SSonny Jiang * The above copyright notice and this permission notice shall be included in 13*855e3e19SSonny Jiang * all copies or substantial portions of the Software. 14*855e3e19SSonny Jiang * 15*855e3e19SSonny Jiang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*855e3e19SSonny Jiang * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*855e3e19SSonny Jiang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*855e3e19SSonny Jiang * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19*855e3e19SSonny Jiang * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20*855e3e19SSonny Jiang * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21*855e3e19SSonny Jiang * OTHER DEALINGS IN THE SOFTWARE. 22*855e3e19SSonny Jiang */ 23*855e3e19SSonny Jiang 24*855e3e19SSonny Jiang #include "amdgpu.h" 25*855e3e19SSonny Jiang #include "amdgpu_jpeg.h" 26*855e3e19SSonny Jiang #include "amdgpu_pm.h" 27*855e3e19SSonny Jiang #include "soc15.h" 28*855e3e19SSonny Jiang #include "soc15d.h" 29*855e3e19SSonny Jiang #include "jpeg_v4_0_3.h" 30*855e3e19SSonny Jiang #include "jpeg_v5_0_2.h" 31*855e3e19SSonny Jiang #include "mmsch_v5_0.h" 32*855e3e19SSonny Jiang 33*855e3e19SSonny Jiang #include "vcn/vcn_5_0_0_offset.h" 34*855e3e19SSonny Jiang #include "vcn/vcn_5_0_0_sh_mask.h" 35*855e3e19SSonny Jiang #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h" 36*855e3e19SSonny Jiang 37*855e3e19SSonny Jiang static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev); 38*855e3e19SSonny Jiang static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev); 39*855e3e19SSonny Jiang static int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block, 40*855e3e19SSonny Jiang enum amd_powergating_state state); 41*855e3e19SSonny Jiang static void jpeg_v5_0_2_dec_ring_set_wptr(struct amdgpu_ring *ring); 42*855e3e19SSonny Jiang 43*855e3e19SSonny Jiang static int amdgpu_ih_srcid_jpeg[] = { 44*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG_DECODE, 45*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG1_DECODE, 46*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG2_DECODE, 47*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG3_DECODE, 48*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG4_DECODE, 49*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG5_DECODE, 50*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG6_DECODE, 51*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG7_DECODE, 52*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG8_DECODE, 53*855e3e19SSonny Jiang VCN_5_0__SRCID__JPEG9_DECODE, 54*855e3e19SSonny Jiang }; 55*855e3e19SSonny Jiang 56*855e3e19SSonny Jiang static const struct amdgpu_hwip_reg_entry jpeg_reg_list_5_0_2[] = { 57*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_POWER_STATUS), 58*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_INT_STAT), 59*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_RPTR), 60*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_RB_WPTR), 61*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC0_UVD_JRBC_STATUS), 62*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_ADDR_MODE), 63*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG), 64*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_Y_GFX10_TILING_SURFACE), 65*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regJPEG_DEC_UV_GFX10_TILING_SURFACE), 66*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_PITCH), 67*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JPEG_UV_PITCH), 68*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_RB_RPTR), 69*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_RB_WPTR), 70*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC1_UVD_JRBC_STATUS), 71*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_RB_RPTR), 72*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_RB_WPTR), 73*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC2_UVD_JRBC_STATUS), 74*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_RB_RPTR), 75*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_RB_WPTR), 76*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC3_UVD_JRBC_STATUS), 77*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_RB_RPTR), 78*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_RB_WPTR), 79*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC4_UVD_JRBC_STATUS), 80*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_RB_RPTR), 81*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_RB_WPTR), 82*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC5_UVD_JRBC_STATUS), 83*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_RB_RPTR), 84*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_RB_WPTR), 85*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC6_UVD_JRBC_STATUS), 86*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_RB_RPTR), 87*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_RB_WPTR), 88*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC7_UVD_JRBC_STATUS), 89*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_RB_RPTR), 90*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_RB_WPTR), 91*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC8_UVD_JRBC_STATUS), 92*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_RB_RPTR), 93*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_RB_WPTR), 94*855e3e19SSonny Jiang SOC15_REG_ENTRY_STR(JPEG, 0, regUVD_JRBC9_UVD_JRBC_STATUS), 95*855e3e19SSonny Jiang }; 96*855e3e19SSonny Jiang 97*855e3e19SSonny Jiang static int jpeg_v5_0_2_core_reg_offset(u32 pipe) 98*855e3e19SSonny Jiang { 99*855e3e19SSonny Jiang if (pipe <= AMDGPU_MAX_JPEG_RINGS_4_0_3) 100*855e3e19SSonny Jiang return ((0x40 * pipe) - 0xc80); 101*855e3e19SSonny Jiang else 102*855e3e19SSonny Jiang return ((0x40 * pipe) - 0x440); 103*855e3e19SSonny Jiang } 104*855e3e19SSonny Jiang 105*855e3e19SSonny Jiang /** 106*855e3e19SSonny Jiang * jpeg_v5_0_2_early_init - set function pointers 107*855e3e19SSonny Jiang * 108*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 109*855e3e19SSonny Jiang * 110*855e3e19SSonny Jiang * Set ring and irq function pointers 111*855e3e19SSonny Jiang */ 112*855e3e19SSonny Jiang static int jpeg_v5_0_2_early_init(struct amdgpu_ip_block *ip_block) 113*855e3e19SSonny Jiang { 114*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 115*855e3e19SSonny Jiang 116*855e3e19SSonny Jiang if (!adev->jpeg.num_jpeg_inst || adev->jpeg.num_jpeg_inst > AMDGPU_MAX_JPEG_INSTANCES) 117*855e3e19SSonny Jiang return -ENOENT; 118*855e3e19SSonny Jiang 119*855e3e19SSonny Jiang adev->jpeg.num_jpeg_rings = AMDGPU_MAX_JPEG_RINGS; 120*855e3e19SSonny Jiang jpeg_v5_0_2_set_dec_ring_funcs(adev); 121*855e3e19SSonny Jiang jpeg_v5_0_2_set_irq_funcs(adev); 122*855e3e19SSonny Jiang 123*855e3e19SSonny Jiang return 0; 124*855e3e19SSonny Jiang } 125*855e3e19SSonny Jiang 126*855e3e19SSonny Jiang /** 127*855e3e19SSonny Jiang * jpeg_v5_0_2_sw_init - sw init for JPEG block 128*855e3e19SSonny Jiang * 129*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 130*855e3e19SSonny Jiang * 131*855e3e19SSonny Jiang * Load firmware and sw initialization 132*855e3e19SSonny Jiang */ 133*855e3e19SSonny Jiang static int jpeg_v5_0_2_sw_init(struct amdgpu_ip_block *ip_block) 134*855e3e19SSonny Jiang { 135*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 136*855e3e19SSonny Jiang struct amdgpu_ring *ring; 137*855e3e19SSonny Jiang int i, j, r, jpeg_inst; 138*855e3e19SSonny Jiang 139*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 140*855e3e19SSonny Jiang /* JPEG TRAP */ 141*855e3e19SSonny Jiang r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 142*855e3e19SSonny Jiang amdgpu_ih_srcid_jpeg[j], &adev->jpeg.inst->irq); 143*855e3e19SSonny Jiang if (r) 144*855e3e19SSonny Jiang return r; 145*855e3e19SSonny Jiang } 146*855e3e19SSonny Jiang 147*855e3e19SSonny Jiang r = amdgpu_jpeg_sw_init(adev); 148*855e3e19SSonny Jiang if (r) 149*855e3e19SSonny Jiang return r; 150*855e3e19SSonny Jiang 151*855e3e19SSonny Jiang r = amdgpu_jpeg_resume(adev); 152*855e3e19SSonny Jiang if (r) 153*855e3e19SSonny Jiang return r; 154*855e3e19SSonny Jiang 155*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 156*855e3e19SSonny Jiang jpeg_inst = GET_INST(JPEG, i); 157*855e3e19SSonny Jiang 158*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 159*855e3e19SSonny Jiang ring = &adev->jpeg.inst[i].ring_dec[j]; 160*855e3e19SSonny Jiang ring->use_doorbell = false; 161*855e3e19SSonny Jiang ring->vm_hub = AMDGPU_MMHUB0(adev->jpeg.inst[i].aid_id); 162*855e3e19SSonny Jiang ring->doorbell_index = 163*855e3e19SSonny Jiang (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 164*855e3e19SSonny Jiang 1 + j + 11 * jpeg_inst; 165*855e3e19SSonny Jiang sprintf(ring->name, "jpeg_dec_%d.%d", adev->jpeg.inst[i].aid_id, j); 166*855e3e19SSonny Jiang r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0, 167*855e3e19SSonny Jiang AMDGPU_RING_PRIO_DEFAULT, NULL); 168*855e3e19SSonny Jiang if (r) 169*855e3e19SSonny Jiang return r; 170*855e3e19SSonny Jiang 171*855e3e19SSonny Jiang adev->jpeg.internal.jpeg_pitch[j] = 172*855e3e19SSonny Jiang regUVD_JRBC0_UVD_JRBC_SCRATCH0_INTERNAL_OFFSET; 173*855e3e19SSonny Jiang adev->jpeg.inst[i].external.jpeg_pitch[j] = 174*855e3e19SSonny Jiang SOC15_REG_OFFSET1(JPEG, jpeg_inst, regUVD_JRBC_SCRATCH0, 175*855e3e19SSonny Jiang (j ? jpeg_v5_0_2_core_reg_offset(j) : 0)); 176*855e3e19SSonny Jiang } 177*855e3e19SSonny Jiang } 178*855e3e19SSonny Jiang 179*855e3e19SSonny Jiang r = amdgpu_jpeg_reg_dump_init(adev, jpeg_reg_list_5_0_2, ARRAY_SIZE(jpeg_reg_list_5_0_2)); 180*855e3e19SSonny Jiang if (r) 181*855e3e19SSonny Jiang return r; 182*855e3e19SSonny Jiang 183*855e3e19SSonny Jiang adev->jpeg.supported_reset = 184*855e3e19SSonny Jiang amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]); 185*855e3e19SSonny Jiang adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; 186*855e3e19SSonny Jiang r = amdgpu_jpeg_sysfs_reset_mask_init(adev); 187*855e3e19SSonny Jiang 188*855e3e19SSonny Jiang return r; 189*855e3e19SSonny Jiang } 190*855e3e19SSonny Jiang 191*855e3e19SSonny Jiang /** 192*855e3e19SSonny Jiang * jpeg_v5_0_2_sw_fini - sw fini for JPEG block 193*855e3e19SSonny Jiang * 194*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 195*855e3e19SSonny Jiang * 196*855e3e19SSonny Jiang * JPEG suspend and free up sw allocation 197*855e3e19SSonny Jiang */ 198*855e3e19SSonny Jiang static int jpeg_v5_0_2_sw_fini(struct amdgpu_ip_block *ip_block) 199*855e3e19SSonny Jiang { 200*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 201*855e3e19SSonny Jiang int r; 202*855e3e19SSonny Jiang 203*855e3e19SSonny Jiang r = amdgpu_jpeg_suspend(adev); 204*855e3e19SSonny Jiang if (r) 205*855e3e19SSonny Jiang return r; 206*855e3e19SSonny Jiang 207*855e3e19SSonny Jiang amdgpu_jpeg_sysfs_reset_mask_fini(adev); 208*855e3e19SSonny Jiang 209*855e3e19SSonny Jiang r = amdgpu_jpeg_sw_fini(adev); 210*855e3e19SSonny Jiang 211*855e3e19SSonny Jiang return r; 212*855e3e19SSonny Jiang } 213*855e3e19SSonny Jiang 214*855e3e19SSonny Jiang /** 215*855e3e19SSonny Jiang * jpeg_v5_0_2_hw_init - start and test JPEG block 216*855e3e19SSonny Jiang * 217*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 218*855e3e19SSonny Jiang * 219*855e3e19SSonny Jiang */ 220*855e3e19SSonny Jiang static int jpeg_v5_0_2_hw_init(struct amdgpu_ip_block *ip_block) 221*855e3e19SSonny Jiang { 222*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 223*855e3e19SSonny Jiang struct amdgpu_ring *ring; 224*855e3e19SSonny Jiang int i, j, r, jpeg_inst, tmp; 225*855e3e19SSonny Jiang 226*855e3e19SSonny Jiang if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100) 227*855e3e19SSonny Jiang adev->jpeg.caps |= AMDGPU_JPEG_CAPS(RRMT_ENABLED); 228*855e3e19SSonny Jiang 229*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 230*855e3e19SSonny Jiang jpeg_inst = GET_INST(JPEG, i); 231*855e3e19SSonny Jiang ring = adev->jpeg.inst[i].ring_dec; 232*855e3e19SSonny Jiang 233*855e3e19SSonny Jiang /* Remove JPEG Tile antihang mechanism */ 234*855e3e19SSonny Jiang tmp = RREG32_SOC15(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS); 235*855e3e19SSonny Jiang tmp &= (~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); 236*855e3e19SSonny Jiang WREG32_SOC15(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS, tmp); 237*855e3e19SSonny Jiang 238*855e3e19SSonny Jiang if (ring->use_doorbell) 239*855e3e19SSonny Jiang adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, 240*855e3e19SSonny Jiang (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 11 * jpeg_inst, 241*855e3e19SSonny Jiang adev->jpeg.inst[i].aid_id); 242*855e3e19SSonny Jiang 243*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 244*855e3e19SSonny Jiang ring = &adev->jpeg.inst[i].ring_dec[j]; 245*855e3e19SSonny Jiang if (ring->use_doorbell) 246*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(VCN, GET_INST(VCN, i), regVCN_JPEG_DB_CTRL, 247*855e3e19SSonny Jiang ring->pipe, 248*855e3e19SSonny Jiang ring->doorbell_index << 249*855e3e19SSonny Jiang VCN_JPEG_DB_CTRL__OFFSET__SHIFT | 250*855e3e19SSonny Jiang VCN_JPEG_DB_CTRL__EN_MASK); 251*855e3e19SSonny Jiang r = amdgpu_ring_test_helper(ring); 252*855e3e19SSonny Jiang if (r) 253*855e3e19SSonny Jiang return r; 254*855e3e19SSonny Jiang } 255*855e3e19SSonny Jiang } 256*855e3e19SSonny Jiang 257*855e3e19SSonny Jiang return 0; 258*855e3e19SSonny Jiang } 259*855e3e19SSonny Jiang 260*855e3e19SSonny Jiang /** 261*855e3e19SSonny Jiang * jpeg_v5_0_2_hw_fini - stop the hardware block 262*855e3e19SSonny Jiang * 263*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 264*855e3e19SSonny Jiang * 265*855e3e19SSonny Jiang * Stop the JPEG block, mark ring as not ready any more 266*855e3e19SSonny Jiang */ 267*855e3e19SSonny Jiang static int jpeg_v5_0_2_hw_fini(struct amdgpu_ip_block *ip_block) 268*855e3e19SSonny Jiang { 269*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 270*855e3e19SSonny Jiang int ret = 0; 271*855e3e19SSonny Jiang 272*855e3e19SSonny Jiang cancel_delayed_work_sync(&adev->jpeg.idle_work); 273*855e3e19SSonny Jiang 274*855e3e19SSonny Jiang if (adev->jpeg.cur_state != AMD_PG_STATE_GATE) 275*855e3e19SSonny Jiang ret = jpeg_v5_0_2_set_powergating_state(ip_block, AMD_PG_STATE_GATE); 276*855e3e19SSonny Jiang 277*855e3e19SSonny Jiang return ret; 278*855e3e19SSonny Jiang } 279*855e3e19SSonny Jiang 280*855e3e19SSonny Jiang /** 281*855e3e19SSonny Jiang * jpeg_v5_0_2_suspend - suspend JPEG block 282*855e3e19SSonny Jiang * 283*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 284*855e3e19SSonny Jiang * 285*855e3e19SSonny Jiang * HW fini and suspend JPEG block 286*855e3e19SSonny Jiang */ 287*855e3e19SSonny Jiang static int jpeg_v5_0_2_suspend(struct amdgpu_ip_block *ip_block) 288*855e3e19SSonny Jiang { 289*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 290*855e3e19SSonny Jiang int r; 291*855e3e19SSonny Jiang 292*855e3e19SSonny Jiang r = jpeg_v5_0_2_hw_fini(ip_block); 293*855e3e19SSonny Jiang if (r) 294*855e3e19SSonny Jiang return r; 295*855e3e19SSonny Jiang 296*855e3e19SSonny Jiang r = amdgpu_jpeg_suspend(adev); 297*855e3e19SSonny Jiang 298*855e3e19SSonny Jiang return r; 299*855e3e19SSonny Jiang } 300*855e3e19SSonny Jiang 301*855e3e19SSonny Jiang /** 302*855e3e19SSonny Jiang * jpeg_v5_0_2_resume - resume JPEG block 303*855e3e19SSonny Jiang * 304*855e3e19SSonny Jiang * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 305*855e3e19SSonny Jiang * 306*855e3e19SSonny Jiang * Resume firmware and hw init JPEG block 307*855e3e19SSonny Jiang */ 308*855e3e19SSonny Jiang static int jpeg_v5_0_2_resume(struct amdgpu_ip_block *ip_block) 309*855e3e19SSonny Jiang { 310*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 311*855e3e19SSonny Jiang int r; 312*855e3e19SSonny Jiang 313*855e3e19SSonny Jiang r = amdgpu_jpeg_resume(adev); 314*855e3e19SSonny Jiang if (r) 315*855e3e19SSonny Jiang return r; 316*855e3e19SSonny Jiang 317*855e3e19SSonny Jiang r = jpeg_v5_0_2_hw_init(ip_block); 318*855e3e19SSonny Jiang 319*855e3e19SSonny Jiang return r; 320*855e3e19SSonny Jiang } 321*855e3e19SSonny Jiang 322*855e3e19SSonny Jiang static void jpeg_v5_0_2_init_inst(struct amdgpu_device *adev, int i) 323*855e3e19SSonny Jiang { 324*855e3e19SSonny Jiang int jpeg_inst = GET_INST(JPEG, i); 325*855e3e19SSonny Jiang 326*855e3e19SSonny Jiang /* disable anti hang mechanism */ 327*855e3e19SSonny Jiang WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0, 328*855e3e19SSonny Jiang ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); 329*855e3e19SSonny Jiang 330*855e3e19SSonny Jiang /* keep the JPEG in static PG mode */ 331*855e3e19SSonny Jiang WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0, 332*855e3e19SSonny Jiang ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK); 333*855e3e19SSonny Jiang 334*855e3e19SSonny Jiang /* MJPEG global tiling registers */ 335*855e3e19SSonny Jiang WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG, 336*855e3e19SSonny Jiang adev->gfx.config.gb_addr_config); 337*855e3e19SSonny Jiang 338*855e3e19SSonny Jiang /* enable JMI channel */ 339*855e3e19SSonny Jiang WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0, 340*855e3e19SSonny Jiang ~UVD_JMI_CNTL__SOFT_RESET_MASK); 341*855e3e19SSonny Jiang } 342*855e3e19SSonny Jiang 343*855e3e19SSonny Jiang static void jpeg_v5_0_2_deinit_inst(struct amdgpu_device *adev, int i) 344*855e3e19SSonny Jiang { 345*855e3e19SSonny Jiang int jpeg_inst = GET_INST(JPEG, i); 346*855e3e19SSonny Jiang /* reset JMI */ 347*855e3e19SSonny Jiang WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 348*855e3e19SSonny Jiang UVD_JMI_CNTL__SOFT_RESET_MASK, 349*855e3e19SSonny Jiang ~UVD_JMI_CNTL__SOFT_RESET_MASK); 350*855e3e19SSonny Jiang 351*855e3e19SSonny Jiang /* enable anti hang mechanism */ 352*855e3e19SSonny Jiang WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 353*855e3e19SSonny Jiang UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK, 354*855e3e19SSonny Jiang ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK); 355*855e3e19SSonny Jiang } 356*855e3e19SSonny Jiang 357*855e3e19SSonny Jiang static void jpeg_v5_0_2_init_jrbc(struct amdgpu_ring *ring) 358*855e3e19SSonny Jiang { 359*855e3e19SSonny Jiang struct amdgpu_device *adev = ring->adev; 360*855e3e19SSonny Jiang u32 reg, data, mask; 361*855e3e19SSonny Jiang int jpeg_inst = GET_INST(JPEG, ring->me); 362*855e3e19SSonny Jiang int reg_offset = ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0; 363*855e3e19SSonny Jiang 364*855e3e19SSonny Jiang /* enable System Interrupt for JRBC */ 365*855e3e19SSonny Jiang reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN); 366*855e3e19SSonny Jiang if (ring->pipe < AMDGPU_MAX_JPEG_RINGS_4_0_3) { 367*855e3e19SSonny Jiang data = JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe; 368*855e3e19SSonny Jiang mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe); 369*855e3e19SSonny Jiang WREG32_P(reg, data, mask); 370*855e3e19SSonny Jiang } else { 371*855e3e19SSonny Jiang data = JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12); 372*855e3e19SSonny Jiang mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12)); 373*855e3e19SSonny Jiang WREG32_P(reg, data, mask); 374*855e3e19SSonny Jiang } 375*855e3e19SSonny Jiang 376*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 377*855e3e19SSonny Jiang regUVD_LMI_JRBC_RB_VMID, 378*855e3e19SSonny Jiang reg_offset, 0); 379*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 380*855e3e19SSonny Jiang regUVD_JRBC_RB_CNTL, 381*855e3e19SSonny Jiang reg_offset, 382*855e3e19SSonny Jiang (0x00000001L | 0x00000002L)); 383*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 384*855e3e19SSonny Jiang regUVD_LMI_JRBC_RB_64BIT_BAR_LOW, 385*855e3e19SSonny Jiang reg_offset, lower_32_bits(ring->gpu_addr)); 386*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 387*855e3e19SSonny Jiang regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, 388*855e3e19SSonny Jiang reg_offset, upper_32_bits(ring->gpu_addr)); 389*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 390*855e3e19SSonny Jiang regUVD_JRBC_RB_RPTR, 391*855e3e19SSonny Jiang reg_offset, 0); 392*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 393*855e3e19SSonny Jiang regUVD_JRBC_RB_WPTR, 394*855e3e19SSonny Jiang reg_offset, 0); 395*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 396*855e3e19SSonny Jiang regUVD_JRBC_RB_CNTL, 397*855e3e19SSonny Jiang reg_offset, 0x00000002L); 398*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 399*855e3e19SSonny Jiang regUVD_JRBC_RB_SIZE, 400*855e3e19SSonny Jiang reg_offset, ring->ring_size / 4); 401*855e3e19SSonny Jiang ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR, 402*855e3e19SSonny Jiang reg_offset); 403*855e3e19SSonny Jiang } 404*855e3e19SSonny Jiang 405*855e3e19SSonny Jiang /** 406*855e3e19SSonny Jiang * jpeg_v5_0_2_start - start JPEG block 407*855e3e19SSonny Jiang * 408*855e3e19SSonny Jiang * @adev: amdgpu_device pointer 409*855e3e19SSonny Jiang * 410*855e3e19SSonny Jiang * Setup and start the JPEG block 411*855e3e19SSonny Jiang */ 412*855e3e19SSonny Jiang static int jpeg_v5_0_2_start(struct amdgpu_device *adev) 413*855e3e19SSonny Jiang { 414*855e3e19SSonny Jiang struct amdgpu_ring *ring; 415*855e3e19SSonny Jiang int i, j; 416*855e3e19SSonny Jiang 417*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 418*855e3e19SSonny Jiang jpeg_v5_0_2_init_inst(adev, i); 419*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 420*855e3e19SSonny Jiang ring = &adev->jpeg.inst[i].ring_dec[j]; 421*855e3e19SSonny Jiang jpeg_v5_0_2_init_jrbc(ring); 422*855e3e19SSonny Jiang } 423*855e3e19SSonny Jiang } 424*855e3e19SSonny Jiang 425*855e3e19SSonny Jiang return 0; 426*855e3e19SSonny Jiang } 427*855e3e19SSonny Jiang 428*855e3e19SSonny Jiang /** 429*855e3e19SSonny Jiang * jpeg_v5_0_2_stop - stop JPEG block 430*855e3e19SSonny Jiang * 431*855e3e19SSonny Jiang * @adev: amdgpu_device pointer 432*855e3e19SSonny Jiang * 433*855e3e19SSonny Jiang * stop the JPEG block 434*855e3e19SSonny Jiang */ 435*855e3e19SSonny Jiang static int jpeg_v5_0_2_stop(struct amdgpu_device *adev) 436*855e3e19SSonny Jiang { 437*855e3e19SSonny Jiang int i; 438*855e3e19SSonny Jiang 439*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) 440*855e3e19SSonny Jiang jpeg_v5_0_2_deinit_inst(adev, i); 441*855e3e19SSonny Jiang 442*855e3e19SSonny Jiang return 0; 443*855e3e19SSonny Jiang } 444*855e3e19SSonny Jiang 445*855e3e19SSonny Jiang /** 446*855e3e19SSonny Jiang * jpeg_v5_0_2_dec_ring_get_rptr - get read pointer 447*855e3e19SSonny Jiang * 448*855e3e19SSonny Jiang * @ring: amdgpu_ring pointer 449*855e3e19SSonny Jiang * 450*855e3e19SSonny Jiang * Returns the current hardware read pointer 451*855e3e19SSonny Jiang */ 452*855e3e19SSonny Jiang static uint64_t jpeg_v5_0_2_dec_ring_get_rptr(struct amdgpu_ring *ring) 453*855e3e19SSonny Jiang { 454*855e3e19SSonny Jiang struct amdgpu_device *adev = ring->adev; 455*855e3e19SSonny Jiang 456*855e3e19SSonny Jiang return RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC_RB_RPTR, 457*855e3e19SSonny Jiang ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0); 458*855e3e19SSonny Jiang } 459*855e3e19SSonny Jiang 460*855e3e19SSonny Jiang /** 461*855e3e19SSonny Jiang * jpeg_v5_0_2_dec_ring_get_wptr - get write pointer 462*855e3e19SSonny Jiang * 463*855e3e19SSonny Jiang * @ring: amdgpu_ring pointer 464*855e3e19SSonny Jiang * 465*855e3e19SSonny Jiang * Returns the current hardware write pointer 466*855e3e19SSonny Jiang */ 467*855e3e19SSonny Jiang static uint64_t jpeg_v5_0_2_dec_ring_get_wptr(struct amdgpu_ring *ring) 468*855e3e19SSonny Jiang { 469*855e3e19SSonny Jiang struct amdgpu_device *adev = ring->adev; 470*855e3e19SSonny Jiang 471*855e3e19SSonny Jiang if (ring->use_doorbell) 472*855e3e19SSonny Jiang return adev->wb.wb[ring->wptr_offs]; 473*855e3e19SSonny Jiang 474*855e3e19SSonny Jiang return RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC_RB_WPTR, 475*855e3e19SSonny Jiang ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0); 476*855e3e19SSonny Jiang } 477*855e3e19SSonny Jiang 478*855e3e19SSonny Jiang /** 479*855e3e19SSonny Jiang * jpeg_v5_0_2_dec_ring_set_wptr - set write pointer 480*855e3e19SSonny Jiang * 481*855e3e19SSonny Jiang * @ring: amdgpu_ring pointer 482*855e3e19SSonny Jiang * 483*855e3e19SSonny Jiang * Commits the write pointer to the hardware 484*855e3e19SSonny Jiang */ 485*855e3e19SSonny Jiang static void jpeg_v5_0_2_dec_ring_set_wptr(struct amdgpu_ring *ring) 486*855e3e19SSonny Jiang { 487*855e3e19SSonny Jiang struct amdgpu_device *adev = ring->adev; 488*855e3e19SSonny Jiang 489*855e3e19SSonny Jiang if (ring->use_doorbell) { 490*855e3e19SSonny Jiang adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr); 491*855e3e19SSonny Jiang WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); 492*855e3e19SSonny Jiang } else { 493*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me), 494*855e3e19SSonny Jiang regUVD_JRBC_RB_WPTR, 495*855e3e19SSonny Jiang (ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0), 496*855e3e19SSonny Jiang lower_32_bits(ring->wptr)); 497*855e3e19SSonny Jiang } 498*855e3e19SSonny Jiang } 499*855e3e19SSonny Jiang 500*855e3e19SSonny Jiang static bool jpeg_v5_0_2_is_idle(struct amdgpu_ip_block *ip_block) 501*855e3e19SSonny Jiang { 502*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 503*855e3e19SSonny Jiang bool ret = false; 504*855e3e19SSonny Jiang int i, j; 505*855e3e19SSonny Jiang 506*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 507*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 508*855e3e19SSonny Jiang int reg_offset = (j ? jpeg_v5_0_2_core_reg_offset(j) : 0); 509*855e3e19SSonny Jiang 510*855e3e19SSonny Jiang ret &= ((RREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, i), 511*855e3e19SSonny Jiang regUVD_JRBC_STATUS, reg_offset) & 512*855e3e19SSonny Jiang UVD_JRBC_STATUS__RB_JOB_DONE_MASK) == 513*855e3e19SSonny Jiang UVD_JRBC_STATUS__RB_JOB_DONE_MASK); 514*855e3e19SSonny Jiang } 515*855e3e19SSonny Jiang } 516*855e3e19SSonny Jiang 517*855e3e19SSonny Jiang return ret; 518*855e3e19SSonny Jiang } 519*855e3e19SSonny Jiang 520*855e3e19SSonny Jiang static int jpeg_v5_0_2_wait_for_idle(struct amdgpu_ip_block *ip_block) 521*855e3e19SSonny Jiang { 522*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 523*855e3e19SSonny Jiang int ret = 0; 524*855e3e19SSonny Jiang int i, j; 525*855e3e19SSonny Jiang 526*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 527*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 528*855e3e19SSonny Jiang int reg_offset = (j ? jpeg_v5_0_2_core_reg_offset(j) : 0); 529*855e3e19SSonny Jiang 530*855e3e19SSonny Jiang ret &= SOC15_WAIT_ON_RREG_OFFSET(JPEG, GET_INST(JPEG, i), 531*855e3e19SSonny Jiang regUVD_JRBC_STATUS, reg_offset, 532*855e3e19SSonny Jiang UVD_JRBC_STATUS__RB_JOB_DONE_MASK, 533*855e3e19SSonny Jiang UVD_JRBC_STATUS__RB_JOB_DONE_MASK); 534*855e3e19SSonny Jiang } 535*855e3e19SSonny Jiang } 536*855e3e19SSonny Jiang return ret; 537*855e3e19SSonny Jiang } 538*855e3e19SSonny Jiang 539*855e3e19SSonny Jiang static int jpeg_v5_0_2_set_clockgating_state(struct amdgpu_ip_block *ip_block, 540*855e3e19SSonny Jiang enum amd_clockgating_state state) 541*855e3e19SSonny Jiang { 542*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 543*855e3e19SSonny Jiang bool enable = state == AMD_CG_STATE_GATE; 544*855e3e19SSonny Jiang 545*855e3e19SSonny Jiang int i; 546*855e3e19SSonny Jiang 547*855e3e19SSonny Jiang if (!enable) 548*855e3e19SSonny Jiang return 0; 549*855e3e19SSonny Jiang 550*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 551*855e3e19SSonny Jiang if (!jpeg_v5_0_2_is_idle(ip_block)) 552*855e3e19SSonny Jiang return -EBUSY; 553*855e3e19SSonny Jiang } 554*855e3e19SSonny Jiang 555*855e3e19SSonny Jiang return 0; 556*855e3e19SSonny Jiang } 557*855e3e19SSonny Jiang 558*855e3e19SSonny Jiang static int jpeg_v5_0_2_set_powergating_state(struct amdgpu_ip_block *ip_block, 559*855e3e19SSonny Jiang enum amd_powergating_state state) 560*855e3e19SSonny Jiang { 561*855e3e19SSonny Jiang struct amdgpu_device *adev = ip_block->adev; 562*855e3e19SSonny Jiang int ret; 563*855e3e19SSonny Jiang 564*855e3e19SSonny Jiang if (state == adev->jpeg.cur_state) 565*855e3e19SSonny Jiang return 0; 566*855e3e19SSonny Jiang 567*855e3e19SSonny Jiang if (state == AMD_PG_STATE_GATE) 568*855e3e19SSonny Jiang ret = jpeg_v5_0_2_stop(adev); 569*855e3e19SSonny Jiang else 570*855e3e19SSonny Jiang ret = jpeg_v5_0_2_start(adev); 571*855e3e19SSonny Jiang 572*855e3e19SSonny Jiang if (!ret) 573*855e3e19SSonny Jiang adev->jpeg.cur_state = state; 574*855e3e19SSonny Jiang 575*855e3e19SSonny Jiang return ret; 576*855e3e19SSonny Jiang } 577*855e3e19SSonny Jiang 578*855e3e19SSonny Jiang static int jpeg_v5_0_2_set_interrupt_state(struct amdgpu_device *adev, 579*855e3e19SSonny Jiang struct amdgpu_irq_src *source, 580*855e3e19SSonny Jiang unsigned int type, 581*855e3e19SSonny Jiang enum amdgpu_interrupt_state state) 582*855e3e19SSonny Jiang { 583*855e3e19SSonny Jiang return 0; 584*855e3e19SSonny Jiang } 585*855e3e19SSonny Jiang 586*855e3e19SSonny Jiang static int jpeg_v5_0_2_process_interrupt(struct amdgpu_device *adev, 587*855e3e19SSonny Jiang struct amdgpu_irq_src *source, 588*855e3e19SSonny Jiang struct amdgpu_iv_entry *entry) 589*855e3e19SSonny Jiang { 590*855e3e19SSonny Jiang u32 i, inst; 591*855e3e19SSonny Jiang 592*855e3e19SSonny Jiang i = node_id_to_phys_map[entry->node_id]; 593*855e3e19SSonny Jiang DRM_DEV_DEBUG(adev->dev, "IH: JPEG TRAP\n"); 594*855e3e19SSonny Jiang 595*855e3e19SSonny Jiang for (inst = 0; inst < adev->jpeg.num_jpeg_inst; ++inst) 596*855e3e19SSonny Jiang if (adev->jpeg.inst[inst].aid_id == i) 597*855e3e19SSonny Jiang break; 598*855e3e19SSonny Jiang 599*855e3e19SSonny Jiang if (inst >= adev->jpeg.num_jpeg_inst) { 600*855e3e19SSonny Jiang dev_WARN_ONCE(adev->dev, 1, 601*855e3e19SSonny Jiang "Interrupt received for unknown JPEG instance %d", 602*855e3e19SSonny Jiang entry->node_id); 603*855e3e19SSonny Jiang return 0; 604*855e3e19SSonny Jiang } 605*855e3e19SSonny Jiang 606*855e3e19SSonny Jiang switch (entry->src_id) { 607*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG_DECODE: 608*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[0]); 609*855e3e19SSonny Jiang break; 610*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG1_DECODE: 611*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[1]); 612*855e3e19SSonny Jiang break; 613*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG2_DECODE: 614*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[2]); 615*855e3e19SSonny Jiang break; 616*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG3_DECODE: 617*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[3]); 618*855e3e19SSonny Jiang break; 619*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG4_DECODE: 620*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[4]); 621*855e3e19SSonny Jiang break; 622*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG5_DECODE: 623*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[5]); 624*855e3e19SSonny Jiang break; 625*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG6_DECODE: 626*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[6]); 627*855e3e19SSonny Jiang break; 628*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG7_DECODE: 629*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[7]); 630*855e3e19SSonny Jiang break; 631*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG8_DECODE: 632*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[8]); 633*855e3e19SSonny Jiang break; 634*855e3e19SSonny Jiang case VCN_5_0__SRCID__JPEG9_DECODE: 635*855e3e19SSonny Jiang amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[9]); 636*855e3e19SSonny Jiang break; 637*855e3e19SSonny Jiang default: 638*855e3e19SSonny Jiang DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n", 639*855e3e19SSonny Jiang entry->src_id, entry->src_data[0]); 640*855e3e19SSonny Jiang break; 641*855e3e19SSonny Jiang } 642*855e3e19SSonny Jiang 643*855e3e19SSonny Jiang return 0; 644*855e3e19SSonny Jiang } 645*855e3e19SSonny Jiang 646*855e3e19SSonny Jiang static void jpeg_v5_0_2_core_stall_reset(struct amdgpu_ring *ring) 647*855e3e19SSonny Jiang { 648*855e3e19SSonny Jiang struct amdgpu_device *adev = ring->adev; 649*855e3e19SSonny Jiang int jpeg_inst = GET_INST(JPEG, ring->me); 650*855e3e19SSonny Jiang int reg_offset = ring->pipe ? jpeg_v5_0_2_core_reg_offset(ring->pipe) : 0; 651*855e3e19SSonny Jiang 652*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 653*855e3e19SSonny Jiang regUVD_JMI0_UVD_JMI_CLIENT_STALL, 654*855e3e19SSonny Jiang reg_offset, 0x1F); 655*855e3e19SSonny Jiang SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst, 656*855e3e19SSonny Jiang regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS, 657*855e3e19SSonny Jiang reg_offset, 0x1F, 0x1F); 658*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 659*855e3e19SSonny Jiang regUVD_JMI0_JPEG_LMI_DROP, 660*855e3e19SSonny Jiang reg_offset, 0x1F); 661*855e3e19SSonny Jiang WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe); 662*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 663*855e3e19SSonny Jiang regUVD_JMI0_UVD_JMI_CLIENT_STALL, 664*855e3e19SSonny Jiang reg_offset, 0x00); 665*855e3e19SSonny Jiang WREG32_SOC15_OFFSET(JPEG, jpeg_inst, 666*855e3e19SSonny Jiang regUVD_JMI0_JPEG_LMI_DROP, 667*855e3e19SSonny Jiang reg_offset, 0x00); 668*855e3e19SSonny Jiang WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00); 669*855e3e19SSonny Jiang } 670*855e3e19SSonny Jiang 671*855e3e19SSonny Jiang static int jpeg_v5_0_2_ring_reset(struct amdgpu_ring *ring, 672*855e3e19SSonny Jiang unsigned int vmid, 673*855e3e19SSonny Jiang struct amdgpu_fence *timedout_fence) 674*855e3e19SSonny Jiang { 675*855e3e19SSonny Jiang amdgpu_ring_reset_helper_begin(ring, timedout_fence); 676*855e3e19SSonny Jiang jpeg_v5_0_2_core_stall_reset(ring); 677*855e3e19SSonny Jiang jpeg_v5_0_2_init_jrbc(ring); 678*855e3e19SSonny Jiang return amdgpu_ring_reset_helper_end(ring, timedout_fence); 679*855e3e19SSonny Jiang } 680*855e3e19SSonny Jiang 681*855e3e19SSonny Jiang static const struct amd_ip_funcs jpeg_v5_0_2_ip_funcs = { 682*855e3e19SSonny Jiang .name = "jpeg_v5_0_2", 683*855e3e19SSonny Jiang .early_init = jpeg_v5_0_2_early_init, 684*855e3e19SSonny Jiang .late_init = NULL, 685*855e3e19SSonny Jiang .sw_init = jpeg_v5_0_2_sw_init, 686*855e3e19SSonny Jiang .sw_fini = jpeg_v5_0_2_sw_fini, 687*855e3e19SSonny Jiang .hw_init = jpeg_v5_0_2_hw_init, 688*855e3e19SSonny Jiang .hw_fini = jpeg_v5_0_2_hw_fini, 689*855e3e19SSonny Jiang .suspend = jpeg_v5_0_2_suspend, 690*855e3e19SSonny Jiang .resume = jpeg_v5_0_2_resume, 691*855e3e19SSonny Jiang .is_idle = jpeg_v5_0_2_is_idle, 692*855e3e19SSonny Jiang .wait_for_idle = jpeg_v5_0_2_wait_for_idle, 693*855e3e19SSonny Jiang .check_soft_reset = NULL, 694*855e3e19SSonny Jiang .pre_soft_reset = NULL, 695*855e3e19SSonny Jiang .soft_reset = NULL, 696*855e3e19SSonny Jiang .post_soft_reset = NULL, 697*855e3e19SSonny Jiang .set_clockgating_state = jpeg_v5_0_2_set_clockgating_state, 698*855e3e19SSonny Jiang .set_powergating_state = jpeg_v5_0_2_set_powergating_state, 699*855e3e19SSonny Jiang .dump_ip_state = amdgpu_jpeg_dump_ip_state, 700*855e3e19SSonny Jiang .print_ip_state = amdgpu_jpeg_print_ip_state, 701*855e3e19SSonny Jiang }; 702*855e3e19SSonny Jiang 703*855e3e19SSonny Jiang static const struct amdgpu_ring_funcs jpeg_v5_0_2_dec_ring_vm_funcs = { 704*855e3e19SSonny Jiang .type = AMDGPU_RING_TYPE_VCN_JPEG, 705*855e3e19SSonny Jiang .align_mask = 0xf, 706*855e3e19SSonny Jiang .get_rptr = jpeg_v5_0_2_dec_ring_get_rptr, 707*855e3e19SSonny Jiang .get_wptr = jpeg_v5_0_2_dec_ring_get_wptr, 708*855e3e19SSonny Jiang .set_wptr = jpeg_v5_0_2_dec_ring_set_wptr, 709*855e3e19SSonny Jiang .emit_frame_size = 710*855e3e19SSonny Jiang SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + 711*855e3e19SSonny Jiang SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + 712*855e3e19SSonny Jiang 8 + /* jpeg_v5_0_2_dec_ring_emit_vm_flush */ 713*855e3e19SSonny Jiang 22 + 22 + /* jpeg_v5_0_2_dec_ring_emit_fence x2 vm fence */ 714*855e3e19SSonny Jiang 8 + 16, 715*855e3e19SSonny Jiang .emit_ib_size = 22, /* jpeg_v5_0_2_dec_ring_emit_ib */ 716*855e3e19SSonny Jiang .emit_ib = jpeg_v4_0_3_dec_ring_emit_ib, 717*855e3e19SSonny Jiang .emit_fence = jpeg_v4_0_3_dec_ring_emit_fence, 718*855e3e19SSonny Jiang .emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush, 719*855e3e19SSonny Jiang .emit_hdp_flush = jpeg_v4_0_3_ring_emit_hdp_flush, 720*855e3e19SSonny Jiang .test_ring = amdgpu_jpeg_dec_ring_test_ring, 721*855e3e19SSonny Jiang .test_ib = amdgpu_jpeg_dec_ring_test_ib, 722*855e3e19SSonny Jiang .insert_nop = jpeg_v4_0_3_dec_ring_nop, 723*855e3e19SSonny Jiang .insert_start = jpeg_v4_0_3_dec_ring_insert_start, 724*855e3e19SSonny Jiang .insert_end = jpeg_v4_0_3_dec_ring_insert_end, 725*855e3e19SSonny Jiang .pad_ib = amdgpu_ring_generic_pad_ib, 726*855e3e19SSonny Jiang .begin_use = amdgpu_jpeg_ring_begin_use, 727*855e3e19SSonny Jiang .end_use = amdgpu_jpeg_ring_end_use, 728*855e3e19SSonny Jiang .emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg, 729*855e3e19SSonny Jiang .emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait, 730*855e3e19SSonny Jiang .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, 731*855e3e19SSonny Jiang .reset = jpeg_v5_0_2_ring_reset, 732*855e3e19SSonny Jiang }; 733*855e3e19SSonny Jiang 734*855e3e19SSonny Jiang static void jpeg_v5_0_2_set_dec_ring_funcs(struct amdgpu_device *adev) 735*855e3e19SSonny Jiang { 736*855e3e19SSonny Jiang int i, j, jpeg_inst; 737*855e3e19SSonny Jiang 738*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 739*855e3e19SSonny Jiang for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 740*855e3e19SSonny Jiang adev->jpeg.inst[i].ring_dec[j].funcs = &jpeg_v5_0_2_dec_ring_vm_funcs; 741*855e3e19SSonny Jiang adev->jpeg.inst[i].ring_dec[j].me = i; 742*855e3e19SSonny Jiang adev->jpeg.inst[i].ring_dec[j].pipe = j; 743*855e3e19SSonny Jiang } 744*855e3e19SSonny Jiang jpeg_inst = GET_INST(JPEG, i); 745*855e3e19SSonny Jiang adev->jpeg.inst[i].aid_id = 746*855e3e19SSonny Jiang jpeg_inst / adev->jpeg.num_inst_per_aid; 747*855e3e19SSonny Jiang } 748*855e3e19SSonny Jiang } 749*855e3e19SSonny Jiang 750*855e3e19SSonny Jiang static const struct amdgpu_irq_src_funcs jpeg_v5_0_2_irq_funcs = { 751*855e3e19SSonny Jiang .set = jpeg_v5_0_2_set_interrupt_state, 752*855e3e19SSonny Jiang .process = jpeg_v5_0_2_process_interrupt, 753*855e3e19SSonny Jiang }; 754*855e3e19SSonny Jiang 755*855e3e19SSonny Jiang static void jpeg_v5_0_2_set_irq_funcs(struct amdgpu_device *adev) 756*855e3e19SSonny Jiang { 757*855e3e19SSonny Jiang int i; 758*855e3e19SSonny Jiang 759*855e3e19SSonny Jiang for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) 760*855e3e19SSonny Jiang adev->jpeg.inst->irq.num_types += adev->jpeg.num_jpeg_rings; 761*855e3e19SSonny Jiang 762*855e3e19SSonny Jiang adev->jpeg.inst->irq.funcs = &jpeg_v5_0_2_irq_funcs; 763*855e3e19SSonny Jiang } 764*855e3e19SSonny Jiang 765*855e3e19SSonny Jiang const struct amdgpu_ip_block_version jpeg_v5_0_2_ip_block = { 766*855e3e19SSonny Jiang .type = AMD_IP_BLOCK_TYPE_JPEG, 767*855e3e19SSonny Jiang .major = 5, 768*855e3e19SSonny Jiang .minor = 0, 769*855e3e19SSonny Jiang .rev = 2, 770*855e3e19SSonny Jiang .funcs = &jpeg_v5_0_2_ip_funcs, 771*855e3e19SSonny Jiang }; 772*855e3e19SSonny Jiang 773*855e3e19SSonny Jiang #if 0 774*855e3e19SSonny Jiang static int jpeg_v5_0_2_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, 775*855e3e19SSonny Jiang enum aca_smu_type type, void *data) 776*855e3e19SSonny Jiang { 777*855e3e19SSonny Jiang struct aca_bank_info info; 778*855e3e19SSonny Jiang u64 misc0; 779*855e3e19SSonny Jiang int ret; 780*855e3e19SSonny Jiang 781*855e3e19SSonny Jiang ret = aca_bank_info_decode(bank, &info); 782*855e3e19SSonny Jiang if (ret) 783*855e3e19SSonny Jiang return ret; 784*855e3e19SSonny Jiang 785*855e3e19SSonny Jiang misc0 = bank->regs[ACA_REG_IDX_MISC0]; 786*855e3e19SSonny Jiang switch (type) { 787*855e3e19SSonny Jiang case ACA_SMU_TYPE_UE: 788*855e3e19SSonny Jiang bank->aca_err_type = ACA_ERROR_TYPE_UE; 789*855e3e19SSonny Jiang ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_UE, 790*855e3e19SSonny Jiang 1ULL); 791*855e3e19SSonny Jiang break; 792*855e3e19SSonny Jiang case ACA_SMU_TYPE_CE: 793*855e3e19SSonny Jiang bank->aca_err_type = ACA_ERROR_TYPE_CE; 794*855e3e19SSonny Jiang ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, 795*855e3e19SSonny Jiang ACA_REG__MISC0__ERRCNT(misc0)); 796*855e3e19SSonny Jiang break; 797*855e3e19SSonny Jiang default: 798*855e3e19SSonny Jiang return -EINVAL; 799*855e3e19SSonny Jiang } 800*855e3e19SSonny Jiang 801*855e3e19SSonny Jiang return ret; 802*855e3e19SSonny Jiang } 803*855e3e19SSonny Jiang 804*855e3e19SSonny Jiang /* reference to smu driver if header file */ 805*855e3e19SSonny Jiang static int jpeg_v5_0_2_err_codes[] = { 806*855e3e19SSonny Jiang 16, 17, 18, 19, 20, 21, 22, 23, /* JPEG[0-9][S|D] */ 807*855e3e19SSonny Jiang 24, 25, 26, 27, 28, 29, 30, 31, 808*855e3e19SSonny Jiang 48, 49, 50, 51, 809*855e3e19SSonny Jiang }; 810*855e3e19SSonny Jiang 811*855e3e19SSonny Jiang static bool jpeg_v5_0_2_aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, 812*855e3e19SSonny Jiang enum aca_smu_type type, void *data) 813*855e3e19SSonny Jiang { 814*855e3e19SSonny Jiang u32 instlo; 815*855e3e19SSonny Jiang 816*855e3e19SSonny Jiang instlo = ACA_REG__IPID__INSTANCEIDLO(bank->regs[ACA_REG_IDX_IPID]); 817*855e3e19SSonny Jiang instlo &= GENMASK(31, 1); 818*855e3e19SSonny Jiang 819*855e3e19SSonny Jiang if (instlo != mmSMNAID_AID0_MCA_SMU) 820*855e3e19SSonny Jiang return false; 821*855e3e19SSonny Jiang 822*855e3e19SSonny Jiang if (aca_bank_check_error_codes(handle->adev, bank, 823*855e3e19SSonny Jiang jpeg_v5_0_2_err_codes, 824*855e3e19SSonny Jiang ARRAY_SIZE(jpeg_v5_0_2_err_codes))) 825*855e3e19SSonny Jiang return false; 826*855e3e19SSonny Jiang 827*855e3e19SSonny Jiang return true; 828*855e3e19SSonny Jiang } 829*855e3e19SSonny Jiang 830*855e3e19SSonny Jiang static const struct aca_bank_ops jpeg_v5_0_2_aca_bank_ops = { 831*855e3e19SSonny Jiang .aca_bank_parser = jpeg_v5_0_2_aca_bank_parser, 832*855e3e19SSonny Jiang .aca_bank_is_valid = jpeg_v5_0_2_aca_bank_is_valid, 833*855e3e19SSonny Jiang }; 834*855e3e19SSonny Jiang 835*855e3e19SSonny Jiang static const struct aca_info jpeg_v5_0_2_aca_info = { 836*855e3e19SSonny Jiang .hwip = ACA_HWIP_TYPE_SMU, 837*855e3e19SSonny Jiang .mask = ACA_ERROR_UE_MASK, 838*855e3e19SSonny Jiang .bank_ops = &jpeg_v5_0_2_aca_bank_ops, 839*855e3e19SSonny Jiang }; 840*855e3e19SSonny Jiang #endif 841