833 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 */23 24#include "amdgpu.h"25#include "amdgpu_jpeg.h"26#include "amdgpu_pm.h"27#include "soc15.h"28#include "soc15d.h"29#include "jpeg_v2_0.h"30#include "jpeg_v4_0_5.h"31#include "mmsch_v4_0.h"32 33#include "vcn/vcn_4_0_5_offset.h"34#include "vcn/vcn_4_0_5_sh_mask.h"35#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"36 37#define mmUVD_DPG_LMA_CTL regUVD_DPG_LMA_CTL38#define mmUVD_DPG_LMA_CTL_BASE_IDX regUVD_DPG_LMA_CTL_BASE_IDX39#define mmUVD_DPG_LMA_DATA regUVD_DPG_LMA_DATA40#define mmUVD_DPG_LMA_DATA_BASE_IDX regUVD_DPG_LMA_DATA_BASE_IDX41 42#define regUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f43#define regJPEG_DEC_GFX10_ADDR_CONFIG_INTERNAL_OFFSET 0x402644#define regJPEG_SYS_INT_EN_INTERNAL_OFFSET 0x414145#define regJPEG_CGC_CTRL_INTERNAL_OFFSET 0x416146#define regJPEG_CGC_GATE_INTERNAL_OFFSET 0x416047#define regUVD_NO_OP_INTERNAL_OFFSET 0x002948 49static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev);50static void jpeg_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);51static int jpeg_v4_0_5_set_powergating_state(void *handle,52 enum amd_powergating_state state);53 54static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring);55 56static int amdgpu_ih_clientid_jpeg[] = {57 SOC15_IH_CLIENTID_VCN,58 SOC15_IH_CLIENTID_VCN159};60 61/**62 * jpeg_v4_0_5_early_init - set function pointers63 *64 * @handle: amdgpu_device pointer65 *66 * Set ring and irq function pointers67 */68static int jpeg_v4_0_5_early_init(void *handle)69{70 struct amdgpu_device *adev = (struct amdgpu_device *)handle;71 72 switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) {73 case IP_VERSION(4, 0, 5):74 adev->jpeg.num_jpeg_inst = 1;75 break;76 case IP_VERSION(4, 0, 6):77 adev->jpeg.num_jpeg_inst = 2;78 break;79 default:80 DRM_DEV_ERROR(adev->dev,81 "Failed to init vcn ip block(UVD_HWIP:0x%x)\n",82 amdgpu_ip_version(adev, UVD_HWIP, 0));83 return -EINVAL;84 }85 86 adev->jpeg.num_jpeg_rings = 1;87 88 jpeg_v4_0_5_set_dec_ring_funcs(adev);89 jpeg_v4_0_5_set_irq_funcs(adev);90 91 return 0;92}93 94/**95 * jpeg_v4_0_5_sw_init - sw init for JPEG block96 *97 * @handle: amdgpu_device pointer98 *99 * Load firmware and sw initialization100 */101static int jpeg_v4_0_5_sw_init(void *handle)102{103 struct amdgpu_device *adev = (struct amdgpu_device *)handle;104 struct amdgpu_ring *ring;105 int r, i;106 107 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {108 if (adev->jpeg.harvest_config & (1 << i))109 continue;110 111 /* JPEG TRAP */112 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],113 VCN_4_0__SRCID__JPEG_DECODE, &adev->jpeg.inst[i].irq);114 if (r)115 return r;116 117 /* JPEG DJPEG POISON EVENT */118 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],119 VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].irq);120 if (r)121 return r;122 123 /* JPEG EJPEG POISON EVENT */124 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],125 VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].irq);126 if (r)127 return r;128 }129 130 r = amdgpu_jpeg_sw_init(adev);131 if (r)132 return r;133 134 r = amdgpu_jpeg_resume(adev);135 if (r)136 return r;137 138 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {139 if (adev->jpeg.harvest_config & (1 << i))140 continue;141 142 ring = adev->jpeg.inst[i].ring_dec;143 ring->use_doorbell = true;144 ring->vm_hub = AMDGPU_MMHUB0(0);145 ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;146 sprintf(ring->name, "jpeg_dec_%d", i);147 r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq,148 0, AMDGPU_RING_PRIO_DEFAULT, NULL);149 if (r)150 return r;151 152 adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;153 adev->jpeg.inst[i].external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, i, regUVD_JPEG_PITCH);154 }155 156 return 0;157}158 159/**160 * jpeg_v4_0_5_sw_fini - sw fini for JPEG block161 *162 * @handle: amdgpu_device pointer163 *164 * JPEG suspend and free up sw allocation165 */166static int jpeg_v4_0_5_sw_fini(void *handle)167{168 struct amdgpu_device *adev = (struct amdgpu_device *)handle;169 int r;170 171 r = amdgpu_jpeg_suspend(adev);172 if (r)173 return r;174 175 r = amdgpu_jpeg_sw_fini(adev);176 177 return r;178}179 180/**181 * jpeg_v4_0_5_hw_init - start and test JPEG block182 *183 * @handle: amdgpu_device pointer184 *185 */186static int jpeg_v4_0_5_hw_init(void *handle)187{188 struct amdgpu_device *adev = (struct amdgpu_device *)handle;189 struct amdgpu_ring *ring;190 int i, r = 0;191 192 // TODO: Enable ring test with DPG support193 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {194 return 0;195 }196 197 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {198 if (adev->jpeg.harvest_config & (1 << i))199 continue;200 201 ring = adev->jpeg.inst[i].ring_dec;202 r = amdgpu_ring_test_helper(ring);203 if (r)204 return r;205 }206 207 return 0;208}209 210/**211 * jpeg_v4_0_5_hw_fini - stop the hardware block212 *213 * @handle: amdgpu_device pointer214 *215 * Stop the JPEG block, mark ring as not ready any more216 */217static int jpeg_v4_0_5_hw_fini(void *handle)218{219 struct amdgpu_device *adev = (struct amdgpu_device *)handle;220 int i;221 222 cancel_delayed_work_sync(&adev->vcn.idle_work);223 224 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {225 if (adev->jpeg.harvest_config & (1 << i))226 continue;227 228 if (!amdgpu_sriov_vf(adev)) {229 if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&230 RREG32_SOC15(JPEG, i, regUVD_JRBC_STATUS))231 jpeg_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE);232 }233 }234 return 0;235}236 237/**238 * jpeg_v4_0_5_suspend - suspend JPEG block239 *240 * @handle: amdgpu_device pointer241 *242 * HW fini and suspend JPEG block243 */244static int jpeg_v4_0_5_suspend(void *handle)245{246 struct amdgpu_device *adev = (struct amdgpu_device *)handle;247 int r;248 249 r = jpeg_v4_0_5_hw_fini(adev);250 if (r)251 return r;252 253 r = amdgpu_jpeg_suspend(adev);254 255 return r;256}257 258/**259 * jpeg_v4_0_5_resume - resume JPEG block260 *261 * @handle: amdgpu_device pointer262 *263 * Resume firmware and hw init JPEG block264 */265static int jpeg_v4_0_5_resume(void *handle)266{267 struct amdgpu_device *adev = (struct amdgpu_device *)handle;268 int r;269 270 r = amdgpu_jpeg_resume(adev);271 if (r)272 return r;273 274 r = jpeg_v4_0_5_hw_init(adev);275 276 return r;277}278 279static void jpeg_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst)280{281 uint32_t data = 0;282 283 data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL);284 if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {285 data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;286 data &= (~JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK);287 } else {288 data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;289 }290 291 data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;292 data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;293 WREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL, data);294 295 data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE);296 data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK297 | JPEG_CGC_GATE__JPEG2_DEC_MASK298 | JPEG_CGC_GATE__JMCIF_MASK299 | JPEG_CGC_GATE__JRBBM_MASK);300 WREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE, data);301}302 303static void jpeg_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)304{305 uint32_t data = 0;306 307 data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL);308 if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {309 data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;310 data |= JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK;311 } else {312 data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;313 }314 315 data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;316 data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;317 WREG32_SOC15(JPEG, inst, regJPEG_CGC_CTRL, data);318 319 data = RREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE);320 data |= (JPEG_CGC_GATE__JPEG_DEC_MASK321 |JPEG_CGC_GATE__JPEG2_DEC_MASK322 |JPEG_CGC_GATE__JMCIF_MASK323 |JPEG_CGC_GATE__JRBBM_MASK);324 WREG32_SOC15(JPEG, inst, regJPEG_CGC_GATE, data);325}326 327static void jpeg_engine_4_0_5_dpg_clock_gating_mode(struct amdgpu_device *adev,328 int inst_idx, uint8_t indirect)329{330 uint32_t data = 0;331 332 if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)333 data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;334 else335 data |= 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;336 337 data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;338 data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;339 WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_CGC_CTRL_INTERNAL_OFFSET, data, indirect);340 341 data = 0;342 WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_CGC_GATE_INTERNAL_OFFSET,343 data, indirect);344}345 346static int jpeg_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst)347{348 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {349 WREG32(SOC15_REG_OFFSET(JPEG, inst, regUVD_IPX_DLDO_CONFIG),350 1 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT);351 SOC15_WAIT_ON_RREG(JPEG, inst, regUVD_IPX_DLDO_STATUS,352 0, UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);353 }354 355 /* disable anti hang mechanism */356 WREG32_P(SOC15_REG_OFFSET(JPEG, inst, regUVD_JPEG_POWER_STATUS), 0,357 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);358 359 /* keep the JPEG in static PG mode */360 WREG32_P(SOC15_REG_OFFSET(JPEG, inst, regUVD_JPEG_POWER_STATUS), 0,361 ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);362 363 return 0;364}365 366static int jpeg_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst)367{368 /* enable anti hang mechanism */369 WREG32_P(SOC15_REG_OFFSET(JPEG, inst, regUVD_JPEG_POWER_STATUS),370 UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,371 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);372 373 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {374 WREG32(SOC15_REG_OFFSET(JPEG, inst, regUVD_IPX_DLDO_CONFIG),375 2 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT);376 SOC15_WAIT_ON_RREG(JPEG, inst, regUVD_IPX_DLDO_STATUS,377 1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT,378 UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);379 }380 381 return 0;382}383 384/**385 * jpeg_v4_0_5_start_dpg_mode - Jpeg start with dpg mode386 *387 * @adev: amdgpu_device pointer388 * @inst_idx: instance number index389 * @indirect: indirectly write sram390 *391 * Start JPEG block with dpg mode392 */393static void jpeg_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)394{395 struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec;396 uint32_t reg_data = 0;397 398 /* enable anti hang mechanism */399 reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);400 reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK;401 reg_data |= 0x1;402 WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);403 404 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {405 WREG32(SOC15_REG_OFFSET(JPEG, inst_idx, regUVD_IPX_DLDO_CONFIG),406 2 << UVD_IPX_DLDO_CONFIG__ONO1_PWR_CONFIG__SHIFT);407 SOC15_WAIT_ON_RREG(JPEG, inst_idx, regUVD_IPX_DLDO_STATUS,408 1 << UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS__SHIFT,409 UVD_IPX_DLDO_STATUS__ONO1_PWR_STATUS_MASK);410 }411 412 reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);413 reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;414 WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);415 416 if (indirect)417 adev->jpeg.inst[inst_idx].dpg_sram_curr_addr =418 (uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr;419 420 jpeg_engine_4_0_5_dpg_clock_gating_mode(adev, inst_idx, indirect);421 422 /* MJPEG global tiling registers */423 WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_DEC_GFX10_ADDR_CONFIG_INTERNAL_OFFSET,424 adev->gfx.config.gb_addr_config, indirect);425 /* enable System Interrupt for JRBC */426 WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regJPEG_SYS_INT_EN_INTERNAL_OFFSET,427 JPEG_SYS_INT_EN__DJRBC_MASK, indirect);428 429 /* add nop to workaround PSP size check */430 WREG32_SOC15_JPEG_DPG_MODE(inst_idx, regUVD_NO_OP_INTERNAL_OFFSET, 0, indirect);431 432 if (indirect)433 amdgpu_jpeg_psp_update_sram(adev, inst_idx, 0);434 435 WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0);436 WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));437 WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,438 lower_32_bits(ring->gpu_addr));439 WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,440 upper_32_bits(ring->gpu_addr));441 WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_RPTR, 0);442 WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR, 0);443 WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, 0x00000002L);444 WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);445 ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR);446}447 448/**449 * jpeg_v4_0_5_stop_dpg_mode - Jpeg stop with dpg mode450 *451 * @adev: amdgpu_device pointer452 * @inst_idx: instance number index453 *454 * Stop JPEG block with dpg mode455 */456static void jpeg_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)457{458 uint32_t reg_data = 0;459 460 reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);461 reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;462 WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);463 464}465 466/**467 * jpeg_v4_0_5_start - start JPEG block468 *469 * @adev: amdgpu_device pointer470 *471 * Setup and start the JPEG block472 */473static int jpeg_v4_0_5_start(struct amdgpu_device *adev)474{475 struct amdgpu_ring *ring;476 int r, i;477 478 if (adev->pm.dpm_enabled)479 amdgpu_dpm_enable_jpeg(adev, true);480 481 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {482 if (adev->jpeg.harvest_config & (1 << i))483 continue;484 485 ring = adev->jpeg.inst[i].ring_dec;486 /* doorbell programming is done for every playback */487 adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,488 (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i);489 490 WREG32_SOC15(VCN, i, regVCN_JPEG_DB_CTRL,491 ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |492 VCN_JPEG_DB_CTRL__EN_MASK);493 494 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {495 jpeg_v4_0_5_start_dpg_mode(adev, i, adev->jpeg.indirect_sram);496 continue;497 }498 499 /* disable power gating */500 r = jpeg_v4_0_5_disable_static_power_gating(adev, i);501 if (r)502 return r;503 504 /* JPEG disable CGC */505 jpeg_v4_0_5_disable_clock_gating(adev, i);506 507 /* MJPEG global tiling registers */508 WREG32_SOC15(JPEG, i, regJPEG_DEC_GFX10_ADDR_CONFIG,509 adev->gfx.config.gb_addr_config);510 511 /* enable JMI channel */512 WREG32_P(SOC15_REG_OFFSET(JPEG, i, regUVD_JMI_CNTL), 0,513 ~UVD_JMI_CNTL__SOFT_RESET_MASK);514 515 /* enable System Interrupt for JRBC */516 WREG32_P(SOC15_REG_OFFSET(JPEG, i, regJPEG_SYS_INT_EN),517 JPEG_SYS_INT_EN__DJRBC_MASK,518 ~JPEG_SYS_INT_EN__DJRBC_MASK);519 520 WREG32_SOC15(JPEG, i, regUVD_LMI_JRBC_RB_VMID, 0);521 WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));522 WREG32_SOC15(JPEG, i, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,523 lower_32_bits(ring->gpu_addr));524 WREG32_SOC15(JPEG, i, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,525 upper_32_bits(ring->gpu_addr));526 WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_RPTR, 0);527 WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_WPTR, 0);528 WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_CNTL, 0x00000002L);529 WREG32_SOC15(JPEG, i, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);530 ring->wptr = RREG32_SOC15(JPEG, i, regUVD_JRBC_RB_WPTR);531 }532 533 return 0;534}535 536/**537 * jpeg_v4_0_5_stop - stop JPEG block538 *539 * @adev: amdgpu_device pointer540 *541 * stop the JPEG block542 */543static int jpeg_v4_0_5_stop(struct amdgpu_device *adev)544{545 int r, i;546 547 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {548 if (adev->jpeg.harvest_config & (1 << i))549 continue;550 551 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {552 jpeg_v4_0_5_stop_dpg_mode(adev, i);553 continue;554 }555 556 /* reset JMI */557 WREG32_P(SOC15_REG_OFFSET(JPEG, i, regUVD_JMI_CNTL),558 UVD_JMI_CNTL__SOFT_RESET_MASK,559 ~UVD_JMI_CNTL__SOFT_RESET_MASK);560 561 jpeg_v4_0_5_enable_clock_gating(adev, i);562 563 /* enable power gating */564 r = jpeg_v4_0_5_enable_static_power_gating(adev, i);565 if (r)566 return r;567 }568 if (adev->pm.dpm_enabled)569 amdgpu_dpm_enable_jpeg(adev, false);570 571 return 0;572}573 574/**575 * jpeg_v4_0_5_dec_ring_get_rptr - get read pointer576 *577 * @ring: amdgpu_ring pointer578 *579 * Returns the current hardware read pointer580 */581static uint64_t jpeg_v4_0_5_dec_ring_get_rptr(struct amdgpu_ring *ring)582{583 struct amdgpu_device *adev = ring->adev;584 585 return RREG32_SOC15(JPEG, ring->me, regUVD_JRBC_RB_RPTR);586}587 588/**589 * jpeg_v4_0_5_dec_ring_get_wptr - get write pointer590 *591 * @ring: amdgpu_ring pointer592 *593 * Returns the current hardware write pointer594 */595static uint64_t jpeg_v4_0_5_dec_ring_get_wptr(struct amdgpu_ring *ring)596{597 struct amdgpu_device *adev = ring->adev;598 599 if (ring->use_doorbell)600 return *ring->wptr_cpu_addr;601 else602 return RREG32_SOC15(JPEG, ring->me, regUVD_JRBC_RB_WPTR);603}604 605/**606 * jpeg_v4_0_5_dec_ring_set_wptr - set write pointer607 *608 * @ring: amdgpu_ring pointer609 *610 * Commits the write pointer to the hardware611 */612static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring)613{614 struct amdgpu_device *adev = ring->adev;615 616 if (ring->use_doorbell) {617 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);618 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));619 } else {620 WREG32_SOC15(JPEG, ring->me, regUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));621 }622}623 624static bool jpeg_v4_0_5_is_idle(void *handle)625{626 struct amdgpu_device *adev = (struct amdgpu_device *)handle;627 int i, ret = 1;628 629 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {630 if (adev->jpeg.harvest_config & (1 << i))631 continue;632 633 ret &= (((RREG32_SOC15(JPEG, i, regUVD_JRBC_STATUS) &634 UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==635 UVD_JRBC_STATUS__RB_JOB_DONE_MASK));636 }637 return ret;638}639 640static int jpeg_v4_0_5_wait_for_idle(void *handle)641{642 struct amdgpu_device *adev = (struct amdgpu_device *)handle;643 int i;644 645 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {646 if (adev->jpeg.harvest_config & (1 << i))647 continue;648 649 return SOC15_WAIT_ON_RREG(JPEG, i, regUVD_JRBC_STATUS,650 UVD_JRBC_STATUS__RB_JOB_DONE_MASK,651 UVD_JRBC_STATUS__RB_JOB_DONE_MASK);652 }653 654 return 0;655}656 657static int jpeg_v4_0_5_set_clockgating_state(void *handle,658 enum amd_clockgating_state state)659{660 struct amdgpu_device *adev = (struct amdgpu_device *)handle;661 bool enable = (state == AMD_CG_STATE_GATE) ? true : false;662 int i;663 664 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {665 if (adev->jpeg.harvest_config & (1 << i))666 continue;667 668 if (enable) {669 if (!jpeg_v4_0_5_is_idle(handle))670 return -EBUSY;671 672 jpeg_v4_0_5_enable_clock_gating(adev, i);673 } else {674 jpeg_v4_0_5_disable_clock_gating(adev, i);675 }676 }677 678 return 0;679}680 681static int jpeg_v4_0_5_set_powergating_state(void *handle,682 enum amd_powergating_state state)683{684 struct amdgpu_device *adev = (struct amdgpu_device *)handle;685 int ret;686 687 if (amdgpu_sriov_vf(adev)) {688 adev->jpeg.cur_state = AMD_PG_STATE_UNGATE;689 return 0;690 }691 692 if (state == adev->jpeg.cur_state)693 return 0;694 695 if (state == AMD_PG_STATE_GATE)696 ret = jpeg_v4_0_5_stop(adev);697 else698 ret = jpeg_v4_0_5_start(adev);699 700 if (!ret)701 adev->jpeg.cur_state = state;702 703 return ret;704}705 706static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev,707 struct amdgpu_irq_src *source,708 struct amdgpu_iv_entry *entry)709{710 uint32_t ip_instance;711 712 DRM_DEBUG("IH: JPEG TRAP\n");713 714 switch (entry->client_id) {715 case SOC15_IH_CLIENTID_VCN:716 ip_instance = 0;717 break;718 case SOC15_IH_CLIENTID_VCN1:719 ip_instance = 1;720 break;721 default:722 DRM_ERROR("Unhandled client id: %d\n", entry->client_id);723 return 0;724 }725 726 switch (entry->src_id) {727 case VCN_4_0__SRCID__JPEG_DECODE:728 amdgpu_fence_process(adev->jpeg.inst[ip_instance].ring_dec);729 break;730 case VCN_4_0__SRCID_DJPEG0_POISON:731 case VCN_4_0__SRCID_EJPEG0_POISON:732 amdgpu_jpeg_process_poison_irq(adev, source, entry);733 break;734 default:735 DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",736 entry->src_id, entry->src_data[0]);737 break;738 }739 740 return 0;741}742 743static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {744 .name = "jpeg_v4_0_5",745 .early_init = jpeg_v4_0_5_early_init,746 .late_init = NULL,747 .sw_init = jpeg_v4_0_5_sw_init,748 .sw_fini = jpeg_v4_0_5_sw_fini,749 .hw_init = jpeg_v4_0_5_hw_init,750 .hw_fini = jpeg_v4_0_5_hw_fini,751 .suspend = jpeg_v4_0_5_suspend,752 .resume = jpeg_v4_0_5_resume,753 .is_idle = jpeg_v4_0_5_is_idle,754 .wait_for_idle = jpeg_v4_0_5_wait_for_idle,755 .check_soft_reset = NULL,756 .pre_soft_reset = NULL,757 .soft_reset = NULL,758 .post_soft_reset = NULL,759 .set_clockgating_state = jpeg_v4_0_5_set_clockgating_state,760 .set_powergating_state = jpeg_v4_0_5_set_powergating_state,761 .dump_ip_state = NULL,762 .print_ip_state = NULL,763};764 765static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = {766 .type = AMDGPU_RING_TYPE_VCN_JPEG,767 .align_mask = 0xf,768 .get_rptr = jpeg_v4_0_5_dec_ring_get_rptr,769 .get_wptr = jpeg_v4_0_5_dec_ring_get_wptr,770 .set_wptr = jpeg_v4_0_5_dec_ring_set_wptr,771 .parse_cs = jpeg_v2_dec_ring_parse_cs,772 .emit_frame_size =773 SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +774 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +775 8 + /* jpeg_v4_0_5_dec_ring_emit_vm_flush */776 18 + 18 + /* jpeg_v4_0_5_dec_ring_emit_fence x2 vm fence */777 8 + 16,778 .emit_ib_size = 22, /* jpeg_v4_0_5_dec_ring_emit_ib */779 .emit_ib = jpeg_v2_0_dec_ring_emit_ib,780 .emit_fence = jpeg_v2_0_dec_ring_emit_fence,781 .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,782 .test_ring = amdgpu_jpeg_dec_ring_test_ring,783 .test_ib = amdgpu_jpeg_dec_ring_test_ib,784 .insert_nop = jpeg_v2_0_dec_ring_nop,785 .insert_start = jpeg_v2_0_dec_ring_insert_start,786 .insert_end = jpeg_v2_0_dec_ring_insert_end,787 .pad_ib = amdgpu_ring_generic_pad_ib,788 .begin_use = amdgpu_jpeg_ring_begin_use,789 .end_use = amdgpu_jpeg_ring_end_use,790 .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,791 .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,792 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,793};794 795static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)796{797 int i;798 799 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {800 if (adev->jpeg.harvest_config & (1 << i))801 continue;802 803 adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v4_0_5_dec_ring_vm_funcs;804 adev->jpeg.inst[i].ring_dec->me = i;805 }806}807 808static const struct amdgpu_irq_src_funcs jpeg_v4_0_5_irq_funcs = {809 .process = jpeg_v4_0_5_process_interrupt,810};811 812static void jpeg_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)813{814 int i;815 816 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {817 if (adev->jpeg.harvest_config & (1 << i))818 continue;819 820 adev->jpeg.inst[i].irq.num_types = 1;821 adev->jpeg.inst[i].irq.funcs = &jpeg_v4_0_5_irq_funcs;822 }823}824 825const struct amdgpu_ip_block_version jpeg_v4_0_5_ip_block = {826 .type = AMD_IP_BLOCK_TYPE_JPEG,827 .major = 4,828 .minor = 0,829 .rev = 5,830 .funcs = &jpeg_v4_0_5_ip_funcs,831};832 833