843 lines · c
1/*2 * Copyright 2021 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.h"31#include "mmsch_v4_0.h"32 33#include "vcn/vcn_4_0_0_offset.h"34#include "vcn/vcn_4_0_0_sh_mask.h"35#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"36 37#define regUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f38 39static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev);40static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev);41static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev);42static int jpeg_v4_0_set_powergating_state(void *handle,43 enum amd_powergating_state state);44static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev);45 46static void jpeg_v4_0_dec_ring_set_wptr(struct amdgpu_ring *ring);47 48/**49 * jpeg_v4_0_early_init - set function pointers50 *51 * @handle: amdgpu_device pointer52 *53 * Set ring and irq function pointers54 */55static int jpeg_v4_0_early_init(void *handle)56{57 struct amdgpu_device *adev = (struct amdgpu_device *)handle;58 59 60 adev->jpeg.num_jpeg_inst = 1;61 adev->jpeg.num_jpeg_rings = 1;62 63 jpeg_v4_0_set_dec_ring_funcs(adev);64 jpeg_v4_0_set_irq_funcs(adev);65 jpeg_v4_0_set_ras_funcs(adev);66 67 return 0;68}69 70/**71 * jpeg_v4_0_sw_init - sw init for JPEG block72 *73 * @handle: amdgpu_device pointer74 *75 * Load firmware and sw initialization76 */77static int jpeg_v4_0_sw_init(void *handle)78{79 struct amdgpu_device *adev = (struct amdgpu_device *)handle;80 struct amdgpu_ring *ring;81 int r;82 83 /* JPEG TRAP */84 r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,85 VCN_4_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);86 if (r)87 return r;88 89 /* JPEG DJPEG POISON EVENT */90 r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,91 VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq);92 if (r)93 return r;94 95 /* JPEG EJPEG POISON EVENT */96 r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,97 VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq);98 if (r)99 return r;100 101 r = amdgpu_jpeg_sw_init(adev);102 if (r)103 return r;104 105 r = amdgpu_jpeg_resume(adev);106 if (r)107 return r;108 109 ring = adev->jpeg.inst->ring_dec;110 ring->use_doorbell = true;111 ring->doorbell_index = amdgpu_sriov_vf(adev) ? (((adev->doorbell_index.vcn.vcn_ring0_1) << 1) + 4) : ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1);112 ring->vm_hub = AMDGPU_MMHUB0(0);113 114 sprintf(ring->name, "jpeg_dec");115 r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,116 AMDGPU_RING_PRIO_DEFAULT, NULL);117 if (r)118 return r;119 120 adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;121 adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);122 123 r = amdgpu_jpeg_ras_sw_init(adev);124 if (r)125 return r;126 127 return 0;128}129 130/**131 * jpeg_v4_0_sw_fini - sw fini for JPEG block132 *133 * @handle: amdgpu_device pointer134 *135 * JPEG suspend and free up sw allocation136 */137static int jpeg_v4_0_sw_fini(void *handle)138{139 struct amdgpu_device *adev = (struct amdgpu_device *)handle;140 int r;141 142 r = amdgpu_jpeg_suspend(adev);143 if (r)144 return r;145 146 r = amdgpu_jpeg_sw_fini(adev);147 148 return r;149}150 151/**152 * jpeg_v4_0_hw_init - start and test JPEG block153 *154 * @handle: amdgpu_device pointer155 *156 */157static int jpeg_v4_0_hw_init(void *handle)158{159 struct amdgpu_device *adev = (struct amdgpu_device *)handle;160 struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;161 int r;162 163 if (amdgpu_sriov_vf(adev)) {164 r = jpeg_v4_0_start_sriov(adev);165 if (r)166 return r;167 ring->wptr = 0;168 ring->wptr_old = 0;169 jpeg_v4_0_dec_ring_set_wptr(ring);170 ring->sched.ready = true;171 } else {172 adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,173 (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);174 175 WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,176 ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |177 VCN_JPEG_DB_CTRL__EN_MASK);178 179 r = amdgpu_ring_test_helper(ring);180 if (r)181 return r;182 }183 184 return 0;185}186 187/**188 * jpeg_v4_0_hw_fini - stop the hardware block189 *190 * @handle: amdgpu_device pointer191 *192 * Stop the JPEG block, mark ring as not ready any more193 */194static int jpeg_v4_0_hw_fini(void *handle)195{196 struct amdgpu_device *adev = (struct amdgpu_device *)handle;197 198 cancel_delayed_work_sync(&adev->vcn.idle_work);199 if (!amdgpu_sriov_vf(adev)) {200 if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&201 RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))202 jpeg_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE);203 }204 if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG))205 amdgpu_irq_put(adev, &adev->jpeg.inst->ras_poison_irq, 0);206 207 return 0;208}209 210/**211 * jpeg_v4_0_suspend - suspend JPEG block212 *213 * @handle: amdgpu_device pointer214 *215 * HW fini and suspend JPEG block216 */217static int jpeg_v4_0_suspend(void *handle)218{219 struct amdgpu_device *adev = (struct amdgpu_device *)handle;220 int r;221 222 r = jpeg_v4_0_hw_fini(adev);223 if (r)224 return r;225 226 r = amdgpu_jpeg_suspend(adev);227 228 return r;229}230 231/**232 * jpeg_v4_0_resume - resume JPEG block233 *234 * @handle: amdgpu_device pointer235 *236 * Resume firmware and hw init JPEG block237 */238static int jpeg_v4_0_resume(void *handle)239{240 struct amdgpu_device *adev = (struct amdgpu_device *)handle;241 int r;242 243 r = amdgpu_jpeg_resume(adev);244 if (r)245 return r;246 247 r = jpeg_v4_0_hw_init(adev);248 249 return r;250}251 252static void jpeg_v4_0_disable_clock_gating(struct amdgpu_device *adev)253{254 uint32_t data = 0;255 256 data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);257 if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {258 data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;259 data &= (~JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK);260 } else {261 data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;262 }263 264 data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;265 data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;266 WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);267 268 data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);269 data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK270 | JPEG_CGC_GATE__JPEG2_DEC_MASK271 | JPEG_CGC_GATE__JMCIF_MASK272 | JPEG_CGC_GATE__JRBBM_MASK);273 WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);274}275 276static void jpeg_v4_0_enable_clock_gating(struct amdgpu_device *adev)277{278 uint32_t data = 0;279 280 data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);281 if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {282 data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;283 data |= JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK;284 } else {285 data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;286 }287 288 data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;289 data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;290 WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);291 292 data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);293 data |= (JPEG_CGC_GATE__JPEG_DEC_MASK294 |JPEG_CGC_GATE__JPEG2_DEC_MASK295 |JPEG_CGC_GATE__JMCIF_MASK296 |JPEG_CGC_GATE__JRBBM_MASK);297 WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);298}299 300static int jpeg_v4_0_disable_static_power_gating(struct amdgpu_device *adev)301{302 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {303 uint32_t data = 0;304 int r = 0;305 306 data = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;307 WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_PGFSM_CONFIG), data);308 309 r = SOC15_WAIT_ON_RREG(JPEG, 0,310 regUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON,311 UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);312 313 if (r) {314 DRM_DEV_ERROR(adev->dev, "amdgpu: JPEG disable power gating failed\n");315 return r;316 }317 }318 319 /* disable anti hang mechanism */320 WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,321 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);322 323 /* keep the JPEG in static PG mode */324 WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,325 ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);326 327 return 0;328}329 330static int jpeg_v4_0_enable_static_power_gating(struct amdgpu_device *adev)331{332 /* enable anti hang mechanism */333 WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),334 UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,335 ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);336 337 if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {338 uint32_t data = 0;339 int r = 0;340 341 data = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;342 WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_PGFSM_CONFIG), data);343 344 r = SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_PGFSM_STATUS,345 (2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT),346 UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);347 348 if (r) {349 DRM_DEV_ERROR(adev->dev, "amdgpu: JPEG enable power gating failed\n");350 return r;351 }352 }353 354 return 0;355}356 357/**358 * jpeg_v4_0_start - start JPEG block359 *360 * @adev: amdgpu_device pointer361 *362 * Setup and start the JPEG block363 */364static int jpeg_v4_0_start(struct amdgpu_device *adev)365{366 struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;367 int r;368 369 if (adev->pm.dpm_enabled)370 amdgpu_dpm_enable_jpeg(adev, true);371 372 /* disable power gating */373 r = jpeg_v4_0_disable_static_power_gating(adev);374 if (r)375 return r;376 377 /* JPEG disable CGC */378 jpeg_v4_0_disable_clock_gating(adev);379 380 /* MJPEG global tiling registers */381 WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,382 adev->gfx.config.gb_addr_config);383 384 385 /* enable JMI channel */386 WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,387 ~UVD_JMI_CNTL__SOFT_RESET_MASK);388 389 /* enable System Interrupt for JRBC */390 WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regJPEG_SYS_INT_EN),391 JPEG_SYS_INT_EN__DJRBC_MASK,392 ~JPEG_SYS_INT_EN__DJRBC_MASK);393 394 WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);395 WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));396 WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,397 lower_32_bits(ring->gpu_addr));398 WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,399 upper_32_bits(ring->gpu_addr));400 WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR, 0);401 WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, 0);402 WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, 0x00000002L);403 WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);404 ring->wptr = RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);405 406 return 0;407}408 409static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev)410{411 struct amdgpu_ring *ring;412 uint64_t ctx_addr;413 uint32_t param, resp, expected;414 uint32_t tmp, timeout;415 416 struct amdgpu_mm_table *table = &adev->virt.mm_table;417 uint32_t *table_loc;418 uint32_t table_size;419 uint32_t size, size_dw;420 uint32_t init_status;421 422 struct mmsch_v4_0_cmd_direct_write423 direct_wt = { {0} };424 struct mmsch_v4_0_cmd_end end = { {0} };425 struct mmsch_v4_0_init_header header;426 427 direct_wt.cmd_header.command_type =428 MMSCH_COMMAND__DIRECT_REG_WRITE;429 end.cmd_header.command_type =430 MMSCH_COMMAND__END;431 432 size = sizeof(struct mmsch_v4_0_init_header);433 table_loc = (uint32_t *)table->cpu_addr;434 memcpy(&header, (void *)table_loc, size);435 436 header.version = MMSCH_VERSION;437 header.total_size = RREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE);438 439 header.jpegdec.init_status = 0;440 header.jpegdec.table_offset = 0;441 header.jpegdec.table_size = 0;442 443 table_loc = (uint32_t *)table->cpu_addr;444 table_loc += header.total_size;445 446 table_size = 0;447 448 ring = adev->jpeg.inst->ring_dec;449 450 MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,451 regUVD_LMI_JRBC_RB_64BIT_BAR_LOW),452 lower_32_bits(ring->gpu_addr));453 MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,454 regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH),455 upper_32_bits(ring->gpu_addr));456 MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,457 regUVD_JRBC_RB_SIZE), ring->ring_size / 4);458 459 /* add end packet */460 MMSCH_V4_0_INSERT_END();461 462 /* refine header */463 header.jpegdec.init_status = 0;464 header.jpegdec.table_offset = header.total_size;465 header.jpegdec.table_size = table_size;466 header.total_size += table_size;467 468 /* Update init table header in memory */469 size = sizeof(struct mmsch_v4_0_init_header);470 table_loc = (uint32_t *)table->cpu_addr;471 memcpy((void *)table_loc, &header, size);472 473 /* Perform HDP flush before writing to MMSCH registers */474 amdgpu_device_flush_hdp(adev, NULL);475 476 /* message MMSCH (in VCN[0]) to initialize this client477 * 1, write to mmsch_vf_ctx_addr_lo/hi register with GPU mc addr478 * of memory descriptor location479 */480 ctx_addr = table->gpu_addr;481 WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_ADDR_LO, lower_32_bits(ctx_addr));482 WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_ADDR_HI, upper_32_bits(ctx_addr));483 484 /* 2, update vmid of descriptor */485 tmp = RREG32_SOC15(VCN, 0, regMMSCH_VF_VMID);486 tmp &= ~MMSCH_VF_VMID__VF_CTX_VMID_MASK;487 /* use domain0 for MM scheduler */488 tmp |= (0 << MMSCH_VF_VMID__VF_CTX_VMID__SHIFT);489 WREG32_SOC15(VCN, 0, regMMSCH_VF_VMID, tmp);490 491 /* 3, notify mmsch about the size of this descriptor */492 size = header.total_size;493 WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE, size);494 495 /* 4, set resp to zero */496 WREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_RESP, 0);497 498 /* 5, kick off the initialization and wait until499 * MMSCH_VF_MAILBOX_RESP becomes non-zero500 */501 param = 0x00000001;502 WREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_HOST, param);503 tmp = 0;504 timeout = 1000;505 resp = 0;506 expected = MMSCH_VF_MAILBOX_RESP__OK;507 init_status = ((struct mmsch_v4_0_init_header *)(table_loc))->jpegdec.init_status;508 while (resp != expected) {509 resp = RREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_RESP);510 511 if (resp != 0)512 break;513 udelay(10);514 tmp = tmp + 10;515 if (tmp >= timeout) {516 DRM_ERROR("failed to init MMSCH. TIME-OUT after %d usec"\517 " waiting for regMMSCH_VF_MAILBOX_RESP "\518 "(expected=0x%08x, readback=0x%08x)\n",519 tmp, expected, resp);520 return -EBUSY;521 }522 }523 if (resp != expected && resp != MMSCH_VF_MAILBOX_RESP__INCOMPLETE524 && init_status != MMSCH_VF_ENGINE_STATUS__PASS) {525 DRM_ERROR("MMSCH init status is incorrect! readback=0x%08x, header init status for jpeg: %x\n", resp, init_status);526 return -EINVAL;527 }528 529 return 0;530 531}532 533/**534 * jpeg_v4_0_stop - stop JPEG block535 *536 * @adev: amdgpu_device pointer537 *538 * stop the JPEG block539 */540static int jpeg_v4_0_stop(struct amdgpu_device *adev)541{542 int r;543 544 /* reset JMI */545 WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),546 UVD_JMI_CNTL__SOFT_RESET_MASK,547 ~UVD_JMI_CNTL__SOFT_RESET_MASK);548 549 jpeg_v4_0_enable_clock_gating(adev);550 551 /* enable power gating */552 r = jpeg_v4_0_enable_static_power_gating(adev);553 if (r)554 return r;555 556 if (adev->pm.dpm_enabled)557 amdgpu_dpm_enable_jpeg(adev, false);558 559 return 0;560}561 562/**563 * jpeg_v4_0_dec_ring_get_rptr - get read pointer564 *565 * @ring: amdgpu_ring pointer566 *567 * Returns the current hardware read pointer568 */569static uint64_t jpeg_v4_0_dec_ring_get_rptr(struct amdgpu_ring *ring)570{571 struct amdgpu_device *adev = ring->adev;572 573 return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR);574}575 576/**577 * jpeg_v4_0_dec_ring_get_wptr - get write pointer578 *579 * @ring: amdgpu_ring pointer580 *581 * Returns the current hardware write pointer582 */583static uint64_t jpeg_v4_0_dec_ring_get_wptr(struct amdgpu_ring *ring)584{585 struct amdgpu_device *adev = ring->adev;586 587 if (ring->use_doorbell)588 return *ring->wptr_cpu_addr;589 else590 return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);591}592 593/**594 * jpeg_v4_0_dec_ring_set_wptr - set write pointer595 *596 * @ring: amdgpu_ring pointer597 *598 * Commits the write pointer to the hardware599 */600static void jpeg_v4_0_dec_ring_set_wptr(struct amdgpu_ring *ring)601{602 struct amdgpu_device *adev = ring->adev;603 604 if (ring->use_doorbell) {605 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);606 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));607 } else {608 WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));609 }610}611 612static bool jpeg_v4_0_is_idle(void *handle)613{614 struct amdgpu_device *adev = (struct amdgpu_device *)handle;615 int ret = 1;616 617 ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) &618 UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==619 UVD_JRBC_STATUS__RB_JOB_DONE_MASK));620 621 return ret;622}623 624static int jpeg_v4_0_wait_for_idle(void *handle)625{626 struct amdgpu_device *adev = (struct amdgpu_device *)handle;627 628 return SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_JRBC_STATUS,629 UVD_JRBC_STATUS__RB_JOB_DONE_MASK,630 UVD_JRBC_STATUS__RB_JOB_DONE_MASK);631}632 633static int jpeg_v4_0_set_clockgating_state(void *handle,634 enum amd_clockgating_state state)635{636 struct amdgpu_device *adev = (struct amdgpu_device *)handle;637 bool enable = state == AMD_CG_STATE_GATE;638 639 if (enable) {640 if (!jpeg_v4_0_is_idle(handle))641 return -EBUSY;642 jpeg_v4_0_enable_clock_gating(adev);643 } else {644 jpeg_v4_0_disable_clock_gating(adev);645 }646 647 return 0;648}649 650static int jpeg_v4_0_set_powergating_state(void *handle,651 enum amd_powergating_state state)652{653 struct amdgpu_device *adev = (struct amdgpu_device *)handle;654 int ret;655 656 if (amdgpu_sriov_vf(adev)) {657 adev->jpeg.cur_state = AMD_PG_STATE_UNGATE;658 return 0;659 }660 661 if (state == adev->jpeg.cur_state)662 return 0;663 664 if (state == AMD_PG_STATE_GATE)665 ret = jpeg_v4_0_stop(adev);666 else667 ret = jpeg_v4_0_start(adev);668 669 if (!ret)670 adev->jpeg.cur_state = state;671 672 return ret;673}674 675static int jpeg_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev,676 struct amdgpu_irq_src *source,677 unsigned int type,678 enum amdgpu_interrupt_state state)679{680 return 0;681}682 683static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,684 struct amdgpu_irq_src *source,685 struct amdgpu_iv_entry *entry)686{687 DRM_DEBUG("IH: JPEG TRAP\n");688 689 switch (entry->src_id) {690 case VCN_4_0__SRCID__JPEG_DECODE:691 amdgpu_fence_process(adev->jpeg.inst->ring_dec);692 break;693 default:694 DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",695 entry->src_id, entry->src_data[0]);696 break;697 }698 699 return 0;700}701 702static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {703 .name = "jpeg_v4_0",704 .early_init = jpeg_v4_0_early_init,705 .late_init = NULL,706 .sw_init = jpeg_v4_0_sw_init,707 .sw_fini = jpeg_v4_0_sw_fini,708 .hw_init = jpeg_v4_0_hw_init,709 .hw_fini = jpeg_v4_0_hw_fini,710 .suspend = jpeg_v4_0_suspend,711 .resume = jpeg_v4_0_resume,712 .is_idle = jpeg_v4_0_is_idle,713 .wait_for_idle = jpeg_v4_0_wait_for_idle,714 .check_soft_reset = NULL,715 .pre_soft_reset = NULL,716 .soft_reset = NULL,717 .post_soft_reset = NULL,718 .set_clockgating_state = jpeg_v4_0_set_clockgating_state,719 .set_powergating_state = jpeg_v4_0_set_powergating_state,720 .dump_ip_state = NULL,721 .print_ip_state = NULL,722};723 724static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {725 .type = AMDGPU_RING_TYPE_VCN_JPEG,726 .align_mask = 0xf,727 .get_rptr = jpeg_v4_0_dec_ring_get_rptr,728 .get_wptr = jpeg_v4_0_dec_ring_get_wptr,729 .set_wptr = jpeg_v4_0_dec_ring_set_wptr,730 .parse_cs = jpeg_v2_dec_ring_parse_cs,731 .emit_frame_size =732 SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +733 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +734 8 + /* jpeg_v4_0_dec_ring_emit_vm_flush */735 18 + 18 + /* jpeg_v4_0_dec_ring_emit_fence x2 vm fence */736 8 + 16,737 .emit_ib_size = 22, /* jpeg_v4_0_dec_ring_emit_ib */738 .emit_ib = jpeg_v2_0_dec_ring_emit_ib,739 .emit_fence = jpeg_v2_0_dec_ring_emit_fence,740 .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,741 .test_ring = amdgpu_jpeg_dec_ring_test_ring,742 .test_ib = amdgpu_jpeg_dec_ring_test_ib,743 .insert_nop = jpeg_v2_0_dec_ring_nop,744 .insert_start = jpeg_v2_0_dec_ring_insert_start,745 .insert_end = jpeg_v2_0_dec_ring_insert_end,746 .pad_ib = amdgpu_ring_generic_pad_ib,747 .begin_use = amdgpu_jpeg_ring_begin_use,748 .end_use = amdgpu_jpeg_ring_end_use,749 .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,750 .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,751 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,752};753 754static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev)755{756 adev->jpeg.inst->ring_dec->funcs = &jpeg_v4_0_dec_ring_vm_funcs;757}758 759static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = {760 .process = jpeg_v4_0_process_interrupt,761};762 763static const struct amdgpu_irq_src_funcs jpeg_v4_0_ras_irq_funcs = {764 .set = jpeg_v4_0_set_ras_interrupt_state,765 .process = amdgpu_jpeg_process_poison_irq,766};767 768static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev)769{770 adev->jpeg.inst->irq.num_types = 1;771 adev->jpeg.inst->irq.funcs = &jpeg_v4_0_irq_funcs;772 773 adev->jpeg.inst->ras_poison_irq.num_types = 1;774 adev->jpeg.inst->ras_poison_irq.funcs = &jpeg_v4_0_ras_irq_funcs;775}776 777const struct amdgpu_ip_block_version jpeg_v4_0_ip_block = {778 .type = AMD_IP_BLOCK_TYPE_JPEG,779 .major = 4,780 .minor = 0,781 .rev = 0,782 .funcs = &jpeg_v4_0_ip_funcs,783};784 785static uint32_t jpeg_v4_0_query_poison_by_instance(struct amdgpu_device *adev,786 uint32_t instance, uint32_t sub_block)787{788 uint32_t poison_stat = 0, reg_value = 0;789 790 switch (sub_block) {791 case AMDGPU_JPEG_V4_0_JPEG0:792 reg_value = RREG32_SOC15(JPEG, instance, regUVD_RAS_JPEG0_STATUS);793 poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF);794 break;795 case AMDGPU_JPEG_V4_0_JPEG1:796 reg_value = RREG32_SOC15(JPEG, instance, regUVD_RAS_JPEG1_STATUS);797 poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF);798 break;799 default:800 break;801 }802 803 if (poison_stat)804 dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n",805 instance, sub_block);806 807 return poison_stat;808}809 810static bool jpeg_v4_0_query_ras_poison_status(struct amdgpu_device *adev)811{812 uint32_t inst = 0, sub = 0, poison_stat = 0;813 814 for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++)815 for (sub = 0; sub < AMDGPU_JPEG_V4_0_MAX_SUB_BLOCK; sub++)816 poison_stat +=817 jpeg_v4_0_query_poison_by_instance(adev, inst, sub);818 819 return !!poison_stat;820}821 822const struct amdgpu_ras_block_hw_ops jpeg_v4_0_ras_hw_ops = {823 .query_poison_status = jpeg_v4_0_query_ras_poison_status,824};825 826static struct amdgpu_jpeg_ras jpeg_v4_0_ras = {827 .ras_block = {828 .hw_ops = &jpeg_v4_0_ras_hw_ops,829 .ras_late_init = amdgpu_jpeg_ras_late_init,830 },831};832 833static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev)834{835 switch (amdgpu_ip_version(adev, JPEG_HWIP, 0)) {836 case IP_VERSION(4, 0, 0):837 adev->jpeg.ras = &jpeg_v4_0_ras;838 break;839 default:840 break;841 }842}843