834 lines · c
1/*2 * Copyright 2019 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 "soc15.h"27#include "soc15d.h"28#include "jpeg_v2_0.h"29#include "jpeg_v2_5.h"30 31#include "vcn/vcn_2_5_offset.h"32#include "vcn/vcn_2_5_sh_mask.h"33#include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"34 35#define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f36 37#define JPEG25_MAX_HW_INSTANCES_ARCTURUS 238 39static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);40static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev);41static int jpeg_v2_5_set_powergating_state(void *handle,42 enum amd_powergating_state state);43static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev);44 45static int amdgpu_ih_clientid_jpeg[] = {46 SOC15_IH_CLIENTID_VCN,47 SOC15_IH_CLIENTID_VCN148};49 50/**51 * jpeg_v2_5_early_init - set function pointers52 *53 * @handle: amdgpu_device pointer54 *55 * Set ring and irq function pointers56 */57static int jpeg_v2_5_early_init(void *handle)58{59 struct amdgpu_device *adev = (struct amdgpu_device *)handle;60 u32 harvest;61 int i;62 63 adev->jpeg.num_jpeg_rings = 1;64 adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS;65 for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {66 harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING);67 if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)68 adev->jpeg.harvest_config |= 1 << i;69 }70 if (adev->jpeg.harvest_config == (AMDGPU_JPEG_HARVEST_JPEG0 |71 AMDGPU_JPEG_HARVEST_JPEG1))72 return -ENOENT;73 74 jpeg_v2_5_set_dec_ring_funcs(adev);75 jpeg_v2_5_set_irq_funcs(adev);76 jpeg_v2_5_set_ras_funcs(adev);77 78 return 0;79}80 81/**82 * jpeg_v2_5_sw_init - sw init for JPEG block83 *84 * @handle: amdgpu_device pointer85 *86 * Load firmware and sw initialization87 */88static int jpeg_v2_5_sw_init(void *handle)89{90 struct amdgpu_ring *ring;91 int i, r;92 struct amdgpu_device *adev = (struct amdgpu_device *)handle;93 94 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {95 if (adev->jpeg.harvest_config & (1 << i))96 continue;97 98 /* JPEG TRAP */99 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],100 VCN_2_0__SRCID__JPEG_DECODE, &adev->jpeg.inst[i].irq);101 if (r)102 return r;103 104 /* JPEG DJPEG POISON EVENT */105 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],106 VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq);107 if (r)108 return r;109 110 /* JPEG EJPEG POISON EVENT */111 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],112 VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq);113 if (r)114 return r;115 }116 117 r = amdgpu_jpeg_sw_init(adev);118 if (r)119 return r;120 121 r = amdgpu_jpeg_resume(adev);122 if (r)123 return r;124 125 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {126 if (adev->jpeg.harvest_config & (1 << i))127 continue;128 129 ring = adev->jpeg.inst[i].ring_dec;130 ring->use_doorbell = true;131 if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(2, 5, 0))132 ring->vm_hub = AMDGPU_MMHUB1(0);133 else134 ring->vm_hub = AMDGPU_MMHUB0(0);135 ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;136 sprintf(ring->name, "jpeg_dec_%d", i);137 r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq,138 0, AMDGPU_RING_PRIO_DEFAULT, NULL);139 if (r)140 return r;141 142 adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;143 adev->jpeg.inst[i].external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);144 }145 146 r = amdgpu_jpeg_ras_sw_init(adev);147 if (r)148 return r;149 150 return 0;151}152 153/**154 * jpeg_v2_5_sw_fini - sw fini for JPEG block155 *156 * @handle: amdgpu_device pointer157 *158 * JPEG suspend and free up sw allocation159 */160static int jpeg_v2_5_sw_fini(void *handle)161{162 int r;163 struct amdgpu_device *adev = (struct amdgpu_device *)handle;164 165 r = amdgpu_jpeg_suspend(adev);166 if (r)167 return r;168 169 r = amdgpu_jpeg_sw_fini(adev);170 171 return r;172}173 174/**175 * jpeg_v2_5_hw_init - start and test JPEG block176 *177 * @handle: amdgpu_device pointer178 *179 */180static int jpeg_v2_5_hw_init(void *handle)181{182 struct amdgpu_device *adev = (struct amdgpu_device *)handle;183 struct amdgpu_ring *ring;184 int i, r;185 186 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {187 if (adev->jpeg.harvest_config & (1 << i))188 continue;189 190 ring = adev->jpeg.inst[i].ring_dec;191 adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,192 (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i);193 194 r = amdgpu_ring_test_helper(ring);195 if (r)196 return r;197 }198 199 return 0;200}201 202/**203 * jpeg_v2_5_hw_fini - stop the hardware block204 *205 * @handle: amdgpu_device pointer206 *207 * Stop the JPEG block, mark ring as not ready any more208 */209static int jpeg_v2_5_hw_fini(void *handle)210{211 struct amdgpu_device *adev = (struct amdgpu_device *)handle;212 int i;213 214 cancel_delayed_work_sync(&adev->vcn.idle_work);215 216 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {217 if (adev->jpeg.harvest_config & (1 << i))218 continue;219 220 if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&221 RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))222 jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);223 224 if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG))225 amdgpu_irq_put(adev, &adev->jpeg.inst[i].ras_poison_irq, 0);226 }227 228 return 0;229}230 231/**232 * jpeg_v2_5_suspend - suspend JPEG block233 *234 * @handle: amdgpu_device pointer235 *236 * HW fini and suspend JPEG block237 */238static int jpeg_v2_5_suspend(void *handle)239{240 struct amdgpu_device *adev = (struct amdgpu_device *)handle;241 int r;242 243 r = jpeg_v2_5_hw_fini(adev);244 if (r)245 return r;246 247 r = amdgpu_jpeg_suspend(adev);248 249 return r;250}251 252/**253 * jpeg_v2_5_resume - resume JPEG block254 *255 * @handle: amdgpu_device pointer256 *257 * Resume firmware and hw init JPEG block258 */259static int jpeg_v2_5_resume(void *handle)260{261 struct amdgpu_device *adev = (struct amdgpu_device *)handle;262 int r;263 264 r = amdgpu_jpeg_resume(adev);265 if (r)266 return r;267 268 r = jpeg_v2_5_hw_init(adev);269 270 return r;271}272 273static void jpeg_v2_5_disable_clock_gating(struct amdgpu_device *adev, int inst)274{275 uint32_t data;276 277 data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);278 if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)279 data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;280 else281 data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;282 283 data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;284 data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;285 WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);286 287 data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);288 data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK289 | JPEG_CGC_GATE__JPEG2_DEC_MASK290 | JPEG_CGC_GATE__JMCIF_MASK291 | JPEG_CGC_GATE__JRBBM_MASK);292 WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);293 294 data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);295 data &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK296 | JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK297 | JPEG_CGC_CTRL__JMCIF_MODE_MASK298 | JPEG_CGC_CTRL__JRBBM_MODE_MASK);299 WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);300}301 302static void jpeg_v2_5_enable_clock_gating(struct amdgpu_device *adev, int inst)303{304 uint32_t data;305 306 data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);307 data |= (JPEG_CGC_GATE__JPEG_DEC_MASK308 |JPEG_CGC_GATE__JPEG2_DEC_MASK309 |JPEG_CGC_GATE__JPEG_ENC_MASK310 |JPEG_CGC_GATE__JMCIF_MASK311 |JPEG_CGC_GATE__JRBBM_MASK);312 WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);313}314 315/**316 * jpeg_v2_5_start - start JPEG block317 *318 * @adev: amdgpu_device pointer319 *320 * Setup and start the JPEG block321 */322static int jpeg_v2_5_start(struct amdgpu_device *adev)323{324 struct amdgpu_ring *ring;325 int i;326 327 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {328 if (adev->jpeg.harvest_config & (1 << i))329 continue;330 331 ring = adev->jpeg.inst[i].ring_dec;332 /* disable anti hang mechanism */333 WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS), 0,334 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);335 336 /* JPEG disable CGC */337 jpeg_v2_5_disable_clock_gating(adev, i);338 339 /* MJPEG global tiling registers */340 WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX8_ADDR_CONFIG,341 adev->gfx.config.gb_addr_config);342 WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX10_ADDR_CONFIG,343 adev->gfx.config.gb_addr_config);344 345 /* enable JMI channel */346 WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL), 0,347 ~UVD_JMI_CNTL__SOFT_RESET_MASK);348 349 /* enable System Interrupt for JRBC */350 WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmJPEG_SYS_INT_EN),351 JPEG_SYS_INT_EN__DJRBC_MASK,352 ~JPEG_SYS_INT_EN__DJRBC_MASK);353 354 WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_VMID, 0);355 WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));356 WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,357 lower_32_bits(ring->gpu_addr));358 WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,359 upper_32_bits(ring->gpu_addr));360 WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_RPTR, 0);361 WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR, 0);362 WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, 0x00000002L);363 WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);364 ring->wptr = RREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR);365 }366 367 return 0;368}369 370/**371 * jpeg_v2_5_stop - stop JPEG block372 *373 * @adev: amdgpu_device pointer374 *375 * stop the JPEG block376 */377static int jpeg_v2_5_stop(struct amdgpu_device *adev)378{379 int i;380 381 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {382 if (adev->jpeg.harvest_config & (1 << i))383 continue;384 385 /* reset JMI */386 WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL),387 UVD_JMI_CNTL__SOFT_RESET_MASK,388 ~UVD_JMI_CNTL__SOFT_RESET_MASK);389 390 jpeg_v2_5_enable_clock_gating(adev, i);391 392 /* enable anti hang mechanism */393 WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS),394 UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,395 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);396 }397 398 return 0;399}400 401/**402 * jpeg_v2_5_dec_ring_get_rptr - get read pointer403 *404 * @ring: amdgpu_ring pointer405 *406 * Returns the current hardware read pointer407 */408static uint64_t jpeg_v2_5_dec_ring_get_rptr(struct amdgpu_ring *ring)409{410 struct amdgpu_device *adev = ring->adev;411 412 return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_RPTR);413}414 415/**416 * jpeg_v2_5_dec_ring_get_wptr - get write pointer417 *418 * @ring: amdgpu_ring pointer419 *420 * Returns the current hardware write pointer421 */422static uint64_t jpeg_v2_5_dec_ring_get_wptr(struct amdgpu_ring *ring)423{424 struct amdgpu_device *adev = ring->adev;425 426 if (ring->use_doorbell)427 return *ring->wptr_cpu_addr;428 else429 return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR);430}431 432/**433 * jpeg_v2_5_dec_ring_set_wptr - set write pointer434 *435 * @ring: amdgpu_ring pointer436 *437 * Commits the write pointer to the hardware438 */439static void jpeg_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring)440{441 struct amdgpu_device *adev = ring->adev;442 443 if (ring->use_doorbell) {444 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);445 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));446 } else {447 WREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));448 }449}450 451/**452 * jpeg_v2_6_dec_ring_insert_start - insert a start command453 *454 * @ring: amdgpu_ring pointer455 *456 * Write a start command to the ring.457 */458static void jpeg_v2_6_dec_ring_insert_start(struct amdgpu_ring *ring)459{460 amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,461 0, 0, PACKETJ_TYPE0));462 amdgpu_ring_write(ring, 0x6aa04); /* PCTL0_MMHUB_DEEPSLEEP_IB */463 464 amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,465 0, 0, PACKETJ_TYPE0));466 amdgpu_ring_write(ring, 0x80000000 | (1 << (ring->me * 2 + 14)));467}468 469/**470 * jpeg_v2_6_dec_ring_insert_end - insert a end command471 *472 * @ring: amdgpu_ring pointer473 *474 * Write a end command to the ring.475 */476static void jpeg_v2_6_dec_ring_insert_end(struct amdgpu_ring *ring)477{478 amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,479 0, 0, PACKETJ_TYPE0));480 amdgpu_ring_write(ring, 0x6aa04); /* PCTL0_MMHUB_DEEPSLEEP_IB */481 482 amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,483 0, 0, PACKETJ_TYPE0));484 amdgpu_ring_write(ring, (1 << (ring->me * 2 + 14)));485}486 487static bool jpeg_v2_5_is_idle(void *handle)488{489 struct amdgpu_device *adev = (struct amdgpu_device *)handle;490 int i, ret = 1;491 492 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {493 if (adev->jpeg.harvest_config & (1 << i))494 continue;495 496 ret &= (((RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS) &497 UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==498 UVD_JRBC_STATUS__RB_JOB_DONE_MASK));499 }500 501 return ret;502}503 504static int jpeg_v2_5_wait_for_idle(void *handle)505{506 struct amdgpu_device *adev = (struct amdgpu_device *)handle;507 int i, ret;508 509 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {510 if (adev->jpeg.harvest_config & (1 << i))511 continue;512 513 ret = SOC15_WAIT_ON_RREG(JPEG, i, mmUVD_JRBC_STATUS,514 UVD_JRBC_STATUS__RB_JOB_DONE_MASK,515 UVD_JRBC_STATUS__RB_JOB_DONE_MASK);516 if (ret)517 return ret;518 }519 520 return 0;521}522 523static int jpeg_v2_5_set_clockgating_state(void *handle,524 enum amd_clockgating_state state)525{526 struct amdgpu_device *adev = (struct amdgpu_device *)handle;527 bool enable = (state == AMD_CG_STATE_GATE);528 int i;529 530 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {531 if (adev->jpeg.harvest_config & (1 << i))532 continue;533 534 if (enable) {535 if (!jpeg_v2_5_is_idle(handle))536 return -EBUSY;537 jpeg_v2_5_enable_clock_gating(adev, i);538 } else {539 jpeg_v2_5_disable_clock_gating(adev, i);540 }541 }542 543 return 0;544}545 546static int jpeg_v2_5_set_powergating_state(void *handle,547 enum amd_powergating_state state)548{549 struct amdgpu_device *adev = (struct amdgpu_device *)handle;550 int ret;551 552 if (state == adev->jpeg.cur_state)553 return 0;554 555 if (state == AMD_PG_STATE_GATE)556 ret = jpeg_v2_5_stop(adev);557 else558 ret = jpeg_v2_5_start(adev);559 560 if (!ret)561 adev->jpeg.cur_state = state;562 563 return ret;564}565 566static int jpeg_v2_5_set_interrupt_state(struct amdgpu_device *adev,567 struct amdgpu_irq_src *source,568 unsigned type,569 enum amdgpu_interrupt_state state)570{571 return 0;572}573 574static int jpeg_v2_6_set_ras_interrupt_state(struct amdgpu_device *adev,575 struct amdgpu_irq_src *source,576 unsigned int type,577 enum amdgpu_interrupt_state state)578{579 return 0;580}581 582static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,583 struct amdgpu_irq_src *source,584 struct amdgpu_iv_entry *entry)585{586 uint32_t ip_instance;587 588 switch (entry->client_id) {589 case SOC15_IH_CLIENTID_VCN:590 ip_instance = 0;591 break;592 case SOC15_IH_CLIENTID_VCN1:593 ip_instance = 1;594 break;595 default:596 DRM_ERROR("Unhandled client id: %d\n", entry->client_id);597 return 0;598 }599 600 DRM_DEBUG("IH: JPEG TRAP\n");601 602 switch (entry->src_id) {603 case VCN_2_0__SRCID__JPEG_DECODE:604 amdgpu_fence_process(adev->jpeg.inst[ip_instance].ring_dec);605 break;606 default:607 DRM_ERROR("Unhandled interrupt: %d %d\n",608 entry->src_id, entry->src_data[0]);609 break;610 }611 612 return 0;613}614 615static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {616 .name = "jpeg_v2_5",617 .early_init = jpeg_v2_5_early_init,618 .late_init = NULL,619 .sw_init = jpeg_v2_5_sw_init,620 .sw_fini = jpeg_v2_5_sw_fini,621 .hw_init = jpeg_v2_5_hw_init,622 .hw_fini = jpeg_v2_5_hw_fini,623 .suspend = jpeg_v2_5_suspend,624 .resume = jpeg_v2_5_resume,625 .is_idle = jpeg_v2_5_is_idle,626 .wait_for_idle = jpeg_v2_5_wait_for_idle,627 .check_soft_reset = NULL,628 .pre_soft_reset = NULL,629 .soft_reset = NULL,630 .post_soft_reset = NULL,631 .set_clockgating_state = jpeg_v2_5_set_clockgating_state,632 .set_powergating_state = jpeg_v2_5_set_powergating_state,633 .dump_ip_state = NULL,634 .print_ip_state = NULL,635};636 637static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = {638 .name = "jpeg_v2_6",639 .early_init = jpeg_v2_5_early_init,640 .late_init = NULL,641 .sw_init = jpeg_v2_5_sw_init,642 .sw_fini = jpeg_v2_5_sw_fini,643 .hw_init = jpeg_v2_5_hw_init,644 .hw_fini = jpeg_v2_5_hw_fini,645 .suspend = jpeg_v2_5_suspend,646 .resume = jpeg_v2_5_resume,647 .is_idle = jpeg_v2_5_is_idle,648 .wait_for_idle = jpeg_v2_5_wait_for_idle,649 .check_soft_reset = NULL,650 .pre_soft_reset = NULL,651 .soft_reset = NULL,652 .post_soft_reset = NULL,653 .set_clockgating_state = jpeg_v2_5_set_clockgating_state,654 .set_powergating_state = jpeg_v2_5_set_powergating_state,655 .dump_ip_state = NULL,656 .print_ip_state = NULL,657};658 659static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {660 .type = AMDGPU_RING_TYPE_VCN_JPEG,661 .align_mask = 0xf,662 .get_rptr = jpeg_v2_5_dec_ring_get_rptr,663 .get_wptr = jpeg_v2_5_dec_ring_get_wptr,664 .set_wptr = jpeg_v2_5_dec_ring_set_wptr,665 .parse_cs = jpeg_v2_dec_ring_parse_cs,666 .emit_frame_size =667 SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +668 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +669 8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */670 18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */671 8 + 16,672 .emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */673 .emit_ib = jpeg_v2_0_dec_ring_emit_ib,674 .emit_fence = jpeg_v2_0_dec_ring_emit_fence,675 .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,676 .test_ring = amdgpu_jpeg_dec_ring_test_ring,677 .test_ib = amdgpu_jpeg_dec_ring_test_ib,678 .insert_nop = jpeg_v2_0_dec_ring_nop,679 .insert_start = jpeg_v2_0_dec_ring_insert_start,680 .insert_end = jpeg_v2_0_dec_ring_insert_end,681 .pad_ib = amdgpu_ring_generic_pad_ib,682 .begin_use = amdgpu_jpeg_ring_begin_use,683 .end_use = amdgpu_jpeg_ring_end_use,684 .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,685 .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,686 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,687};688 689static const struct amdgpu_ring_funcs jpeg_v2_6_dec_ring_vm_funcs = {690 .type = AMDGPU_RING_TYPE_VCN_JPEG,691 .align_mask = 0xf,692 .get_rptr = jpeg_v2_5_dec_ring_get_rptr,693 .get_wptr = jpeg_v2_5_dec_ring_get_wptr,694 .set_wptr = jpeg_v2_5_dec_ring_set_wptr,695 .parse_cs = jpeg_v2_dec_ring_parse_cs,696 .emit_frame_size =697 SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +698 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +699 8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */700 18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */701 8 + 16,702 .emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */703 .emit_ib = jpeg_v2_0_dec_ring_emit_ib,704 .emit_fence = jpeg_v2_0_dec_ring_emit_fence,705 .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,706 .test_ring = amdgpu_jpeg_dec_ring_test_ring,707 .test_ib = amdgpu_jpeg_dec_ring_test_ib,708 .insert_nop = jpeg_v2_0_dec_ring_nop,709 .insert_start = jpeg_v2_6_dec_ring_insert_start,710 .insert_end = jpeg_v2_6_dec_ring_insert_end,711 .pad_ib = amdgpu_ring_generic_pad_ib,712 .begin_use = amdgpu_jpeg_ring_begin_use,713 .end_use = amdgpu_jpeg_ring_end_use,714 .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,715 .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,716 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,717};718 719static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)720{721 int i;722 723 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {724 if (adev->jpeg.harvest_config & (1 << i))725 continue;726 if (adev->asic_type == CHIP_ARCTURUS)727 adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_5_dec_ring_vm_funcs;728 else /* CHIP_ALDEBARAN */729 adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_6_dec_ring_vm_funcs;730 adev->jpeg.inst[i].ring_dec->me = i;731 }732}733 734static const struct amdgpu_irq_src_funcs jpeg_v2_5_irq_funcs = {735 .set = jpeg_v2_5_set_interrupt_state,736 .process = jpeg_v2_5_process_interrupt,737};738 739static const struct amdgpu_irq_src_funcs jpeg_v2_6_ras_irq_funcs = {740 .set = jpeg_v2_6_set_ras_interrupt_state,741 .process = amdgpu_jpeg_process_poison_irq,742};743 744static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev)745{746 int i;747 748 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {749 if (adev->jpeg.harvest_config & (1 << i))750 continue;751 752 adev->jpeg.inst[i].irq.num_types = 1;753 adev->jpeg.inst[i].irq.funcs = &jpeg_v2_5_irq_funcs;754 755 adev->jpeg.inst[i].ras_poison_irq.num_types = 1;756 adev->jpeg.inst[i].ras_poison_irq.funcs = &jpeg_v2_6_ras_irq_funcs;757 }758}759 760const struct amdgpu_ip_block_version jpeg_v2_5_ip_block = {761 .type = AMD_IP_BLOCK_TYPE_JPEG,762 .major = 2,763 .minor = 5,764 .rev = 0,765 .funcs = &jpeg_v2_5_ip_funcs,766};767 768const struct amdgpu_ip_block_version jpeg_v2_6_ip_block = {769 .type = AMD_IP_BLOCK_TYPE_JPEG,770 .major = 2,771 .minor = 6,772 .rev = 0,773 .funcs = &jpeg_v2_6_ip_funcs,774};775 776static uint32_t jpeg_v2_6_query_poison_by_instance(struct amdgpu_device *adev,777 uint32_t instance, uint32_t sub_block)778{779 uint32_t poison_stat = 0, reg_value = 0;780 781 switch (sub_block) {782 case AMDGPU_JPEG_V2_6_JPEG0:783 reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG0_STATUS);784 poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF);785 break;786 case AMDGPU_JPEG_V2_6_JPEG1:787 reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG1_STATUS);788 poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF);789 break;790 default:791 break;792 }793 794 if (poison_stat)795 dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n",796 instance, sub_block);797 798 return poison_stat;799}800 801static bool jpeg_v2_6_query_ras_poison_status(struct amdgpu_device *adev)802{803 uint32_t inst = 0, sub = 0, poison_stat = 0;804 805 for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++)806 for (sub = 0; sub < AMDGPU_JPEG_V2_6_MAX_SUB_BLOCK; sub++)807 poison_stat +=808 jpeg_v2_6_query_poison_by_instance(adev, inst, sub);809 810 return !!poison_stat;811}812 813const struct amdgpu_ras_block_hw_ops jpeg_v2_6_ras_hw_ops = {814 .query_poison_status = jpeg_v2_6_query_ras_poison_status,815};816 817static struct amdgpu_jpeg_ras jpeg_v2_6_ras = {818 .ras_block = {819 .hw_ops = &jpeg_v2_6_ras_hw_ops,820 .ras_late_init = amdgpu_jpeg_ras_late_init,821 },822};823 824static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev)825{826 switch (amdgpu_ip_version(adev, JPEG_HWIP, 0)) {827 case IP_VERSION(2, 6, 0):828 adev->jpeg.ras = &jpeg_v2_6_ras;829 break;830 default:831 break;832 }833}834