Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -7705,8 +7705,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)
+1 −2
Original line number Diff line number Diff line
@@ -5291,8 +5291,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)
+1 −2
Original line number Diff line number Diff line
@@ -2225,8 +2225,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)
+20 −13
Original line number Diff line number Diff line
@@ -2623,31 +2623,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);
}

static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test)
{
	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 */
@@ -2662,7 +2669,7 @@ static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test)
	/* 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);

	if (ring_test) {
		ring->ready = true;
+0 −1
Original line number Diff line number Diff line
@@ -1027,7 +1027,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
Loading