drm/radeon: restructure UVD code to handle UVD PG (v2)
When we PG (powergate) UVD, we need to re-initialize it before we can use it again. v2: rebase on UVD stop fixes Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9e9d976205
commit
5e884f606c
|
@ -69,6 +69,7 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev);
|
||||||
static void cik_program_aspm(struct radeon_device *rdev);
|
static void cik_program_aspm(struct radeon_device *rdev);
|
||||||
static void cik_init_pg(struct radeon_device *rdev);
|
static void cik_init_pg(struct radeon_device *rdev);
|
||||||
static void cik_init_cg(struct radeon_device *rdev);
|
static void cik_init_cg(struct radeon_device *rdev);
|
||||||
|
static void cik_uvd_resume(struct radeon_device *rdev);
|
||||||
|
|
||||||
/* get temperature in millidegrees */
|
/* get temperature in millidegrees */
|
||||||
int ci_get_temp(struct radeon_device *rdev)
|
int ci_get_temp(struct radeon_device *rdev)
|
||||||
|
@ -7619,8 +7620,9 @@ static int cik_startup(struct radeon_device *rdev)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = cik_uvd_resume(rdev);
|
r = radeon_uvd_resume(rdev);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
|
cik_uvd_resume(rdev);
|
||||||
r = radeon_fence_driver_start_ring(rdev,
|
r = radeon_fence_driver_start_ring(rdev,
|
||||||
R600_RING_TYPE_UVD_INDEX);
|
R600_RING_TYPE_UVD_INDEX);
|
||||||
if (r)
|
if (r)
|
||||||
|
@ -7708,7 +7710,7 @@ static int cik_startup(struct radeon_device *rdev)
|
||||||
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)
|
||||||
r = r600_uvd_init(rdev);
|
r = r600_uvd_init(rdev, true);
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
||||||
}
|
}
|
||||||
|
@ -8598,15 +8600,10 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cik_uvd_resume(struct radeon_device *rdev)
|
static void cik_uvd_resume(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
int r;
|
|
||||||
|
|
||||||
r = radeon_uvd_resume(rdev);
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* programm the VCPU memory controller bits 0-27 */
|
/* programm the VCPU memory controller bits 0-27 */
|
||||||
addr = rdev->uvd.gpu_addr >> 3;
|
addr = rdev->uvd.gpu_addr >> 3;
|
||||||
|
@ -8632,7 +8629,6 @@ int cik_uvd_resume(struct radeon_device *rdev)
|
||||||
addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
|
addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
|
||||||
WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
|
WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cik_pcie_gen3_enable(struct radeon_device *rdev)
|
static void cik_pcie_gen3_enable(struct radeon_device *rdev)
|
||||||
|
|
|
@ -5296,7 +5296,7 @@ static int evergreen_startup(struct radeon_device *rdev)
|
||||||
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)
|
||||||
r = r600_uvd_init(rdev);
|
r = r600_uvd_init(rdev, true);
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
|
DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
|
||||||
|
|
|
@ -2230,7 +2230,7 @@ static int cayman_startup(struct radeon_device *rdev)
|
||||||
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)
|
||||||
r = r600_uvd_init(rdev);
|
r = r600_uvd_init(rdev, true);
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2623,7 +2623,7 @@ void r600_dma_fini(struct radeon_device *rdev)
|
||||||
/*
|
/*
|
||||||
* UVD
|
* UVD
|
||||||
*/
|
*/
|
||||||
int r600_uvd_rbc_start(struct radeon_device *rdev)
|
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;
|
uint64_t rptr_addr;
|
||||||
|
@ -2664,47 +2664,47 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
|
||||||
rb_bufsz = (0x1 << 8) | rb_bufsz;
|
rb_bufsz = (0x1 << 8) | rb_bufsz;
|
||||||
WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
|
WREG32(UVD_RBC_RB_CNTL, rb_bufsz);
|
||||||
|
|
||||||
ring->ready = true;
|
if (ring_test) {
|
||||||
r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
|
ring->ready = true;
|
||||||
if (r) {
|
r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
|
||||||
ring->ready = false;
|
if (r) {
|
||||||
return r;
|
ring->ready = false;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = radeon_ring_lock(rdev, ring, 10);
|
||||||
|
if (r) {
|
||||||
|
DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
|
||||||
|
radeon_ring_write(ring, tmp);
|
||||||
|
radeon_ring_write(ring, 0xFFFFF);
|
||||||
|
|
||||||
|
tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
|
||||||
|
radeon_ring_write(ring, tmp);
|
||||||
|
radeon_ring_write(ring, 0xFFFFF);
|
||||||
|
|
||||||
|
tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
|
||||||
|
radeon_ring_write(ring, tmp);
|
||||||
|
radeon_ring_write(ring, 0xFFFFF);
|
||||||
|
|
||||||
|
/* Clear timeout status bits */
|
||||||
|
radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
|
||||||
|
radeon_ring_write(ring, 0x8);
|
||||||
|
|
||||||
|
radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
|
||||||
|
radeon_ring_write(ring, 3);
|
||||||
|
|
||||||
|
radeon_ring_unlock_commit(rdev, ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = radeon_ring_lock(rdev, ring, 10);
|
|
||||||
if (r) {
|
|
||||||
DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
|
|
||||||
radeon_ring_write(ring, tmp);
|
|
||||||
radeon_ring_write(ring, 0xFFFFF);
|
|
||||||
|
|
||||||
tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
|
|
||||||
radeon_ring_write(ring, tmp);
|
|
||||||
radeon_ring_write(ring, 0xFFFFF);
|
|
||||||
|
|
||||||
tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
|
|
||||||
radeon_ring_write(ring, tmp);
|
|
||||||
radeon_ring_write(ring, 0xFFFFF);
|
|
||||||
|
|
||||||
/* Clear timeout status bits */
|
|
||||||
radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
|
|
||||||
radeon_ring_write(ring, 0x8);
|
|
||||||
|
|
||||||
radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
|
|
||||||
radeon_ring_write(ring, 3);
|
|
||||||
|
|
||||||
radeon_ring_unlock_commit(rdev, ring);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void r600_uvd_stop(struct radeon_device *rdev)
|
void r600_do_uvd_stop(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
|
|
||||||
|
|
||||||
/* force RBC into idle state */
|
/* force RBC into idle state */
|
||||||
WREG32(UVD_RBC_RB_CNTL, 0x11010101);
|
WREG32(UVD_RBC_RB_CNTL, 0x11010101);
|
||||||
|
|
||||||
|
@ -2723,11 +2723,17 @@ void r600_uvd_stop(struct radeon_device *rdev)
|
||||||
/* Unstall UMC and register bus */
|
/* Unstall UMC and register bus */
|
||||||
WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
|
WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
|
||||||
WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
|
WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void r600_uvd_stop(struct radeon_device *rdev)
|
||||||
|
{
|
||||||
|
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
|
||||||
|
|
||||||
|
r600_do_uvd_stop(rdev);
|
||||||
ring->ready = false;
|
ring->ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r600_uvd_init(struct radeon_device *rdev)
|
int r600_uvd_init(struct radeon_device *rdev, bool ring_test)
|
||||||
{
|
{
|
||||||
int i, j, r;
|
int i, j, r;
|
||||||
/* disable byte swapping */
|
/* disable byte swapping */
|
||||||
|
@ -2815,17 +2821,17 @@ int r600_uvd_init(struct radeon_device *rdev)
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
DRM_ERROR("UVD not responding, giving up!!!\n");
|
DRM_ERROR("UVD not responding, giving up!!!\n");
|
||||||
radeon_set_uvd_clocks(rdev, 0, 0);
|
goto done;
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable interupt */
|
/* enable interupt */
|
||||||
WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
|
WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
|
||||||
|
|
||||||
r = r600_uvd_rbc_start(rdev);
|
r = r600_uvd_rbc_start(rdev, ring_test);
|
||||||
if (!r)
|
if (!r)
|
||||||
DRM_INFO("UVD initialized successfully.\n");
|
DRM_INFO("UVD initialized successfully.\n");
|
||||||
|
|
||||||
|
done:
|
||||||
/* lower clocks again */
|
/* lower clocks again */
|
||||||
radeon_set_uvd_clocks(rdev, 0, 0);
|
radeon_set_uvd_clocks(rdev, 0, 0);
|
||||||
|
|
||||||
|
|
|
@ -424,8 +424,7 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||||
struct seq_file *m);
|
struct seq_file *m);
|
||||||
|
|
||||||
/* uvd */
|
/* uvd */
|
||||||
int r600_uvd_init(struct radeon_device *rdev);
|
int r600_uvd_init(struct radeon_device *rdev, bool ring_test);
|
||||||
int r600_uvd_rbc_start(struct radeon_device *rdev);
|
|
||||||
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);
|
||||||
void r600_uvd_fence_emit(struct radeon_device *rdev,
|
void r600_uvd_fence_emit(struct radeon_device *rdev,
|
||||||
|
@ -696,7 +695,6 @@ u32 cik_get_xclk(struct radeon_device *rdev);
|
||||||
uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
|
uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
|
||||||
void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||||
int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
|
int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
|
||||||
int cik_uvd_resume(struct radeon_device *rdev);
|
|
||||||
void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
|
void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
|
||||||
struct radeon_fence *fence);
|
struct radeon_fence *fence);
|
||||||
void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
|
void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
|
||||||
|
|
|
@ -1928,7 +1928,7 @@ static int rv770_startup(struct radeon_device *rdev)
|
||||||
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)
|
||||||
r = r600_uvd_init(rdev);
|
r = r600_uvd_init(rdev, true);
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
||||||
|
|
|
@ -6421,7 +6421,7 @@ static int si_startup(struct radeon_device *rdev)
|
||||||
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)
|
||||||
r = r600_uvd_init(rdev);
|
r = r600_uvd_init(rdev, true);
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue