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

Christian König deathsimple at vodafone.de
Thu Jul 4 06:30:24 PDT 2013


From: Christian König <christian.koenig at amd.com>

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 at amd.com>
---
 drivers/gpu/drm/radeon/cik.c         |    3 +--
 drivers/gpu/drm/radeon/evergreen.c   |    3 +--
 drivers/gpu/drm/radeon/ni.c          |    3 +--
 drivers/gpu/drm/radeon/r600.c        |   34 +++++++++++++++++++++-------------
 drivers/gpu/drm/radeon/radeon.h      |    1 -
 drivers/gpu/drm/radeon/radeon_asic.c |   12 ++++++------
 drivers/gpu/drm/radeon/radeon_asic.h |    6 ++++++
 drivers/gpu/drm/radeon/radeon_ring.c |    2 +-
 drivers/gpu/drm/radeon/rv770.c       |    3 +--
 drivers/gpu/drm/radeon/si.c          |    3 +--
 10 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index ed1d910..c60b96b 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -6107,8 +6107,7 @@ static int cik_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/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 2e1de4f..8717f3c 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -5225,8 +5225,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 f30127c..4a04f07 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -2238,8 +2238,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 2d3655f..2b1d238 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2630,31 +2630,39 @@ 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 */
@@ -2669,7 +2677,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.h b/drivers/gpu/drm/radeon/radeon.h
index 2365b4b..ed26da2 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1029,7 +1029,6 @@ struct radeon_wb {
 #define R600_WB_DMA_RPTR_OFFSET   1792
 #define R600_WB_IH_WPTR_OFFSET   2048
 #define CAYMAN_WB_DMA1_RPTR_OFFSET   2304
-#define R600_WB_UVD_RPTR_OFFSET  2560
 #define R600_WB_EVENT_OFFSET     3072
 #define CIK_WB_CP1_WPTR_OFFSET     3328
 #define CIK_WB_CP2_WPTR_OFFSET     3584
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index baa2a97..f533add 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1155,9 +1155,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 = {
@@ -1584,9 +1584,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 6822c7a..3a5f353 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -433,6 +433,12 @@ void rs780_dpm_print_power_state(struct radeon_device *rdev,
 
 /* uvd */
 int r600_uvd_init(struct radeon_device *rdev);
+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_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);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 5f1c51a..a01d252 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -362,7 +362,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 4a62ad2..836de93 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1928,8 +1928,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 2349067..3ca2420 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -6310,8 +6310,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)
-- 
1.7.9.5



More information about the dri-devel mailing list