70,6 → 70,82 |
} |
|
/** |
* uvd_v1_0_fence_emit - emit an fence & trap command |
* |
* @rdev: radeon_device pointer |
* @fence: fence to emit |
* |
* Write a fence and a trap command to the ring. |
*/ |
void uvd_v1_0_fence_emit(struct radeon_device *rdev, |
struct radeon_fence *fence) |
{ |
struct radeon_ring *ring = &rdev->ring[fence->ring]; |
uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr; |
|
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, fence->seq); |
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; |
} |
|
/** |
* uvd_v1_0_resume - memory controller programming |
* |
* @rdev: radeon_device pointer |
* |
* Let the UVD memory controller know it's offsets |
*/ |
int uvd_v1_0_resume(struct radeon_device *rdev) |
{ |
uint64_t addr; |
uint32_t 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) + 16; |
size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size) >> 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)); |
|
WREG32(UVD_FW_START, *((uint32_t*)rdev->uvd.cpu_addr)); |
|
return 0; |
} |
|
/** |
* uvd_v1_0_init - start and test UVD block |
* |
* @rdev: radeon_device pointer |
130,8 → 206,32 |
/* lower clocks again */ |
radeon_set_uvd_clocks(rdev, 0, 0); |
|
if (!r) |
if (!r) { |
switch (rdev->family) { |
case CHIP_RV610: |
case CHIP_RV630: |
case CHIP_RV620: |
/* 64byte granularity workaround */ |
WREG32(MC_CONFIG, 0); |
WREG32(MC_CONFIG, 1 << 4); |
WREG32(RS_DQ_RD_RET_CONF, 0x3f); |
WREG32(MC_CONFIG, 0x1f); |
|
/* fall through */ |
case CHIP_RV670: |
case CHIP_RV635: |
|
/* write clean workaround */ |
WREG32_P(UVD_VCPU_CNTL, 0x10, ~0x10); |
break; |
|
default: |
/* TODO: Do we need more? */ |
break; |
} |
|
DRM_INFO("UVD initialized successfully.\n"); |
} |
|
return r; |
} |
218,12 → 318,12 |
/* enable UMC */ |
WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8)); |
|
WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3)); |
|
/* 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) { |