aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2014-03-19 14:34:19 -0300
committerEli Qiao <taget@linux.vnet.ibm.com>2014-03-25 17:00:52 +0800
commitc4071924107e1eac14da825f58984f51dda3ec07 (patch)
tree79277716a1af087700dd37eac88c9e1112b734e9
parenteaf2b79e10c5e16a6e58ac5db6e43f732d5d50bd (diff)
downloadpowerkvm-c4071924107e1eac14da825f58984f51dda3ec07.tar.gz
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: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (backported from commit 02c9f7fa4e7230fc4ae8bf26f64e45aa76011f9c) Signed-off-by: Kleber Sacilotto de Souza <klebers@linux.vnet.ibm.com> LTC-Bugzilla: #99530
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c3
-rw-r--r--drivers/gpu/drm/radeon/ni.c3
-rw-r--r--drivers/gpu/drm/radeon/r600.c33
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h6
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c2
-rw-r--r--drivers/gpu/drm/radeon/rv770.c3
-rw-r--r--drivers/gpu/drm/radeon/si.c3
8 files changed, 37 insertions, 28 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 8b6b0ba6ae4095..61f1cd6250181a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4812,8 +4812,7 @@ static int evergreen_startup(struct radeon_device *rdev)
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,
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 3bf43a16adcc3a..c9c9b786ab079d 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -2075,8 +2075,7 @@ static int cayman_startup(struct radeon_device *rdev)
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,
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index f19620b472f537..83865f06a2d867 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2597,31 +2597,38 @@ void r600_dma_fini(struct radeon_device *rdev)
/*
* 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);
+}
+
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) |
+ WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
(0x7 << 16) | (0x1 << 31));
/* Initialize the ring buffer's read and write pointers */
@@ -2636,7 +2643,7 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
/* Set ring buffer size */
rb_bufsz = drm_order(ring->ring_size);
rb_bufsz = (0x1 << 8) | rb_bufsz;
- WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
+ WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
ring->ready = true;
r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index cc82604775cf5a..36f77d46fa95ee 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1049,9 +1049,9 @@ static struct radeon_asic_ring rv770_uvd_ring = {
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
- .get_rptr = &radeon_ring_generic_get_rptr,
- .get_wptr = &radeon_ring_generic_get_wptr,
- .set_wptr = &radeon_ring_generic_set_wptr,
+ .get_rptr = &r600_uvd_get_rptr,
+ .get_wptr = &r600_uvd_get_wptr,
+ .set_wptr = &r600_uvd_set_wptr,
};
static struct radeon_asic rv770_asic = {
@@ -1414,9 +1414,9 @@ static struct radeon_asic_ring cayman_uvd_ring = {
.ring_test = &r600_uvd_ring_test,
.ib_test = &r600_uvd_ib_test,
.is_lockup = &radeon_ring_test_lockup,
- .get_rptr = &radeon_ring_generic_get_rptr,
- .get_wptr = &radeon_ring_generic_get_wptr,
- .set_wptr = &radeon_ring_generic_set_wptr,
+ .get_rptr = &r600_uvd_get_rptr,
+ .get_wptr = &r600_uvd_get_wptr,
+ .set_wptr = &r600_uvd_set_wptr,
};
static struct radeon_asic cayman_asic = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index a5ca5b86ef53ea..2d03b6f280fd4d 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -403,6 +403,12 @@ u32 r600_get_xclk(struct radeon_device *rdev);
uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
/* 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);
int r600_uvd_rbc_start(struct radeon_device *rdev);
void r600_uvd_stop(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 09eb67964c26be..31d9043ee647ec 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -363,7 +363,7 @@ u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
{
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]);
else
rptr = RREG32(ring->rptr_reg);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index f5e92cfcc14098..4fc8a465e0397d 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1929,8 +1929,7 @@ static int rv770_startup(struct radeon_device *rdev)
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,
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index f054a3b6c4b86d..facd9c075ee74d 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5447,8 +5447,7 @@ static int si_startup(struct radeon_device *rdev)
if (rdev->has_uvd) {
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,
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
0, 0xfffff, RADEON_CP_PACKET2);
if (!r)