summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/video/fbdev/aty/radeon_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/video/fbdev/aty/radeon_base.c')
-rw-r--r--kernel/drivers/video/fbdev/aty/radeon_base.c162
1 files changed, 137 insertions, 25 deletions
diff --git a/kernel/drivers/video/fbdev/aty/radeon_base.c b/kernel/drivers/video/fbdev/aty/radeon_base.c
index 01237c8fc..ce0b1d05a 100644
--- a/kernel/drivers/video/fbdev/aty/radeon_base.c
+++ b/kernel/drivers/video/fbdev/aty/radeon_base.c
@@ -85,10 +85,6 @@
#endif /* CONFIG_PPC */
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
#include <video/radeon.h>
#include <linux/radeonfb.h>
@@ -271,9 +267,7 @@ static bool mirror = 0;
static int panel_yres = 0;
static bool force_dfp = 0;
static bool force_measure_pll = 0;
-#ifdef CONFIG_MTRR
static bool nomtrr = 0;
-#endif
static bool force_sleep;
static bool ignore_devlist;
#ifdef CONFIG_PMAC_BACKLIGHT
@@ -282,9 +276,138 @@ static int backlight = 1;
static int backlight = 0;
#endif
-/*
- * prototypes
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mechanism. At this point, interrupts are off
+ * and scheduling is not permitted
*/
+void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+ if (rinfo->no_schedule || oops_in_progress)
+ mdelay(ms);
+ else
+ msleep(ms);
+}
+
+void radeon_pll_errata_after_index_slow(struct radeonfb_info *rinfo)
+{
+ /* Called if (rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS) is set */
+ (void)INREG(CLOCK_CNTL_DATA);
+ (void)INREG(CRTC_GEN_CNTL);
+}
+
+void radeon_pll_errata_after_data_slow(struct radeonfb_info *rinfo)
+{
+ if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+ /* we can't deal with posted writes here ... */
+ _radeon_msleep(rinfo, 5);
+ }
+ if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+ u32 save, tmp;
+ save = INREG(CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | PLL_WR_EN);
+ OUTREG(CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(CLOCK_CNTL_DATA);
+ OUTREG(CLOCK_CNTL_INDEX, save);
+ }
+}
+
+void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, u32 val, u32 mask)
+{
+ unsigned long flags;
+ unsigned int tmp;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
+ tmp = INREG(addr);
+ tmp &= (mask);
+ tmp |= (val);
+ OUTREG(addr, tmp);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+}
+
+u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+ u32 data;
+
+ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+ radeon_pll_errata_after_index(rinfo);
+ data = INREG(CLOCK_CNTL_DATA);
+ radeon_pll_errata_after_data(rinfo);
+ return data;
+}
+
+void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
+{
+ OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+ radeon_pll_errata_after_index(rinfo);
+ OUTREG(CLOCK_CNTL_DATA, val);
+ radeon_pll_errata_after_data(rinfo);
+}
+
+void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
+{
+ unsigned int tmp;
+
+ tmp = __INPLL(rinfo, index);
+ tmp &= (mask);
+ tmp |= (val);
+ __OUTPLL(rinfo, index, tmp);
+}
+
+void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+ int i;
+
+ for (i=0; i<2000000; i++) {
+ if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+}
+
+void radeon_engine_flush(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* Initiate flush */
+ OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+ ~RB2D_DC_FLUSH_ALL);
+
+ /* Ensure FIFO is empty, ie, make sure the flush commands
+ * has reached the cache
+ */
+ _radeon_fifo_wait(rinfo, 64);
+
+ /* Wait for the flush to complete */
+ for (i=0; i < 2000000; i++) {
+ if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: Flush Timeout !\n");
+}
+
+void _radeon_engine_idle(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* ensure FIFO is empty before waiting for idle */
+ _radeon_fifo_wait(rinfo, 64);
+
+ for (i=0; i<2000000; i++) {
+ if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
+ radeon_engine_flush(rinfo);
+ return;
+ }
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: Idle Timeout !\n");
+}
+
+
static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
{
@@ -2260,8 +2383,8 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
do {
- rinfo->fb_base = ioremap (rinfo->fb_base_phys,
- rinfo->mapped_vram);
+ rinfo->fb_base = ioremap_wc(rinfo->fb_base_phys,
+ rinfo->mapped_vram);
} while (rinfo->fb_base == NULL &&
((rinfo->mapped_vram /= 2) >= MIN_MAPPED_VRAM));
@@ -2359,11 +2482,9 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
goto err_unmap_fb;
}
-#ifdef CONFIG_MTRR
- rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
- rinfo->video_ram,
- MTRR_TYPE_WRCOMB, 1);
-#endif
+ if (!nomtrr)
+ rinfo->wc_cookie = arch_phys_wc_add(rinfo->fb_base_phys,
+ rinfo->video_ram);
if (backlight)
radeonfb_bl_init(rinfo);
@@ -2428,12 +2549,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev)
#endif
del_timer_sync(&rinfo->lvds_timer);
-
-#ifdef CONFIG_MTRR
- if (rinfo->mtrr_hdl >= 0)
- mtrr_del(rinfo->mtrr_hdl, 0, 0);
-#endif
-
+ arch_phys_wc_del(rinfo->wc_cookie);
unregister_framebuffer(info);
radeonfb_bl_exit(rinfo);
@@ -2489,10 +2605,8 @@ static int __init radeonfb_setup (char *options)
panel_yres = simple_strtoul((this_opt+11), NULL, 0);
} else if (!strncmp(this_opt, "backlight:", 10)) {
backlight = simple_strtoul(this_opt+10, NULL, 0);
-#ifdef CONFIG_MTRR
} else if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1;
-#endif
} else if (!strncmp(this_opt, "nomodeset", 9)) {
nomodeset = 1;
} else if (!strncmp(this_opt, "force_measure_pll", 17)) {
@@ -2552,10 +2666,8 @@ module_param(monitor_layout, charp, 0);
MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)");
module_param(force_measure_pll, bool, 0);
MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)");
-#ifdef CONFIG_MTRR
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
-#endif
module_param(panel_yres, int, 0);
MODULE_PARM_DESC(panel_yres, "int: set panel yres");
module_param(mode_option, charp, 0);