From 655efd3dc92cd0d37292157178d33deb0430aeaa Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 2 Feb 2010 11:51:45 +0100 Subject: drm/radeon/kms: don't call suspend path before cleaning up GPU In suspend path we unmap the GART table while in cleaning up path we will unbind buffer and thus try to write to unmapped GART leading to oops. In order to avoid this we don't call the suspend path in cleanup path. Cleanup path is clever enough to desactive GPU like the suspend path is doing, thus this was redondant. Tested on: RV370, R420, RV515, RV570, RV610, RV770 (all PCIE) Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 0051d11b907c..e699e6d053dd 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1327,7 +1327,6 @@ int r300_suspend(struct radeon_device *rdev) void r300_fini(struct radeon_device *rdev) { - r300_suspend(rdev); r100_cp_fini(rdev); r100_wb_fini(rdev); r100_ib_fini(rdev); @@ -1418,15 +1417,15 @@ int r300_init(struct radeon_device *rdev) if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); - r300_suspend(rdev); r100_cp_fini(rdev); r100_wb_fini(rdev); r100_ib_fini(rdev); + radeon_irq_kms_fini(rdev); if (rdev->flags & RADEON_IS_PCIE) rv370_pcie_gart_fini(rdev); if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_fini(rdev); - radeon_irq_kms_fini(rdev); + radeon_agp_fini(rdev); rdev->accel_working = false; } return 0; -- cgit v1.2.3 From 5ff55717674470b96562f931f778c878080755b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 5 Feb 2010 13:57:03 +1000 Subject: drm/radeon/kms: fix r300 vram width calculations This was incorrect according to the docs and the UMS driver does it like this. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index e699e6d053dd..43b55a030b4d 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -506,11 +506,14 @@ void r300_vram_info(struct radeon_device *rdev) /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; + tmp = RREG32(RADEON_MEM_CNTL); - if (tmp & R300_MEM_NUM_CHANNELS_MASK) { - rdev->mc.vram_width = 128; - } else { - rdev->mc.vram_width = 64; + tmp &= R300_MEM_NUM_CHANNELS_MASK; + switch (tmp) { + case 0: rdev->mc.vram_width = 64; break; + case 1: rdev->mc.vram_width = 128; break; + case 2: rdev->mc.vram_width = 256; break; + default: rdev->mc.vram_width = 128; break; } r100_vram_init_sizes(rdev); -- cgit v1.2.3 From 4612dc97991a09e1a9e4d5d981e16589d7cb150c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 5 Feb 2010 01:58:28 -0500 Subject: drm/radeon/kms: clean up some low-hanging magic numbers Switch some magic numbers to their proper defines. The register header madness needs to be cleaned up at some point. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 12 ++++++------ drivers/gpu/drm/radeon/r300.c | 38 ++++++++++++++++++++------------------ drivers/gpu/drm/radeon/r420.c | 13 +++++++------ 3 files changed, 33 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 38209a61e515..597f85b283bc 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -366,8 +366,8 @@ void r100_fence_ring_emit(struct radeon_device *rdev, radeon_ring_write(rdev, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); radeon_ring_write(rdev, RADEON_RB3D_ZC_FLUSH_ALL); /* Wait until IDLE & CLEAN */ - radeon_ring_write(rdev, PACKET0(0x1720, 0)); - radeon_ring_write(rdev, (1 << 16) | (1 << 17)); + radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); radeon_ring_write(rdev, rdev->config.r100.hdp_cntl | RADEON_HDP_READ_BUFFER_INVALIDATE); @@ -1701,7 +1701,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev) } for (i = 0; i < rdev->usec_timeout; i++) { tmp = RREG32(RADEON_RBBM_STATUS); - if (!(tmp & (1 << 31))) { + if (!(tmp & RADEON_RBBM_ACTIVE)) { return 0; } DRM_UDELAY(1); @@ -1716,8 +1716,8 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev) for (i = 0; i < rdev->usec_timeout; i++) { /* read MC_STATUS */ - tmp = RREG32(0x0150); - if (tmp & (1 << 2)) { + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & RADEON_MC_IDLE) { return 0; } DRM_UDELAY(1); @@ -1790,7 +1790,7 @@ int r100_gpu_reset(struct radeon_device *rdev) } /* Check if GPU is idle */ status = RREG32(RADEON_RBBM_STATUS); - if (status & (1 << 31)) { + if (status & RADEON_RBBM_ACTIVE) { DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); return -1; } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 43b55a030b4d..748335c5fa84 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -174,18 +174,20 @@ void r300_fence_ring_emit(struct radeon_device *rdev, /* Who ever call radeon_fence_emit should call ring_lock and ask * for enough space (today caller are ib schedule and buffer move) */ /* Write SC register so SC & US assert idle */ - radeon_ring_write(rdev, PACKET0(0x43E0, 0)); + radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_TL, 0)); radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, PACKET0(0x43E4, 0)); + radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_BR, 0)); radeon_ring_write(rdev, 0); /* Flush 3D cache */ - radeon_ring_write(rdev, PACKET0(0x4E4C, 0)); - radeon_ring_write(rdev, (2 << 0)); - radeon_ring_write(rdev, PACKET0(0x4F18, 0)); - radeon_ring_write(rdev, (1 << 0)); + radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, R300_RB3D_DC_FLUSH); + radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, R300_ZC_FLUSH); /* Wait until IDLE & CLEAN */ - radeon_ring_write(rdev, PACKET0(0x1720, 0)); - radeon_ring_write(rdev, (1 << 17) | (1 << 16) | (1 << 9)); + radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(rdev, (RADEON_WAIT_3D_IDLECLEAN | + RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_DMA_GUI_IDLE)); radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); radeon_ring_write(rdev, rdev->config.r300.hdp_cntl | RADEON_HDP_READ_BUFFER_INVALIDATE); @@ -219,7 +221,7 @@ int r300_copy_dma(struct radeon_device *rdev, } /* Must wait for 2D idle & clean before DMA or hangs might happen */ radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 )); - radeon_ring_write(rdev, (1 << 16)); + radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN); for (i = 0; i < num_loops; i++) { cur_size = size; if (cur_size > 0x1FFFFF) { @@ -281,8 +283,8 @@ void r300_ring_start(struct radeon_device *rdev) radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - radeon_ring_write(rdev, PACKET0(0x170C, 0)); - radeon_ring_write(rdev, 1 << 31); + radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0)); + radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG); radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0)); radeon_ring_write(rdev, 0); radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0)); @@ -349,8 +351,8 @@ int r300_mc_wait_for_idle(struct radeon_device *rdev) for (i = 0; i < rdev->usec_timeout; i++) { /* read MC_STATUS */ - tmp = RREG32(0x0150); - if (tmp & (1 << 4)) { + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & R300_MC_IDLE) { return 0; } DRM_UDELAY(1); @@ -395,8 +397,8 @@ void r300_gpu_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } - tmp = RREG32(0x170C); - WREG32(0x170C, tmp | (1 << 31)); + tmp = RREG32(R300_DST_PIPE_CONFIG); + WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); WREG32(R300_RB2D_DSTCACHE_MODE, R300_DC_AUTOFLUSH_ENABLE | @@ -437,8 +439,8 @@ int r300_ga_reset(struct radeon_device *rdev) /* GA still busy soft reset it */ WREG32(0x429C, 0x200); WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0); - WREG32(0x43E0, 0); - WREG32(0x43E4, 0); + WREG32(R300_RE_SCISSORS_TL, 0); + WREG32(R300_RE_SCISSORS_BR, 0); WREG32(0x24AC, 0); } /* Wait to prevent race in RBBM_STATUS */ @@ -488,7 +490,7 @@ int r300_gpu_reset(struct radeon_device *rdev) } /* Check if GPU is idle */ status = RREG32(RADEON_RBBM_STATUS); - if (status & (1 << 31)) { + if (status & RADEON_RBBM_ACTIVE) { DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); return -1; } diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index d9373246c97f..12ebbdb83d1c 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -69,7 +69,8 @@ void r420_pipes_init(struct radeon_device *rdev) unsigned num_pipes; /* GA_ENHANCE workaround TCL deadlock issue */ - WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + WREG32(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL | + (1 << 2) | (1 << 3)); /* add idle wait as per freedesktop.org bug 24041 */ if (r100_gui_wait_for_idle(rdev)) { printk(KERN_WARNING "Failed to wait GUI idle while " @@ -97,17 +98,17 @@ void r420_pipes_init(struct radeon_device *rdev) tmp = (7 << 1); break; } - WREG32(0x42C8, (1 << num_pipes) - 1); + WREG32(R500_SU_REG_DEST, (1 << num_pipes) - 1); /* Sub pixel 1/12 so we can have 4K rendering according to doc */ - tmp |= (1 << 4) | (1 << 0); - WREG32(0x4018, tmp); + tmp |= R300_TILE_SIZE_16 | R300_ENABLE_TILING; + WREG32(R300_GB_TILE_CONFIG, tmp); if (r100_gui_wait_for_idle(rdev)) { printk(KERN_WARNING "Failed to wait GUI idle while " "programming pipes. Bad things might happen.\n"); } - tmp = RREG32(0x170C); - WREG32(0x170C, tmp | (1 << 31)); + tmp = RREG32(R300_DST_PIPE_CONFIG); + WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); WREG32(R300_RB2D_DSTCACHE_MODE, RREG32(R300_RB2D_DSTCACHE_MODE) | -- cgit v1.2.3 From c836a4126768cd76af9ee33b3c11f57695d5fda6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 23 Dec 2009 10:07:50 -0500 Subject: drm/radeon/kms: add functions to get current pcie lanes Currently unused. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 31 +++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_asic.h | 11 +++++++++++ 3 files changed, 44 insertions(+) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 748335c5fa84..5897bd00591e 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -580,6 +580,37 @@ void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes) } +int rv370_get_pcie_lanes(struct radeon_device *rdev) +{ + u32 link_width_cntl; + + if (rdev->flags & RADEON_IS_IGP) + return 0; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return 0; + + /* FIXME wait for idle */ + + link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + + switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { + case RADEON_PCIE_LC_LINK_WIDTH_X0: + return 0; + case RADEON_PCIE_LC_LINK_WIDTH_X1: + return 1; + case RADEON_PCIE_LC_LINK_WIDTH_X2: + return 2; + case RADEON_PCIE_LC_LINK_WIDTH_X4: + return 4; + case RADEON_PCIE_LC_LINK_WIDTH_X8: + return 8; + case RADEON_PCIE_LC_LINK_WIDTH_X16: + default: + return 16; + } +} + #if defined(CONFIG_DEBUG_FS) static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data) { diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d7da6e742de8..df21edcbae16 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -678,6 +678,7 @@ struct radeon_asic { void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock); uint32_t (*get_memory_clock)(struct radeon_device *rdev); void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); + int (*get_pcie_lanes)(struct radeon_device *rdev); void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); void (*set_clock_gating)(struct radeon_device *rdev, int enable); int (*set_surface_reg)(struct radeon_device *rdev, int reg, @@ -1044,6 +1045,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) #define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev)) #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e)) +#define radeon_get_pcie_lanes(rdev) (rdev)->asic->get_pcie_lanes((rdev)) #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 05ee1aeac3fd..d758b1ffb74c 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -108,6 +108,7 @@ static struct radeon_asic r100_asic = { .set_engine_clock = &radeon_legacy_set_engine_clock, .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -138,6 +139,7 @@ extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg); extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); +extern int rv370_get_pcie_lanes(struct radeon_device *rdev); extern int r300_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, @@ -168,6 +170,7 @@ static struct radeon_asic r300_asic = { .set_engine_clock = &radeon_legacy_set_engine_clock, .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, + .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_legacy_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -212,6 +215,7 @@ static struct radeon_asic r420_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -261,6 +265,7 @@ static struct radeon_asic rs400_asic = { .set_engine_clock = &radeon_legacy_set_engine_clock, .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -320,6 +325,7 @@ static struct radeon_asic rs600_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .bandwidth_update = &rs600_bandwidth_update, @@ -366,6 +372,7 @@ static struct radeon_asic rs690_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -418,6 +425,7 @@ static struct radeon_asic rv515_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -461,6 +469,7 @@ static struct radeon_asic r520_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, @@ -538,6 +547,7 @@ static struct radeon_asic r600_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r600_set_surface_reg, @@ -583,6 +593,7 @@ static struct radeon_asic rv770_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r600_set_surface_reg, -- cgit v1.2.3 From 82568565683b4991964a5fc89a9ca0c7122818e8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 5 Feb 2010 16:00:07 +1000 Subject: drm/radeon/kms: set gart pages to invalid on unbind and point to dummy page this uses a new entrypoint to invalidate gart entries instead of using 0. Changed to rather than pointing to 0 address point empty entry to dummy page. This might help to avoid hard lockup if for some wrong reasons GPU try to access unmapped GART entry. I'm not 100% sure this is going to work, we probably need to allocate a dummy page and point all the GTT entries at it similiar to what AGP does. but we can test this first I suppose. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 1 + drivers/gpu/drm/radeon/r100.c | 1 + drivers/gpu/drm/radeon/r300.c | 1 + drivers/gpu/drm/radeon/r600.c | 1 + drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 2 ++ drivers/gpu/drm/radeon/radeon_gart.c | 32 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/rs400.c | 1 + drivers/gpu/drm/radeon/rs600.c | 1 + drivers/gpu/drm/radeon/rv770.c | 1 + 10 files changed, 40 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index c2f9752e4ee0..3368920df5f4 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -93,6 +93,7 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) r = radeon_gart_table_vram_pin(rdev); if (r) return r; + radeon_gart_restore(rdev); /* Setup L2 cache */ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 346ae3d7e0d4..bc7d9e9211c8 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -197,6 +197,7 @@ int r100_pci_gart_enable(struct radeon_device *rdev) { uint32_t tmp; + radeon_gart_restore(rdev); /* discard memory request outside of configured range */ tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; WREG32(RADEON_AIC_CNTL, tmp); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 5897bd00591e..654aca1cdf05 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -117,6 +117,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) r = radeon_gart_table_vram_pin(rdev); if (r) return r; + radeon_gart_restore(rdev); /* discard memory request outside of configured range */ tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index c9723daee357..4facbab20456 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -416,6 +416,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev) r = radeon_gart_table_vram_pin(rdev); if (r) return r; + radeon_gart_restore(rdev); /* Setup L2 cache */ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9eeca6f07222..993cdf20d8e6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1145,6 +1145,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) /* AGP */ extern void radeon_agp_disable(struct radeon_device *rdev); extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); +extern void radeon_gart_restore(struct radeon_device *rdev); extern int radeon_modeset_init(struct radeon_device *rdev); extern void radeon_modeset_fini(struct radeon_device *rdev); extern bool radeon_card_posted(struct radeon_device *rdev); @@ -1269,7 +1270,6 @@ extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); extern int r600_cp_resume(struct radeon_device *rdev); extern void r600_cp_fini(struct radeon_device *rdev); extern int r600_count_pipe_bits(uint32_t val); -extern int r600_gart_clear_page(struct radeon_device *rdev, int i); extern int r600_mc_wait_for_idle(struct radeon_device *rdev); extern int r600_pcie_gart_init(struct radeon_device *rdev); extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c224c1d944ef..fb55faf8e284 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -238,6 +238,8 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev) int radeon_dummy_page_init(struct radeon_device *rdev) { + if (rdev->dummy_page.page) + return 0; rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); if (rdev->dummy_page.page == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index e73d56e83fa6..1770d3c07fd0 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -139,6 +139,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, unsigned t; unsigned p; int i, j; + u64 page_base; if (!rdev->gart.ready) { WARN(1, "trying to unbind memory to unitialized GART !\n"); @@ -151,9 +152,11 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); rdev->gart.pages[p] = NULL; - rdev->gart.pages_addr[p] = 0; + rdev->gart.pages_addr[p] = rdev->dummy_page.addr; + page_base = rdev->gart.pages_addr[p]; for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { - radeon_gart_set_page(rdev, t, 0); + radeon_gart_set_page(rdev, t, page_base); + page_base += RADEON_GPU_PAGE_SIZE; } } } @@ -199,8 +202,26 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, return 0; } +void radeon_gart_restore(struct radeon_device *rdev) +{ + int i, j, t; + u64 page_base; + + for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) { + page_base = rdev->gart.pages_addr[i]; + for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { + radeon_gart_set_page(rdev, t, page_base); + page_base += RADEON_GPU_PAGE_SIZE; + } + } + mb(); + radeon_gart_tlb_flush(rdev); +} + int radeon_gart_init(struct radeon_device *rdev) { + int r, i; + if (rdev->gart.pages) { return 0; } @@ -209,6 +230,9 @@ int radeon_gart_init(struct radeon_device *rdev) DRM_ERROR("Page size is smaller than GPU page size!\n"); return -EINVAL; } + r = radeon_dummy_page_init(rdev); + if (r) + return r; /* Compute table size */ rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE; @@ -227,6 +251,10 @@ int radeon_gart_init(struct radeon_device *rdev) radeon_gart_fini(rdev); return -ENOMEM; } + /* set GART entry to point to the dummy page by default */ + for (i = 0; i < rdev->gart.num_cpu_pages; i++) { + rdev->gart.pages_addr[i] = rdev->dummy_page.addr; + } return 0; } diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 287fcebfb4e6..1e4582e27c14 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -113,6 +113,7 @@ int rs400_gart_enable(struct radeon_device *rdev) uint32_t size_reg; uint32_t tmp; + radeon_gart_restore(rdev); tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 979b00034de9..28c8690c7a35 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -213,6 +213,7 @@ int rs600_gart_enable(struct radeon_device *rdev) r = radeon_gart_table_vram_pin(rdev); if (r) return r; + radeon_gart_restore(rdev); /* Enable bus master */ tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS; WREG32(R_00004C_BUS_CNTL, tmp); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 3ecd138815d8..6f1f4abbe88c 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -56,6 +56,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) r = radeon_gart_table_vram_pin(rdev); if (r) return r; + radeon_gart_restore(rdev); /* Setup L2 cache */ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | -- cgit v1.2.3 From 44ca7478d46aaad488d916f7262253e000ee60f9 Mon Sep 17 00:00:00 2001 From: Pauli Nieminen Date: Thu, 11 Feb 2010 17:25:47 +0000 Subject: drm/radeon: Add asic hook for dma copy to r200 cards. r200 cards have dma engine which can be used to tranfer data between vram and system memory. r300 dma engine registers match r200 dma engine. Enabling dma copy for r200 is simple as hooking r200 asic to already existing function r300_copy_dma. Rename r300_dma_copy to r200_dma_copyto reflect that supports starts from r200 cards. v2: Created a new asic object for r200 cards. Signed-off-by: Pauli Nieminen Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r200.c | 46 +++++++++++++++++++++++ drivers/gpu/drm/radeon/r300.c | 44 ---------------------- drivers/gpu/drm/radeon/radeon_asic.h | 69 +++++++++++++++++++++++++++------- drivers/gpu/drm/radeon/radeon_device.c | 4 +- 4 files changed, 104 insertions(+), 59 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index ff1e0cd608bf..1146c9909c2c 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -31,6 +31,7 @@ #include "radeon_reg.h" #include "radeon.h" +#include "r100d.h" #include "r200_reg_safe.h" #include "r100_track.h" @@ -79,6 +80,51 @@ static int r200_get_vtx_size_0(uint32_t vtx_fmt_0) return vtx_size; } +int r200_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_pages, + struct radeon_fence *fence) +{ + uint32_t size; + uint32_t cur_size; + int i, num_loops; + int r = 0; + + /* radeon pitch is /64 */ + size = num_pages << PAGE_SHIFT; + num_loops = DIV_ROUND_UP(size, 0x1FFFFF); + r = radeon_ring_lock(rdev, num_loops * 4 + 64); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + /* Must wait for 2D idle & clean before DMA or hangs might happen */ + radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(rdev, (1 << 16)); + for (i = 0; i < num_loops; i++) { + cur_size = size; + if (cur_size > 0x1FFFFF) { + cur_size = 0x1FFFFF; + } + size -= cur_size; + radeon_ring_write(rdev, PACKET0(0x720, 2)); + radeon_ring_write(rdev, src_offset); + radeon_ring_write(rdev, dst_offset); + radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30)); + src_offset += cur_size; + dst_offset += cur_size; + } + radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE); + if (fence) { + r = radeon_fence_emit(rdev, fence); + } + radeon_ring_unlock_commit(rdev); + return r; +} + + static int r200_get_vtx_size_1(uint32_t vtx_fmt_1) { int vtx_size, i, tex_size; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 654aca1cdf05..a4f395226b34 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -201,50 +201,6 @@ void r300_fence_ring_emit(struct radeon_device *rdev, radeon_ring_write(rdev, RADEON_SW_INT_FIRE); } -int r300_copy_dma(struct radeon_device *rdev, - uint64_t src_offset, - uint64_t dst_offset, - unsigned num_pages, - struct radeon_fence *fence) -{ - uint32_t size; - uint32_t cur_size; - int i, num_loops; - int r = 0; - - /* radeon pitch is /64 */ - size = num_pages << PAGE_SHIFT; - num_loops = DIV_ROUND_UP(size, 0x1FFFFF); - r = radeon_ring_lock(rdev, num_loops * 4 + 64); - if (r) { - DRM_ERROR("radeon: moving bo (%d).\n", r); - return r; - } - /* Must wait for 2D idle & clean before DMA or hangs might happen */ - radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 )); - radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN); - for (i = 0; i < num_loops; i++) { - cur_size = size; - if (cur_size > 0x1FFFFF) { - cur_size = 0x1FFFFF; - } - size -= cur_size; - radeon_ring_write(rdev, PACKET0(0x720, 2)); - radeon_ring_write(rdev, src_offset); - radeon_ring_write(rdev, dst_offset); - radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30)); - src_offset += cur_size; - dst_offset += cur_size; - } - radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); - radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE); - if (fence) { - r = radeon_fence_emit(rdev, fence); - } - radeon_ring_unlock_commit(rdev); - return r; -} - void r300_ring_start(struct radeon_device *rdev) { unsigned gb_tile_config; diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 9d2a113f78eb..b7030d7c0396 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -43,7 +43,7 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); /* - * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 + * r100,rv100,rs100,rv200,rs200 */ extern int r100_init(struct radeon_device *rdev); extern void r100_fini(struct radeon_device *rdev); @@ -121,6 +121,51 @@ static struct radeon_asic r100_asic = { .ioctl_wait_idle = NULL, }; +/* + * r200,rv250,rs300,rv280 + */ +extern int r200_copy_dma(struct radeon_device *rdev, + uint64_t src_offset, + uint64_t dst_offset, + unsigned num_pages, + struct radeon_fence *fence); +static struct radeon_asic r200_asic = { + .init = &r100_init, + .fini = &r100_fini, + .suspend = &r100_suspend, + .resume = &r100_resume, + .vga_set_state = &r100_vga_set_state, + .gpu_reset = &r100_gpu_reset, + .gart_tlb_flush = &r100_pci_gart_tlb_flush, + .gart_set_page = &r100_pci_gart_set_page, + .cp_commit = &r100_cp_commit, + .ring_start = &r100_ring_start, + .ring_test = &r100_ring_test, + .ring_ib_execute = &r100_ring_ib_execute, + .irq_set = &r100_irq_set, + .irq_process = &r100_irq_process, + .get_vblank_counter = &r100_get_vblank_counter, + .fence_ring_emit = &r100_fence_ring_emit, + .cs_parse = &r100_cs_parse, + .copy_blit = &r100_copy_blit, + .copy_dma = &r200_copy_dma, + .copy = &r100_copy_blit, + .get_engine_clock = &radeon_legacy_get_engine_clock, + .set_engine_clock = &radeon_legacy_set_engine_clock, + .get_memory_clock = &radeon_legacy_get_memory_clock, + .set_memory_clock = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = &radeon_legacy_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &r100_bandwidth_update, + .hpd_init = &r100_hpd_init, + .hpd_fini = &r100_hpd_fini, + .hpd_sense = &r100_hpd_sense, + .hpd_set_polarity = &r100_hpd_set_polarity, + .ioctl_wait_idle = NULL, +}; + /* * r300,r350,rv350,rv380 @@ -140,11 +185,7 @@ extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg); extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); extern int rv370_get_pcie_lanes(struct radeon_device *rdev); -extern int r300_copy_dma(struct radeon_device *rdev, - uint64_t src_offset, - uint64_t dst_offset, - unsigned num_pages, - struct radeon_fence *fence); + static struct radeon_asic r300_asic = { .init = &r300_init, .fini = &r300_fini, @@ -164,7 +205,7 @@ static struct radeon_asic r300_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, + .copy_dma = &r200_copy_dma, .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, @@ -247,7 +288,7 @@ static struct radeon_asic r420_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, + .copy_dma = &r200_copy_dma, .copy = &r100_copy_blit, .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, @@ -297,7 +338,7 @@ static struct radeon_asic rs400_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, + .copy_dma = &r200_copy_dma, .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, @@ -357,7 +398,7 @@ static struct radeon_asic rs600_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, + .copy_dma = &r200_copy_dma, .copy = &r100_copy_blit, .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, @@ -404,8 +445,8 @@ static struct radeon_asic rs690_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, - .copy = &r300_copy_dma, + .copy_dma = &r200_copy_dma, + .copy = &r200_copy_dma, .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, @@ -457,7 +498,7 @@ static struct radeon_asic rv515_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, + .copy_dma = &r200_copy_dma, .copy = &r100_copy_blit, .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, @@ -501,7 +542,7 @@ static struct radeon_asic r520_asic = { .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, - .copy_dma = &r300_copy_dma, + .copy_dma = &r200_copy_dma, .copy = &r100_copy_blit, .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7a30f6955e41..7be3a6968463 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -340,11 +340,13 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_RS100: case CHIP_RV200: case CHIP_RS200: + rdev->asic = &r100_asic; + break; case CHIP_R200: case CHIP_RV250: case CHIP_RS300: case CHIP_RV280: - rdev->asic = &r100_asic; + rdev->asic = &r200_asic; break; case CHIP_R300: case CHIP_R350: -- cgit v1.2.3 From d594e46ace22afa1621254f6f669e65430048153 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 17 Feb 2010 21:54:29 +0000 Subject: drm/radeon/kms: simplify memory controller setup V2 Get rid of _location and use _start/_end also simplify the computation of vram_start|end & gtt_start|end. For R1XX-R2XX we place VRAM at the same address of PCI aperture, those GPU shouldn't have much memory and seems to behave better when setup that way. For R3XX and newer we place VRAM at 0. For R6XX-R7XX AGP we place VRAM before or after AGP aperture this might limit to limit the VRAM size but it's very unlikely. For IGP we don't change the VRAM placement. Tested on (compiz,quake3,suspend/resume): PCI/PCIE:RV280,R420,RV515,RV570,RV610,RV710 AGP:RV100,RV280,R420,RV350,RV620(RPB*),RV730 IGP:RS480(RPB*),RS690,RS780(RPB*),RS880 RPB: resume previously broken V2 correct commit message to reflect more accurately the bug and move VRAM placement to 0 for most of the GPU to avoid limiting VRAM. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 51 ++------- drivers/gpu/drm/radeon/r100.c | 93 ++++++---------- drivers/gpu/drm/radeon/r300.c | 27 ++--- drivers/gpu/drm/radeon/r420.c | 36 ++----- drivers/gpu/drm/radeon/r520.c | 21 ++-- drivers/gpu/drm/radeon/r600.c | 123 ++++++++++++---------- drivers/gpu/drm/radeon/radeon.h | 13 +-- drivers/gpu/drm/radeon/radeon_agp.c | 4 + drivers/gpu/drm/radeon/radeon_device.c | 157 ++++++++++++++++------------ drivers/gpu/drm/radeon/radeon_fb.c | 2 +- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 2 +- drivers/gpu/drm/radeon/radeon_test.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 12 +-- drivers/gpu/drm/radeon/rs400.c | 38 ++----- drivers/gpu/drm/radeon/rs600.c | 42 ++------ drivers/gpu/drm/radeon/rs690.c | 40 ++----- drivers/gpu/drm/radeon/rv515.c | 21 ++-- drivers/gpu/drm/radeon/rv770.c | 41 +------- 18 files changed, 301 insertions(+), 424 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 3368920df5f4..3f973d411d61 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -439,7 +439,6 @@ int evergreen_mc_init(struct radeon_device *rdev) fixed20_12 a; u32 tmp; int chansize, numchan; - int r; /* Get VRAM informations */ rdev->mc.vram_is_ddr = true; @@ -475,48 +474,12 @@ int evergreen_mc_init(struct radeon_device *rdev) /* size in MB on evergreen */ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; - - if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + /* FIXME remove this once we support unmappable VRAM */ + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) { rdev->mc.mc_vram_size = rdev->mc.aper_size; - - if (rdev->mc.real_vram_size > rdev->mc.aper_size) rdev->mc.real_vram_size = rdev->mc.aper_size; - - if (rdev->flags & RADEON_IS_AGP) { - r = radeon_agp_init(rdev); - if (r) - return r; - /* gtt_size is setup by radeon_agp_init */ - rdev->mc.gtt_location = rdev->mc.agp_base; - tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; - /* Try to put vram before or after AGP because we - * we want SYSTEM_APERTURE to cover both VRAM and - * AGP so that GPU can catch out of VRAM/AGP access - */ - if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) { - /* Enought place before */ - rdev->mc.vram_location = rdev->mc.gtt_location - - rdev->mc.mc_vram_size; - } else if (tmp > rdev->mc.mc_vram_size) { - /* Enought place after */ - rdev->mc.vram_location = rdev->mc.gtt_location + - rdev->mc.gtt_size; - } else { - /* Try to setup VRAM then AGP might not - * not work on some card - */ - rdev->mc.vram_location = 0x00000000UL; - rdev->mc.gtt_location = rdev->mc.mc_vram_size; - } - } else { - rdev->mc.vram_location = 0x00000000UL; - rdev->mc.gtt_location = rdev->mc.mc_vram_size; - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; } - rdev->mc.vram_start = rdev->mc.vram_location; - rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; - rdev->mc.gtt_start = rdev->mc.gtt_location; - rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; + r600_vram_gtt_location(rdev, &rdev->mc); /* FIXME: we should enforce default clock in case GPU is not in * default setup */ @@ -525,6 +488,7 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); return 0; } + int evergreen_gpu_reset(struct radeon_device *rdev) { /* FIXME: implement for evergreen */ @@ -726,6 +690,13 @@ int evergreen_init(struct radeon_device *rdev) r = radeon_fence_driver_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 */ r = evergreen_mc_init(rdev); if (r) return r; diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index bc7d9e9211c8..1fdd793343b9 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -202,9 +202,8 @@ int r100_pci_gart_enable(struct radeon_device *rdev) tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; WREG32(RADEON_AIC_CNTL, tmp); /* set address range for PCI address translate */ - WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); - tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; - WREG32(RADEON_AIC_HI_ADDR, tmp); + WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_start); + WREG32(RADEON_AIC_HI_ADDR, rdev->mc.gtt_end); /* set PCI GART page-table base address */ WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; @@ -1957,17 +1956,17 @@ static u32 r100_get_accessible_vram(struct radeon_device *rdev) void r100_vram_init_sizes(struct radeon_device *rdev) { u64 config_aper_size; - u32 accessible; + /* work out accessible VRAM */ + rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev); + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); - if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; /* read NB_TOM to get the amount of ram stolen for the GPU */ tom = RREG32(RADEON_NB_TOM); rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); - /* for IGPs we need to keep VRAM where it was put by the BIOS */ - rdev->mc.vram_location = (tom & 0xffff) << 16; WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; } else { @@ -1979,30 +1978,19 @@ void r100_vram_init_sizes(struct radeon_device *rdev) rdev->mc.real_vram_size = 8192 * 1024; WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); } - /* let driver place VRAM */ - rdev->mc.vram_location = 0xFFFFFFFFUL; - /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - - * Novell bug 204882 + along with lots of ubuntu ones */ + /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - + * Novell bug 204882 + along with lots of ubuntu ones + */ if (config_aper_size > rdev->mc.real_vram_size) rdev->mc.mc_vram_size = config_aper_size; else rdev->mc.mc_vram_size = rdev->mc.real_vram_size; } - - /* work out accessible VRAM */ - accessible = r100_get_accessible_vram(rdev); - - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); - - if (accessible > rdev->mc.aper_size) - accessible = rdev->mc.aper_size; - - if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + /* FIXME remove this once we support unmappable VRAM */ + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) { rdev->mc.mc_vram_size = rdev->mc.aper_size; - - if (rdev->mc.real_vram_size > rdev->mc.aper_size) rdev->mc.real_vram_size = rdev->mc.aper_size; + } } void r100_vga_set_state(struct radeon_device *rdev, bool state) @@ -2019,11 +2007,18 @@ void r100_vga_set_state(struct radeon_device *rdev, bool state) WREG32(RADEON_CONFIG_CNTL, temp); } -void r100_vram_info(struct radeon_device *rdev) +void r100_mc_init(struct radeon_device *rdev) { - r100_vram_get_type(rdev); + u64 base; + r100_vram_get_type(rdev); r100_vram_init_sizes(rdev); + base = rdev->mc.aper_base; + if (rdev->flags & RADEON_IS_IGP) + base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); } @@ -3294,10 +3289,9 @@ void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save) { /* Update base address for crtc */ - WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location); + WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_start); if (!(rdev->flags & RADEON_SINGLE_CRTC)) { - WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, - rdev->mc.vram_location); + WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, rdev->mc.vram_start); } /* Restore CRTC registers */ WREG8(R_0003C2_GENMO_WT, save->GENMO_WT); @@ -3458,32 +3452,6 @@ void r100_fini(struct radeon_device *rdev) rdev->bios = NULL; } -int r100_mc_init(struct radeon_device *rdev) -{ - int r; - u32 tmp; - - /* Setup GPU memory space */ - rdev->mc.vram_location = 0xFFFFFFFFUL; - rdev->mc.gtt_location = 0xFFFFFFFFUL; - if (rdev->flags & RADEON_IS_IGP) { - tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM)); - rdev->mc.vram_location = tmp << 16; - } - if (rdev->flags & RADEON_IS_AGP) { - r = radeon_agp_init(rdev); - if (r) { - radeon_agp_disable(rdev); - } else { - rdev->mc.gtt_location = rdev->mc.agp_base; - } - } - r = radeon_mc_setup(rdev); - if (r) - return r; - return 0; -} - int r100_init(struct radeon_device *rdev) { int r; @@ -3526,12 +3494,15 @@ int r100_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - r100_vram_info(rdev); - /* Initialize memory controller (also test AGP) */ - r = r100_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 VRAM */ + r100_mc_init(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index a4f395226b34..7e9f95653cbe 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -121,15 +121,15 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) /* discard memory request outside of configured range */ tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); - WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location); - tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - RADEON_GPU_PAGE_SIZE; + WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start); + tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK; WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp); WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); table_addr = rdev->gart.table_addr; WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr); /* FIXME: setup default page */ - WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location); + WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start); WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); /* Clear error */ WREG32_PCIE(0x18, 0); @@ -459,13 +459,12 @@ int r300_gpu_reset(struct radeon_device *rdev) /* * r300,r350,rv350,rv380 VRAM info */ -void r300_vram_info(struct radeon_device *rdev) +void r300_mc_init(struct radeon_device *rdev) { uint32_t tmp; /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; - tmp = RREG32(RADEON_MEM_CNTL); tmp &= R300_MEM_NUM_CHANNELS_MASK; switch (tmp) { @@ -474,8 +473,9 @@ void r300_vram_info(struct radeon_device *rdev) case 2: rdev->mc.vram_width = 256; break; default: rdev->mc.vram_width = 128; break; } - r100_vram_init_sizes(rdev); + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); } void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes) @@ -1377,12 +1377,15 @@ int r300_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - r300_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 */ + r300_mc_init(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 12ebbdb83d1c..c7593b8f58ee 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -40,28 +40,6 @@ static void r420_set_reg_safe(struct radeon_device *rdev) rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm); } -int r420_mc_init(struct radeon_device *rdev) -{ - int r; - - /* Setup GPU memory space */ - rdev->mc.vram_location = 0xFFFFFFFFUL; - rdev->mc.gtt_location = 0xFFFFFFFFUL; - if (rdev->flags & RADEON_IS_AGP) { - r = radeon_agp_init(rdev); - if (r) { - radeon_agp_disable(rdev); - } else { - rdev->mc.gtt_location = rdev->mc.agp_base; - } - } - r = radeon_mc_setup(rdev); - if (r) { - return r; - } - return 0; -} - void r420_pipes_init(struct radeon_device *rdev) { unsigned tmp; @@ -349,13 +327,15 @@ int r420_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - r300_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 */ + r300_mc_init(rdev); r420_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index ddf5731eba0d..2b8a5dd13516 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -119,13 +119,15 @@ static void r520_vram_get_type(struct radeon_device *rdev) rdev->mc.vram_width *= 2; } -void r520_vram_info(struct radeon_device *rdev) +void r520_mc_init(struct radeon_device *rdev) { fixed20_12 a; r520_vram_get_type(rdev); - r100_vram_init_sizes(rdev); + radeon_vram_location(rdev, &rdev->mc, 0); + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); /* FIXME: we should enforce default clock in case GPU is not in * default setup */ @@ -267,12 +269,15 @@ int r520_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - r520_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 */ + r520_mc_init(rdev); rv515_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index a865946d2d08..694a4c564f52 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -611,6 +611,68 @@ static void r600_mc_program(struct radeon_device *rdev) rv515_vga_render_disable(rdev); } +/** + * r600_vram_gtt_location - try to find VRAM & GTT location + * @rdev: radeon device structure holding all necessary informations + * @mc: memory controller structure holding memory informations + * + * Function will place try to place VRAM at same place as in CPU (PCI) + * address space as some GPU seems to have issue when we reprogram at + * different address space. + * + * If there is not enough space to fit the unvisible VRAM after the + * aperture then we limit the VRAM size to the aperture. + * + * If we are using AGP then place VRAM adjacent to AGP aperture are we need + * them to be in one from GPU point of view so that we can program GPU to + * catch access outside them (weird GPU policy see ??). + * + * This function will never fails, worst case are limiting VRAM or GTT. + * + * Note: GTT start, end, size should be initialized before calling this + * function on AGP platform. + */ +void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +{ + u64 size_bf, size_af; + + if (mc->mc_vram_size > 0xE0000000) { + /* leave room for at least 512M GTT */ + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = 0xE0000000; + mc->mc_vram_size = 0xE0000000; + } + if (rdev->flags & RADEON_IS_AGP) { + size_bf = mc->gtt_start; + size_af = 0xFFFFFFFF - mc->gtt_end + 1; + if (size_bf > size_af) { + if (mc->mc_vram_size > size_bf) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_bf; + mc->mc_vram_size = size_bf; + } + mc->vram_start = mc->gtt_start - mc->mc_vram_size; + } else { + if (mc->mc_vram_size > size_af) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_af; + mc->mc_vram_size = size_af; + } + mc->vram_start = mc->gtt_end; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", + mc->mc_vram_size >> 20, mc->vram_start, + mc->vram_end, mc->real_vram_size >> 20); + } else { + u64 base = 0; + if (rdev->flags & RADEON_IS_IGP) + base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24; + radeon_vram_location(rdev, &rdev->mc, base); + radeon_gtt_location(rdev, mc); + } +} + int r600_mc_init(struct radeon_device *rdev) { fixed20_12 a; @@ -650,75 +712,20 @@ int r600_mc_init(struct radeon_device *rdev) /* Setup GPU memory space */ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); - - if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + /* FIXME remove this once we support unmappable VRAM */ + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) { rdev->mc.mc_vram_size = rdev->mc.aper_size; - - if (rdev->mc.real_vram_size > rdev->mc.aper_size) rdev->mc.real_vram_size = rdev->mc.aper_size; - - if (rdev->flags & RADEON_IS_AGP) { - /* gtt_size is setup by radeon_agp_init */ - rdev->mc.gtt_location = rdev->mc.agp_base; - tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; - /* Try to put vram before or after AGP because we - * we want SYSTEM_APERTURE to cover both VRAM and - * AGP so that GPU can catch out of VRAM/AGP access - */ - if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) { - /* Enought place before */ - rdev->mc.vram_location = rdev->mc.gtt_location - - rdev->mc.mc_vram_size; - } else if (tmp > rdev->mc.mc_vram_size) { - /* Enought place after */ - rdev->mc.vram_location = rdev->mc.gtt_location + - rdev->mc.gtt_size; - } else { - /* Try to setup VRAM then AGP might not - * not work on some card - */ - rdev->mc.vram_location = 0x00000000UL; - rdev->mc.gtt_location = rdev->mc.mc_vram_size; - } - } else { - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; - rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) & - 0xFFFF) << 24; - tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size; - if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { - /* Enough place after vram */ - rdev->mc.gtt_location = tmp; - } else if (rdev->mc.vram_location >= rdev->mc.gtt_size) { - /* Enough place before vram */ - rdev->mc.gtt_location = 0; - } else { - /* Not enough place after or before shrink - * gart size - */ - if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) { - rdev->mc.gtt_location = 0; - rdev->mc.gtt_size = rdev->mc.vram_location; - } else { - rdev->mc.gtt_location = tmp; - rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp; - } - } - rdev->mc.gtt_location = rdev->mc.mc_vram_size; } - rdev->mc.vram_start = rdev->mc.vram_location; - rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; - rdev->mc.gtt_start = rdev->mc.gtt_location; - rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; + r600_vram_gtt_location(rdev, &rdev->mc); /* 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); - if (rdev->flags & RADEON_IS_IGP) rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); - return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 350ae71953e9..0ca83ca91111 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -282,6 +282,7 @@ union radeon_gart_table { }; #define RADEON_GPU_PAGE_SIZE 4096 +#define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1) struct radeon_gart { dma_addr_t table_addr; @@ -316,21 +317,19 @@ struct radeon_mc { /* for some chips with <= 32MB we need to lie * about vram size near mc fb location */ u64 mc_vram_size; - u64 gtt_location; + u64 visible_vram_size; u64 gtt_size; u64 gtt_start; u64 gtt_end; - u64 vram_location; u64 vram_start; u64 vram_end; unsigned vram_width; u64 real_vram_size; int vram_mtrr; bool vram_is_ddr; - bool igp_sideport_enabled; + bool igp_sideport_enabled; }; -int radeon_mc_setup(struct radeon_device *rdev); bool radeon_combios_sideport_present(struct radeon_device *rdev); bool radeon_atombios_sideport_present(struct radeon_device *rdev); @@ -1165,6 +1164,8 @@ extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enabl extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); +extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); +extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ struct r100_mc_save { @@ -1219,7 +1220,7 @@ extern void r200_set_safe_registers(struct radeon_device *rdev); /* r300,r350,rv350,rv370,rv380 */ extern void r300_set_reg_safe(struct radeon_device *rdev); extern void r300_mc_program(struct radeon_device *rdev); -extern void r300_vram_info(struct radeon_device *rdev); +extern void r300_mc_init(struct radeon_device *rdev); extern void r300_clock_startup(struct radeon_device *rdev); extern int r300_mc_wait_for_idle(struct radeon_device *rdev); extern int rv370_pcie_gart_init(struct radeon_device *rdev); @@ -1228,7 +1229,6 @@ extern int rv370_pcie_gart_enable(struct radeon_device *rdev); extern void rv370_pcie_gart_disable(struct radeon_device *rdev); /* r420,r423,rv410 */ -extern int r420_mc_init(struct radeon_device *rdev); extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v); extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev); @@ -1270,6 +1270,7 @@ extern void rs690_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode2); /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ +extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern bool r600_card_posted(struct radeon_device *rdev); extern void r600_cp_stop(struct radeon_device *rdev); extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index c0681a5556dc..c4457791dff1 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -237,6 +237,10 @@ int radeon_agp_init(struct radeon_device *rdev) rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base; rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20; + rdev->mc.gtt_start = rdev->mc.agp_base; + rdev->mc.gtt_end = rdev->mc.gtt_start + rdev->mc.gtt_size - 1; + dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", + rdev->mc.gtt_size >> 20, rdev->mc.gtt_start, rdev->mc.gtt_end); /* workaround some hw issues */ if (rdev->family < CHIP_R200) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7be3a6968463..91a9b966238e 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -100,80 +100,103 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) } } -/* - * MC common functions +/** + * radeon_vram_location - try to find VRAM location + * @rdev: radeon device structure holding all necessary informations + * @mc: memory controller structure holding memory informations + * @base: base address at which to put VRAM + * + * Function will place try to place VRAM at base address provided + * as parameter (which is so far either PCI aperture address or + * for IGP TOM base address). + * + * If there is not enough space to fit the unvisible VRAM in the 32bits + * address space then we limit the VRAM size to the aperture. + * + * If we are using AGP and if the AGP aperture doesn't allow us to have + * room for all the VRAM than we restrict the VRAM to the PCI aperture + * size and print a warning. + * + * This function will never fails, worst case are limiting VRAM. + * + * Note: GTT start, end, size should be initialized before calling this + * function on AGP platform. + * + * Note: We don't explictly enforce VRAM start to be aligned on VRAM size, + * this shouldn't be a problem as we are using the PCI aperture as a reference. + * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but + * not IGP. + * + * Note: we use mc_vram_size as on some board we need to program the mc to + * cover the whole aperture even if VRAM size is inferior to aperture size + * Novell bug 204882 + along with lots of ubuntu ones + * + * Note: when limiting vram it's safe to overwritte real_vram_size because + * we are not in case where real_vram_size is inferior to mc_vram_size (ie + * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu + * ones) + * + * Note: IGP TOM addr should be the same as the aperture addr, we don't + * explicitly check for that thought. + * + * FIXME: when reducing VRAM size align new size on power of 2. */ -int radeon_mc_setup(struct radeon_device *rdev) +void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base) +{ + mc->vram_start = base; + if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { + dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); + mc->real_vram_size = mc->aper_size; + mc->mc_vram_size = mc->aper_size; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) { + dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); + mc->real_vram_size = mc->aper_size; + mc->mc_vram_size = mc->aper_size; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", + mc->mc_vram_size >> 20, mc->vram_start, + mc->vram_end, mc->real_vram_size >> 20); +} + +/** + * radeon_gtt_location - try to find GTT location + * @rdev: radeon device structure holding all necessary informations + * @mc: memory controller structure holding memory informations + * + * Function will place try to place GTT before or after VRAM. + * + * If GTT size is bigger than space left then we ajust GTT size. + * Thus function will never fails. + * + * FIXME: when reducing GTT size align new size on power of 2. + */ +void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) { - uint32_t tmp; + u64 size_af, size_bf; - /* Some chips have an "issue" with the memory controller, the - * location must be aligned to the size. We just align it down, - * too bad if we walk over the top of system memory, we don't - * use DMA without a remapped anyway. - * Affected chips are rv280, all r3xx, and all r4xx, but not IGP - */ - /* FGLRX seems to setup like this, VRAM a 0, then GART. - */ - /* - * Note: from R6xx the address space is 40bits but here we only - * use 32bits (still have to see a card which would exhaust 4G - * address space). - */ - if (rdev->mc.vram_location != 0xFFFFFFFFUL) { - /* vram location was already setup try to put gtt after - * if it fits */ - tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size; - tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); - if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { - rdev->mc.gtt_location = tmp; - } else { - if (rdev->mc.gtt_size >= rdev->mc.vram_location) { - printk(KERN_ERR "[drm] GTT too big to fit " - "before or after vram location.\n"); - return -EINVAL; - } - rdev->mc.gtt_location = 0; - } - } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { - /* gtt location was already setup try to put vram before - * if it fits */ - if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) { - rdev->mc.vram_location = 0; - } else { - tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; - tmp += (rdev->mc.mc_vram_size - 1); - tmp &= ~(rdev->mc.mc_vram_size - 1); - if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) { - rdev->mc.vram_location = tmp; - } else { - printk(KERN_ERR "[drm] vram too big to fit " - "before or after GTT location.\n"); - return -EINVAL; - } + size_af = 0xFFFFFFFF - mc->vram_end; + size_bf = mc->vram_start; + if (size_bf > size_af) { + if (mc->gtt_size > size_bf) { + dev_warn(rdev->dev, "limiting GTT\n"); + mc->gtt_size = size_bf; } + mc->gtt_start = mc->vram_start - mc->gtt_size; } else { - rdev->mc.vram_location = 0; - tmp = rdev->mc.mc_vram_size; - tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); - rdev->mc.gtt_location = tmp; - } - rdev->mc.vram_start = rdev->mc.vram_location; - rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; - rdev->mc.gtt_start = rdev->mc.gtt_location; - rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; - DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20)); - DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", - (unsigned)rdev->mc.vram_location, - (unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1)); - DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20)); - DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", - (unsigned)rdev->mc.gtt_location, - (unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1)); - return 0; + if (mc->gtt_size > size_af) { + dev_warn(rdev->dev, "limiting GTT\n"); + mc->gtt_size = size_af; + } + mc->gtt_start = mc->vram_end + 1; + } + mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; + dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", + mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); } - /* * GPU helpers function. */ diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 105c678fa73a..c39ddda13840 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -252,7 +252,7 @@ int radeonfb_create(struct drm_device *dev, info->flags = FBINFO_DEFAULT; info->fbops = &radeonfb_ops; - tmp = fb_gpuaddr - rdev->mc.vram_location; + tmp = fb_gpuaddr - rdev->mc.vram_start; info->fix.smem_start = rdev->mc.aper_base + tmp; info->fix.smem_len = size; info->screen_base = fbptr; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 83d4dbd6d067..643251719f1c 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -403,7 +403,7 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, /* if scanout was in GTT this really wouldn't work */ /* crtc offset is from display base addr not FB location */ - radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location; + radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start; base -= radeon_crtc->legacy_display_base_addr; diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 9f5e2f929da9..313c96bc09da 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -186,7 +186,7 @@ void radeon_test_moves(struct radeon_device *rdev) radeon_bo_kunmap(gtt_obj[i]); DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", - gtt_addr - rdev->mc.gtt_location); + gtt_addr - rdev->mc.gtt_start); } out_cleanup: diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index db820ae9a034..1157e0f758fa 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -150,7 +150,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_TT: - man->gpu_offset = rdev->mc.gtt_location; + man->gpu_offset = rdev->mc.gtt_start; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; @@ -180,7 +180,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_VRAM: /* "On-card" video ram */ - man->gpu_offset = rdev->mc.vram_location; + man->gpu_offset = rdev->mc.vram_start; man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_NEEDS_IOREMAP | TTM_MEMTYPE_FLAG_MAPPABLE; @@ -262,10 +262,10 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, switch (old_mem->mem_type) { case TTM_PL_VRAM: - old_start += rdev->mc.vram_location; + old_start += rdev->mc.vram_start; break; case TTM_PL_TT: - old_start += rdev->mc.gtt_location; + old_start += rdev->mc.gtt_start; break; default: DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); @@ -273,10 +273,10 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, } switch (new_mem->mem_type) { case TTM_PL_VRAM: - new_start += rdev->mc.vram_location; + new_start += rdev->mc.vram_start; break; case TTM_PL_TT: - new_start += rdev->mc.gtt_location; + new_start += rdev->mc.gtt_start; break; default: DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 1e4582e27c14..626d51891ee9 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -151,9 +151,8 @@ int rs400_gart_enable(struct radeon_device *rdev) WREG32(RADEON_AGP_BASE, 0xFFFFFFFF); WREG32(RS480_AGP_BASE_2, 0); } - tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; - tmp = REG_SET(RS690_MC_AGP_TOP, tmp >> 16); - tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_location >> 16); + tmp = REG_SET(RS690_MC_AGP_TOP, rdev->mc.gtt_end >> 16); + tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_start >> 16); if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp); tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; @@ -252,14 +251,19 @@ void rs400_gpu_init(struct radeon_device *rdev) } } -void rs400_vram_info(struct radeon_device *rdev) +void rs400_mc_init(struct radeon_device *rdev) { + u64 base; + rs400_gart_adjust_size(rdev); + rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev); /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; - r100_vram_init_sizes(rdev); + base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + radeon_gtt_location(rdev, &rdev->mc); } uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg) @@ -363,22 +367,6 @@ static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev) #endif } -static int rs400_mc_init(struct radeon_device *rdev) -{ - int r; - u32 tmp; - - /* Setup GPU memory space */ - tmp = RREG32(R_00015C_NB_TOM); - rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16; - rdev->mc.gtt_location = 0xFFFFFFFFUL; - r = radeon_mc_setup(rdev); - rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev); - if (r) - return r; - return 0; -} - void rs400_mc_program(struct radeon_device *rdev) { struct r100_mc_save save; @@ -517,12 +505,8 @@ int rs400_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - rs400_vram_info(rdev); - /* Initialize memory controller (also test AGP) */ - r = rs400_mc_init(rdev); - if (r) - return r; + /* initialize memory controller */ + rs400_mc_init(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 28c8690c7a35..d5aeb2a31d59 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -45,23 +45,6 @@ void rs600_gpu_init(struct radeon_device *rdev); int rs600_mc_wait_for_idle(struct radeon_device *rdev); -int rs600_mc_init(struct radeon_device *rdev) -{ - /* read back the MC value from the hw */ - int r; - u32 tmp; - - /* Setup GPU memory space */ - tmp = RREG32_MC(R_000004_MC_FB_LOCATION); - rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16; - rdev->mc.gtt_location = 0xffffffffUL; - r = radeon_mc_setup(rdev); - rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); - if (r) - return r; - return 0; -} - /* hpd for digital panel detect/disconnect */ bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) { @@ -475,22 +458,21 @@ void rs600_gpu_init(struct radeon_device *rdev) dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); } -void rs600_vram_info(struct radeon_device *rdev) +void rs600_mc_init(struct radeon_device *rdev) { + u64 base; + rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; - rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); - - if (rdev->mc.mc_vram_size > rdev->mc.aper_size) - rdev->mc.mc_vram_size = rdev->mc.aper_size; - - if (rdev->mc.real_vram_size > rdev->mc.aper_size) - rdev->mc.real_vram_size = rdev->mc.aper_size; + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + base = RREG32_MC(R_000004_MC_FB_LOCATION); + base = G_000004_MC_FB_START(base) << 16; + radeon_vram_location(rdev, &rdev->mc, base); + radeon_gtt_location(rdev, &rdev->mc); } void rs600_bandwidth_update(struct radeon_device *rdev) @@ -666,12 +648,8 @@ int rs600_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - rs600_vram_info(rdev); - /* Initialize memory controller (also test AGP) */ - r = rs600_mc_init(rdev); - if (r) - return r; + /* initialize memory controller */ + rs600_mc_init(rdev); rs600_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 06e2771aee5a..8d37501da7df 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -129,27 +129,20 @@ void rs690_pm_info(struct radeon_device *rdev) rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp); } -void rs690_vram_info(struct radeon_device *rdev) +void rs690_mc_init(struct radeon_device *rdev) { fixed20_12 a; + u64 base; rs400_gart_adjust_size(rdev); - rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; - rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); - - if (rdev->mc.mc_vram_size > rdev->mc.aper_size) - rdev->mc.mc_vram_size = rdev->mc.aper_size; - - if (rdev->mc.real_vram_size > rdev->mc.aper_size) - rdev->mc.real_vram_size = rdev->mc.aper_size; - + base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); + base = G_000100_MC_FB_START(base) << 16; rs690_pm_info(rdev); /* FIXME: we should enforce default clock in case GPU is not in * default setup @@ -160,22 +153,9 @@ void rs690_vram_info(struct radeon_device *rdev) a.full = rfixed_const(16); /* core_bandwidth = sclk(Mhz) * 16 */ rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a); -} - -static int rs690_mc_init(struct radeon_device *rdev) -{ - int r; - u32 tmp; - - /* Setup GPU memory space */ - tmp = RREG32_MC(R_000100_MCCFG_FB_LOCATION); - rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16; - rdev->mc.gtt_location = 0xFFFFFFFFUL; - r = radeon_mc_setup(rdev); rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); - if (r) - return r; - return 0; + radeon_vram_location(rdev, &rdev->mc, base); + radeon_gtt_location(rdev, &rdev->mc); } void rs690_line_buffer_adjust(struct radeon_device *rdev, @@ -728,12 +708,8 @@ int rs690_init(struct radeon_device *rdev) radeon_get_clock_info(rdev->ddev); /* Initialize power management */ radeon_pm_init(rdev); - /* Get vram informations */ - rs690_vram_info(rdev); - /* Initialize memory controller (also test AGP) */ - r = rs690_mc_init(rdev); - if (r) - return r; + /* initialize memory controller */ + rs690_mc_init(rdev); rv515_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 0e1e6b8632b8..bea747da123f 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -277,13 +277,15 @@ static void rv515_vram_get_type(struct radeon_device *rdev) } } -void rv515_vram_info(struct radeon_device *rdev) +void rv515_mc_init(struct radeon_device *rdev) { fixed20_12 a; rv515_vram_get_type(rdev); - r100_vram_init_sizes(rdev); + radeon_vram_location(rdev, &rdev->mc, 0); + if (!(rdev->flags & RADEON_IS_AGP)) + radeon_gtt_location(rdev, &rdev->mc); /* FIXME: we should enforce default clock in case GPU is not in * default setup */ @@ -587,12 +589,15 @@ int rv515_init(struct radeon_device *rdev) 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); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 6f1f4abbe88c..323fa6be5082 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -820,45 +820,12 @@ int rv770_mc_init(struct radeon_device *rdev) /* Setup GPU memory space */ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); - - if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + /* FIXME remove this once we support unmappable VRAM */ + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) { rdev->mc.mc_vram_size = rdev->mc.aper_size; - - if (rdev->mc.real_vram_size > rdev->mc.aper_size) rdev->mc.real_vram_size = rdev->mc.aper_size; - - if (rdev->flags & RADEON_IS_AGP) { - /* gtt_size is setup by radeon_agp_init */ - rdev->mc.gtt_location = rdev->mc.agp_base; - tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; - /* Try to put vram before or after AGP because we - * we want SYSTEM_APERTURE to cover both VRAM and - * AGP so that GPU can catch out of VRAM/AGP access - */ - if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) { - /* Enought place before */ - rdev->mc.vram_location = rdev->mc.gtt_location - - rdev->mc.mc_vram_size; - } else if (tmp > rdev->mc.mc_vram_size) { - /* Enought place after */ - rdev->mc.vram_location = rdev->mc.gtt_location + - rdev->mc.gtt_size; - } else { - /* Try to setup VRAM then AGP might not - * not work on some card - */ - rdev->mc.vram_location = 0x00000000UL; - rdev->mc.gtt_location = rdev->mc.mc_vram_size; - } - } else { - rdev->mc.vram_location = 0x00000000UL; - rdev->mc.gtt_location = rdev->mc.mc_vram_size; - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; } - rdev->mc.vram_start = rdev->mc.vram_location; - rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; - rdev->mc.gtt_start = rdev->mc.gtt_location; - rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; + r600_vram_gtt_location(rdev, &rdev->mc); /* FIXME: we should enforce default clock in case GPU is not in * default setup */ @@ -867,6 +834,7 @@ int rv770_mc_init(struct radeon_device *rdev) rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); return 0; } + int rv770_gpu_reset(struct radeon_device *rdev) { /* FIXME: implement any rv770 specific bits */ @@ -1042,6 +1010,7 @@ int rv770_init(struct radeon_device *rdev) r = radeon_fence_driver_init(rdev); if (r) return r; + /* initialize AGP */ if (rdev->flags & RADEON_IS_AGP) { r = radeon_agp_init(rdev); if (r) -- cgit v1.2.3 From 8e36113082821980c60ce89a6c5d45fc9492fc26 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 18 Feb 2010 14:23:49 +0000 Subject: drm/radeon/kms: fix R3XX/R4XX memory controller initialization Version 2 of memory controller did break the initialization for R3XX/R4XX hardware. This patch fix it. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 7e9f95653cbe..b188aae764cc 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -461,7 +461,8 @@ int r300_gpu_reset(struct radeon_device *rdev) */ void r300_mc_init(struct radeon_device *rdev) { - uint32_t tmp; + u64 base; + u32 tmp; /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; @@ -474,6 +475,10 @@ void r300_mc_init(struct radeon_device *rdev) default: rdev->mc.vram_width = 128; break; } r100_vram_init_sizes(rdev); + base = rdev->mc.aper_base; + if (rdev->flags & RADEON_IS_IGP) + base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; + radeon_vram_location(rdev, &rdev->mc, base); if (!(rdev->flags & RADEON_IS_AGP)) radeon_gtt_location(rdev, &rdev->mc); } -- cgit v1.2.3 From aa5120d2ef228042416d3023fb7eda9ee487dcf9 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 18 Feb 2010 20:24:28 +0000 Subject: drm/radeon/kms: implement reading active PCIE lanes on R600+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 5 ++++- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_asic.h | 4 ++-- drivers/gpu/drm/radeon/radeon_pm.c | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index b188aae764cc..dc32cd13a837 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -554,7 +554,10 @@ int rv370_get_pcie_lanes(struct radeon_device *rdev) /* FIXME wait for idle */ - link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + if (rdev->family < CHIP_R600) + link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); + else + link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL); switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { case RADEON_PCIE_LC_LINK_WIDTH_X0: diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index fc9044edc0aa..2434d553bbbc 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1014,6 +1014,8 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32 #define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v)) #define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg)) #define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v)) +#define RREG32_PCIE_P(reg) rdev->pciep_rreg(rdev, (reg)) +#define WREG32_PCIE_P(reg, v) rdev->pciep_wreg(rdev, (reg), (v)) #define WREG32_P(reg, val, mask) \ do { \ uint32_t tmp_ = RREG32(reg); \ diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index b7030d7c0396..4572a6699884 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -626,7 +626,7 @@ static struct radeon_asic r600_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, - .get_pcie_lanes = NULL, + .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = NULL, .set_clock_gating = NULL, .set_surface_reg = r600_set_surface_reg, @@ -672,7 +672,7 @@ static struct radeon_asic rv770_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, - .get_pcie_lanes = NULL, + .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r600_set_surface_reg, diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index d174d93c9386..d4d1c39a0e99 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -442,6 +442,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); if (rdev->asic->get_memory_clock) seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); + if (rdev->asic->get_pcie_lanes) + seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); return 0; } -- cgit v1.2.3 From 939461d59d6ac4e5142f767d24810c9b4b5caa38 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sun, 14 Feb 2010 07:10:10 +0100 Subject: drm/radeon/kms: add support for square microtiles on r3xx-r5xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Olšák Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 8 +++++++- drivers/gpu/drm/radeon/r300_reg.h | 2 ++ include/drm/radeon_drm.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/r300.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index dc32cd13a837..4cef90cd74e5 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -705,6 +705,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p, tile_flags |= R300_TXO_MACRO_TILE; if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) tile_flags |= R300_TXO_MICRO_TILE; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_TXO_MICRO_TILE_SQUARE; tmp = idx_value + ((u32)reloc->lobj.gpu_offset); tmp |= tile_flags; @@ -755,6 +757,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p, tile_flags |= R300_COLOR_TILE_ENABLE; if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) tile_flags |= R300_COLOR_MICROTILE_ENABLE; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; tmp = idx_value & ~(0x7 << 16); tmp |= tile_flags; @@ -826,7 +830,9 @@ static int r300_packet0_check(struct radeon_cs_parser *p, if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) tile_flags |= R300_DEPTHMACROTILE_ENABLE; if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - tile_flags |= R300_DEPTHMICROTILE_TILED;; + tile_flags |= R300_DEPTHMICROTILE_TILED; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; tmp = idx_value & ~(0x7 << 16); tmp |= tile_flags; diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index 1735a2b69580..1a0d5362cd79 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h @@ -952,6 +952,7 @@ # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) # define R300_TXO_MACRO_TILE (1 << 2) # define R300_TXO_MICRO_TILE (1 << 3) +# define R300_TXO_MICRO_TILE_SQUARE (2 << 3) # define R300_TXO_OFFSET_MASK 0xffffffe0 # define R300_TXO_OFFSET_SHIFT 5 /* END: Guess from R200 */ @@ -1360,6 +1361,7 @@ # define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */ # define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */ # define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */ +# define R300_COLOR_MICROTILE_SQUARE_ENABLE (2 << 17) # define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */ # define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */ # define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */ diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 39537f3cf98a..81e614bf2dc3 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -808,6 +808,7 @@ struct drm_radeon_gem_create { #define RADEON_TILING_SWAP_32BIT 0x8 #define RADEON_TILING_SURFACE 0x10 /* this object requires a surface * when mapped - i.e. front buffer */ +#define RADEON_TILING_MICRO_SQUARE 0x20 struct drm_radeon_gem_set_tiling { uint32_t handle; -- cgit v1.2.3