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

drm/radeon: add UVD support for older asics v4

v2: cleanup R600 support
v3: rebased on current drm-fixes-3.12
v4: rebased on drm-next-3.14
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4a956a70
...@@ -3009,6 +3009,17 @@ static int r600_startup(struct radeon_device *rdev) ...@@ -3009,6 +3009,17 @@ static int r600_startup(struct radeon_device *rdev)
return r; return r;
} }
r = uvd_v1_0_resume(rdev);
if (!r) {
r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
if (r) {
dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
}
}
if (r) {
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
}
/* Enable IRQ */ /* Enable IRQ */
if (!rdev->irq.installed) { if (!rdev->irq.installed) {
r = radeon_irq_kms_init(rdev); r = radeon_irq_kms_init(rdev);
...@@ -3037,6 +3048,16 @@ static int r600_startup(struct radeon_device *rdev) ...@@ -3037,6 +3048,16 @@ static int r600_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, 0,
RADEON_CP_PACKET2);
if (!r)
r = uvd_v1_0_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);
...@@ -3096,6 +3117,8 @@ int r600_suspend(struct radeon_device *rdev) ...@@ -3096,6 +3117,8 @@ int r600_suspend(struct radeon_device *rdev)
radeon_pm_suspend(rdev); radeon_pm_suspend(rdev);
r600_audio_fini(rdev); r600_audio_fini(rdev);
r600_cp_stop(rdev); r600_cp_stop(rdev);
uvd_v1_0_fini(rdev);
radeon_uvd_suspend(rdev);
r600_irq_suspend(rdev); r600_irq_suspend(rdev);
radeon_wb_disable(rdev); radeon_wb_disable(rdev);
r600_pcie_gart_disable(rdev); r600_pcie_gart_disable(rdev);
...@@ -3175,6 +3198,12 @@ int r600_init(struct radeon_device *rdev) ...@@ -3175,6 +3198,12 @@ int r600_init(struct radeon_device *rdev)
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 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);
...@@ -3204,6 +3233,8 @@ void r600_fini(struct radeon_device *rdev) ...@@ -3204,6 +3233,8 @@ void r600_fini(struct radeon_device *rdev)
r600_audio_fini(rdev); r600_audio_fini(rdev);
r600_cp_fini(rdev); r600_cp_fini(rdev);
r600_irq_fini(rdev); r600_irq_fini(rdev);
uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev);
radeon_wb_fini(rdev); radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
......
...@@ -1485,6 +1485,7 @@ ...@@ -1485,6 +1485,7 @@
#define UVD_CGC_GATE 0xf4a8 #define UVD_CGC_GATE 0xf4a8
#define UVD_LMI_CTRL2 0xf4f4 #define UVD_LMI_CTRL2 0xf4f4
#define UVD_MASTINT_EN 0xf500 #define UVD_MASTINT_EN 0xf500
#define UVD_FW_START 0xf51C
#define UVD_LMI_ADDR_EXT 0xf594 #define UVD_LMI_ADDR_EXT 0xf594
#define UVD_LMI_CTRL 0xf598 #define UVD_LMI_CTRL 0xf598
#define UVD_LMI_SWAP_CNTL 0xf5b4 #define UVD_LMI_SWAP_CNTL 0xf5b4
...@@ -1497,6 +1498,13 @@ ...@@ -1497,6 +1498,13 @@
#define UVD_MPC_SET_MUX 0xf5f4 #define UVD_MPC_SET_MUX 0xf5f4
#define UVD_MPC_SET_ALU 0xf5f8 #define UVD_MPC_SET_ALU 0xf5f8
#define UVD_VCPU_CACHE_OFFSET0 0xf608
#define UVD_VCPU_CACHE_SIZE0 0xf60c
#define UVD_VCPU_CACHE_OFFSET1 0xf610
#define UVD_VCPU_CACHE_SIZE1 0xf614
#define UVD_VCPU_CACHE_OFFSET2 0xf618
#define UVD_VCPU_CACHE_SIZE2 0xf61c
#define UVD_VCPU_CNTL 0xf660 #define UVD_VCPU_CNTL 0xf660
#define UVD_SOFT_RESET 0xf680 #define UVD_SOFT_RESET 0xf680
#define RBC_SOFT_RESET (1<<0) #define RBC_SOFT_RESET (1<<0)
......
...@@ -965,6 +965,19 @@ static struct radeon_asic r600_asic = { ...@@ -965,6 +965,19 @@ static struct radeon_asic r600_asic = {
}, },
}; };
static struct radeon_asic_ring rv6xx_uvd_ring = {
.ib_execute = &uvd_v1_0_ib_execute,
.emit_fence = &uvd_v1_0_fence_emit,
.emit_semaphore = &uvd_v1_0_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &uvd_v1_0_ring_test,
.ib_test = &uvd_v1_0_ib_test,
.is_lockup = &radeon_ring_test_lockup,
.get_rptr = &uvd_v1_0_get_rptr,
.get_wptr = &uvd_v1_0_get_wptr,
.set_wptr = &uvd_v1_0_set_wptr,
};
static struct radeon_asic rv6xx_asic = { static struct radeon_asic rv6xx_asic = {
.init = &r600_init, .init = &r600_init,
.fini = &r600_fini, .fini = &r600_fini,
...@@ -984,6 +997,7 @@ static struct radeon_asic rv6xx_asic = { ...@@ -984,6 +997,7 @@ static struct radeon_asic rv6xx_asic = {
.ring = { .ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &r600_gfx_ring, [RADEON_RING_TYPE_GFX_INDEX] = &r600_gfx_ring,
[R600_RING_TYPE_DMA_INDEX] = &r600_dma_ring, [R600_RING_TYPE_DMA_INDEX] = &r600_dma_ring,
[R600_RING_TYPE_UVD_INDEX] = &rv6xx_uvd_ring,
}, },
.irq = { .irq = {
.set = &r600_irq_set, .set = &r600_irq_set,
...@@ -1074,6 +1088,7 @@ static struct radeon_asic rs780_asic = { ...@@ -1074,6 +1088,7 @@ static struct radeon_asic rs780_asic = {
.ring = { .ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &r600_gfx_ring, [RADEON_RING_TYPE_GFX_INDEX] = &r600_gfx_ring,
[R600_RING_TYPE_DMA_INDEX] = &r600_dma_ring, [R600_RING_TYPE_DMA_INDEX] = &r600_dma_ring,
[R600_RING_TYPE_UVD_INDEX] = &rv6xx_uvd_ring,
}, },
.irq = { .irq = {
.set = &r600_irq_set, .set = &r600_irq_set,
......
...@@ -883,6 +883,7 @@ uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev, ...@@ -883,6 +883,7 @@ uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring); struct radeon_ring *ring);
void uvd_v1_0_set_wptr(struct radeon_device *rdev, void uvd_v1_0_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring); struct radeon_ring *ring);
int uvd_v1_0_resume(struct radeon_device *rdev);
int uvd_v1_0_init(struct radeon_device *rdev); int uvd_v1_0_init(struct radeon_device *rdev);
void uvd_v1_0_fini(struct radeon_device *rdev); void uvd_v1_0_fini(struct radeon_device *rdev);
...@@ -890,6 +891,8 @@ int uvd_v1_0_start(struct radeon_device *rdev); ...@@ -890,6 +891,8 @@ int uvd_v1_0_start(struct radeon_device *rdev);
void uvd_v1_0_stop(struct radeon_device *rdev); void uvd_v1_0_stop(struct radeon_device *rdev);
int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring); int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
void uvd_v1_0_fence_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev, bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
struct radeon_ring *ring, struct radeon_ring *ring,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* Authors: Christian König <christian.koenig@amd.com> * Authors: Christian König <christian.koenig@amd.com>
*/ */
#include <linux/firmware.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include "radeon.h" #include "radeon.h"
#include "radeon_asic.h" #include "radeon_asic.h"
...@@ -69,6 +70,82 @@ void uvd_v1_0_set_wptr(struct radeon_device *rdev, ...@@ -69,6 +70,82 @@ void uvd_v1_0_set_wptr(struct radeon_device *rdev,
WREG32(UVD_RBC_RB_WPTR, ring->wptr); WREG32(UVD_RBC_RB_WPTR, ring->wptr);
} }
/**
* 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 * uvd_v1_0_init - start and test UVD block
* *
......
...@@ -72,6 +72,10 @@ int uvd_v2_2_resume(struct radeon_device *rdev) ...@@ -72,6 +72,10 @@ int uvd_v2_2_resume(struct radeon_device *rdev)
uint32_t chip_id, size; uint32_t chip_id, size;
int r; int r;
/* RV770 uses V1.0 MC */
if (rdev->family == CHIP_RV770)
return uvd_v1_0_resume(rdev);
r = radeon_uvd_resume(rdev); r = radeon_uvd_resume(rdev);
if (r) if (r)
return r; return r;
......
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