aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon/rv515.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/rv515.c')
-rw-r--r--drivers/gpu/drm/radeon/rv515.c873
1 files changed, 498 insertions, 375 deletions
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 59632a506b4..3e21e869015 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -26,18 +26,26 @@
* Jerome Glisse
*/
#include <linux/seq_file.h>
-#include "drmP.h"
+#include <linux/slab.h>
+#include <drm/drmP.h>
#include "rv515d.h"
#include "radeon.h"
+#include "radeon_asic.h"
#include "atom.h"
#include "rv515_reg_safe.h"
/* This files gather functions specifics to: rv515 */
-int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
-int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
-void rv515_gpu_init(struct radeon_device *rdev);
+static int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
+static int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
+static void rv515_gpu_init(struct radeon_device *rdev);
int rv515_mc_wait_for_idle(struct radeon_device *rdev);
+static const u32 crtc_offsets[2] =
+{
+ 0,
+ AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
+};
+
void rv515_debugfs(struct radeon_device *rdev)
{
if (r100_debugfs_rbbm_init(rdev)) {
@@ -51,46 +59,46 @@ void rv515_debugfs(struct radeon_device *rdev)
}
}
-void rv515_ring_start(struct radeon_device *rdev)
+void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring)
{
int r;
- r = radeon_ring_lock(rdev, 64);
+ r = radeon_ring_lock(rdev, ring, 64);
if (r) {
return;
}
- radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0));
- radeon_ring_write(rdev,
+ radeon_ring_write(ring, PACKET0(ISYNC_CNTL, 0));
+ radeon_ring_write(ring,
ISYNC_ANY2D_IDLE3D |
ISYNC_ANY3D_IDLE2D |
ISYNC_WAIT_IDLEGUI |
ISYNC_CPSCRATCH_IDLEGUI);
- radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
- radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
- radeon_ring_write(rdev, PACKET0(0x170C, 0));
- radeon_ring_write(rdev, 1 << 31);
- radeon_ring_write(rdev, PACKET0(GB_SELECT, 0));
- radeon_ring_write(rdev, 0);
- radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0));
- radeon_ring_write(rdev, 0);
- radeon_ring_write(rdev, PACKET0(0x42C8, 0));
- radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1);
- radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0));
- radeon_ring_write(rdev, 0);
- radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
- radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
- radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
- radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
- radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
- radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
- radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0));
- radeon_ring_write(rdev, 0);
- radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
- radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
- radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
- radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
- radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0));
- radeon_ring_write(rdev,
+ radeon_ring_write(ring, PACKET0(WAIT_UNTIL, 0));
+ radeon_ring_write(ring, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
+ radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0));
+ radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG);
+ radeon_ring_write(ring, PACKET0(GB_SELECT, 0));
+ radeon_ring_write(ring, 0);
+ radeon_ring_write(ring, PACKET0(GB_ENABLE, 0));
+ radeon_ring_write(ring, 0);
+ radeon_ring_write(ring, PACKET0(R500_SU_REG_DEST, 0));
+ radeon_ring_write(ring, (1 << rdev->num_gb_pipes) - 1);
+ radeon_ring_write(ring, PACKET0(VAP_INDEX_OFFSET, 0));
+ radeon_ring_write(ring, 0);
+ radeon_ring_write(ring, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
+ radeon_ring_write(ring, RB3D_DC_FLUSH | RB3D_DC_FREE);
+ radeon_ring_write(ring, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
+ radeon_ring_write(ring, ZC_FLUSH | ZC_FREE);
+ radeon_ring_write(ring, PACKET0(WAIT_UNTIL, 0));
+ radeon_ring_write(ring, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
+ radeon_ring_write(ring, PACKET0(GB_AA_CONFIG, 0));
+ radeon_ring_write(ring, 0);
+ radeon_ring_write(ring, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
+ radeon_ring_write(ring, RB3D_DC_FLUSH | RB3D_DC_FREE);
+ radeon_ring_write(ring, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
+ radeon_ring_write(ring, ZC_FLUSH | ZC_FREE);
+ radeon_ring_write(ring, PACKET0(GB_MSPOS0, 0));
+ radeon_ring_write(ring,
((6 << MS_X0_SHIFT) |
(6 << MS_Y0_SHIFT) |
(6 << MS_X1_SHIFT) |
@@ -99,8 +107,8 @@ void rv515_ring_start(struct radeon_device *rdev)
(6 << MS_Y2_SHIFT) |
(6 << MSBD0_Y_SHIFT) |
(6 << MSBD0_X_SHIFT)));
- radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0));
- radeon_ring_write(rdev,
+ radeon_ring_write(ring, PACKET0(GB_MSPOS1, 0));
+ radeon_ring_write(ring,
((6 << MS_X3_SHIFT) |
(6 << MS_Y3_SHIFT) |
(6 << MS_X4_SHIFT) |
@@ -108,15 +116,15 @@ void rv515_ring_start(struct radeon_device *rdev)
(6 << MS_X5_SHIFT) |
(6 << MS_Y5_SHIFT) |
(6 << MSBD1_SHIFT)));
- radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0));
- radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL);
- radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0));
- radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE);
- radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0));
- radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST);
- radeon_ring_write(rdev, PACKET0(0x20C8, 0));
- radeon_ring_write(rdev, 0);
- radeon_ring_unlock_commit(rdev);
+ radeon_ring_write(ring, PACKET0(GA_ENHANCE, 0));
+ radeon_ring_write(ring, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL);
+ radeon_ring_write(ring, PACKET0(GA_POLY_MODE, 0));
+ radeon_ring_write(ring, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE);
+ radeon_ring_write(ring, PACKET0(GA_ROUND_MODE, 0));
+ radeon_ring_write(ring, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST);
+ radeon_ring_write(ring, PACKET0(0x20C8, 0));
+ radeon_ring_write(ring, 0);
+ radeon_ring_unlock_commit(rdev, ring);
}
int rv515_mc_wait_for_idle(struct radeon_device *rdev)
@@ -141,30 +149,25 @@ void rv515_vga_render_disable(struct radeon_device *rdev)
RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL);
}
-void rv515_gpu_init(struct radeon_device *rdev)
+static void rv515_gpu_init(struct radeon_device *rdev)
{
unsigned pipe_select_current, gb_pipe_select, tmp;
- r100_hdp_reset(rdev);
- r100_rb2d_reset(rdev);
-
if (r100_gui_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait GUI idle while "
- "reseting GPU. Bad things might happen.\n");
+ "resetting GPU. Bad things might happen.\n");
}
-
rv515_vga_render_disable(rdev);
-
r420_pipes_init(rdev);
- gb_pipe_select = RREG32(0x402C);
- tmp = RREG32(0x170C);
+ gb_pipe_select = RREG32(R400_GB_PIPE_SELECT);
+ tmp = RREG32(R300_DST_PIPE_CONFIG);
pipe_select_current = (tmp >> 2) & 3;
tmp = (1 << pipe_select_current) |
(((gb_pipe_select >> 8) & 0xF) << 4);
WREG32_PLL(0x000D, tmp);
if (r100_gui_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait GUI idle while "
- "reseting GPU. Bad things might happen.\n");
+ "resetting GPU. Bad things might happen.\n");
}
if (rv515_mc_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait MC idle while "
@@ -172,91 +175,6 @@ void rv515_gpu_init(struct radeon_device *rdev)
}
}
-int rv515_ga_reset(struct radeon_device *rdev)
-{
- uint32_t tmp;
- bool reinit_cp;
- int i;
-
- reinit_cp = rdev->cp.ready;
- rdev->cp.ready = false;
- for (i = 0; i < rdev->usec_timeout; i++) {
- WREG32(CP_CSQ_MODE, 0);
- WREG32(CP_CSQ_CNTL, 0);
- WREG32(RBBM_SOFT_RESET, 0x32005);
- (void)RREG32(RBBM_SOFT_RESET);
- udelay(200);
- WREG32(RBBM_SOFT_RESET, 0);
- /* Wait to prevent race in RBBM_STATUS */
- mdelay(1);
- tmp = RREG32(RBBM_STATUS);
- if (tmp & ((1 << 20) | (1 << 26))) {
- DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp);
- /* GA still busy soft reset it */
- WREG32(0x429C, 0x200);
- WREG32(VAP_PVS_STATE_FLUSH_REG, 0);
- WREG32(0x43E0, 0);
- WREG32(0x43E4, 0);
- WREG32(0x24AC, 0);
- }
- /* Wait to prevent race in RBBM_STATUS */
- mdelay(1);
- tmp = RREG32(RBBM_STATUS);
- if (!(tmp & ((1 << 20) | (1 << 26)))) {
- break;
- }
- }
- for (i = 0; i < rdev->usec_timeout; i++) {
- tmp = RREG32(RBBM_STATUS);
- if (!(tmp & ((1 << 20) | (1 << 26)))) {
- DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
- tmp);
- DRM_INFO("GA_IDLE=0x%08X\n", RREG32(0x425C));
- DRM_INFO("RB3D_RESET_STATUS=0x%08X\n", RREG32(0x46f0));
- DRM_INFO("ISYNC_CNTL=0x%08X\n", RREG32(0x1724));
- if (reinit_cp) {
- return r100_cp_init(rdev, rdev->cp.ring_size);
- }
- return 0;
- }
- DRM_UDELAY(1);
- }
- tmp = RREG32(RBBM_STATUS);
- DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
- return -1;
-}
-
-int rv515_gpu_reset(struct radeon_device *rdev)
-{
- uint32_t status;
-
- /* reset order likely matter */
- status = RREG32(RBBM_STATUS);
- /* reset HDP */
- r100_hdp_reset(rdev);
- /* reset rb2d */
- if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
- r100_rb2d_reset(rdev);
- }
- /* reset GA */
- if (status & ((1 << 20) | (1 << 26))) {
- rv515_ga_reset(rdev);
- }
- /* reset CP */
- status = RREG32(RBBM_STATUS);
- if (status & (1 << 16)) {
- r100_cp_reset(rdev);
- }
- /* Check if GPU is idle */
- status = RREG32(RBBM_STATUS);
- if (status & (1 << 31)) {
- DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
- return -1;
- }
- DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status);
- return 0;
-}
-
static void rv515_vram_get_type(struct radeon_device *rdev)
{
uint32_t tmp;
@@ -277,36 +195,41 @@ static void rv515_vram_get_type(struct radeon_device *rdev)
}
}
-void rv515_vram_info(struct radeon_device *rdev)
+static void rv515_mc_init(struct radeon_device *rdev)
{
- fixed20_12 a;
rv515_vram_get_type(rdev);
-
r100_vram_init_sizes(rdev);
- /* FIXME: we should enforce default clock in case GPU is not in
- * default setup
- */
- a.full = rfixed_const(100);
- rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
- rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+ radeon_vram_location(rdev, &rdev->mc, 0);
+ rdev->mc.gtt_base_align = 0;
+ if (!(rdev->flags & RADEON_IS_AGP))
+ radeon_gtt_location(rdev, &rdev->mc);
+ radeon_update_bandwidth_info(rdev);
}
uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
{
+ unsigned long flags;
uint32_t r;
+ spin_lock_irqsave(&rdev->mc_idx_lock, flags);
WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
r = RREG32(MC_IND_DATA);
WREG32(MC_IND_INDEX, 0);
+ spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
+
return r;
}
void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rdev->mc_idx_lock, flags);
WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
WREG32(MC_IND_DATA, (v));
WREG32(MC_IND_INDEX, 0);
+ spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
}
#if defined(CONFIG_DEBUG_FS)
@@ -337,7 +260,7 @@ static int rv515_debugfs_ga_info(struct seq_file *m, void *data)
tmp = RREG32(0x2140);
seq_printf(m, "VAP_CNTL_STATUS 0x%08x\n", tmp);
- radeon_gpu_reset(rdev);
+ radeon_asic_reset(rdev);
tmp = RREG32(0x425C);
seq_printf(m, "GA_IDLE 0x%08x\n", tmp);
return 0;
@@ -352,7 +275,7 @@ static struct drm_info_list rv515_ga_info_list[] = {
};
#endif
-int rv515_debugfs_pipes_info_init(struct radeon_device *rdev)
+static int rv515_debugfs_pipes_info_init(struct radeon_device *rdev)
{
#if defined(CONFIG_DEBUG_FS)
return radeon_debugfs_add_files(rdev, rv515_pipes_info_list, 1);
@@ -361,7 +284,7 @@ int rv515_debugfs_pipes_info_init(struct radeon_device *rdev)
#endif
}
-int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
+static int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
{
#if defined(CONFIG_DEBUG_FS)
return radeon_debugfs_add_files(rdev, rv515_ga_info_list, 1);
@@ -372,49 +295,177 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
{
- save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL);
- save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);
+ u32 crtc_enabled, tmp, frame_count, blackout;
+ int i, j;
+
save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);
save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
- save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL);
- save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);
- /* Stop all video */
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
+ /* disable VGA render */
WREG32(R_000300_VGA_RENDER_CONTROL, 0);
- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
- WREG32(R_006080_D1CRTC_CONTROL, 0);
- WREG32(R_006880_D2CRTC_CONTROL, 0);
- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
- WREG32(R_000330_D1VGA_CONTROL, 0);
- WREG32(R_000338_D2VGA_CONTROL, 0);
+ /* blank the display controllers */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ crtc_enabled = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN;
+ if (crtc_enabled) {
+ save->crtc_enabled[i] = true;
+ tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
+ if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) {
+ radeon_wait_for_vblank(rdev, i);
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
+ WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ }
+ /* wait for the next frame */
+ frame_count = radeon_get_vblank_counter(rdev, i);
+ for (j = 0; j < rdev->usec_timeout; j++) {
+ if (radeon_get_vblank_counter(rdev, i) != frame_count)
+ break;
+ udelay(1);
+ }
+
+ /* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
+ tmp &= ~AVIVO_CRTC_EN;
+ WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ save->crtc_enabled[i] = false;
+ /* ***** */
+ } else {
+ save->crtc_enabled[i] = false;
+ }
+ }
+
+ radeon_mc_wait_for_idle(rdev);
+
+ if (rdev->family >= CHIP_R600) {
+ if (rdev->family >= CHIP_RV770)
+ blackout = RREG32(R700_MC_CITF_CNTL);
+ else
+ blackout = RREG32(R600_CITF_CNTL);
+ if ((blackout & R600_BLACKOUT_MASK) != R600_BLACKOUT_MASK) {
+ /* Block CPU access */
+ WREG32(R600_BIF_FB_EN, 0);
+ /* blackout the MC */
+ blackout |= R600_BLACKOUT_MASK;
+ if (rdev->family >= CHIP_RV770)
+ WREG32(R700_MC_CITF_CNTL, blackout);
+ else
+ WREG32(R600_CITF_CNTL, blackout);
+ }
+ }
+ /* wait for the MC to settle */
+ udelay(100);
+
+ /* lock double buffered regs */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+ if (!(tmp & AVIVO_D1GRPH_UPDATE_LOCK)) {
+ tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
+ WREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ if (!(tmp & 1)) {
+ tmp |= 1;
+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ }
+ }
+ }
}
void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
{
- WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
- WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
- WREG32(R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
- WREG32(R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
- WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
- /* Unlock host access */
+ u32 tmp, frame_count;
+ int i, j;
+
+ /* update crtc base addresses */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (rdev->family >= CHIP_RV770) {
+ if (i == 0) {
+ WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
+ upper_32_bits(rdev->mc.vram_start));
+ WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
+ upper_32_bits(rdev->mc.vram_start));
+ } else {
+ WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
+ upper_32_bits(rdev->mc.vram_start));
+ WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
+ upper_32_bits(rdev->mc.vram_start));
+ }
+ }
+ WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
+ (u32)rdev->mc.vram_start);
+ WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
+ (u32)rdev->mc.vram_start);
+ }
+ WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
+
+ /* unlock regs and wait for update */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i]);
+ if ((tmp & 0x7) != 3) {
+ tmp &= ~0x7;
+ tmp |= 0x3;
+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+ if (tmp & AVIVO_D1GRPH_UPDATE_LOCK) {
+ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
+ WREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ if (tmp & 1) {
+ tmp &= ~1;
+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ }
+ for (j = 0; j < rdev->usec_timeout; j++) {
+ tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+ if ((tmp & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) == 0)
+ break;
+ udelay(1);
+ }
+ }
+ }
+
+ if (rdev->family >= CHIP_R600) {
+ /* unblackout the MC */
+ if (rdev->family >= CHIP_RV770)
+ tmp = RREG32(R700_MC_CITF_CNTL);
+ else
+ tmp = RREG32(R600_CITF_CNTL);
+ tmp &= ~R600_BLACKOUT_MASK;
+ if (rdev->family >= CHIP_RV770)
+ WREG32(R700_MC_CITF_CNTL, tmp);
+ else
+ WREG32(R600_CITF_CNTL, tmp);
+ /* allow CPU access */
+ WREG32(R600_BIF_FB_EN, R600_FB_READ_EN | R600_FB_WRITE_EN);
+ }
+
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
+ tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
+ WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+ /* wait for the next frame */
+ frame_count = radeon_get_vblank_counter(rdev, i);
+ for (j = 0; j < rdev->usec_timeout; j++) {
+ if (radeon_get_vblank_counter(rdev, i) != frame_count)
+ break;
+ udelay(1);
+ }
+ }
+ }
+ /* Unlock vga access */
WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
mdelay(1);
- /* Restore video state */
- WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control);
- WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control);
- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
- WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control);
- WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control);
- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
}
-void rv515_mc_program(struct radeon_device *rdev)
+static void rv515_mc_program(struct radeon_device *rdev)
{
struct rv515_mc_save save;
@@ -477,34 +528,54 @@ static int rv515_startup(struct radeon_device *rdev)
if (r)
return r;
}
+
+ /* allocate wb buffer */
+ r = radeon_wb_init(rdev);
+ if (r)
+ return r;
+
+ r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
+ return r;
+ }
+
/* Enable IRQ */
+ if (!rdev->irq.installed) {
+ r = radeon_irq_kms_init(rdev);
+ if (r)
+ return r;
+ }
+
rs600_irq_set(rdev);
+ rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
if (r) {
- dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+ dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
return r;
}
- r = r100_wb_init(rdev);
- if (r)
- dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
- r = r100_ib_init(rdev);
+
+ r = radeon_ib_pool_init(rdev);
if (r) {
- dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+ dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
return r;
}
+
return 0;
}
int rv515_resume(struct radeon_device *rdev)
{
+ int r;
+
/* Make sur GART are not working */
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_disable(rdev);
/* Resume clock before doing reset */
rv515_clock_startup(rdev);
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
- if (radeon_gpu_reset(rdev)) {
+ if (radeon_asic_reset(rdev)) {
dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
RREG32(R_000E40_RBBM_STATUS),
RREG32(R_0007C0_CP_STAT));
@@ -515,13 +586,20 @@ int rv515_resume(struct radeon_device *rdev)
rv515_clock_startup(rdev);
/* Initialize surface registers */
radeon_surface_init(rdev);
- return rv515_startup(rdev);
+
+ rdev->accel_working = true;
+ r = rv515_startup(rdev);
+ if (r) {
+ rdev->accel_working = false;
+ }
+ return r;
}
int rv515_suspend(struct radeon_device *rdev)
{
+ radeon_pm_suspend(rdev);
r100_cp_disable(rdev);
- r100_wb_disable(rdev);
+ radeon_wb_disable(rdev);
rs600_irq_disable(rdev);
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_disable(rdev);
@@ -536,10 +614,10 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
void rv515_fini(struct radeon_device *rdev)
{
- rv515_suspend(rdev);
+ radeon_pm_fini(rdev);
r100_cp_fini(rdev);
- r100_wb_fini(rdev);
- r100_ib_fini(rdev);
+ radeon_wb_fini(rdev);
+ radeon_ib_pool_fini(rdev);
radeon_gem_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
@@ -560,6 +638,8 @@ int rv515_init(struct radeon_device *rdev)
/* Initialize surface registers */
radeon_surface_init(rdev);
/* TODO: disable VGA need to use VGA request */
+ /* restore some register to sane defaults */
+ r100_restore_sanity(rdev);
/* BIOS*/
if (!radeon_get_bios(rdev)) {
if (ASIC_IS_AVIVO(rdev))
@@ -574,7 +654,7 @@ int rv515_init(struct radeon_device *rdev)
return -EINVAL;
}
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
- if (radeon_gpu_reset(rdev)) {
+ if (radeon_asic_reset(rdev)) {
dev_warn(rdev->dev,
"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
RREG32(R_000E40_RBBM_STATUS),
@@ -585,22 +665,20 @@ int rv515_init(struct radeon_device *rdev)
return -EINVAL;
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
- /* Initialize power management */
- radeon_pm_init(rdev);
- /* Get vram informations */
- rv515_vram_info(rdev);
- /* Initialize memory controller (also test AGP) */
- r = r420_mc_init(rdev);
- if (r)
- return r;
+ /* initialize AGP */
+ if (rdev->flags & RADEON_IS_AGP) {
+ r = radeon_agp_init(rdev);
+ if (r) {
+ radeon_agp_disable(rdev);
+ }
+ }
+ /* initialize memory controller */
+ rv515_mc_init(rdev);
rv515_debugfs(rdev);
/* Fence driver */
r = radeon_fence_driver_init(rdev);
if (r)
return r;
- r = radeon_irq_kms_init(rdev);
- if (r)
- return r;
/* Memory manager */
r = radeon_bo_init(rdev);
if (r)
@@ -609,18 +687,21 @@ int rv515_init(struct radeon_device *rdev)
if (r)
return r;
rv515_set_safe_registers(rdev);
+
+ /* Initialize power management */
+ radeon_pm_init(rdev);
+
rdev->accel_working = true;
r = rv515_startup(rdev);
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
- rv515_suspend(rdev);
r100_cp_fini(rdev);
- r100_wb_fini(rdev);
- r100_ib_fini(rdev);
+ radeon_wb_fini(rdev);
+ radeon_ib_pool_fini(rdev);
+ radeon_irq_kms_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
- radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;
@@ -869,14 +950,17 @@ struct rv515_watermark {
fixed20_12 sclk;
};
-void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
- struct radeon_crtc *crtc,
- struct rv515_watermark *wm)
+static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
+ struct radeon_crtc *crtc,
+ struct rv515_watermark *wm,
+ bool low)
{
struct drm_display_mode *mode = &crtc->base.mode;
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
+ fixed20_12 sclk;
+ u32 selected_sclk;
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
@@ -884,20 +968,32 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
return;
}
- if (crtc->vsc.full > rfixed_const(2))
- wm->num_line_pair.full = rfixed_const(2);
+ /* rv6xx, rv7xx */
+ if ((rdev->family >= CHIP_RV610) &&
+ (rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
+ selected_sclk = radeon_dpm_get_sclk(rdev, low);
else
- wm->num_line_pair.full = rfixed_const(1);
-
- b.full = rfixed_const(mode->crtc_hdisplay);
- c.full = rfixed_const(256);
- a.full = rfixed_div(b, c);
- request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair);
- request_fifo_depth.full = rfixed_ceil(request_fifo_depth);
- if (a.full < rfixed_const(4)) {
+ selected_sclk = rdev->pm.current_sclk;
+
+ /* sclk in Mhz */
+ a.full = dfixed_const(100);
+ sclk.full = dfixed_const(selected_sclk);
+ sclk.full = dfixed_div(sclk, a);
+
+ if (crtc->vsc.full > dfixed_const(2))
+ wm->num_line_pair.full = dfixed_const(2);
+ else
+ wm->num_line_pair.full = dfixed_const(1);
+
+ b.full = dfixed_const(mode->crtc_hdisplay);
+ c.full = dfixed_const(256);
+ a.full = dfixed_div(b, c);
+ request_fifo_depth.full = dfixed_mul(a, wm->num_line_pair);
+ request_fifo_depth.full = dfixed_ceil(request_fifo_depth);
+ if (a.full < dfixed_const(4)) {
wm->lb_request_fifo_depth = 4;
} else {
- wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
+ wm->lb_request_fifo_depth = dfixed_trunc(request_fifo_depth);
}
/* Determine consumption rate
@@ -906,23 +1002,23 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
* vsc = vertical scaling ratio, defined as source/destination
* hsc = horizontal scaling ration, defined as source/destination
*/
- a.full = rfixed_const(mode->clock);
- b.full = rfixed_const(1000);
- a.full = rfixed_div(a, b);
- pclk.full = rfixed_div(b, a);
+ a.full = dfixed_const(mode->clock);
+ b.full = dfixed_const(1000);
+ a.full = dfixed_div(a, b);
+ pclk.full = dfixed_div(b, a);
if (crtc->rmx_type != RMX_OFF) {
- b.full = rfixed_const(2);
+ b.full = dfixed_const(2);
if (crtc->vsc.full > b.full)
b.full = crtc->vsc.full;
- b.full = rfixed_mul(b, crtc->hsc);
- c.full = rfixed_const(2);
- b.full = rfixed_div(b, c);
- consumption_time.full = rfixed_div(pclk, b);
+ b.full = dfixed_mul(b, crtc->hsc);
+ c.full = dfixed_const(2);
+ b.full = dfixed_div(b, c);
+ consumption_time.full = dfixed_div(pclk, b);
} else {
consumption_time.full = pclk.full;
}
- a.full = rfixed_const(1);
- wm->consumption_rate.full = rfixed_div(a, consumption_time);
+ a.full = dfixed_const(1);
+ wm->consumption_rate.full = dfixed_div(a, consumption_time);
/* Determine line time
@@ -930,27 +1026,27 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
* LineTime = total number of horizontal pixels
* pclk = pixel clock period(ns)
*/
- a.full = rfixed_const(crtc->base.mode.crtc_htotal);
- line_time.full = rfixed_mul(a, pclk);
+ a.full = dfixed_const(crtc->base.mode.crtc_htotal);
+ line_time.full = dfixed_mul(a, pclk);
/* Determine active time
* ActiveTime = time of active region of display within one line,
* hactive = total number of horizontal active pixels
* htotal = total number of horizontal pixels
*/
- a.full = rfixed_const(crtc->base.mode.crtc_htotal);
- b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
- wm->active_time.full = rfixed_mul(line_time, b);
- wm->active_time.full = rfixed_div(wm->active_time, a);
+ a.full = dfixed_const(crtc->base.mode.crtc_htotal);
+ b.full = dfixed_const(crtc->base.mode.crtc_hdisplay);
+ wm->active_time.full = dfixed_mul(line_time, b);
+ wm->active_time.full = dfixed_div(wm->active_time, a);
/* Determine chunk time
* ChunkTime = the time it takes the DCP to send one chunk of data
* to the LB which consists of pipeline delay and inter chunk gap
* sclk = system clock(Mhz)
*/
- a.full = rfixed_const(600 * 1000);
- chunk_time.full = rfixed_div(a, rdev->pm.sclk);
- read_delay_latency.full = rfixed_const(1000);
+ a.full = dfixed_const(600 * 1000);
+ chunk_time.full = dfixed_div(a, sclk);
+ read_delay_latency.full = dfixed_const(1000);
/* Determine the worst case latency
* NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
@@ -960,9 +1056,9 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
* ChunkTime = time it takes the DCP to send one chunk of data to the LB
* which consists of pipeline delay and inter chunk gap
*/
- if (rfixed_trunc(wm->num_line_pair) > 1) {
- a.full = rfixed_const(3);
- wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+ if (dfixed_trunc(wm->num_line_pair) > 1) {
+ a.full = dfixed_const(3);
+ wm->worst_case_latency.full = dfixed_mul(a, chunk_time);
wm->worst_case_latency.full += read_delay_latency.full;
} else {
wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full;
@@ -978,185 +1074,211 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
* of data to the LB which consists of
* pipeline delay and inter chunk gap
*/
- if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
+ if ((2+wm->lb_request_fifo_depth) >= dfixed_trunc(request_fifo_depth)) {
tolerable_latency.full = line_time.full;
} else {
- tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
+ tolerable_latency.full = dfixed_const(wm->lb_request_fifo_depth - 2);
tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
- tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
+ tolerable_latency.full = dfixed_mul(tolerable_latency, chunk_time);
tolerable_latency.full = line_time.full - tolerable_latency.full;
}
/* We assume worst case 32bits (4 bytes) */
- wm->dbpp.full = rfixed_const(2 * 16);
+ wm->dbpp.full = dfixed_const(2 * 16);
/* Determine the maximum priority mark
* width = viewport width in pixels
*/
- a.full = rfixed_const(16);
- wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
- wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
- wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max);
+ a.full = dfixed_const(16);
+ wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay);
+ wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a);
+ wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max);
/* Determine estimated width */
estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
- estimated_width.full = rfixed_div(estimated_width, consumption_time);
- if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
+ estimated_width.full = dfixed_div(estimated_width, consumption_time);
+ if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
wm->priority_mark.full = wm->priority_mark_max.full;
} else {
- a.full = rfixed_const(16);
- wm->priority_mark.full = rfixed_div(estimated_width, a);
- wm->priority_mark.full = rfixed_ceil(wm->priority_mark);
+ a.full = dfixed_const(16);
+ wm->priority_mark.full = dfixed_div(estimated_width, a);
+ wm->priority_mark.full = dfixed_ceil(wm->priority_mark);
wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
}
}
-void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
+static void rv515_compute_mode_priority(struct radeon_device *rdev,
+ struct rv515_watermark *wm0,
+ struct rv515_watermark *wm1,
+ struct drm_display_mode *mode0,
+ struct drm_display_mode *mode1,
+ u32 *d1mode_priority_a_cnt,
+ u32 *d2mode_priority_a_cnt)
{
- struct drm_display_mode *mode0 = NULL;
- struct drm_display_mode *mode1 = NULL;
- struct rv515_watermark wm0;
- struct rv515_watermark wm1;
- u32 tmp;
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
- if (rdev->mode_info.crtcs[0]->base.enabled)
- mode0 = &rdev->mode_info.crtcs[0]->base.mode;
- if (rdev->mode_info.crtcs[1]->base.enabled)
- mode1 = &rdev->mode_info.crtcs[1]->base.mode;
- rs690_line_buffer_adjust(rdev, mode0, mode1);
-
- rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
- rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
-
- tmp = wm0.lb_request_fifo_depth;
- tmp |= wm1.lb_request_fifo_depth << 16;
- WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+ *d1mode_priority_a_cnt = MODE_PRIORITY_OFF;
+ *d2mode_priority_a_cnt = MODE_PRIORITY_OFF;
if (mode0 && mode1) {
- if (rfixed_trunc(wm0.dbpp) > 64)
- a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
+ if (dfixed_trunc(wm0->dbpp) > 64)
+ a.full = dfixed_div(wm0->dbpp, wm0->num_line_pair);
else
- a.full = wm0.num_line_pair.full;
- if (rfixed_trunc(wm1.dbpp) > 64)
- b.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
+ a.full = wm0->num_line_pair.full;
+ if (dfixed_trunc(wm1->dbpp) > 64)
+ b.full = dfixed_div(wm1->dbpp, wm1->num_line_pair);
else
- b.full = wm1.num_line_pair.full;
+ b.full = wm1->num_line_pair.full;
a.full += b.full;
- fill_rate.full = rfixed_div(wm0.sclk, a);
- if (wm0.consumption_rate.full > fill_rate.full) {
- b.full = wm0.consumption_rate.full - fill_rate.full;
- b.full = rfixed_mul(b, wm0.active_time);
- a.full = rfixed_const(16);
- b.full = rfixed_div(b, a);
- a.full = rfixed_mul(wm0.worst_case_latency,
- wm0.consumption_rate);
+ fill_rate.full = dfixed_div(wm0->sclk, a);
+ if (wm0->consumption_rate.full > fill_rate.full) {
+ b.full = wm0->consumption_rate.full - fill_rate.full;
+ b.full = dfixed_mul(b, wm0->active_time);
+ a.full = dfixed_const(16);
+ b.full = dfixed_div(b, a);
+ a.full = dfixed_mul(wm0->worst_case_latency,
+ wm0->consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
- a.full = rfixed_mul(wm0.worst_case_latency,
- wm0.consumption_rate);
- b.full = rfixed_const(16 * 1000);
- priority_mark02.full = rfixed_div(a, b);
+ a.full = dfixed_mul(wm0->worst_case_latency,
+ wm0->consumption_rate);
+ b.full = dfixed_const(16 * 1000);
+ priority_mark02.full = dfixed_div(a, b);
}
- if (wm1.consumption_rate.full > fill_rate.full) {
- b.full = wm1.consumption_rate.full - fill_rate.full;
- b.full = rfixed_mul(b, wm1.active_time);
- a.full = rfixed_const(16);
- b.full = rfixed_div(b, a);
- a.full = rfixed_mul(wm1.worst_case_latency,
- wm1.consumption_rate);
+ if (wm1->consumption_rate.full > fill_rate.full) {
+ b.full = wm1->consumption_rate.full - fill_rate.full;
+ b.full = dfixed_mul(b, wm1->active_time);
+ a.full = dfixed_const(16);
+ b.full = dfixed_div(b, a);
+ a.full = dfixed_mul(wm1->worst_case_latency,
+ wm1->consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
- a.full = rfixed_mul(wm1.worst_case_latency,
- wm1.consumption_rate);
- b.full = rfixed_const(16 * 1000);
- priority_mark12.full = rfixed_div(a, b);
+ a.full = dfixed_mul(wm1->worst_case_latency,
+ wm1->consumption_rate);
+ b.full = dfixed_const(16 * 1000);
+ priority_mark12.full = dfixed_div(a, b);
+ }
+ if (wm0->priority_mark.full > priority_mark02.full)
+ priority_mark02.full = wm0->priority_mark.full;
+ if (wm0->priority_mark_max.full > priority_mark02.full)
+ priority_mark02.full = wm0->priority_mark_max.full;
+ if (wm1->priority_mark.full > priority_mark12.full)
+ priority_mark12.full = wm1->priority_mark.full;
+ if (wm1->priority_mark_max.full > priority_mark12.full)
+ priority_mark12.full = wm1->priority_mark_max.full;
+ *d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
+ *d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
+ if (rdev->disp_priority == 2) {
+ *d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
+ *d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
- if (wm0.priority_mark.full > priority_mark02.full)
- priority_mark02.full = wm0.priority_mark.full;
- if (rfixed_trunc(priority_mark02) < 0)
- priority_mark02.full = 0;
- if (wm0.priority_mark_max.full > priority_mark02.full)
- priority_mark02.full = wm0.priority_mark_max.full;
- if (wm1.priority_mark.full > priority_mark12.full)
- priority_mark12.full = wm1.priority_mark.full;
- if (rfixed_trunc(priority_mark12) < 0)
- priority_mark12.full = 0;
- if (wm1.priority_mark_max.full > priority_mark12.full)
- priority_mark12.full = wm1.priority_mark_max.full;
- WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
- WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
- WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
- WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
} else if (mode0) {
- if (rfixed_trunc(wm0.dbpp) > 64)
- a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
+ if (dfixed_trunc(wm0->dbpp) > 64)
+ a.full = dfixed_div(wm0->dbpp, wm0->num_line_pair);
else
- a.full = wm0.num_line_pair.full;
- fill_rate.full = rfixed_div(wm0.sclk, a);
- if (wm0.consumption_rate.full > fill_rate.full) {
- b.full = wm0.consumption_rate.full - fill_rate.full;
- b.full = rfixed_mul(b, wm0.active_time);
- a.full = rfixed_const(16);
- b.full = rfixed_div(b, a);
- a.full = rfixed_mul(wm0.worst_case_latency,
- wm0.consumption_rate);
+ a.full = wm0->num_line_pair.full;
+ fill_rate.full = dfixed_div(wm0->sclk, a);
+ if (wm0->consumption_rate.full > fill_rate.full) {
+ b.full = wm0->consumption_rate.full - fill_rate.full;
+ b.full = dfixed_mul(b, wm0->active_time);
+ a.full = dfixed_const(16);
+ b.full = dfixed_div(b, a);
+ a.full = dfixed_mul(wm0->worst_case_latency,
+ wm0->consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
- a.full = rfixed_mul(wm0.worst_case_latency,
- wm0.consumption_rate);
- b.full = rfixed_const(16);
- priority_mark02.full = rfixed_div(a, b);
+ a.full = dfixed_mul(wm0->worst_case_latency,
+ wm0->consumption_rate);
+ b.full = dfixed_const(16);
+ priority_mark02.full = dfixed_div(a, b);
}
- if (wm0.priority_mark.full > priority_mark02.full)
- priority_mark02.full = wm0.priority_mark.full;
- if (rfixed_trunc(priority_mark02) < 0)
- priority_mark02.full = 0;
- if (wm0.priority_mark_max.full > priority_mark02.full)
- priority_mark02.full = wm0.priority_mark_max.full;
- WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
- WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
- WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
- WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
- } else {
- if (rfixed_trunc(wm1.dbpp) > 64)
- a.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
+ if (wm0->priority_mark.full > priority_mark02.full)
+ priority_mark02.full = wm0->priority_mark.full;
+ if (wm0->priority_mark_max.full > priority_mark02.full)
+ priority_mark02.full = wm0->priority_mark_max.full;
+ *d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
+ if (rdev->disp_priority == 2)
+ *d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
+ } else if (mode1) {
+ if (dfixed_trunc(wm1->dbpp) > 64)
+ a.full = dfixed_div(wm1->dbpp, wm1->num_line_pair);
else
- a.full = wm1.num_line_pair.full;
- fill_rate.full = rfixed_div(wm1.sclk, a);
- if (wm1.consumption_rate.full > fill_rate.full) {
- b.full = wm1.consumption_rate.full - fill_rate.full;
- b.full = rfixed_mul(b, wm1.active_time);
- a.full = rfixed_const(16);
- b.full = rfixed_div(b, a);
- a.full = rfixed_mul(wm1.worst_case_latency,
- wm1.consumption_rate);
+ a.full = wm1->num_line_pair.full;
+ fill_rate.full = dfixed_div(wm1->sclk, a);
+ if (wm1->consumption_rate.full > fill_rate.full) {
+ b.full = wm1->consumption_rate.full - fill_rate.full;
+ b.full = dfixed_mul(b, wm1->active_time);
+ a.full = dfixed_const(16);
+ b.full = dfixed_div(b, a);
+ a.full = dfixed_mul(wm1->worst_case_latency,
+ wm1->consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
- a.full = rfixed_mul(wm1.worst_case_latency,
- wm1.consumption_rate);
- b.full = rfixed_const(16 * 1000);
- priority_mark12.full = rfixed_div(a, b);
+ a.full = dfixed_mul(wm1->worst_case_latency,
+ wm1->consumption_rate);
+ b.full = dfixed_const(16 * 1000);
+ priority_mark12.full = dfixed_div(a, b);
}
- if (wm1.priority_mark.full > priority_mark12.full)
- priority_mark12.full = wm1.priority_mark.full;
- if (rfixed_trunc(priority_mark12) < 0)
- priority_mark12.full = 0;
- if (wm1.priority_mark_max.full > priority_mark12.full)
- priority_mark12.full = wm1.priority_mark_max.full;
- WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
- WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
- WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
- WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+ if (wm1->priority_mark.full > priority_mark12.full)
+ priority_mark12.full = wm1->priority_mark.full;
+ if (wm1->priority_mark_max.full > priority_mark12.full)
+ priority_mark12.full = wm1->priority_mark_max.full;
+ *d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
+ if (rdev->disp_priority == 2)
+ *d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
}
+void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
+{
+ struct drm_display_mode *mode0 = NULL;
+ struct drm_display_mode *mode1 = NULL;
+ struct rv515_watermark wm0_high, wm0_low;
+ struct rv515_watermark wm1_high, wm1_low;
+ u32 tmp;
+ u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt;
+ u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt;
+
+ if (rdev->mode_info.crtcs[0]->base.enabled)
+ mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+ if (rdev->mode_info.crtcs[1]->base.enabled)
+ mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+ rs690_line_buffer_adjust(rdev, mode0, mode1);
+
+ rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_high, false);
+ rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_high, false);
+
+ rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_low, false);
+ rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_low, false);
+
+ tmp = wm0_high.lb_request_fifo_depth;
+ tmp |= wm1_high.lb_request_fifo_depth << 16;
+ WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+
+ rv515_compute_mode_priority(rdev,
+ &wm0_high, &wm1_high,
+ mode0, mode1,
+ &d1mode_priority_a_cnt, &d2mode_priority_a_cnt);
+ rv515_compute_mode_priority(rdev,
+ &wm0_low, &wm1_low,
+ mode0, mode1,
+ &d1mode_priority_b_cnt, &d2mode_priority_b_cnt);
+
+ WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+ WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_b_cnt);
+ WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+ WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_b_cnt);
+}
+
void rv515_bandwidth_update(struct radeon_device *rdev)
{
uint32_t tmp;
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
+ radeon_update_display_priority(rdev);
+
if (rdev->mode_info.crtcs[0]->base.enabled)
mode0 = &rdev->mode_info.crtcs[0]->base.mode;
if (rdev->mode_info.crtcs[1]->base.enabled)
@@ -1166,7 +1288,8 @@ void rv515_bandwidth_update(struct radeon_device *rdev)
* modes if the user specifies HIGH for displaypriority
* option.
*/
- if (rdev->disp_priority == 2) {
+ if ((rdev->disp_priority == 2) &&
+ (rdev->family == CHIP_RV515)) {
tmp = RREG32_MC(MC_MISC_LAT_TIMER);
tmp &= ~MC_DISP1R_INIT_LAT_MASK;
tmp &= ~MC_DISP0R_INIT_LAT_MASK;