/** * uvd_v6_0_ring_test_ring - register write test * * @ring: amdgpu_ring pointer * * Test if we can successfully write to the context register */ static int uvd_v6_0_ring_test_ring(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; uint32_t tmp = 0; unsigned i; int r; WREG32(mmUVD_CONTEXT_ID, 0xCAFEDEAD); r = amdgpu_ring_alloc(ring, 3); if (r) { DRM_ERROR("amdgpu: cp failed to lock ring %d (%d).\n", ring->idx, r); return r; } amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0)); amdgpu_ring_write(ring, 0xDEADBEEF); amdgpu_ring_commit(ring); for (i = 0; i < adev->usec_timeout; i++) { tmp = RREG32(mmUVD_CONTEXT_ID); if (tmp == 0xDEADBEEF) break; DRM_UDELAY(1); } if (i < adev->usec_timeout) { DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); } else { DRM_ERROR("amdgpu: ring %d test failed (0x%08X)\n", ring->idx, tmp); r = -EINVAL; } return r; }
/** * cik_sdma_ring_emit_ib - Schedule an IB on the DMA engine * * @ring: amdgpu ring pointer * @ib: IB object to schedule * * Schedule an IB in the DMA ring (CIK). */ static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { u32 extra_bits = (ib->vm ? ib->vm->ids[ring->idx].id : 0) & 0xf; u32 next_rptr = ring->wptr + 5; while ((next_rptr & 7) != 4) next_rptr++; next_rptr += 4; amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0)); amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); amdgpu_ring_write(ring, 1); /* number of DWs to follow */ amdgpu_ring_write(ring, next_rptr); /* IB packet must end on a 8 DW boundary */ while ((ring->wptr & 7) != 4) amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0)); amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_INDIRECT_BUFFER, 0, extra_bits)); amdgpu_ring_write(ring, ib->gpu_addr & 0xffffffe0); /* base must be 32 byte aligned */ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xffffffff); amdgpu_ring_write(ring, ib->length_dw); }
/** * uvd_v6_0_ring_test_ring - register write test * * @ring: amdgpu_ring pointer * * Test if we can successfully write to the context register */ static int uvd_v6_0_ring_test_ring(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; uint32_t tmp = 0; unsigned i; int r; WREG32(mmUVD_CONTEXT_ID, 0xCAFEDEAD); r = amdgpu_ring_alloc(ring, 3); if (r) return r; amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0)); amdgpu_ring_write(ring, 0xDEADBEEF); amdgpu_ring_commit(ring); for (i = 0; i < adev->usec_timeout; i++) { tmp = RREG32(mmUVD_CONTEXT_ID); if (tmp == 0xDEADBEEF) break; DRM_UDELAY(1); } if (i >= adev->usec_timeout) r = -ETIMEDOUT; return r; }
/** * uvd_v5_0_hw_init - start and test UVD block * * @adev: amdgpu_device pointer * * Initialize the hardware, boot up the VCPU and do some testing */ static int uvd_v5_0_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ring *ring = &adev->uvd.ring; uint32_t tmp; int r; /* raise clocks while booting up the VCPU */ amdgpu_asic_set_uvd_clocks(adev, 53300, 40000); r = uvd_v5_0_start(adev); if (r) goto done; ring->ready = true; r = amdgpu_ring_test_ring(ring); if (r) { ring->ready = false; goto done; } r = amdgpu_ring_alloc(ring, 10); if (r) { DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r); goto done; } tmp = PACKET0(mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0); amdgpu_ring_write(ring, tmp); amdgpu_ring_write(ring, 0xFFFFF); tmp = PACKET0(mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0); amdgpu_ring_write(ring, tmp); amdgpu_ring_write(ring, 0xFFFFF); tmp = PACKET0(mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0); amdgpu_ring_write(ring, tmp); amdgpu_ring_write(ring, 0xFFFFF); /* Clear timeout status bits */ amdgpu_ring_write(ring, PACKET0(mmUVD_SEMA_TIMEOUT_STATUS, 0)); amdgpu_ring_write(ring, 0x8); amdgpu_ring_write(ring, PACKET0(mmUVD_SEMA_CNTL, 0)); amdgpu_ring_write(ring, 3); amdgpu_ring_commit(ring); done: /* lower clocks again */ amdgpu_asic_set_uvd_clocks(adev, 0, 0); if (!r) DRM_INFO("UVD initialized successfully.\n"); return r; }
static void uvd_v6_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned int vmid, uint64_t pd_addr) { amdgpu_ring_write(ring, HEVC_ENC_CMD_UPDATE_PTB); amdgpu_ring_write(ring, vmid); amdgpu_ring_write(ring, pd_addr >> 12); amdgpu_ring_write(ring, HEVC_ENC_CMD_FLUSH_TLB); amdgpu_ring_write(ring, vmid); }
static void uvd_v6_0_enc_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; amdgpu_ring_write(ring, HEVC_ENC_CMD_WAIT_GE); amdgpu_ring_write(ring, lower_32_bits(addr)); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, seq); }
/** * cik_sdma_emit_fill_buffer - fill buffer using the sDMA engine * * @ring: amdgpu_ring structure holding ring information * @src_data: value to write to buffer * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer * * Fill GPU buffers using the DMA engine (CIK). */ static void cik_sdma_emit_fill_buffer(struct amdgpu_ring *ring, uint32_t src_data, uint64_t dst_offset, uint32_t byte_count) { amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, 0)); amdgpu_ring_write(ring, lower_32_bits(dst_offset)); amdgpu_ring_write(ring, upper_32_bits(dst_offset)); amdgpu_ring_write(ring, src_data); amdgpu_ring_write(ring, byte_count); }
/** * uvd_v6_0_enc_ring_emit_fence - emit an enc fence & trap command * * @ring: amdgpu_ring pointer * @fence: fence to emit * * Write enc a fence and a trap command to the ring. */ static void uvd_v6_0_enc_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, unsigned flags) { WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); amdgpu_ring_write(ring, HEVC_ENC_CMD_FENCE); amdgpu_ring_write(ring, addr); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, seq); amdgpu_ring_write(ring, HEVC_ENC_CMD_TRAP); }
static void uvd_v6_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) { int i; WARN_ON(ring->wptr % 2 || count % 2); for (i = 0; i < count / 2; i++) { amdgpu_ring_write(ring, PACKET0(mmUVD_NO_OP, 0)); amdgpu_ring_write(ring, 0); } }
static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) { struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ring); int i; for (i = 0; i < count; i++) if (sdma && sdma->burst_nop && (i == 0)) amdgpu_ring_write(ring, ring->funcs->nop | SDMA_NOP_COUNT(count - 1)); else amdgpu_ring_write(ring, ring->funcs->nop); }
/** * uvd_v5_0_hw_init - start and test UVD block * * @adev: amdgpu_device pointer * * Initialize the hardware, boot up the VCPU and do some testing */ static int uvd_v5_0_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ring *ring = &adev->uvd.ring; uint32_t tmp; int r; amdgpu_asic_set_uvd_clocks(adev, 10000, 10000); uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE); uvd_v5_0_enable_mgcg(adev, true); ring->ready = true; r = amdgpu_ring_test_ring(ring); if (r) { ring->ready = false; goto done; } r = amdgpu_ring_alloc(ring, 10); if (r) { DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r); goto done; } tmp = PACKET0(mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0); amdgpu_ring_write(ring, tmp); amdgpu_ring_write(ring, 0xFFFFF); tmp = PACKET0(mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0); amdgpu_ring_write(ring, tmp); amdgpu_ring_write(ring, 0xFFFFF); tmp = PACKET0(mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0); amdgpu_ring_write(ring, tmp); amdgpu_ring_write(ring, 0xFFFFF); /* Clear timeout status bits */ amdgpu_ring_write(ring, PACKET0(mmUVD_SEMA_TIMEOUT_STATUS, 0)); amdgpu_ring_write(ring, 0x8); amdgpu_ring_write(ring, PACKET0(mmUVD_SEMA_CNTL, 0)); amdgpu_ring_write(ring, 3); amdgpu_ring_commit(ring); done: if (!r) DRM_INFO("UVD initialized successfully.\n"); return r; }
/** * uvd_v6_0_enc_ring_emit_ib - enc execute indirect buffer * * @ring: amdgpu_ring pointer * @ib: indirect buffer to execute * * Write enc ring commands to execute the indirect buffer */ static void uvd_v6_0_enc_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job, struct amdgpu_ib *ib, uint32_t flags) { unsigned vmid = AMDGPU_JOB_GET_VMID(job); amdgpu_ring_write(ring, HEVC_ENC_CMD_IB_VM); amdgpu_ring_write(ring, vmid); amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, ib->length_dw); }
/** * cik_sdma_ring_emit_semaphore - emit a semaphore on the dma ring * * @ring: amdgpu_ring structure holding ring information * @semaphore: amdgpu semaphore object * @emit_wait: wait or signal semaphore * * Add a DMA semaphore packet to the ring wait on or signal * other rings (CIK). */ static bool cik_sdma_ring_emit_semaphore(struct amdgpu_ring *ring, struct amdgpu_semaphore *semaphore, bool emit_wait) { u64 addr = semaphore->gpu_addr; u32 extra_bits = emit_wait ? 0 : SDMA_SEMAPHORE_EXTRA_S; amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SEMAPHORE, 0, extra_bits)); amdgpu_ring_write(ring, addr & 0xfffffff8); amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff); return true; }
static void si_dma_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, unsigned vm_id, bool ctx_switch) { /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring. * Pad as necessary with NOPs. */ while ((ring->wptr & 7) != 5) amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); amdgpu_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, vm_id, 0)); amdgpu_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0)); amdgpu_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF)); }
/** * cik_sdma_ring_test_ring - simple async dma engine test * * @ring: amdgpu_ring structure holding ring information * * Test the DMA engine by writing using it to write an * value to memory. (CIK). * Returns 0 for success, error for failure. */ static int cik_sdma_ring_test_ring(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; unsigned i; unsigned index; int r; u32 tmp; u64 gpu_addr; r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); return r; } gpu_addr = adev->wb.gpu_addr + (index * 4); tmp = 0xCAFEDEAD; adev->wb.wb[index] = cpu_to_le32(tmp); r = amdgpu_ring_alloc(ring, 5); if (r) { DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r); amdgpu_wb_free(adev, index); return r; } amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0)); amdgpu_ring_write(ring, lower_32_bits(gpu_addr)); amdgpu_ring_write(ring, upper_32_bits(gpu_addr)); amdgpu_ring_write(ring, 1); /* number of DWs to follow */ amdgpu_ring_write(ring, 0xDEADBEEF); amdgpu_ring_commit(ring); for (i = 0; i < adev->usec_timeout; i++) { tmp = le32_to_cpu(adev->wb.wb[index]); if (tmp == 0xDEADBEEF) break; DRM_UDELAY(1); } if (i < adev->usec_timeout) { DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); } else { DRM_ERROR("amdgpu: ring %d test failed (0x%08X)\n", ring->idx, tmp); r = -EINVAL; } amdgpu_wb_free(adev, index); return r; }
/** * cik_sdma_ring_emit_ib - Schedule an IB on the DMA engine * * @ring: amdgpu ring pointer * @ib: IB object to schedule * * Schedule an IB in the DMA ring (CIK). */ static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, unsigned vm_id, bool ctx_switch) { u32 extra_bits = vm_id & 0xf; /* IB packet must end on a 8 DW boundary */ cik_sdma_ring_insert_nop(ring, (12 - (lower_32_bits(ring->wptr) & 7)) % 8); amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_INDIRECT_BUFFER, 0, extra_bits)); amdgpu_ring_write(ring, ib->gpu_addr & 0xffffffe0); /* base must be 32 byte aligned */ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xffffffff); amdgpu_ring_write(ring, ib->length_dw); }
/** amdgpu_ring_insert_nop - insert NOP packets * * @ring: amdgpu_ring structure holding ring information * @count: the number of NOP packets to insert * * This is the generic insert_nop function for rings except SDMA */ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) { int i; for (i = 0; i < count; i++) amdgpu_ring_write(ring, ring->nop); }
static void uvd_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0)); amdgpu_ring_write(ring, lower_32_bits(addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0)); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_GP_SCRATCH8, 0)); amdgpu_ring_write(ring, 0xffffffff); /* mask */ amdgpu_ring_write(ring, PACKET0(mmUVD_GP_SCRATCH9, 0)); amdgpu_ring_write(ring, seq); amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0)); amdgpu_ring_write(ring, 0xE); }
static void uvd_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vmid, uint64_t pd_addr) { amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr); amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0)); amdgpu_ring_write(ring, mmVM_INVALIDATE_REQUEST << 2); amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0)); amdgpu_ring_write(ring, 0); amdgpu_ring_write(ring, PACKET0(mmUVD_GP_SCRATCH8, 0)); amdgpu_ring_write(ring, 1 << vmid); /* mask */ amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0)); amdgpu_ring_write(ring, 0xC); }
/** * uvd_v6_0_ring_emit_ib - execute indirect buffer * * @ring: amdgpu_ring pointer * @ib: indirect buffer to execute * * Write ring commands to execute the indirect buffer */ static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib, unsigned vm_id, bool ctx_switch) { amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_VMID, 0)); amdgpu_ring_write(ring, vm_id); amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0)); amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH, 0)); amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_SIZE, 0)); amdgpu_ring_write(ring, ib->length_dw); }
/** * cik_sdma_emit_copy_buffer - copy buffer using the sDMA engine * * @ring: amdgpu_ring structure holding ring information * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer * * Copy GPU buffers using the DMA engine (CIK). * Used by the amdgpu ttm implementation to move pages if * registered as the asic copy callback. */ static void cik_sdma_emit_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count) { amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0)); amdgpu_ring_write(ring, byte_count); amdgpu_ring_write(ring, 0); /* src/dst endian swap */ amdgpu_ring_write(ring, lower_32_bits(src_offset)); amdgpu_ring_write(ring, upper_32_bits(src_offset)); amdgpu_ring_write(ring, lower_32_bits(dst_offset)); amdgpu_ring_write(ring, upper_32_bits(dst_offset)); }
/** * uvd_v6_0_ring_emit_ib - execute indirect buffer * * @ring: amdgpu_ring pointer * @ib: indirect buffer to execute * * Write ring commands to execute the indirect buffer */ static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job, struct amdgpu_ib *ib, uint32_t flags) { unsigned vmid = AMDGPU_JOB_GET_VMID(job); amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_VMID, 0)); amdgpu_ring_write(ring, vmid); amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0)); amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH, 0)); amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_SIZE, 0)); amdgpu_ring_write(ring, ib->length_dw); }
/** * uvd_v6_0_ring_emit_ib - execute indirect buffer * * @ring: amdgpu_ring pointer * @ib: indirect buffer to execute * * Write ring commands to execute the indirect buffer */ static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0)); amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH, 0)); amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_SIZE, 0)); amdgpu_ring_write(ring, ib->length_dw); }
/** * si_dma_ring_emit_fence - emit a fence on the DMA ring * * @ring: amdgpu ring pointer * @fence: amdgpu fence object * * Add a DMA fence packet to the ring to write * the fence seq number and DMA trap packet to generate * an interrupt if needed (VI). */ static void si_dma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, unsigned flags) { bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; /* write the fence */ amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0, 0)); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xff)); amdgpu_ring_write(ring, seq); /* optionally write high bits as well */ if (write64bit) { addr += 4; amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0, 0)); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xff)); amdgpu_ring_write(ring, upper_32_bits(seq)); } /* generate an interrupt */ amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0, 0)); }
static void uvd_v6_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val) { amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0)); amdgpu_ring_write(ring, reg << 2); amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0)); amdgpu_ring_write(ring, val); amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0)); amdgpu_ring_write(ring, 0x8); }
/** * cik_sdma_ring_emit_pipeline_sync - sync the pipeline * * @ring: amdgpu_ring pointer * * Make sure all previous operations are completed (CIK). */ static void si_dma_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; /* wait for idle */ amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_POLL_REG_MEM, 0, 0, 0, 0) | (1 << 27)); /* Poll memory */ amdgpu_ring_write(ring, lower_32_bits(addr)); amdgpu_ring_write(ring, (0xff << 16) | upper_32_bits(addr)); /* retry, addr_hi */ amdgpu_ring_write(ring, 0xffffffff); /* mask */ amdgpu_ring_write(ring, seq); /* value */ amdgpu_ring_write(ring, (3 << 28) | 0x20); /* func(equal) | poll interval */ }
/** * amdgpu_ring_restore - append saved commands to the ring again * * @ring: ring to append commands to * @size: number of dwords we want to write * @data: saved commands * * Allocates space on the ring and restore the previously saved commands. */ int amdgpu_ring_restore(struct amdgpu_ring *ring, unsigned size, uint32_t *data) { int i, r; if (!size || !data) return 0; /* restore the saved ring content */ r = amdgpu_ring_alloc(ring, size); if (r) return r; for (i = 0; i < size; ++i) { amdgpu_ring_write(ring, data[i]); } amdgpu_ring_commit(ring); kfree(data); return 0; }
/** * cik_sdma_ring_emit_pipeline_sync - sync the pipeline * * @ring: amdgpu_ring pointer * * Make sure all previous operations are completed (CIK). */ static void cik_sdma_ring_emit_pipeline_sync(struct amdgpu_ring *ring) { uint32_t seq = ring->fence_drv.sync_seq; uint64_t addr = ring->fence_drv.gpu_addr; /* wait for idle */ amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, SDMA_POLL_REG_MEM_EXTRA_OP(0) | SDMA_POLL_REG_MEM_EXTRA_FUNC(3) | /* equal */ SDMA_POLL_REG_MEM_EXTRA_M)); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff); amdgpu_ring_write(ring, seq); /* reference */ amdgpu_ring_write(ring, 0xfffffff); /* mask */ amdgpu_ring_write(ring, (0xfff << 16) | 4); /* retry count, poll interval */ }
/** * cik_sdma_ring_emit_hdp_flush - emit an hdp flush on the DMA ring * * @ring: amdgpu ring pointer * * Emit an hdp flush packet on the requested DMA ring. */ static void cik_sdma_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) | SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */ u32 ref_and_mask; if (ring == &ring->adev->sdma.instance[0].ring) ref_and_mask = GPU_HDP_FLUSH_DONE__SDMA0_MASK; else ref_and_mask = GPU_HDP_FLUSH_DONE__SDMA1_MASK; amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits)); amdgpu_ring_write(ring, mmGPU_HDP_FLUSH_DONE << 2); amdgpu_ring_write(ring, mmGPU_HDP_FLUSH_REQ << 2); amdgpu_ring_write(ring, ref_and_mask); /* reference */ amdgpu_ring_write(ring, ref_and_mask); /* mask */ amdgpu_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ }
/** * uvd_v6_0_enc_ring_test_ring - test if UVD ENC ring is working * * @ring: the engine to test on * */ static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; uint32_t rptr = amdgpu_ring_get_rptr(ring); unsigned i; int r; r = amdgpu_ring_alloc(ring, 16); if (r) return r; amdgpu_ring_write(ring, HEVC_ENC_CMD_END); amdgpu_ring_commit(ring); for (i = 0; i < adev->usec_timeout; i++) { if (amdgpu_ring_get_rptr(ring) != rptr) break; DRM_UDELAY(1); } if (i >= adev->usec_timeout) r = -ETIMEDOUT; return r; }