Commit f2ba57b5 authored by Christian König's avatar Christian König Committed by Alex Deucher

drm/radeon: UVD bringup v8

Just everything needed to decode videos using UVD.

v6: just all the bugfixes and support for R7xx-SI merged in one patch
v7: UVD_CGC_GATE is a write only register, lockup detection fix
v8: split out VRAM fallback changes, remove support for RV770,
    add support for HEMLOCK, add buffer sizes checks
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4474f3a9
...@@ -76,7 +76,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ ...@@ -76,7 +76,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
si_blit_shaders.o radeon_prime.o si_blit_shaders.o radeon_prime.o radeon_uvd.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
......
...@@ -3360,6 +3360,9 @@ int evergreen_irq_process(struct radeon_device *rdev) ...@@ -3360,6 +3360,9 @@ int evergreen_irq_process(struct radeon_device *rdev)
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
break; break;
} }
case 124: /* UVD */
DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
break; break;
case 146: case 146:
case 147: case 147:
...@@ -3571,7 +3574,7 @@ int evergreen_copy_dma(struct radeon_device *rdev, ...@@ -3571,7 +3574,7 @@ int evergreen_copy_dma(struct radeon_device *rdev,
static int evergreen_startup(struct radeon_device *rdev) static int evergreen_startup(struct radeon_device *rdev)
{ {
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; struct radeon_ring *ring;
int r; int r;
/* enable pcie gen2 link */ /* enable pcie gen2 link */
...@@ -3638,6 +3641,17 @@ static int evergreen_startup(struct radeon_device *rdev) ...@@ -3638,6 +3641,17 @@ static int evergreen_startup(struct radeon_device *rdev)
return r; return r;
} }
r = rv770_uvd_resume(rdev);
if (!r) {
r = radeon_fence_driver_start_ring(rdev,
R600_RING_TYPE_UVD_INDEX);
if (r)
dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
}
if (r)
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
/* Enable IRQ */ /* Enable IRQ */
r = r600_irq_init(rdev); r = r600_irq_init(rdev);
if (r) { if (r) {
...@@ -3647,6 +3661,7 @@ static int evergreen_startup(struct radeon_device *rdev) ...@@ -3647,6 +3661,7 @@ static int evergreen_startup(struct radeon_device *rdev)
} }
evergreen_irq_set(rdev); evergreen_irq_set(rdev);
ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
R600_CP_RB_RPTR, R600_CP_RB_WPTR, R600_CP_RB_RPTR, R600_CP_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2); 0, 0xfffff, RADEON_CP_PACKET2);
...@@ -3670,6 +3685,19 @@ static int evergreen_startup(struct radeon_device *rdev) ...@@ -3670,6 +3685,19 @@ static int evergreen_startup(struct radeon_device *rdev)
if (r) if (r)
return r; return r;
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
r = r600_uvd_init(rdev);
if (r)
DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
}
r = radeon_ib_pool_init(rdev); r = radeon_ib_pool_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
...@@ -3716,8 +3744,10 @@ int evergreen_resume(struct radeon_device *rdev) ...@@ -3716,8 +3744,10 @@ int evergreen_resume(struct radeon_device *rdev)
int evergreen_suspend(struct radeon_device *rdev) int evergreen_suspend(struct radeon_device *rdev)
{ {
r600_audio_fini(rdev); r600_audio_fini(rdev);
radeon_uvd_suspend(rdev);
r700_cp_stop(rdev); r700_cp_stop(rdev);
r600_dma_stop(rdev); r600_dma_stop(rdev);
r600_uvd_rbc_stop(rdev);
evergreen_irq_suspend(rdev); evergreen_irq_suspend(rdev);
radeon_wb_disable(rdev); radeon_wb_disable(rdev);
evergreen_pcie_gart_disable(rdev); evergreen_pcie_gart_disable(rdev);
...@@ -3797,6 +3827,13 @@ int evergreen_init(struct radeon_device *rdev) ...@@ -3797,6 +3827,13 @@ int evergreen_init(struct radeon_device *rdev)
rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
r = radeon_uvd_init(rdev);
if (!r) {
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
4096);
}
rdev->ih.ring_obj = NULL; rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024); r600_ih_ring_init(rdev, 64 * 1024);
...@@ -3843,6 +3880,7 @@ void evergreen_fini(struct radeon_device *rdev) ...@@ -3843,6 +3880,7 @@ void evergreen_fini(struct radeon_device *rdev)
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
evergreen_pcie_gart_fini(rdev); evergreen_pcie_gart_fini(rdev);
radeon_uvd_fini(rdev);
r600_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev); radeon_fence_driver_fini(rdev);
......
...@@ -992,6 +992,13 @@ ...@@ -992,6 +992,13 @@
# define TARGET_LINK_SPEED_MASK (0xf << 0) # define TARGET_LINK_SPEED_MASK (0xf << 0)
# define SELECTABLE_DEEMPHASIS (1 << 6) # define SELECTABLE_DEEMPHASIS (1 << 6)
/*
* UVD
*/
#define UVD_RBC_RB_RPTR 0xf690
#define UVD_RBC_RB_WPTR 0xf694
/* /*
* PM4 * PM4
*/ */
......
...@@ -933,6 +933,23 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -933,6 +933,23 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
radeon_ring_write(ring, 10); /* poll interval */ radeon_ring_write(ring, 10); /* poll interval */
} }
void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
struct radeon_ring *ring,
struct radeon_semaphore *semaphore,
bool emit_wait)
{
uint64_t addr = semaphore->gpu_addr;
radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
radeon_ring_write(ring, 0x80 | (emit_wait ? 1 : 0));
}
static void cayman_cp_enable(struct radeon_device *rdev, bool enable) static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
{ {
if (enable) if (enable)
...@@ -1684,6 +1701,16 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -1684,6 +1701,16 @@ static int cayman_startup(struct radeon_device *rdev)
return r; return r;
} }
r = rv770_uvd_resume(rdev);
if (!r) {
r = radeon_fence_driver_start_ring(rdev,
R600_RING_TYPE_UVD_INDEX);
if (r)
dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
}
if (r)
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
if (r) { if (r) {
dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
...@@ -1750,6 +1777,18 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -1750,6 +1777,18 @@ static int cayman_startup(struct radeon_device *rdev)
if (r) if (r)
return r; return r;
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
r = r600_uvd_init(rdev);
if (r)
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
}
r = radeon_ib_pool_init(rdev); r = radeon_ib_pool_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
...@@ -1796,6 +1835,8 @@ int cayman_suspend(struct radeon_device *rdev) ...@@ -1796,6 +1835,8 @@ int cayman_suspend(struct radeon_device *rdev)
radeon_vm_manager_fini(rdev); radeon_vm_manager_fini(rdev);
cayman_cp_enable(rdev, false); cayman_cp_enable(rdev, false);
cayman_dma_stop(rdev); cayman_dma_stop(rdev);
r600_uvd_rbc_stop(rdev);
radeon_uvd_suspend(rdev);
evergreen_irq_suspend(rdev); evergreen_irq_suspend(rdev);
radeon_wb_disable(rdev); radeon_wb_disable(rdev);
cayman_pcie_gart_disable(rdev); cayman_pcie_gart_disable(rdev);
...@@ -1870,6 +1911,13 @@ int cayman_init(struct radeon_device *rdev) ...@@ -1870,6 +1911,13 @@ int cayman_init(struct radeon_device *rdev)
ring->ring_obj = NULL; ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 64 * 1024); r600_ring_init(rdev, ring, 64 * 1024);
r = radeon_uvd_init(rdev);
if (!r) {
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 4096);
}
rdev->ih.ring_obj = NULL; rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024); r600_ih_ring_init(rdev, 64 * 1024);
...@@ -1921,6 +1969,7 @@ void cayman_fini(struct radeon_device *rdev) ...@@ -1921,6 +1969,7 @@ void cayman_fini(struct radeon_device *rdev)
radeon_vm_manager_fini(rdev); radeon_vm_manager_fini(rdev);
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
radeon_uvd_fini(rdev);
cayman_pcie_gart_fini(rdev); cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
......
...@@ -489,6 +489,15 @@ ...@@ -489,6 +489,15 @@
# define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0) # define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0)
# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) # define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0)
/*
* UVD
*/
#define UVD_SEMA_ADDR_LOW 0xEF00
#define UVD_SEMA_ADDR_HIGH 0xEF04
#define UVD_SEMA_CMD 0xEF08
#define UVD_RBC_RB_RPTR 0xF690
#define UVD_RBC_RB_WPTR 0xF694
/* /*
* PM4 * PM4
*/ */
......
...@@ -2551,6 +2551,185 @@ void r600_dma_fini(struct radeon_device *rdev) ...@@ -2551,6 +2551,185 @@ void r600_dma_fini(struct radeon_device *rdev)
radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]); radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]);
} }
/*
* UVD
*/
int r600_uvd_rbc_start(struct radeon_device *rdev)
{
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
uint64_t rptr_addr;
uint32_t rb_bufsz, tmp;
int r;
rptr_addr = rdev->wb.gpu_addr + R600_WB_UVD_RPTR_OFFSET;
if (upper_32_bits(rptr_addr) != upper_32_bits(ring->gpu_addr)) {
DRM_ERROR("UVD ring and rptr not in the same 4GB segment!\n");
return -EINVAL;
}
/* force RBC into idle state */
WREG32(UVD_RBC_RB_CNTL, 0x11010101);
/* Set the write pointer delay */
WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
/* set the wb address */
WREG32(UVD_RBC_RB_RPTR_ADDR, rptr_addr >> 2);
/* programm the 4GB memory segment for rptr and ring buffer */
WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(rptr_addr) |
(0x7 << 16) | (0x1 << 31));
/* Initialize the ring buffer's read and write pointers */
WREG32(UVD_RBC_RB_RPTR, 0x0);
ring->wptr = ring->rptr = RREG32(UVD_RBC_RB_RPTR);
WREG32(UVD_RBC_RB_WPTR, ring->wptr);
/* set the ring address */
WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
/* Set ring buffer size */
rb_bufsz = drm_order(ring->ring_size);
rb_bufsz = (0x1 << 8) | rb_bufsz;
WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
ring->ready = true;
r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
if (r) {
ring->ready = false;
return r;
}
r = radeon_ring_lock(rdev, ring, 10);
if (r) {
DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
return r;
}
tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
radeon_ring_write(ring, tmp);
radeon_ring_write(ring, 0xFFFFF);
tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
radeon_ring_write(ring, tmp);
radeon_ring_write(ring, 0xFFFFF);
tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
radeon_ring_write(ring, tmp);
radeon_ring_write(ring, 0xFFFFF);
/* Clear timeout status bits */
radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
radeon_ring_write(ring, 0x8);
radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
radeon_ring_write(ring, 1);
radeon_ring_unlock_commit(rdev, ring);
return 0;
}
void r600_uvd_rbc_stop(struct radeon_device *rdev)
{
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
/* force RBC into idle state */
WREG32(UVD_RBC_RB_CNTL, 0x11010101);
ring->ready = false;
}
int r600_uvd_init(struct radeon_device *rdev)
{
int i, j, r;
/* disable clock gating */
WREG32(UVD_CGC_GATE, 0);
/* disable interupt */
WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
/* put LMI, VCPU, RBC etc... into reset */
WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
mdelay(5);
/* take UVD block out of reset */
WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
mdelay(5);
/* initialize UVD memory controller */
WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
(1 << 21) | (1 << 9) | (1 << 20));
/* disable byte swapping */
WREG32(UVD_LMI_SWAP_CNTL, 0);
WREG32(UVD_MP_SWAP_CNTL, 0);
WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
WREG32(UVD_MPC_SET_MUXA1, 0x0);
WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
WREG32(UVD_MPC_SET_MUXB1, 0x0);
WREG32(UVD_MPC_SET_ALU, 0);
WREG32(UVD_MPC_SET_MUX, 0x88);
/* Stall UMC */
WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
/* take all subblocks out of reset, except VCPU */
WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
mdelay(5);
/* enable VCPU clock */
WREG32(UVD_VCPU_CNTL, 1 << 9);
/* enable UMC */
WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
/* boot up the VCPU */
WREG32(UVD_SOFT_RESET, 0);
mdelay(10);
WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
for (i = 0; i < 10; ++i) {
uint32_t status;
for (j = 0; j < 100; ++j) {
status = RREG32(UVD_STATUS);
if (status & 2)
break;
mdelay(10);
}
r = 0;
if (status & 2)
break;
DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
mdelay(10);
WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
mdelay(10);
r = -1;
}
if (r) {
DRM_ERROR("UVD not responding, giving up!!!\n");
return r;
}
/* enable interupt */
WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
r = r600_uvd_rbc_start(rdev);
if (r)
return r;
DRM_INFO("UVD initialized successfully.\n");
return 0;
}
/* /*
* GPU scratch registers helpers function. * GPU scratch registers helpers function.
*/ */
...@@ -2660,6 +2839,40 @@ int r600_dma_ring_test(struct radeon_device *rdev, ...@@ -2660,6 +2839,40 @@ int r600_dma_ring_test(struct radeon_device *rdev,
return r; return r;
} }
int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
{
uint32_t tmp = 0;
unsigned i;
int r;
WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
r = radeon_ring_lock(rdev, ring, 3);
if (r) {
DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
ring->idx, r);
return r;
}
radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
radeon_ring_write(ring, 0xDEADBEEF);
radeon_ring_unlock_commit(rdev, ring);
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(UVD_CONTEXT_ID);
if (tmp == 0xDEADBEEF)
break;
DRM_UDELAY(1);
}
if (i < rdev->usec_timeout) {
DRM_INFO("ring test on %d succeeded in %d usecs\n",
ring->idx, i);
} else {
DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
ring->idx, tmp);
r = -EINVAL;
}
return r;
}
/* /*
* CP fences/semaphores * CP fences/semaphores
*/ */
...@@ -2711,6 +2924,30 @@ void r600_fence_ring_emit(struct radeon_device *rdev, ...@@ -2711,6 +2924,30 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
} }
} }
void r600_uvd_fence_emit(struct radeon_device *rdev,
struct radeon_fence *fence)
{
struct radeon_ring *ring = &rdev->ring[fence->ring];
uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
radeon_ring_write(ring, fence->seq);
radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
radeon_ring_write(ring, addr & 0xffffffff);
radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
radeon_ring_write(ring, 0);
radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
radeon_ring_write(ring, 0);
radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
radeon_ring_write(ring, 0);
radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
radeon_ring_write(ring, 2);
return;
}
void r600_semaphore_ring_emit(struct radeon_device *rdev, void r600_semaphore_ring_emit(struct radeon_device *rdev,
struct radeon_ring *ring, struct radeon_ring *ring,
struct radeon_semaphore *semaphore, struct radeon_semaphore *semaphore,
...@@ -2780,6 +3017,23 @@ void r600_dma_semaphore_ring_emit(struct radeon_device *rdev, ...@@ -2780,6 +3017,23 @@ void r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
radeon_ring_write(ring, upper_32_bits(addr) & 0xff); radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
} }
void r600_uvd_semaphore_emit(struct radeon_device *rdev,
struct radeon_ring *ring,
struct radeon_semaphore *semaphore,
bool emit_wait)
{
uint64_t addr = semaphore->gpu_addr;
radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
radeon_ring_write(ring, emit_wait ? 1 : 0);
}
int r600_copy_blit(struct radeon_device *rdev, int r600_copy_blit(struct radeon_device *rdev,
uint64_t src_offset, uint64_t src_offset,
uint64_t dst_offset, uint64_t dst_offset,
...@@ -3183,6 +3437,16 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -3183,6 +3437,16 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
radeon_ring_write(ring, ib->length_dw); radeon_ring_write(ring, ib->length_dw);
} }
void r600_uvd_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{
struct radeon_ring *ring = &rdev->ring[ib->ring];
radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
radeon_ring_write(ring, ib->gpu_addr);
radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
radeon_ring_write(ring, ib->length_dw);
}
int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
{ {
struct radeon_ib ib; struct radeon_ib ib;
...@@ -3300,6 +3564,33 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -3300,6 +3564,33 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
return r; return r;
} }
int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
{
struct radeon_fence *fence;
int r;
r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
if (r) {
DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
return r;
}
r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
if (r) {
DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
return r;
}
r = radeon_fence_wait(fence, false);
if (r) {
DRM_ERROR("radeon: fence wait failed (%d).\n", r);
return r;
}
DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
radeon_fence_unref(&fence);
return r;
}
/** /**
* r600_dma_ring_ib_execute - Schedule an IB on the DMA engine * r600_dma_ring_ib_execute - Schedule an IB on the DMA engine
* *
......
...@@ -691,6 +691,7 @@ ...@@ -691,6 +691,7 @@
#define SRBM_SOFT_RESET 0xe60 #define SRBM_SOFT_RESET 0xe60
# define SOFT_RESET_DMA (1 << 12) # define SOFT_RESET_DMA (1 << 12)
# define SOFT_RESET_RLC (1 << 13) # define SOFT_RESET_RLC (1 << 13)
# define SOFT_RESET_UVD (1 << 18)
# define RV770_SOFT_RESET_DMA (1 << 20) # define RV770_SOFT_RESET_DMA (1 << 20)
#define CP_INT_CNTL 0xc124 #define CP_INT_CNTL 0xc124
...@@ -1142,6 +1143,66 @@ ...@@ -1142,6 +1143,66 @@
# define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29) # define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29)
# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30) # define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30)
/*
* UVD
*/
#define UVD_SEMA_ADDR_LOW 0xef00
#define UVD_SEMA_ADDR_HIGH 0xef04
#define UVD_SEMA_CMD 0xef08
#define UVD_GPCOM_VCPU_CMD 0xef0c
#define UVD_GPCOM_VCPU_DATA0 0xef10
#define UVD_GPCOM_VCPU_DATA1 0xef14
#define UVD_ENGINE_CNTL 0xef18
#define UVD_SEMA_CNTL 0xf400
#define UVD_RB_ARB_CTRL 0xf480
#define UVD_LMI_EXT40_ADDR 0xf498
#define UVD_CGC_GATE 0xf4a8
#define UVD_LMI_CTRL2 0xf4f4
#define UVD_MASTINT_EN 0xf500
#define UVD_LMI_ADDR_EXT 0xf594
#define UVD_LMI_CTRL 0xf598
#define UVD_LMI_SWAP_CNTL 0xf5b4
#define UVD_MP_SWAP_CNTL 0xf5bC
#define UVD_MPC_CNTL 0xf5dC
#define UVD_MPC_SET_MUXA0 0xf5e4
#define UVD_MPC_SET_MUXA1 0xf5e8
#define UVD_MPC_SET_MUXB0 0xf5eC
#define UVD_MPC_SET_MUXB1 0xf5f0
#define UVD_MPC_SET_MUX 0xf5f4
#define UVD_MPC_SET_ALU 0xf5f8
#define UVD_VCPU_CNTL 0xf660
#define UVD_SOFT_RESET 0xf680
#define RBC_SOFT_RESET (1<<0)
#define LBSI_SOFT_RESET (1<<1)
#define LMI_SOFT_RESET (1<<2)
#define VCPU_SOFT_RESET (1<<3)
#define CSM_SOFT_RESET (1<<5)
#define CXW_SOFT_RESET (1<<6)
#define TAP_SOFT_RESET (1<<7)
#define LMI_UMC_SOFT_RESET (1<<13)
#define UVD_RBC_IB_BASE 0xf684
#define UVD_RBC_IB_SIZE 0xf688
#define UVD_RBC_RB_BASE 0xf68c
#define UVD_RBC_RB_RPTR 0xf690
#define UVD_RBC_RB_WPTR 0xf694
#define UVD_RBC_RB_WPTR_CNTL 0xf698
#define UVD_STATUS 0xf6bc
#define UVD_SEMA_TIMEOUT_STATUS 0xf6c0
#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL 0xf6c4
#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL 0xf6c8
#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL 0xf6cc
#define UVD_RBC_RB_CNTL 0xf6a4
#define UVD_RBC_RB_RPTR_ADDR 0xf6a8
#define UVD_CONTEXT_ID 0xf6f4
/* /*
* PM4 * PM4
*/ */
......
...@@ -110,7 +110,7 @@ extern int radeon_fastfb; ...@@ -110,7 +110,7 @@ extern int radeon_fastfb;
#define RADEON_BIOS_NUM_SCRATCH 8 #define RADEON_BIOS_NUM_SCRATCH 8
/* max number of rings */ /* max number of rings */
#define RADEON_NUM_RINGS 5 #define RADEON_NUM_RINGS 6
/* fence seq are set to this number when signaled */ /* fence seq are set to this number when signaled */
#define RADEON_FENCE_SIGNALED_SEQ 0LL #define RADEON_FENCE_SIGNALED_SEQ 0LL
...@@ -128,6 +128,9 @@ extern int radeon_fastfb; ...@@ -128,6 +128,9 @@ extern int radeon_fastfb;
/* cayman add a second async dma ring */ /* cayman add a second async dma ring */
#define CAYMAN_RING_TYPE_DMA1_INDEX 4 #define CAYMAN_RING_TYPE_DMA1_INDEX 4
/* R600+ */
#define R600_RING_TYPE_UVD_INDEX 5
/* hardcode those limit for now */ /* hardcode those limit for now */
#define RADEON_VA_IB_OFFSET (1 << 20) #define RADEON_VA_IB_OFFSET (1 << 20)
#define RADEON_VA_RESERVED_SIZE (8 << 20) #define RADEON_VA_RESERVED_SIZE (8 << 20)
...@@ -921,6 +924,7 @@ struct radeon_wb { ...@@ -921,6 +924,7 @@ struct radeon_wb {
#define R600_WB_DMA_RPTR_OFFSET 1792 #define R600_WB_DMA_RPTR_OFFSET 1792
#define R600_WB_IH_WPTR_OFFSET 2048 #define R600_WB_IH_WPTR_OFFSET 2048
#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304 #define CAYMAN_WB_DMA1_RPTR_OFFSET 2304
#define R600_WB_UVD_RPTR_OFFSET 2560
#define R600_WB_EVENT_OFFSET 3072 #define R600_WB_EVENT_OFFSET 3072
/** /**
...@@ -1121,6 +1125,33 @@ struct radeon_pm { ...@@ -1121,6 +1125,33 @@ struct radeon_pm {
int radeon_pm_get_type_index(struct radeon_device *rdev, int radeon_pm_get_type_index(struct radeon_device *rdev,
enum radeon_pm_state_type ps_type, enum radeon_pm_state_type ps_type,
int instance); int instance);
/*
* UVD
*/
#define RADEON_MAX_UVD_HANDLES 10
#define RADEON_UVD_STACK_SIZE (1024*1024)
#define RADEON_UVD_HEAP_SIZE (1024*1024)
struct radeon_uvd {
struct radeon_bo *vcpu_bo;
void *cpu_addr;
uint64_t gpu_addr;
atomic_t handles[RADEON_MAX_UVD_HANDLES];
struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
};
int radeon_uvd_init(struct radeon_device *rdev);
void radeon_uvd_fini(struct radeon_device *rdev);
int radeon_uvd_suspend(struct radeon_device *rdev);
int radeon_uvd_resume(struct radeon_device *rdev);
int radeon_uvd_get_create_msg(struct radeon_device *rdev, int ring,
uint32_t handle, struct radeon_fence **fence);
int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring,
uint32_t handle, struct radeon_fence **fence);
void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo);
void radeon_uvd_free_handles(struct radeon_device *rdev,
struct drm_file *filp);
int radeon_uvd_cs_parse(struct radeon_cs_parser *parser);
struct r600_audio { struct r600_audio {
int channels; int channels;
...@@ -1611,6 +1642,7 @@ struct radeon_device { ...@@ -1611,6 +1642,7 @@ struct radeon_device {
struct radeon_asic *asic; struct radeon_asic *asic;
struct radeon_gem gem; struct radeon_gem gem;
struct radeon_pm pm; struct radeon_pm pm;
struct radeon_uvd uvd;
uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH];
struct radeon_wb wb; struct radeon_wb wb;
struct radeon_dummy_page dummy_page; struct radeon_dummy_page dummy_page;
...@@ -1625,6 +1657,7 @@ struct radeon_device { ...@@ -1625,6 +1657,7 @@ struct radeon_device {
const struct firmware *rlc_fw; /* r6/700 RLC firmware */ const struct firmware *rlc_fw; /* r6/700 RLC firmware */
const struct firmware *mc_fw; /* NI MC firmware */ const struct firmware *mc_fw; /* NI MC firmware */
const struct firmware *ce_fw; /* SI CE firmware */ const struct firmware *ce_fw; /* SI CE firmware */
const struct firmware *uvd_fw; /* UVD firmware */
struct r600_blit r600_blit; struct r600_blit r600_blit;
struct r600_vram_scratch vram_scratch; struct r600_vram_scratch vram_scratch;
int msi_enabled; /* msi enabled */ int msi_enabled; /* msi enabled */
......
...@@ -1130,6 +1130,15 @@ static struct radeon_asic rv770_asic = { ...@@ -1130,6 +1130,15 @@ static struct radeon_asic rv770_asic = {
.ring_test = &r600_dma_ring_test, .ring_test = &r600_dma_ring_test,
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &r600_dma_is_lockup, .is_lockup = &r600_dma_is_lockup,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &r600_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
...@@ -1216,6 +1225,15 @@ static struct radeon_asic evergreen_asic = { ...@@ -1216,6 +1225,15 @@ static struct radeon_asic evergreen_asic = {
.ring_test = &r600_dma_ring_test, .ring_test = &r600_dma_ring_test,
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &evergreen_dma_is_lockup, .is_lockup = &evergreen_dma_is_lockup,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &r600_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
...@@ -1302,6 +1320,15 @@ static struct radeon_asic sumo_asic = { ...@@ -1302,6 +1320,15 @@ static struct radeon_asic sumo_asic = {
.ring_test = &r600_dma_ring_test, .ring_test = &r600_dma_ring_test,
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &evergreen_dma_is_lockup, .is_lockup = &evergreen_dma_is_lockup,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &r600_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
...@@ -1388,6 +1415,15 @@ static struct radeon_asic btc_asic = { ...@@ -1388,6 +1415,15 @@ static struct radeon_asic btc_asic = {
.ring_test = &r600_dma_ring_test, .ring_test = &r600_dma_ring_test,
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &evergreen_dma_is_lockup, .is_lockup = &evergreen_dma_is_lockup,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &r600_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
...@@ -1517,6 +1553,15 @@ static struct radeon_asic cayman_asic = { ...@@ -1517,6 +1553,15 @@ static struct radeon_asic cayman_asic = {
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &cayman_dma_is_lockup, .is_lockup = &cayman_dma_is_lockup,
.vm_flush = &cayman_dma_vm_flush, .vm_flush = &cayman_dma_vm_flush,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &cayman_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
...@@ -1646,6 +1691,15 @@ static struct radeon_asic trinity_asic = { ...@@ -1646,6 +1691,15 @@ static struct radeon_asic trinity_asic = {
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &cayman_dma_is_lockup, .is_lockup = &cayman_dma_is_lockup,
.vm_flush = &cayman_dma_vm_flush, .vm_flush = &cayman_dma_vm_flush,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &cayman_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
...@@ -1775,6 +1829,15 @@ static struct radeon_asic si_asic = { ...@@ -1775,6 +1829,15 @@ static struct radeon_asic si_asic = {
.ib_test = &r600_dma_ib_test, .ib_test = &r600_dma_ib_test,
.is_lockup = &si_dma_is_lockup, .is_lockup = &si_dma_is_lockup,
.vm_flush = &si_dma_vm_flush, .vm_flush = &si_dma_vm_flush,
},
[R600_RING_TYPE_UVD_INDEX] = {
.ib_execute = &r600_uvd_ib_execute,
.emit_fence = &r600_uvd_fence_emit,
.emit_semaphore = &cayman_uvd_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
} }
}, },
.irq = { .irq = {
......
...@@ -330,6 +330,7 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); ...@@ -330,6 +330,7 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
int r600_copy_blit(struct radeon_device *rdev, int r600_copy_blit(struct radeon_device *rdev,
uint64_t src_offset, uint64_t dst_offset, uint64_t src_offset, uint64_t dst_offset,
unsigned num_gpu_pages, struct radeon_fence **fence); unsigned num_gpu_pages, struct radeon_fence **fence);
...@@ -392,6 +393,19 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev); ...@@ -392,6 +393,19 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
u32 r600_get_xclk(struct radeon_device *rdev); u32 r600_get_xclk(struct radeon_device *rdev);
uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
/* uvd */
int r600_uvd_init(struct radeon_device *rdev);
int r600_uvd_rbc_start(struct radeon_device *rdev);
void r600_uvd_rbc_stop(struct radeon_device *rdev);
int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
void r600_uvd_fence_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
void r600_uvd_semaphore_emit(struct radeon_device *rdev,
struct radeon_ring *ring,
struct radeon_semaphore *semaphore,
bool emit_wait);
void r600_uvd_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
/* /*
* rv770,rv730,rv710,rv740 * rv770,rv730,rv710,rv740
*/ */
...@@ -409,6 +423,7 @@ int rv770_copy_dma(struct radeon_device *rdev, ...@@ -409,6 +423,7 @@ int rv770_copy_dma(struct radeon_device *rdev,
unsigned num_gpu_pages, unsigned num_gpu_pages,
struct radeon_fence **fence); struct radeon_fence **fence);
u32 rv770_get_xclk(struct radeon_device *rdev); u32 rv770_get_xclk(struct radeon_device *rdev);
int rv770_uvd_resume(struct radeon_device *rdev);
/* /*
* evergreen * evergreen
...@@ -465,6 +480,10 @@ int evergreen_copy_dma(struct radeon_device *rdev, ...@@ -465,6 +480,10 @@ int evergreen_copy_dma(struct radeon_device *rdev,
*/ */
void cayman_fence_ring_emit(struct radeon_device *rdev, void cayman_fence_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence); struct radeon_fence *fence);
void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
struct radeon_ring *ring,
struct radeon_semaphore *semaphore,
bool emit_wait);
void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev);
int cayman_init(struct radeon_device *rdev); int cayman_init(struct radeon_device *rdev);
void cayman_fini(struct radeon_device *rdev); void cayman_fini(struct radeon_device *rdev);
......
...@@ -53,7 +53,6 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) ...@@ -53,7 +53,6 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
} }
for (i = 0; i < p->nrelocs; i++) { for (i = 0; i < p->nrelocs; i++) {
struct drm_radeon_cs_reloc *r; struct drm_radeon_cs_reloc *r;
uint32_t domain;
duplicate = false; duplicate = false;
r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4]; r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
...@@ -81,11 +80,25 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) ...@@ -81,11 +80,25 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
p->relocs[i].lobj.bo = p->relocs[i].robj; p->relocs[i].lobj.bo = p->relocs[i].robj;
p->relocs[i].lobj.written = !!r->write_domain; p->relocs[i].lobj.written = !!r->write_domain;
domain = r->write_domain ? r->write_domain : r->read_domains; /* the first reloc of an UVD job is the
msg and that must be in VRAM */
if (p->ring == R600_RING_TYPE_UVD_INDEX && i == 0) {
/* TODO: is this still needed for NI+ ? */
p->relocs[i].lobj.domain =
RADEON_GEM_DOMAIN_VRAM;
p->relocs[i].lobj.alt_domain =
RADEON_GEM_DOMAIN_VRAM;
} else {
uint32_t domain = r->write_domain ?
r->write_domain : r->read_domains;
p->relocs[i].lobj.domain = domain; p->relocs[i].lobj.domain = domain;
if (domain == RADEON_GEM_DOMAIN_VRAM) if (domain == RADEON_GEM_DOMAIN_VRAM)
domain |= RADEON_GEM_DOMAIN_GTT; domain |= RADEON_GEM_DOMAIN_GTT;
p->relocs[i].lobj.alt_domain = domain; p->relocs[i].lobj.alt_domain = domain;
}
p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo;
p->relocs[i].handle = r->handle; p->relocs[i].handle = r->handle;
...@@ -93,7 +106,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) ...@@ -93,7 +106,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
radeon_bo_list_add_object(&p->relocs[i].lobj, radeon_bo_list_add_object(&p->relocs[i].lobj,
&p->validated); &p->validated);
} }
return radeon_bo_list_validate(&p->validated); return radeon_bo_list_validate(&p->validated, p->ring);
} }
static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
...@@ -128,6 +141,9 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority ...@@ -128,6 +141,9 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
return -EINVAL; return -EINVAL;
} }
break; break;
case RADEON_CS_RING_UVD:
p->ring = R600_RING_TYPE_UVD_INDEX;
break;
} }
return 0; return 0;
} }
......
...@@ -31,9 +31,9 @@ ...@@ -31,9 +31,9 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/list.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/firmware.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
...@@ -767,8 +767,21 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) ...@@ -767,8 +767,21 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) { if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) {
if (ring != R600_RING_TYPE_UVD_INDEX) {
rdev->fence_drv[ring].scratch_reg = 0; rdev->fence_drv[ring].scratch_reg = 0;
index = R600_WB_EVENT_OFFSET + ring * 4; index = R600_WB_EVENT_OFFSET + ring * 4;
rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr +
index;
} else {
/* put fence directly behind firmware */
rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr +
rdev->uvd_fw->size;
rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr +
rdev->uvd_fw->size;
}
} else { } else {
r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg); r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg);
if (r) { if (r) {
...@@ -778,9 +791,9 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) ...@@ -778,9 +791,9 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
index = RADEON_WB_SCRATCH_OFFSET + index = RADEON_WB_SCRATCH_OFFSET +
rdev->fence_drv[ring].scratch_reg - rdev->fence_drv[ring].scratch_reg -
rdev->scratch.reg_base; rdev->scratch.reg_base;
}
rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
}
radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring); radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring);
rdev->fence_drv[ring].initialized = true; rdev->fence_drv[ring].initialized = true;
dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n",
......
...@@ -516,6 +516,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev, ...@@ -516,6 +516,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
rdev->hyperz_filp = NULL; rdev->hyperz_filp = NULL;
if (rdev->cmask_filp == file_priv) if (rdev->cmask_filp == file_priv)
rdev->cmask_filp = NULL; rdev->cmask_filp = NULL;
radeon_uvd_free_handles(rdev, file_priv);
} }
/* /*
......
...@@ -348,7 +348,7 @@ void radeon_bo_list_add_object(struct radeon_bo_list *lobj, ...@@ -348,7 +348,7 @@ void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
} }
} }
int radeon_bo_list_validate(struct list_head *head) int radeon_bo_list_validate(struct list_head *head, int ring)
{ {
struct radeon_bo_list *lobj; struct radeon_bo_list *lobj;
struct radeon_bo *bo; struct radeon_bo *bo;
...@@ -366,6 +366,8 @@ int radeon_bo_list_validate(struct list_head *head) ...@@ -366,6 +366,8 @@ int radeon_bo_list_validate(struct list_head *head)
retry: retry:
radeon_ttm_placement_from_domain(bo, domain); radeon_ttm_placement_from_domain(bo, domain);
if (ring == R600_RING_TYPE_UVD_INDEX)
radeon_uvd_force_into_uvd_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, r = ttm_bo_validate(&bo->tbo, &bo->placement,
true, false); true, false);
if (unlikely(r)) { if (unlikely(r)) {
......
...@@ -128,7 +128,7 @@ extern int radeon_bo_init(struct radeon_device *rdev); ...@@ -128,7 +128,7 @@ extern int radeon_bo_init(struct radeon_device *rdev);
extern void radeon_bo_fini(struct radeon_device *rdev); extern void radeon_bo_fini(struct radeon_device *rdev);
extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj, extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
struct list_head *head); struct list_head *head);
extern int radeon_bo_list_validate(struct list_head *head); extern int radeon_bo_list_validate(struct list_head *head, int ring);
extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
struct vm_area_struct *vma); struct vm_area_struct *vma);
extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
......
...@@ -368,7 +368,7 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -368,7 +368,7 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
{ {
u32 rptr; u32 rptr;
if (rdev->wb.enabled) if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX])
rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
else else
rptr = RREG32(ring->rptr_reg); rptr = RREG32(ring->rptr_reg);
...@@ -821,18 +821,20 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) ...@@ -821,18 +821,20 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
return 0; return 0;
} }
static int radeon_ring_type_gfx_index = RADEON_RING_TYPE_GFX_INDEX; static int radeon_gfx_index = RADEON_RING_TYPE_GFX_INDEX;
static int cayman_ring_type_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX; static int cayman_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX;
static int cayman_ring_type_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX;
static int radeon_ring_type_dma1_index = R600_RING_TYPE_DMA_INDEX; static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX;
static int radeon_ring_type_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX;
static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX;
static struct drm_info_list radeon_debugfs_ring_info_list[] = { static struct drm_info_list radeon_debugfs_ring_info_list[] = {
{"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_ring_type_gfx_index}, {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index},
{"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp1_index}, {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_cp1_index},
{"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index}, {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_cp2_index},
{"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma1_index}, {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index},
{"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma2_index}, {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index},
{"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index},
}; };
static int radeon_debugfs_sa_info(struct seq_file *m, void *data) static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
......
...@@ -252,6 +252,36 @@ void radeon_test_moves(struct radeon_device *rdev) ...@@ -252,6 +252,36 @@ void radeon_test_moves(struct radeon_device *rdev)
radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT); radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT);
} }
static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
struct radeon_ring *ring,
struct radeon_fence **fence)
{
int r;
if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
if (r) {
DRM_ERROR("Failed to get dummy create msg\n");
return r;
}
r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence);
if (r) {
DRM_ERROR("Failed to get dummy destroy msg\n");
return r;
}
} else {
r = radeon_ring_lock(rdev, ring, 64);
if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ring->idx);
return r;
}
radeon_fence_emit(rdev, fence, ring->idx);
radeon_ring_unlock_commit(rdev, ring);
}
return 0;
}
void radeon_test_ring_sync(struct radeon_device *rdev, void radeon_test_ring_sync(struct radeon_device *rdev,
struct radeon_ring *ringA, struct radeon_ring *ringA,
struct radeon_ring *ringB) struct radeon_ring *ringB)
...@@ -272,21 +302,24 @@ void radeon_test_ring_sync(struct radeon_device *rdev, ...@@ -272,21 +302,24 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
r = radeon_fence_emit(rdev, &fence1, ringA->idx); radeon_ring_unlock_commit(rdev, ringA);
if (r) {
DRM_ERROR("Failed to emit fence 1\n"); r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1);
radeon_ring_unlock_undo(rdev, ringA); if (r)
goto out_cleanup; goto out_cleanup;
}
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); r = radeon_ring_lock(rdev, ringA, 64);
r = radeon_fence_emit(rdev, &fence2, ringA->idx);
if (r) { if (r) {
DRM_ERROR("Failed to emit fence 2\n"); DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
radeon_ring_unlock_undo(rdev, ringA);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringA); radeon_ring_unlock_commit(rdev, ringA);
r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2);
if (r)
goto out_cleanup;
mdelay(1000); mdelay(1000);
if (radeon_fence_signaled(fence1)) { if (radeon_fence_signaled(fence1)) {
...@@ -364,27 +397,22 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -364,27 +397,22 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
r = radeon_fence_emit(rdev, &fenceA, ringA->idx);
if (r) {
DRM_ERROR("Failed to emit sync fence 1\n");
radeon_ring_unlock_undo(rdev, ringA);
goto out_cleanup;
}
radeon_ring_unlock_commit(rdev, ringA); radeon_ring_unlock_commit(rdev, ringA);
r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA);
if (r)
goto out_cleanup;
r = radeon_ring_lock(rdev, ringB, 64); r = radeon_ring_lock(rdev, ringB, 64);
if (r) { if (r) {
DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); DRM_ERROR("Failed to lock ring B %d\n", ringB->idx);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
r = radeon_fence_emit(rdev, &fenceB, ringB->idx);
if (r) {
DRM_ERROR("Failed to create sync fence 2\n");
radeon_ring_unlock_undo(rdev, ringB);
goto out_cleanup;
}
radeon_ring_unlock_commit(rdev, ringB); radeon_ring_unlock_commit(rdev, ringB);
r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB);
if (r)
goto out_cleanup;
mdelay(1000); mdelay(1000);
...@@ -393,7 +421,7 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -393,7 +421,7 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
goto out_cleanup; goto out_cleanup;
} }
if (radeon_fence_signaled(fenceB)) { if (radeon_fence_signaled(fenceB)) {
DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); DRM_ERROR("Fence B signaled without waiting for semaphore.\n");
goto out_cleanup; goto out_cleanup;
} }
......
This diff is collapsed.
...@@ -68,6 +68,105 @@ u32 rv770_get_xclk(struct radeon_device *rdev) ...@@ -68,6 +68,105 @@ u32 rv770_get_xclk(struct radeon_device *rdev)
return reference_clock; return reference_clock;
} }
int rv770_uvd_resume(struct radeon_device *rdev)
{
uint64_t addr;
uint32_t chip_id, size;
int r;
r = radeon_uvd_resume(rdev);
if (r)
return r;
/* programm the VCPU memory controller bits 0-27 */
addr = rdev->uvd.gpu_addr >> 3;
size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
WREG32(UVD_VCPU_CACHE_SIZE0, size);
addr += size;
size = RADEON_UVD_STACK_SIZE >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
WREG32(UVD_VCPU_CACHE_SIZE1, size);
addr += size;
size = RADEON_UVD_HEAP_SIZE >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
WREG32(UVD_VCPU_CACHE_SIZE2, size);
/* bits 28-31 */
addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
/* bits 32-39 */
addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
/* tell firmware which hardware it is running on */
switch (rdev->family) {
default:
return -EINVAL;
case CHIP_RV710:
chip_id = 0x01000005;
break;
case CHIP_RV730:
chip_id = 0x01000006;
break;
case CHIP_RV740:
chip_id = 0x01000007;
break;
case CHIP_CYPRESS:
case CHIP_HEMLOCK:
chip_id = 0x01000008;
break;
case CHIP_JUNIPER:
chip_id = 0x01000009;
break;
case CHIP_REDWOOD:
chip_id = 0x0100000a;
break;
case CHIP_CEDAR:
chip_id = 0x0100000b;
break;
case CHIP_SUMO:
chip_id = 0x0100000c;
break;
case CHIP_SUMO2:
chip_id = 0x0100000d;
break;
case CHIP_PALM:
chip_id = 0x0100000e;
break;
case CHIP_CAYMAN:
chip_id = 0x0100000f;
break;
case CHIP_BARTS:
chip_id = 0x01000010;
break;
case CHIP_TURKS:
chip_id = 0x01000011;
break;
case CHIP_CAICOS:
chip_id = 0x01000012;
break;
case CHIP_TAHITI:
chip_id = 0x01000014;
break;
case CHIP_VERDE:
chip_id = 0x01000015;
break;
case CHIP_PITCAIRN:
chip_id = 0x01000016;
break;
case CHIP_ARUBA:
chip_id = 0x01000017;
break;
}
WREG32(UVD_VCPU_CHIP_ID, chip_id);
return 0;
}
u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
{ {
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
...@@ -1040,6 +1139,17 @@ static int rv770_startup(struct radeon_device *rdev) ...@@ -1040,6 +1139,17 @@ static int rv770_startup(struct radeon_device *rdev)
return r; return r;
} }
r = rv770_uvd_resume(rdev);
if (!r) {
r = radeon_fence_driver_start_ring(rdev,
R600_RING_TYPE_UVD_INDEX);
if (r)
dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
}
if (r)
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
/* Enable IRQ */ /* Enable IRQ */
r = r600_irq_init(rdev); r = r600_irq_init(rdev);
if (r) { if (r) {
...@@ -1074,6 +1184,19 @@ static int rv770_startup(struct radeon_device *rdev) ...@@ -1074,6 +1184,19 @@ static int rv770_startup(struct radeon_device *rdev)
if (r) if (r)
return r; return r;
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
r = r600_uvd_init(rdev);
if (r)
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
}
r = radeon_ib_pool_init(rdev); r = radeon_ib_pool_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
...@@ -1115,6 +1238,7 @@ int rv770_resume(struct radeon_device *rdev) ...@@ -1115,6 +1238,7 @@ int rv770_resume(struct radeon_device *rdev)
int rv770_suspend(struct radeon_device *rdev) int rv770_suspend(struct radeon_device *rdev)
{ {
r600_audio_fini(rdev); r600_audio_fini(rdev);
radeon_uvd_suspend(rdev);
r700_cp_stop(rdev); r700_cp_stop(rdev);
r600_dma_stop(rdev); r600_dma_stop(rdev);
r600_irq_suspend(rdev); r600_irq_suspend(rdev);
...@@ -1190,6 +1314,13 @@ int rv770_init(struct radeon_device *rdev) ...@@ -1190,6 +1314,13 @@ int rv770_init(struct radeon_device *rdev)
rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
r = radeon_uvd_init(rdev);
if (!r) {
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
4096);
}
rdev->ih.ring_obj = NULL; rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024); r600_ih_ring_init(rdev, 64 * 1024);
...@@ -1224,6 +1355,7 @@ void rv770_fini(struct radeon_device *rdev) ...@@ -1224,6 +1355,7 @@ void rv770_fini(struct radeon_device *rdev)
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
rv770_pcie_gart_fini(rdev); rv770_pcie_gart_fini(rdev);
radeon_uvd_fini(rdev);
r600_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev); radeon_fence_driver_fini(rdev);
......
...@@ -671,4 +671,18 @@ ...@@ -671,4 +671,18 @@
# define TARGET_LINK_SPEED_MASK (0xf << 0) # define TARGET_LINK_SPEED_MASK (0xf << 0)
# define SELECTABLE_DEEMPHASIS (1 << 6) # define SELECTABLE_DEEMPHASIS (1 << 6)
/* UVD */
#define UVD_LMI_EXT40_ADDR 0xf498
#define UVD_VCPU_CHIP_ID 0xf4d4
#define UVD_VCPU_CACHE_OFFSET0 0xf4d8
#define UVD_VCPU_CACHE_SIZE0 0xf4dc
#define UVD_VCPU_CACHE_OFFSET1 0xf4e0
#define UVD_VCPU_CACHE_SIZE1 0xf4e4
#define UVD_VCPU_CACHE_OFFSET2 0xf4e8
#define UVD_VCPU_CACHE_SIZE2 0xf4ec
#define UVD_LMI_ADDR_EXT 0xf594
#define UVD_RBC_RB_RPTR 0xf690
#define UVD_RBC_RB_WPTR 0xf694
#endif #endif
...@@ -4333,6 +4333,16 @@ static int si_startup(struct radeon_device *rdev) ...@@ -4333,6 +4333,16 @@ static int si_startup(struct radeon_device *rdev)
return r; return r;
} }
r = rv770_uvd_resume(rdev);
if (!r) {
r = radeon_fence_driver_start_ring(rdev,
R600_RING_TYPE_UVD_INDEX);
if (r)
dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
}
if (r)
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
/* Enable IRQ */ /* Enable IRQ */
r = si_irq_init(rdev); r = si_irq_init(rdev);
if (r) { if (r) {
...@@ -4390,6 +4400,18 @@ static int si_startup(struct radeon_device *rdev) ...@@ -4390,6 +4400,18 @@ static int si_startup(struct radeon_device *rdev)
if (r) if (r)
return r; return r;
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
r = r600_uvd_init(rdev);
if (r)
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
}
r = radeon_ib_pool_init(rdev); r = radeon_ib_pool_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
...@@ -4433,6 +4455,8 @@ int si_suspend(struct radeon_device *rdev) ...@@ -4433,6 +4455,8 @@ int si_suspend(struct radeon_device *rdev)
radeon_vm_manager_fini(rdev); radeon_vm_manager_fini(rdev);
si_cp_enable(rdev, false); si_cp_enable(rdev, false);
cayman_dma_stop(rdev); cayman_dma_stop(rdev);
r600_uvd_rbc_stop(rdev);
radeon_uvd_suspend(rdev);
si_irq_suspend(rdev); si_irq_suspend(rdev);
radeon_wb_disable(rdev); radeon_wb_disable(rdev);
si_pcie_gart_disable(rdev); si_pcie_gart_disable(rdev);
...@@ -4518,6 +4542,13 @@ int si_init(struct radeon_device *rdev) ...@@ -4518,6 +4542,13 @@ int si_init(struct radeon_device *rdev)
ring->ring_obj = NULL; ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 64 * 1024); r600_ring_init(rdev, ring, 64 * 1024);
r = radeon_uvd_init(rdev);
if (!r) {
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 4096);
}
rdev->ih.ring_obj = NULL; rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024); r600_ih_ring_init(rdev, 64 * 1024);
...@@ -4566,6 +4597,7 @@ void si_fini(struct radeon_device *rdev) ...@@ -4566,6 +4597,7 @@ void si_fini(struct radeon_device *rdev)
radeon_vm_manager_fini(rdev); radeon_vm_manager_fini(rdev);
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
radeon_uvd_fini(rdev);
si_pcie_gart_fini(rdev); si_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
......
...@@ -799,6 +799,12 @@ ...@@ -799,6 +799,12 @@
# define THREAD_TRACE_FLUSH (54 << 0) # define THREAD_TRACE_FLUSH (54 << 0)
# define THREAD_TRACE_FINISH (55 << 0) # define THREAD_TRACE_FINISH (55 << 0)
/*
* UVD
*/
#define UVD_RBC_RB_RPTR 0xF690
#define UVD_RBC_RB_WPTR 0xF694
/* /*
* PM4 * PM4
*/ */
......
...@@ -918,6 +918,7 @@ struct drm_radeon_gem_va { ...@@ -918,6 +918,7 @@ struct drm_radeon_gem_va {
#define RADEON_CS_RING_GFX 0 #define RADEON_CS_RING_GFX 0
#define RADEON_CS_RING_COMPUTE 1 #define RADEON_CS_RING_COMPUTE 1
#define RADEON_CS_RING_DMA 2 #define RADEON_CS_RING_DMA 2
#define RADEON_CS_RING_UVD 3
/* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */
/* 0 = normal, + = higher priority, - = lower priority */ /* 0 = normal, + = higher priority, - = lower priority */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment