diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rs400.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/rs400.c | 119 |
1 files changed, 76 insertions, 43 deletions
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 233a9b9fa1f7..13cd0a688a65 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -25,15 +25,20 @@ * Alex Deucher * Jerome Glisse */ + +#include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/slab.h> -#include <drm/drmP.h> + +#include <drm/drm_device.h> +#include <drm/drm_file.h> + #include "radeon.h" #include "radeon_asic.h" #include "rs400d.h" /* This files gather functions specifics to : rs400,rs480 */ -static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev); +static void rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev); void rs400_gart_adjust_size(struct radeon_device *rdev) { @@ -67,7 +72,7 @@ void rs400_gart_tlb_flush(struct radeon_device *rdev) tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); if ((tmp & RS480_GART_CACHE_INVALIDATE) == 0) break; - DRM_UDELAY(1); + udelay(1); timeout--; } while (timeout > 0); WREG32_MC(RS480_GART_CACHE_CNTRL, 0); @@ -82,7 +87,7 @@ int rs400_gart_init(struct radeon_device *rdev) return 0; } /* Check gart size */ - switch(rdev->mc.gtt_size / (1024 * 1024)) { + switch (rdev->mc.gtt_size / (1024 * 1024)) { case 32: case 64: case 128: @@ -98,8 +103,7 @@ int rs400_gart_init(struct radeon_device *rdev) r = radeon_gart_init(rdev); if (r) return r; - if (rs400_debugfs_pcie_gart_info_init(rdev)) - DRM_ERROR("Failed to register debugfs file for RS400 GART !\n"); + rs400_debugfs_pcie_gart_info_init(rdev); rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; return radeon_gart_table_ram_alloc(rdev); } @@ -109,12 +113,11 @@ 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); /* Check gart size */ - switch(rdev->mc.gtt_size / (1024 * 1024)) { + switch (rdev->mc.gtt_size / (1024 * 1024)) { case 32: size_reg = RS480_VA_SIZE_32MB; break; @@ -174,10 +177,13 @@ int rs400_gart_enable(struct radeon_device *rdev) /* FIXME: according to doc we should set HIDE_MMCFG_BAR=0, * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */ if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { - WREG32_MC(RS480_MC_MISC_CNTL, - (RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN)); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + tmp |= RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN; + WREG32_MC(RS480_MC_MISC_CNTL, tmp); } else { - WREG32_MC(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + tmp |= RS480_GART_INDEX_REG_EN; + WREG32_MC(RS480_MC_MISC_CNTL, tmp); } /* Enable gart */ WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg)); @@ -206,24 +212,30 @@ void rs400_gart_fini(struct radeon_device *rdev) radeon_gart_table_ram_free(rdev); } +#define RS400_PTE_UNSNOOPED (1 << 0) #define RS400_PTE_WRITEABLE (1 << 2) #define RS400_PTE_READABLE (1 << 3) -int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +uint64_t rs400_gart_get_page_entry(uint64_t addr, uint32_t flags) { uint32_t entry; - u32 *gtt = rdev->gart.ptr; - - if (i < 0 || i > rdev->gart.num_gpu_pages) { - return -EINVAL; - } entry = (lower_32_bits(addr) & PAGE_MASK) | - ((upper_32_bits(addr) & 0xff) << 4) | - RS400_PTE_WRITEABLE | RS400_PTE_READABLE; - entry = cpu_to_le32(entry); - gtt[i] = entry; - return 0; + ((upper_32_bits(addr) & 0xff) << 4); + if (flags & RADEON_GART_PAGE_READ) + entry |= RS400_PTE_READABLE; + if (flags & RADEON_GART_PAGE_WRITE) + entry |= RS400_PTE_WRITEABLE; + if (!(flags & RADEON_GART_PAGE_SNOOP)) + entry |= RS400_PTE_UNSNOOPED; + return entry; +} + +void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t entry) +{ + u32 *gtt = rdev->gart.ptr; + gtt[i] = cpu_to_le32(lower_32_bits(entry)); } int rs400_mc_wait_for_idle(struct radeon_device *rdev) @@ -237,18 +249,32 @@ int rs400_mc_wait_for_idle(struct radeon_device *rdev) if (tmp & RADEON_MC_IDLE) { return 0; } - DRM_UDELAY(1); + udelay(1); } return -1; } static void rs400_gpu_init(struct radeon_device *rdev) { - /* FIXME: is this correct ? */ - r420_pipes_init(rdev); + /* Earlier code was calling r420_pipes_init and then + * rs400_mc_wait_for_idle(rdev). The problem is that + * at least on my Mobility Radeon Xpress 200M RC410 card + * that ends up in this code path ends up num_gb_pipes == 3 + * while the card seems to have only one pipe. With the + * r420 pipe initialization method. + * + * Problems shown up as HyperZ glitches, see: + * https://bugs.freedesktop.org/show_bug.cgi?id=110897 + * + * Delegating initialization to r300 code seems to work + * and results in proper pipe numbers. The rs400 cards + * are said to be not r400, but r300 kind of cards. + */ + r300_gpu_init(rdev); + if (rs400_mc_wait_for_idle(rdev)) { - printk(KERN_WARNING "rs400: Failed to wait MC idle while " - "programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS)); + pr_warn("rs400: Failed to wait MC idle while programming pipes. Bad things might happen. %08x\n", + RREG32(RADEON_MC_STATUS)); } } @@ -271,27 +297,32 @@ static void rs400_mc_init(struct radeon_device *rdev) uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t r; + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(RS480_NB_MC_INDEX, reg & 0xff); r = RREG32(RS480_NB_MC_DATA); WREG32(RS480_NB_MC_INDEX, 0xff); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); return r; } void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN); WREG32(RS480_NB_MC_DATA, (v)); WREG32(RS480_NB_MC_INDEX, 0xff); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } #if defined(CONFIG_DEBUG_FS) -static int rs400_debugfs_gart_info(struct seq_file *m, void *data) +static int rs400_debugfs_gart_info_show(struct seq_file *m, void *unused) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct radeon_device *rdev = dev->dev_private; + struct radeon_device *rdev = m->private; uint32_t tmp; tmp = RREG32(RADEON_HOST_PATH_CNTL); @@ -356,17 +387,16 @@ static int rs400_debugfs_gart_info(struct seq_file *m, void *data) return 0; } -static struct drm_info_list rs400_gart_info_list[] = { - {"rs400_gart_info", rs400_debugfs_gart_info, 0, NULL}, -}; +DEFINE_SHOW_ATTRIBUTE(rs400_debugfs_gart_info); #endif -static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev) +static void rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev) { #if defined(CONFIG_DEBUG_FS) - return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1); -#else - return 0; + struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root; + + debugfs_create_file("rs400_gart_info", 0444, root, rdev, + &rs400_debugfs_gart_info_fops); #endif } @@ -458,7 +488,7 @@ int rs400_resume(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* post */ - radeon_combios_asic_init(rdev->ddev); + radeon_combios_asic_init(rdev_to_drm(rdev)); /* Resume clock after posting */ r300_clock_startup(rdev); /* Initialize surface registers */ @@ -474,6 +504,7 @@ int rs400_resume(struct radeon_device *rdev) int rs400_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -483,6 +514,7 @@ int rs400_suspend(struct radeon_device *rdev) void rs400_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -534,13 +566,11 @@ int rs400_init(struct radeon_device *rdev) return -EINVAL; /* Initialize clocks */ - radeon_get_clock_info(rdev->ddev); + radeon_get_clock_info(rdev_to_drm(rdev)); /* initialize memory controller */ rs400_mc_init(rdev); /* Fence driver */ - r = radeon_fence_driver_init(rdev); - if (r) - return r; + radeon_fence_driver_init(rdev); /* Memory manager */ r = radeon_bo_init(rdev); if (r) @@ -550,6 +580,9 @@ int rs400_init(struct radeon_device *rdev) return r; r300_set_reg_safe(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = rs400_startup(rdev); if (r) { |
