688 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 "amdgpu_cs.h"27#include "soc15.h"28#include "soc15d.h"29#include "vcn_v1_0.h"30#include "jpeg_v1_0.h"31 32#include "vcn/vcn_1_0_offset.h"33#include "vcn/vcn_1_0_sh_mask.h"34 35static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);36static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev);37static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring);38static int jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser *parser,39 struct amdgpu_job *job,40 struct amdgpu_ib *ib);41 42static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)43{44 struct amdgpu_device *adev = ring->adev;45 ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);46 if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||47 ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {48 ring->ring[(*ptr)++] = 0;49 ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0);50 } else {51 ring->ring[(*ptr)++] = reg_offset;52 ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0);53 }54 ring->ring[(*ptr)++] = val;55}56 57static void jpeg_v1_0_decode_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr)58{59 struct amdgpu_device *adev = ring->adev;60 61 uint32_t reg, reg_offset, val, mask, i;62 63 // 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW64 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW);65 reg_offset = (reg << 2);66 val = lower_32_bits(ring->gpu_addr);67 jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);68 69 // 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH70 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH);71 reg_offset = (reg << 2);72 val = upper_32_bits(ring->gpu_addr);73 jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);74 75 // 3rd to 5th: issue MEM_READ commands76 for (i = 0; i <= 2; i++) {77 ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2);78 ring->ring[ptr++] = 0;79 }80 81 // 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability82 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);83 reg_offset = (reg << 2);84 val = 0x13;85 jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);86 87 // 7th: program mmUVD_JRBC_RB_REF_DATA88 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA);89 reg_offset = (reg << 2);90 val = 0x1;91 jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);92 93 // 8th: issue conditional register read mmUVD_JRBC_RB_CNTL94 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);95 reg_offset = (reg << 2);96 val = 0x1;97 mask = 0x1;98 99 ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0);100 ring->ring[ptr++] = 0x01400200;101 ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0);102 ring->ring[ptr++] = val;103 ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);104 if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||105 ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {106 ring->ring[ptr++] = 0;107 ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3);108 } else {109 ring->ring[ptr++] = reg_offset;110 ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3);111 }112 ring->ring[ptr++] = mask;113 114 //9th to 21st: insert no-op115 for (i = 0; i <= 12; i++) {116 ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);117 ring->ring[ptr++] = 0;118 }119 120 //22nd: reset mmUVD_JRBC_RB_RPTR121 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_RPTR);122 reg_offset = (reg << 2);123 val = 0;124 jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);125 126 //23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch127 reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);128 reg_offset = (reg << 2);129 val = 0x12;130 jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);131}132 133/**134 * jpeg_v1_0_decode_ring_get_rptr - get read pointer135 *136 * @ring: amdgpu_ring pointer137 *138 * Returns the current hardware read pointer139 */140static uint64_t jpeg_v1_0_decode_ring_get_rptr(struct amdgpu_ring *ring)141{142 struct amdgpu_device *adev = ring->adev;143 144 return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR);145}146 147/**148 * jpeg_v1_0_decode_ring_get_wptr - get write pointer149 *150 * @ring: amdgpu_ring pointer151 *152 * Returns the current hardware write pointer153 */154static uint64_t jpeg_v1_0_decode_ring_get_wptr(struct amdgpu_ring *ring)155{156 struct amdgpu_device *adev = ring->adev;157 158 return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);159}160 161/**162 * jpeg_v1_0_decode_ring_set_wptr - set write pointer163 *164 * @ring: amdgpu_ring pointer165 *166 * Commits the write pointer to the hardware167 */168static void jpeg_v1_0_decode_ring_set_wptr(struct amdgpu_ring *ring)169{170 struct amdgpu_device *adev = ring->adev;171 172 WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));173}174 175/**176 * jpeg_v1_0_decode_ring_insert_start - insert a start command177 *178 * @ring: amdgpu_ring pointer179 *180 * Write a start command to the ring.181 */182static void jpeg_v1_0_decode_ring_insert_start(struct amdgpu_ring *ring)183{184 struct amdgpu_device *adev = ring->adev;185 186 amdgpu_ring_write(ring,187 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));188 amdgpu_ring_write(ring, 0x68e04);189 190 amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));191 amdgpu_ring_write(ring, 0x80010000);192}193 194/**195 * jpeg_v1_0_decode_ring_insert_end - insert a end command196 *197 * @ring: amdgpu_ring pointer198 *199 * Write a end command to the ring.200 */201static void jpeg_v1_0_decode_ring_insert_end(struct amdgpu_ring *ring)202{203 struct amdgpu_device *adev = ring->adev;204 205 amdgpu_ring_write(ring,206 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));207 amdgpu_ring_write(ring, 0x68e04);208 209 amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));210 amdgpu_ring_write(ring, 0x00010000);211}212 213/**214 * jpeg_v1_0_decode_ring_emit_fence - emit an fence & trap command215 *216 * @ring: amdgpu_ring pointer217 * @addr: address218 * @seq: sequence number219 * @flags: fence related flags220 *221 * Write a fence and a trap command to the ring.222 */223static void jpeg_v1_0_decode_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,224 unsigned flags)225{226 struct amdgpu_device *adev = ring->adev;227 228 WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);229 230 amdgpu_ring_write(ring,231 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA0), 0, 0, PACKETJ_TYPE0));232 amdgpu_ring_write(ring, seq);233 234 amdgpu_ring_write(ring,235 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA1), 0, 0, PACKETJ_TYPE0));236 amdgpu_ring_write(ring, seq);237 238 amdgpu_ring_write(ring,239 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));240 amdgpu_ring_write(ring, lower_32_bits(addr));241 242 amdgpu_ring_write(ring,243 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));244 amdgpu_ring_write(ring, upper_32_bits(addr));245 246 amdgpu_ring_write(ring,247 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, 0, PACKETJ_TYPE0));248 amdgpu_ring_write(ring, 0x8);249 250 amdgpu_ring_write(ring,251 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));252 amdgpu_ring_write(ring, 0);253 254 amdgpu_ring_write(ring,255 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));256 amdgpu_ring_write(ring, 0x01400200);257 258 amdgpu_ring_write(ring,259 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));260 amdgpu_ring_write(ring, seq);261 262 amdgpu_ring_write(ring,263 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));264 amdgpu_ring_write(ring, lower_32_bits(addr));265 266 amdgpu_ring_write(ring,267 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));268 amdgpu_ring_write(ring, upper_32_bits(addr));269 270 amdgpu_ring_write(ring,271 PACKETJ(0, 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE2));272 amdgpu_ring_write(ring, 0xffffffff);273 274 amdgpu_ring_write(ring,275 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));276 amdgpu_ring_write(ring, 0x3fbc);277 278 amdgpu_ring_write(ring,279 PACKETJ(0, 0, 0, PACKETJ_TYPE0));280 amdgpu_ring_write(ring, 0x1);281 282 /* emit trap */283 amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));284 amdgpu_ring_write(ring, 0);285}286 287/**288 * jpeg_v1_0_decode_ring_emit_ib - execute indirect buffer289 *290 * @ring: amdgpu_ring pointer291 * @job: job to retrieve vmid from292 * @ib: indirect buffer to execute293 * @flags: unused294 *295 * Write ring commands to execute the indirect buffer.296 */297static void jpeg_v1_0_decode_ring_emit_ib(struct amdgpu_ring *ring,298 struct amdgpu_job *job,299 struct amdgpu_ib *ib,300 uint32_t flags)301{302 struct amdgpu_device *adev = ring->adev;303 unsigned vmid = AMDGPU_JOB_GET_VMID(job);304 305 amdgpu_ring_write(ring,306 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_VMID), 0, 0, PACKETJ_TYPE0));307 if (ring->funcs->parse_cs)308 amdgpu_ring_write(ring, 0);309 else310 amdgpu_ring_write(ring, (vmid | (vmid << 4)));311 312 amdgpu_ring_write(ring,313 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JPEG_VMID), 0, 0, PACKETJ_TYPE0));314 amdgpu_ring_write(ring, (vmid | (vmid << 4)));315 316 amdgpu_ring_write(ring,317 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));318 amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));319 320 amdgpu_ring_write(ring,321 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));322 amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));323 324 amdgpu_ring_write(ring,325 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_IB_SIZE), 0, 0, PACKETJ_TYPE0));326 amdgpu_ring_write(ring, ib->length_dw);327 328 amdgpu_ring_write(ring,329 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));330 amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));331 332 amdgpu_ring_write(ring,333 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));334 amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));335 336 amdgpu_ring_write(ring,337 PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));338 amdgpu_ring_write(ring, 0);339 340 amdgpu_ring_write(ring,341 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));342 amdgpu_ring_write(ring, 0x01400200);343 344 amdgpu_ring_write(ring,345 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));346 amdgpu_ring_write(ring, 0x2);347 348 amdgpu_ring_write(ring,349 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_STATUS), 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));350 amdgpu_ring_write(ring, 0x2);351}352 353static void jpeg_v1_0_decode_ring_emit_reg_wait(struct amdgpu_ring *ring,354 uint32_t reg, uint32_t val,355 uint32_t mask)356{357 struct amdgpu_device *adev = ring->adev;358 uint32_t reg_offset = (reg << 2);359 360 amdgpu_ring_write(ring,361 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));362 amdgpu_ring_write(ring, 0x01400200);363 364 amdgpu_ring_write(ring,365 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));366 amdgpu_ring_write(ring, val);367 368 amdgpu_ring_write(ring,369 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));370 if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||371 ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {372 amdgpu_ring_write(ring, 0);373 amdgpu_ring_write(ring,374 PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));375 } else {376 amdgpu_ring_write(ring, reg_offset);377 amdgpu_ring_write(ring,378 PACKETJ(0, 0, 0, PACKETJ_TYPE3));379 }380 amdgpu_ring_write(ring, mask);381}382 383static void jpeg_v1_0_decode_ring_emit_vm_flush(struct amdgpu_ring *ring,384 unsigned vmid, uint64_t pd_addr)385{386 struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];387 uint32_t data0, data1, mask;388 389 pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);390 391 /* wait for register write */392 data0 = hub->ctx0_ptb_addr_lo32 + vmid * hub->ctx_addr_distance;393 data1 = lower_32_bits(pd_addr);394 mask = 0xffffffff;395 jpeg_v1_0_decode_ring_emit_reg_wait(ring, data0, data1, mask);396}397 398static void jpeg_v1_0_decode_ring_emit_wreg(struct amdgpu_ring *ring,399 uint32_t reg, uint32_t val)400{401 struct amdgpu_device *adev = ring->adev;402 uint32_t reg_offset = (reg << 2);403 404 amdgpu_ring_write(ring,405 PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));406 if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||407 ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {408 amdgpu_ring_write(ring, 0);409 amdgpu_ring_write(ring,410 PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));411 } else {412 amdgpu_ring_write(ring, reg_offset);413 amdgpu_ring_write(ring,414 PACKETJ(0, 0, 0, PACKETJ_TYPE0));415 }416 amdgpu_ring_write(ring, val);417}418 419static void jpeg_v1_0_decode_ring_nop(struct amdgpu_ring *ring, uint32_t count)420{421 int i;422 423 WARN_ON(ring->wptr % 2 || count % 2);424 425 for (i = 0; i < count / 2; i++) {426 amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));427 amdgpu_ring_write(ring, 0);428 }429}430 431static int jpeg_v1_0_set_interrupt_state(struct amdgpu_device *adev,432 struct amdgpu_irq_src *source,433 unsigned type,434 enum amdgpu_interrupt_state state)435{436 return 0;437}438 439static int jpeg_v1_0_process_interrupt(struct amdgpu_device *adev,440 struct amdgpu_irq_src *source,441 struct amdgpu_iv_entry *entry)442{443 DRM_DEBUG("IH: JPEG decode TRAP\n");444 445 switch (entry->src_id) {446 case 126:447 amdgpu_fence_process(adev->jpeg.inst->ring_dec);448 break;449 default:450 DRM_ERROR("Unhandled interrupt: %d %d\n",451 entry->src_id, entry->src_data[0]);452 break;453 }454 455 return 0;456}457 458/**459 * jpeg_v1_0_early_init - set function pointers460 *461 * @handle: amdgpu_device pointer462 *463 * Set ring and irq function pointers464 */465int jpeg_v1_0_early_init(void *handle)466{467 struct amdgpu_device *adev = (struct amdgpu_device *)handle;468 469 adev->jpeg.num_jpeg_inst = 1;470 adev->jpeg.num_jpeg_rings = 1;471 472 jpeg_v1_0_set_dec_ring_funcs(adev);473 jpeg_v1_0_set_irq_funcs(adev);474 475 return 0;476}477 478/**479 * jpeg_v1_0_sw_init - sw init for JPEG block480 *481 * @handle: amdgpu_device pointer482 *483 */484int jpeg_v1_0_sw_init(void *handle)485{486 struct amdgpu_device *adev = (struct amdgpu_device *)handle;487 struct amdgpu_ring *ring;488 int r;489 490 /* JPEG TRAP */491 r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 126, &adev->jpeg.inst->irq);492 if (r)493 return r;494 495 ring = adev->jpeg.inst->ring_dec;496 ring->vm_hub = AMDGPU_MMHUB0(0);497 sprintf(ring->name, "jpeg_dec");498 r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq,499 0, AMDGPU_RING_PRIO_DEFAULT, NULL);500 if (r)501 return r;502 503 adev->jpeg.internal.jpeg_pitch[0] = adev->jpeg.inst->external.jpeg_pitch[0] =504 SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);505 506 return 0;507}508 509/**510 * jpeg_v1_0_sw_fini - sw fini for JPEG block511 *512 * @handle: amdgpu_device pointer513 *514 * JPEG free up sw allocation515 */516void jpeg_v1_0_sw_fini(void *handle)517{518 struct amdgpu_device *adev = (struct amdgpu_device *)handle;519 520 amdgpu_ring_fini(adev->jpeg.inst->ring_dec);521}522 523/**524 * jpeg_v1_0_start - start JPEG block525 *526 * @adev: amdgpu_device pointer527 * @mode: SPG or DPG mode528 *529 * Setup and start the JPEG block530 */531void jpeg_v1_0_start(struct amdgpu_device *adev, int mode)532{533 struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;534 535 if (mode == 0) {536 WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0);537 WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |538 UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);539 WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr));540 WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, upper_32_bits(ring->gpu_addr));541 WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0);542 WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0);543 WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);544 }545 546 /* initialize wptr */547 ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);548 549 /* copy patch commands to the jpeg ring */550 jpeg_v1_0_decode_ring_set_patch_ring(ring,551 (ring->wptr + ring->max_dw * amdgpu_sched_hw_submission));552}553 554static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {555 .type = AMDGPU_RING_TYPE_VCN_JPEG,556 .align_mask = 0xf,557 .nop = PACKET0(0x81ff, 0),558 .support_64bit_ptrs = false,559 .no_user_fence = true,560 .extra_dw = 64,561 .get_rptr = jpeg_v1_0_decode_ring_get_rptr,562 .get_wptr = jpeg_v1_0_decode_ring_get_wptr,563 .set_wptr = jpeg_v1_0_decode_ring_set_wptr,564 .parse_cs = jpeg_v1_dec_ring_parse_cs,565 .emit_frame_size =566 6 + 6 + /* hdp invalidate / flush */567 SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +568 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +569 8 + /* jpeg_v1_0_decode_ring_emit_vm_flush */570 26 + 26 + /* jpeg_v1_0_decode_ring_emit_fence x2 vm fence */571 6,572 .emit_ib_size = 22, /* jpeg_v1_0_decode_ring_emit_ib */573 .emit_ib = jpeg_v1_0_decode_ring_emit_ib,574 .emit_fence = jpeg_v1_0_decode_ring_emit_fence,575 .emit_vm_flush = jpeg_v1_0_decode_ring_emit_vm_flush,576 .test_ring = amdgpu_jpeg_dec_ring_test_ring,577 .test_ib = amdgpu_jpeg_dec_ring_test_ib,578 .insert_nop = jpeg_v1_0_decode_ring_nop,579 .insert_start = jpeg_v1_0_decode_ring_insert_start,580 .insert_end = jpeg_v1_0_decode_ring_insert_end,581 .pad_ib = amdgpu_ring_generic_pad_ib,582 .begin_use = jpeg_v1_0_ring_begin_use,583 .end_use = vcn_v1_0_ring_end_use,584 .emit_wreg = jpeg_v1_0_decode_ring_emit_wreg,585 .emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait,586 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,587};588 589static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)590{591 adev->jpeg.inst->ring_dec->funcs = &jpeg_v1_0_decode_ring_vm_funcs;592}593 594static const struct amdgpu_irq_src_funcs jpeg_v1_0_irq_funcs = {595 .set = jpeg_v1_0_set_interrupt_state,596 .process = jpeg_v1_0_process_interrupt,597};598 599static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)600{601 adev->jpeg.inst->irq.funcs = &jpeg_v1_0_irq_funcs;602}603 604static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)605{606 struct amdgpu_device *adev = ring->adev;607 bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);608 int cnt = 0;609 610 mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);611 612 if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))613 DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");614 615 for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {616 if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))617 DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);618 }619 620 vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);621}622 623/**624 * jpeg_v1_dec_ring_parse_cs - command submission parser625 *626 * @parser: Command submission parser context627 * @job: the job to parse628 * @ib: the IB to parse629 *630 * Parse the command stream, return -EINVAL for invalid packet,631 * 0 otherwise632 */633static int jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser *parser,634 struct amdgpu_job *job,635 struct amdgpu_ib *ib)636{637 u32 i, reg, res, cond, type;638 int ret = 0;639 struct amdgpu_device *adev = parser->adev;640 641 for (i = 0; i < ib->length_dw ; i += 2) {642 reg = CP_PACKETJ_GET_REG(ib->ptr[i]);643 res = CP_PACKETJ_GET_RES(ib->ptr[i]);644 cond = CP_PACKETJ_GET_COND(ib->ptr[i]);645 type = CP_PACKETJ_GET_TYPE(ib->ptr[i]);646 647 if (res || cond != PACKETJ_CONDITION_CHECK0) /* only allow 0 for now */648 return -EINVAL;649 650 if (reg >= JPEG_V1_REG_RANGE_START && reg <= JPEG_V1_REG_RANGE_END)651 continue;652 653 switch (type) {654 case PACKETJ_TYPE0:655 if (reg != JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_HIGH &&656 reg != JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_LOW &&657 reg != JPEG_V1_LMI_JPEG_READ_64BIT_BAR_HIGH &&658 reg != JPEG_V1_LMI_JPEG_READ_64BIT_BAR_LOW &&659 reg != JPEG_V1_REG_CTX_INDEX &&660 reg != JPEG_V1_REG_CTX_DATA) {661 ret = -EINVAL;662 }663 break;664 case PACKETJ_TYPE1:665 if (reg != JPEG_V1_REG_CTX_DATA)666 ret = -EINVAL;667 break;668 case PACKETJ_TYPE3:669 if (reg != JPEG_V1_REG_SOFT_RESET)670 ret = -EINVAL;671 break;672 case PACKETJ_TYPE6:673 if (ib->ptr[i] != CP_PACKETJ_NOP)674 ret = -EINVAL;675 break;676 default:677 ret = -EINVAL;678 }679 680 if (ret) {681 dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]);682 break;683 }684 }685 686 return ret;687}688