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

drm/radeon: rework UVD writeback & [rw]ptr handling

The hardware just doesn't support this correctly.
Disable it before we accidentally write anywhere we shouldn't.
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 76a0df85
...@@ -7705,8 +7705,7 @@ static int cik_startup(struct radeon_device *rdev) ...@@ -7705,8 +7705,7 @@ static int cik_startup(struct radeon_device *rdev)
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) { if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size, r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2); 0, 0xfffff, RADEON_CP_PACKET2);
if (!r) if (!r)
......
...@@ -5291,8 +5291,7 @@ static int evergreen_startup(struct radeon_device *rdev) ...@@ -5291,8 +5291,7 @@ static int evergreen_startup(struct radeon_device *rdev)
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) { if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size, r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2); 0, 0xfffff, RADEON_CP_PACKET2);
if (!r) if (!r)
......
...@@ -2225,8 +2225,7 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -2225,8 +2225,7 @@ static int cayman_startup(struct radeon_device *rdev)
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) { if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size, r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2); 0, 0xfffff, RADEON_CP_PACKET2);
if (!r) if (!r)
......
...@@ -2623,31 +2623,38 @@ void r600_dma_fini(struct radeon_device *rdev) ...@@ -2623,31 +2623,38 @@ void r600_dma_fini(struct radeon_device *rdev)
/* /*
* UVD * UVD
*/ */
uint32_t r600_uvd_get_rptr(struct radeon_device *rdev,
struct radeon_ring *ring)
{
return RREG32(UVD_RBC_RB_RPTR);
}
uint32_t r600_uvd_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring)
{
return RREG32(UVD_RBC_RB_WPTR);
}
void r600_uvd_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring)
{
WREG32(UVD_RBC_RB_WPTR, ring->wptr);
}
static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test) static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test)
{ {
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
uint64_t rptr_addr;
uint32_t rb_bufsz, tmp; uint32_t rb_bufsz, tmp;
int r; 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 */ /* force RBC into idle state */
WREG32(UVD_RBC_RB_CNTL, 0x11010101); WREG32(UVD_RBC_RB_CNTL, 0x11010101);
/* Set the write pointer delay */ /* Set the write pointer delay */
WREG32(UVD_RBC_RB_WPTR_CNTL, 0); 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 */ /* programm the 4GB memory segment for rptr and ring buffer */
WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(rptr_addr) | WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
(0x7 << 16) | (0x1 << 31)); (0x7 << 16) | (0x1 << 31));
/* Initialize the ring buffer's read and write pointers */ /* Initialize the ring buffer's read and write pointers */
...@@ -2662,7 +2669,7 @@ static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test) ...@@ -2662,7 +2669,7 @@ static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test)
/* Set ring buffer size */ /* Set ring buffer size */
rb_bufsz = drm_order(ring->ring_size); rb_bufsz = drm_order(ring->ring_size);
rb_bufsz = (0x1 << 8) | rb_bufsz; rb_bufsz = (0x1 << 8) | rb_bufsz;
WREG32(UVD_RBC_RB_CNTL, rb_bufsz); WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
if (ring_test) { if (ring_test) {
ring->ready = true; ring->ready = true;
......
...@@ -1027,7 +1027,6 @@ struct radeon_wb { ...@@ -1027,7 +1027,6 @@ 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
#define CIK_WB_CP1_WPTR_OFFSET 3328 #define CIK_WB_CP1_WPTR_OFFSET 3328
#define CIK_WB_CP2_WPTR_OFFSET 3584 #define CIK_WB_CP2_WPTR_OFFSET 3584
......
...@@ -1157,9 +1157,9 @@ static struct radeon_asic_ring rv770_uvd_ring = { ...@@ -1157,9 +1157,9 @@ static struct radeon_asic_ring rv770_uvd_ring = {
.ring_test = &r600_uvd_ring_test, .ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test, .ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup, .is_lockup = &radeon_ring_test_lockup,
.get_rptr = &radeon_ring_generic_get_rptr, .get_rptr = &r600_uvd_get_rptr,
.get_wptr = &radeon_ring_generic_get_wptr, .get_wptr = &r600_uvd_get_wptr,
.set_wptr = &radeon_ring_generic_set_wptr, .set_wptr = &r600_uvd_set_wptr,
}; };
static struct radeon_asic rv770_asic = { static struct radeon_asic rv770_asic = {
...@@ -1593,9 +1593,9 @@ static struct radeon_asic_ring cayman_uvd_ring = { ...@@ -1593,9 +1593,9 @@ static struct radeon_asic_ring cayman_uvd_ring = {
.ring_test = &r600_uvd_ring_test, .ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test, .ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup, .is_lockup = &radeon_ring_test_lockup,
.get_rptr = &radeon_ring_generic_get_rptr, .get_rptr = &r600_uvd_get_rptr,
.get_wptr = &radeon_ring_generic_get_wptr, .get_wptr = &r600_uvd_get_wptr,
.set_wptr = &radeon_ring_generic_set_wptr, .set_wptr = &r600_uvd_set_wptr,
}; };
static struct radeon_asic cayman_asic = { static struct radeon_asic cayman_asic = {
......
...@@ -424,6 +424,12 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde ...@@ -424,6 +424,12 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
struct seq_file *m); struct seq_file *m);
/* uvd */ /* uvd */
uint32_t r600_uvd_get_rptr(struct radeon_device *rdev,
struct radeon_ring *ring);
uint32_t r600_uvd_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
void r600_uvd_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
int r600_uvd_init(struct radeon_device *rdev, bool ring_test); int r600_uvd_init(struct radeon_device *rdev, bool ring_test);
void r600_uvd_stop(struct radeon_device *rdev); void r600_uvd_stop(struct radeon_device *rdev);
int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
......
...@@ -363,7 +363,7 @@ u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev, ...@@ -363,7 +363,7 @@ u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
{ {
u32 rptr; u32 rptr;
if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX]) if (rdev->wb.enabled)
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);
......
...@@ -1923,8 +1923,7 @@ static int rv770_startup(struct radeon_device *rdev) ...@@ -1923,8 +1923,7 @@ static int rv770_startup(struct radeon_device *rdev)
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) { if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size, r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2); 0, 0xfffff, RADEON_CP_PACKET2);
if (!r) if (!r)
......
...@@ -6416,8 +6416,7 @@ static int si_startup(struct radeon_device *rdev) ...@@ -6416,8 +6416,7 @@ static int si_startup(struct radeon_device *rdev)
if (rdev->has_uvd) { if (rdev->has_uvd) {
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
if (ring->ring_size) { if (ring->ring_size) {
r = radeon_ring_init(rdev, ring, ring->ring_size, r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
R600_WB_UVD_RPTR_OFFSET,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2); 0, 0xfffff, RADEON_CP_PACKET2);
if (!r) if (!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