patch-2.3.21 linux/drivers/video/atyfb.c
Next file: linux/drivers/video/chipsfb.c
Previous file: linux/drivers/video/aty.h
Back to the patch index
Back to the overall index
- Lines: 409
- Date:
Mon Oct 11 10:26:52 1999
- Orig file:
v2.3.20/linux/drivers/video/atyfb.c
- Orig date:
Fri Sep 10 23:57:36 1999
diff -u --recursive --new-file v2.3.20/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.122 1999/09/06 20:44:08 geert Exp $
+/* $Id: atyfb.c,v 1.126 1999/09/16 18:46:23 geert Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -52,7 +52,6 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/pci.h>
-#include <linux/nvram.h>
#include <linux/kd.h>
#include <linux/vt_kern.h>
@@ -62,12 +61,15 @@
#include <asm/io.h>
-#if defined(CONFIG_PPC)
+#ifdef __powerpc__
+#include <linux/adb.h>
+#include <linux/pmu.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <video/macmodes.h>
-#include <asm/adb.h>
-#include <asm/pmu.h>
+#endif
+#ifdef CONFIG_NVRAM
+#include <linux/nvram.h>
#endif
#ifdef __sparc__
#include <asm/pbm.h>
@@ -272,8 +274,20 @@
int vtconsole;
int consolecnt;
#endif
+#ifdef CONFIG_PMAC_PBOOK
+ unsigned char *save_framebuffer;
+ unsigned long save_pll[64];
+#endif
};
+#ifdef CONFIG_PMAC_PBOOK
+ int aty_sleep_notify(struct pmu_sleep_notifier *self, int when);
+ static struct pmu_sleep_notifier aty_sleep_notifier = {
+ aty_sleep_notify, SLEEP_LEVEL_VIDEO,
+ };
+ static struct fb_info_aty* first_display = NULL;
+#endif
+
/*
* Frame buffer device API
@@ -446,7 +460,7 @@
static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *fb);
static void do_install_cmap(int con, struct fb_info *info);
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
static int read_aty_sense(const struct fb_info_aty *info);
#endif
@@ -488,9 +502,14 @@
static const char *mode_option __initdata = NULL;
#endif
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
+#ifdef CONFIG_NVRAM
static int default_vmode __initdata = VMODE_NVRAM;
static int default_cmode __initdata = CMODE_NVRAM;
+#else
+static int default_vmode __initdata = VMODE_CHOOSE;
+static int default_cmode __initdata = CMODE_CHOOSE;
+#endif
#endif
#ifdef CONFIG_ATARI
@@ -550,58 +569,46 @@
static inline u32 aty_ld_le32(unsigned int regindex,
const struct fb_info_aty *info)
{
+#if defined(__powerpc__)
unsigned long temp;
u32 val;
-#if defined(__powerpc__)
temp = info->ati_regbase;
asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
-#elif defined(__sparc_v9__)
- temp = info->ati_regbase + regindex;
- val = readl(temp);
+ return val;
+#elif defined(__mc68000__)
+ return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
#else
- temp = info->ati_regbase+regindex;
- val = le32_to_cpu(*((volatile u32 *)(temp)));
+ return readl (info->ati_regbase + regindex);
#endif
- return val;
}
static inline void aty_st_le32(unsigned int regindex, u32 val,
const struct fb_info_aty *info)
{
+#if defined(__powerpc__)
unsigned long temp;
-#if defined(__powerpc__)
temp = info->ati_regbase;
asm volatile("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
"memory");
-#elif defined(__sparc_v9__)
- temp = info->ati_regbase + regindex;
- writel(val, temp);
+#elif defined(__mc68000__)
+ *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
#else
- temp = info->ati_regbase+regindex;
- *((volatile u32 *)(temp)) = cpu_to_le32(val);
+ writel (val, info->ati_regbase + regindex);
#endif
}
static inline u8 aty_ld_8(unsigned int regindex,
const struct fb_info_aty *info)
{
-#ifdef __sparc_v9__
- return readb(info->ati_regbase + regindex);
-#else
- return *(volatile u8 *)(info->ati_regbase+regindex);
-#endif
+ return readb (info->ati_regbase + regindex);
}
static inline void aty_st_8(unsigned int regindex, u8 val,
const struct fb_info_aty *info)
{
-#ifdef __sparc_v9__
- writeb(val, info->ati_regbase + regindex);
-#else
- *(volatile u8 *)(info->ati_regbase+regindex) = val;
-#endif
+ writeb (val, info->ati_regbase + regindex);
}
@@ -791,7 +798,7 @@
return res;
}
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
/*
* Apple monitor sense
@@ -831,7 +838,7 @@
return sense;
}
-#endif /* defined(CONFIG_PPC) */
+#endif /* CONFIG_PMAC */
/* ------------------------------------------------------------------------- */
@@ -903,17 +910,19 @@
for (x = 0; x < c->size.x >> 2; x++) {
m = c->mask[x][y];
b = c->bits[x][y];
- *ram++ = cursor_mask_lookup[m >> 4] |
- cursor_bits_lookup[(b & m) >> 4];
- *ram++ = cursor_mask_lookup[m & 0x0f] |
- cursor_bits_lookup[(b & m) & 0x0f];
+ fb_writeb (cursor_mask_lookup[m >> 4] |
+ cursor_bits_lookup[(b & m) >> 4],
+ ram++);
+ fb_writeb (cursor_mask_lookup[m & 0x0f] |
+ cursor_bits_lookup[(b & m) & 0x0f],
+ ram++);
}
for ( ; x < 8; x++) {
- *ram++ = 0xaa;
- *ram++ = 0xaa;
+ fb_writeb (0xaa, ram++);
+ fb_writeb (0xaa, ram++);
}
}
- memset(ram, 0xaa, (64 - c->size.y) * 16);
+ fb_memset (ram, 0xaa, (64 - c->size.y) * 16);
}
static void
@@ -3239,7 +3248,7 @@
struct display *disp;
const char *chipname = NULL, *ramname = NULL, *xtal;
int pll, mclk, gtb_memsize;
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
int sense;
#endif
u8 pll_ref_div;
@@ -3501,16 +3510,22 @@
var = default_var;
#else /* !MODULE */
memset(&var, 0, sizeof(var));
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
+ /*
+ * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
+ * applies to all Mac video cards
+ */
if (mode_option) {
if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
var = default_var;
} else {
+#ifdef CONFIG_NVRAM
if (default_vmode == VMODE_NVRAM) {
default_vmode = nvram_read_byte(NV_VMODE);
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_CHOOSE;
}
+#endif
if (default_vmode == VMODE_CHOOSE) {
if (Gx == LG_CHIP_ID)
/* G3 PowerBook with 1024x768 LCD */
@@ -3522,14 +3537,16 @@
}
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
+#ifdef CONFIG_NVRAM
if (default_cmode == CMODE_NVRAM)
default_cmode = nvram_read_byte(NV_CMODE);
+#endif
if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
default_cmode = CMODE_8;
if (mac_vmode_to_var(default_vmode, default_cmode, &var))
var = default_var;
}
-#else /* !CONFIG_PPC */
+#else /* !CONFIG_PMAC */
#ifdef __sparc__
if (mode_option) {
if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
@@ -3540,7 +3557,7 @@
if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
var = default_var;
#endif /* !__sparc__ */
-#endif /* !CONFIG_PPC */
+#endif /* !CONFIG_PMAC */
#endif /* !MODULE */
if (noaccel)
var.accel_flags &= ~FB_ACCELF_TEXT;
@@ -3964,6 +3981,13 @@
struct fb_info_aty *info;
int i;
+ if (device_is_compatible(dp, "ATY,264LTPro")) {
+ /* XXX kludge for now */
+ if (dp->name == 0 || strcmp(dp->name, "ATY,264LTProA") != 0
+ || dp->parent == 0)
+ return;
+ dp = dp->parent;
+ }
switch (dp->n_addrs) {
case 1:
case 2:
@@ -4032,6 +4056,14 @@
return;
}
+#ifdef CONFIG_PMAC_PBOOK
+ if (first_display == NULL)
+ pmu_register_sleep_notifier(&aty_sleep_notifier);
+ info->next = first_display;
+ first_display = info;
+#endif
+
+
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info)
console_fb_info = &info->fb_info;
@@ -4070,7 +4102,7 @@
default_pll = simple_strtoul(this_opt+4, NULL, 0);
else if (!strncmp(this_opt, "mclk:", 5))
default_mclk = simple_strtoul(this_opt+5, NULL, 0);
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
@@ -4207,7 +4239,7 @@
struct fb_info_aty *info = (struct fb_info_aty *)fb;
u8 gen_cntl;
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
if ((_machine == _MACH_Pmac) && blank)
pmu_enable_backlight(0);
#endif
@@ -4232,7 +4264,7 @@
gen_cntl &= ~(0x4c);
aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
-#if defined(CONFIG_PPC)
+#ifdef CONFIG_PMAC
if ((_machine == _MACH_Pmac) && !blank)
pmu_enable_backlight(1);
#endif
@@ -4735,6 +4767,98 @@
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Save the contents of the frame buffer when we go to sleep,
+ * and restore it when we wake up again.
+ */
+int
+aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+ struct fb_info_aty *info;
+ unsigned int pm;
+
+ for (info = first_display; info != NULL; info = info->next) {
+ struct fb_fix_screeninfo fix;
+ int nb;
+
+ atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
+ nb = fb_display[fg_console].var.yres * fix.line_length;
+
+ switch (when) {
+ case PBOOK_SLEEP_NOW:
+ /* Stop accel engine (stop bus mastering) */
+ if (info->current_par.accel_flags & FB_ACCELF_TEXT)
+ reset_engine(info);
+#if 1
+ /* Backup fb content */
+ info->save_framebuffer = vmalloc(nb);
+ if (info->save_framebuffer)
+ memcpy(info->save_framebuffer,
+ (void *)info->frame_buffer, nb);
+#endif
+ /* Blank display and LCD */
+ atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
+
+ /* Set chip to "suspend" mode. Note: There's an HW bug in the
+ chip which prevents proper resync on wakeup with automatic
+ power management, we handle suspend manually using the
+ following (weird) sequence described by ATI. Note2:
+ We could enable this for all Rage LT Pro chip ids */
+ if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ pm &= ~PWR_MGT_ON;
+ aty_st_le32(POWER_MANAGEMENT, pm, info);
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ pm &= ~(PWR_BLON | AUTO_PWR_UP);
+ pm |= SUSPEND_NOW;
+ aty_st_le32(POWER_MANAGEMENT, pm, info);
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ pm |= PWR_MGT_ON;
+ aty_st_le32(POWER_MANAGEMENT, pm, info);
+ do {
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+ mdelay(500);
+ }
+ break;
+ case PBOOK_WAKE:
+ /* Wakeup chip */
+ if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ pm &= ~PWR_MGT_ON;
+ aty_st_le32(POWER_MANAGEMENT, pm, info);
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ pm |= (PWR_BLON | AUTO_PWR_UP);
+ pm &= ~SUSPEND_NOW;
+ aty_st_le32(POWER_MANAGEMENT, pm, info);
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ pm |= PWR_MGT_ON;
+ aty_st_le32(POWER_MANAGEMENT, pm, info);
+ do {
+ pm = aty_ld_le32(POWER_MANAGEMENT, info);
+ } while ((pm & PWR_MGT_STATUS_MASK) != 0);
+ mdelay(500);
+ }
+#if 1
+ /* Restore fb content */
+ if (info->save_framebuffer) {
+ memcpy((void *)info->frame_buffer,
+ info->save_framebuffer, nb);
+ vfree(info->save_framebuffer);
+ info->save_framebuffer = 0;
+ }
+#endif
+ /* Restore display */
+ atyfb_set_par(&info->current_par, info);
+ atyfbcon_blank(0, (struct fb_info *)info);
+ break;
+ }
+ }
+ return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PMAC_PBOOK */
#ifdef MODULE
int __init init_module(void)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)