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>
This commit is contained in:

committed by
Alex Deucher

parent
76a0df859d
commit
02c9f7fa4e
@@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
/* 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 {
|
|||||||
#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 = {
|
|||||||
.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 = {
|
|||||||
.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
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
||||||
|
Reference in New Issue
Block a user