Necessary for proper gfx/rlc/smu handshaking.
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/r600.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 4ea5b10..0bc39cd 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2710,6 +2710,22 @@ int r600_cp_start(struct radeon_device *rdev) return 0; }
+static void r600_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable) +{ + u32 tmp = RREG32(CP_INT_CNTL); + + if (enable) + tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + else + tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL, tmp); + + if (!enable) + /* read a gfx register */ + tmp = RREG32(R_028010_DB_DEPTH_INFO); +} + int r600_cp_resume(struct radeon_device *rdev) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; @@ -2723,6 +2739,8 @@ int r600_cp_resume(struct radeon_device *rdev) mdelay(15); WREG32(GRBM_SOFT_RESET, 0);
+ r600_enable_gui_idle_interrupt(rdev, false); + /* Set ring buffer size */ rb_bufsz = order_base_2(ring->ring_size / 8); tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; @@ -2768,6 +2786,8 @@ int r600_cp_resume(struct radeon_device *rdev) return r; }
+ r600_enable_gui_idle_interrupt(rdev, true); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
@@ -3573,7 +3593,7 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) { u32 tmp;
- WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL, 0); tmp = RREG32(DMA_CNTL) & ~TRAP_ENABLE; WREG32(DMA_CNTL, tmp); WREG32(GRBM_INT_CNTL, 0); @@ -3714,7 +3734,7 @@ void r600_irq_fini(struct radeon_device *rdev)
int r600_irq_set(struct radeon_device *rdev) { - u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 cp_int_cntl; u32 mode_int = 0; u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; @@ -3734,6 +3754,8 @@ int r600_irq_set(struct radeon_device *rdev) return 0; }
+ cp_int_cntl = RREG32(CP_INT_CNTL) & ~(RB_INT_ENABLE | TIME_STAMP_INT_ENABLE); + if (ASIC_IS_DCE3(rdev)) { hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
Necessary for proper gfx/rlc/smu handshaking.
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 12 ++++++++++-- drivers/gpu/drm/radeon/r600.c | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0acde19..0e0fb07 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -216,6 +216,8 @@ extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); extern u32 cik_get_csb_size(struct radeon_device *rdev); extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev); +extern void r600_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable);
static const u32 evergreen_golden_registers[] = { @@ -3037,6 +3039,8 @@ static int evergreen_cp_resume(struct radeon_device *rdev) WREG32(GRBM_SOFT_RESET, 0); RREG32(GRBM_SOFT_RESET);
+ r600_enable_gui_idle_interrupt(rdev, false); + /* Set ring buffer size */ rb_bufsz = order_base_2(ring->ring_size / 8); tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; @@ -3082,6 +3086,9 @@ static int evergreen_cp_resume(struct radeon_device *rdev) ring->ready = false; return r; } + + r600_enable_gui_idle_interrupt(rdev, true); + return 0; }
@@ -4419,7 +4426,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) tmp = RREG32(CAYMAN_DMA1_CNTL) & ~TRAP_ENABLE; WREG32(CAYMAN_DMA1_CNTL, tmp); } else - WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL, 0); tmp = RREG32(DMA_CNTL) & ~TRAP_ENABLE; WREG32(DMA_CNTL, tmp); WREG32(GRBM_INT_CNTL, 0); @@ -4468,7 +4475,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
int evergreen_irq_set(struct radeon_device *rdev) { - u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 cp_int_cntl = 0; u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; @@ -4526,6 +4533,7 @@ int evergreen_irq_set(struct radeon_device *rdev) cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; } } else { + cp_int_cntl = RREG32(CP_INT_CNTL) & ~(RB_INT_ENABLE | TIME_STAMP_INT_ENABLE); if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); cp_int_cntl |= RB_INT_ENABLE; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 0bc39cd..df59d8c 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2710,8 +2710,8 @@ int r600_cp_start(struct radeon_device *rdev) return 0; }
-static void r600_enable_gui_idle_interrupt(struct radeon_device *rdev, - bool enable) +void r600_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable) { u32 tmp = RREG32(CP_INT_CNTL);
Necessary for proper gfx/rlc/smu handshaking.
Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen.c | 35 ++++++++++++++++++++++++++--------- drivers/gpu/drm/radeon/ni.c | 29 ++++++++++++++++++++++++++--- drivers/gpu/drm/radeon/nid.h | 3 +++ 3 files changed, 55 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0e0fb07..b7f3a18 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -205,8 +205,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); void evergreen_pcie_gen2_enable(struct radeon_device *rdev); void evergreen_program_aspm(struct radeon_device *rdev); -extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev, - int ring, u32 cp_int_cntl); +extern void cayman_cp_int_cntl_select(struct radeon_device *rdev, + int ring); extern void cayman_vm_decode_fault(struct radeon_device *rdev, u32 status, u32 addr); void cik_init_cp_pg_table(struct radeon_device *rdev); @@ -4419,10 +4419,14 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) u32 tmp;
if (rdev->family >= CHIP_CAYMAN) { - cayman_cp_int_cntl_setup(rdev, 0, - CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); - cayman_cp_int_cntl_setup(rdev, 1, 0); - cayman_cp_int_cntl_setup(rdev, 2, 0); + mutex_lock(&rdev->grbm_idx_mutex); + cayman_cp_int_cntl_select(rdev, 0); + WREG32(CP_INT_CNTL, 0); + cayman_cp_int_cntl_select(rdev, 1); + WREG32(CP_INT_CNTL, 0); + cayman_cp_int_cntl_select(rdev, 2); + WREG32(CP_INT_CNTL, 0); + mutex_unlock(&rdev->grbm_idx_mutex); tmp = RREG32(CAYMAN_DMA1_CNTL) & ~TRAP_ENABLE; WREG32(CAYMAN_DMA1_CNTL, tmp); } else @@ -4519,19 +4523,27 @@ int evergreen_irq_set(struct radeon_device *rdev) dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE;
if (rdev->family >= CHIP_CAYMAN) { + mutex_lock(&rdev->grbm_idx_mutex); /* enable CP interrupts on all rings */ + cayman_cp_int_cntl_select(rdev, 0); + cp_int_cntl = RREG32(CP_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); cp_int_cntl |= TIME_STAMP_INT_ENABLE; } + cayman_cp_int_cntl_select(rdev, 1); + cp_int_cntl1 = RREG32(CP_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; } + cayman_cp_int_cntl_select(rdev, 2); + cp_int_cntl2 = RREG32(CP_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; } + mutex_unlock(&rdev->grbm_idx_mutex); } else { cp_int_cntl = RREG32(CP_INT_CNTL) & ~(RB_INT_ENABLE | TIME_STAMP_INT_ENABLE); if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { @@ -4639,9 +4651,14 @@ int evergreen_irq_set(struct radeon_device *rdev) }
if (rdev->family >= CHIP_CAYMAN) { - cayman_cp_int_cntl_setup(rdev, 0, cp_int_cntl); - cayman_cp_int_cntl_setup(rdev, 1, cp_int_cntl1); - cayman_cp_int_cntl_setup(rdev, 2, cp_int_cntl2); + mutex_lock(&rdev->grbm_idx_mutex); + cayman_cp_int_cntl_select(rdev, 0); + WREG32(CP_INT_CNTL, cp_int_cntl); + cayman_cp_int_cntl_select(rdev, 1); + WREG32(CP_INT_CNTL, cp_int_cntl1); + cayman_cp_int_cntl_select(rdev, 2); + WREG32(CP_INT_CNTL, cp_int_cntl2); + mutex_unlock(&rdev->grbm_idx_mutex); } else WREG32(CP_INT_CNTL, cp_int_cntl);
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 6de9d363..2b2e177 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1393,13 +1393,12 @@ static void cayman_pcie_gart_fini(struct radeon_device *rdev) radeon_gart_fini(rdev); }
-void cayman_cp_int_cntl_setup(struct radeon_device *rdev, - int ring, u32 cp_int_cntl) +void cayman_cp_int_cntl_select(struct radeon_device *rdev, + int ring) { u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3;
WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3)); - WREG32(CP_INT_CNTL, cp_int_cntl); }
/* @@ -1619,6 +1618,26 @@ static int cayman_cp_start(struct radeon_device *rdev) return 0; }
+static void cayman_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable) +{ + u32 tmp; + + mutex_lock(&rdev->grbm_idx_mutex); + cayman_cp_int_cntl_select(rdev, 0); + tmp = RREG32(CP_INT_CNTL); + if (enable) + tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + else + tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL, tmp); + mutex_unlock(&rdev->grbm_idx_mutex); + + if (!enable) + /* read a gfx register */ + tmp = RREG32(DB_DEPTH_INFO); +} + static void cayman_cp_fini(struct radeon_device *rdev) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; @@ -1679,6 +1698,8 @@ static int cayman_cp_resume(struct radeon_device *rdev) WREG32(GRBM_SOFT_RESET, 0); RREG32(GRBM_SOFT_RESET);
+ cayman_enable_gui_idle_interrupt(rdev, false); + WREG32(CP_SEM_WAIT_TIMER, 0x0); WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
@@ -1743,6 +1764,8 @@ static int cayman_cp_resume(struct radeon_device *rdev) return r; }
+ cayman_enable_gui_idle_interrupt(rdev, true); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 47eb49b..90df28c 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -1141,6 +1141,9 @@ #define UVD_RBC_RB_WPTR 0xF694 #define UVD_STATUS 0xf6bc
+ +#define DB_DEPTH_INFO 0x2803C + /* * PM4 */
dri-devel@lists.freedesktop.org