#include <asm/io.h>
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include "../macmodes.h"
static int aty128_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void aty128_remove(struct pci_dev *pdev);
-static int aty128_pci_suspend(struct pci_dev *pdev, u32 state);
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state);
static int aty128_pci_resume(struct pci_dev *pdev);
+static int aty128_do_resume(struct pci_dev *pdev);
/* supported Rage128 chipsets */
static struct pci_device_id aty128_pci_tbl[] = {
static int default_cmode __initdata = CMODE_8;
#endif
-#ifdef CONFIG_PMAC_PBOOK
static int default_crt_on __initdata = 0;
static int default_lcd_on __initdata = 1;
-#endif
#ifdef CONFIG_MTRR
static int mtrr = 1;
struct aty128_ddafifo fifo_reg;
u32 accel_flags;
struct aty128_constants constants; /* PLL and others */
- void *regbase; /* remapped mmio */
+ void __iomem *regbase; /* remapped mmio */
u32 vram_size; /* onboard video ram */
int chip_gen;
const struct aty128_meminfo *mem; /* onboard mem info */
#define round_div(n, d) ((n+(d/2))/d)
- /*
- * Interface used by the world
- */
-int aty128fb_init(void);
-
static int aty128fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
static int aty128fb_set_par(struct fb_info *info);
static int aty128fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *fb);
static int aty128fb_blank(int blank, struct fb_info *fb);
-static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info);
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
static int aty128fb_sync(struct fb_info *info);
/*
struct aty128fb_par *par);
#if 0
static void __init aty128_get_pllinfo(struct aty128fb_par *par,
- void *bios);
-static void __init *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par);
-static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom);
+ void __iomem *bios);
+static void __init __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par);
#endif
static void aty128_timings(struct aty128fb_par *par);
static void aty128_init_engine(struct aty128fb_par *par);
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
#ifdef CONFIG_PMAC_BACKLIGHT
#ifndef __sparc__
-static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom)
+static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev)
{
- struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
-
- iounmap(rom);
-
- /* Release the ROM resource if we used it in the first place */
- if (r->parent && r->flags & PCI_ROM_ADDRESS_ENABLE) {
- release_resource(r);
- r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
- r->end -= r->start;
- r->start = 0;
- }
- /* This will disable and set address to unassigned */
- pci_write_config_dword(dev, dev->rom_base_reg, 0);
-}
-
-
-static void * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev)
-{
- struct resource *r;
u16 dptr;
u8 rom_type;
- void *bios;
+ void __iomem *bios;
+ size_t rom_size;
/* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */
unsigned int temp;
aty_st_le32(RAGE128_MPP_TB_CONFIG, temp);
temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
- /* no need to search for the ROM, just ask the card where it is. */
- r = &dev->resource[PCI_ROM_RESOURCE];
+ bios = pci_map_rom(dev, &rom_size);
- /* assign the ROM an address if it doesn't have one */
- if (r->parent == NULL)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
-
- /* enable if needed */
- if (!(r->flags & PCI_ROM_ADDRESS_ENABLE)) {
- pci_write_config_dword(dev, dev->rom_base_reg,
- r->start | PCI_ROM_ADDRESS_ENABLE);
- r->flags |= PCI_ROM_ADDRESS_ENABLE;
- }
-
- bios = ioremap(r->start, r->end - r->start + 1);
if (!bios) {
printk(KERN_ERR "aty128fb: ROM failed to map\n");
return NULL;
}
-
+
/* Very simple test to make sure it appeared */
if (BIOS_IN16(0) != 0xaa55) {
- printk(KERN_ERR "aty128fb: Invalid ROM signature %x should be 0xaa55\n",
- BIOS_IN16(0));
+ printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
+ " be 0xaa55\n", BIOS_IN16(0));
goto failed;
}
return bios;
failed:
- aty128_unmap_ROM(dev, bios);
+ pci_unmap_rom(dev, bios);
return NULL;
}
-static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char *bios)
+static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios)
{
unsigned int bios_hdr;
unsigned int bios_pll;
}
-#ifdef __i386__
-static void * __devinit aty128_find_mem_vbios(struct aty128fb_par *par)
+#ifdef CONFIG_X86
+static void __iomem * __devinit aty128_find_mem_vbios(struct aty128fb_par *par)
{
/* I simplified this code as we used to miss the signatures in
* a lot of case. It's now closer to XFree, we just don't check
* if we end up having conflicts
*/
u32 segstart;
- unsigned char *rom_base = NULL;
+ unsigned char __iomem *rom_base = NULL;
for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
- rom_base = (char *)ioremap(segstart, 0x10000);
+ rom_base = ioremap(segstart, 0x10000);
if (rom_base == NULL)
return NULL;
- if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
+ if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
break;
iounmap(rom_base);
rom_base = NULL;
}
return rom_base;
}
-#endif /* __i386__ */
+#endif
#endif /* ndef(__sparc__) */
/* fill in known card constants if pll_block is not available */
return 0;
}
-#ifdef CONFIG_PMAC_PBOOK
static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
{
if (on) {
aty_st_le32(LVDS_GEN_CNTL, reg);
}
}
-#endif /* CONFIG_PMAC_PBOOK */
static void aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
{
unsigned char post_dividers[] = {1,2,4,8,3,6,12};
u32 output_freq;
u32 vclk; /* in .01 MHz */
- int i;
+ int i = 0;
u32 n, d;
vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */
/* now, find an acceptable divider */
for (i = 0; i < sizeof(post_dividers); i++) {
output_freq = post_dividers[i] * vclk;
- if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)
+ if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
+ pll->post_divider = post_dividers[i];
break;
+ }
}
/* calculate feedback divider */
n = c.ref_divider * output_freq;
d = c.ref_clk;
- pll->post_divider = post_dividers[i];
pll->feedback_divider = round_div(n, d);
pll->vclk = vclk;
info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
-#ifdef CONFIG_PMAC_PBOOK
if (par->chip_gen == rage_M3) {
aty128_set_crt_enable(par, par->crt_on);
aty128_set_lcd_enable(par, par->lcd_on);
}
-#endif
if (par->accel_flags & FB_ACCELF_TEXT)
aty128_init_engine(par);
return 0;
}
-int __init aty128fb_setup(char *options)
+#ifndef MODULE
+static int __init aty128fb_setup(char *options)
{
char *this_opt;
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
-#ifdef CONFIG_PMAC_PBOOK
if (!strncmp(this_opt, "lcd:", 4)) {
default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
continue;
default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
continue;
}
-#endif
#ifdef CONFIG_MTRR
if(!strncmp(this_opt, "nomtrr", 6)) {
mtrr = 0;
}
return 0;
}
+#endif /* MODULE */
/*
* Initialisation
*/
+#ifdef CONFIG_PPC_PMAC
+static void aty128_early_resume(void *data)
+{
+ struct aty128fb_par *par = data;
+
+ if (try_acquire_console_sem())
+ return;
+ aty128_do_resume(par->pdev);
+ release_console_sem();
+}
+#endif /* CONFIG_PPC_PMAC */
+
static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct fb_info *info = pci_get_drvdata(pdev);
strcpy(video_card, "Rage128 XX ");
video_card[8] = ent->device >> 8;
video_card[9] = ent->device & 0xFF;
-
+
/* range check to make sure */
- if (ent->driver_data < (sizeof(r128_family)/sizeof(char *)))
+ if (ent->driver_data < ARRAY_SIZE(r128_family))
strncat(video_card, r128_family[ent->driver_data], sizeof(video_card));
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
info->fbops = &aty128fb_ops;
info->flags = FBINFO_FLAG_DEFAULT;
-#ifdef CONFIG_PMAC_PBOOK
par->lcd_on = default_lcd_on;
par->crt_on = default_crt_on;
-#endif
var = default_var;
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
+ /* Indicate sleep capability */
+ if (par->chip_gen == rage_M3) {
+ pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
+ pmac_set_early_video_resume(aty128_early_resume, par);
+ }
+
+ /* Find default mode */
if (mode_option) {
if (!mac_find_mode(&var, info, mode_option, 8))
var = default_var;
struct fb_info *info;
int err;
#ifndef __sparc__
- void *bios = NULL;
+ void __iomem *bios = NULL;
#endif
/* Enable device in PCI config */
#ifndef __sparc__
bios = aty128_map_ROM(par, pdev);
-#ifdef __i386__
+#ifdef CONFIG_X86
if (bios == NULL)
bios = aty128_find_mem_vbios(par);
#endif
else {
printk(KERN_INFO "aty128fb: Rage128 BIOS located\n");
aty128_get_pllinfo(par, bios);
- aty128_unmap_ROM(pdev, bios);
+ pci_unmap_rom(pdev, bios);
}
#endif /* __sparc__ */
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
- release_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
framebuffer_release(info);
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank)
+ if (machine_is(powermac) && blank)
set_backlight_enable(0);
#endif /* CONFIG_PMAC_BACKLIGHT */
- if (blank & VESA_VSYNC_SUSPEND)
+ if (blank & FB_BLANK_VSYNC_SUSPEND)
state |= 2;
- if (blank & VESA_HSYNC_SUSPEND)
+ if (blank & FB_BLANK_HSYNC_SUSPEND)
state |= 1;
- if (blank & VESA_POWERDOWN)
+ if (blank & FB_BLANK_POWERDOWN)
state |= 4;
aty_st_8(CRTC_EXT_CNTL+1, state);
-#ifdef CONFIG_PMAC_PBOOK
if (par->chip_gen == rage_M3) {
aty128_set_crt_enable(par, par->crt_on && !blank);
aty128_set_lcd_enable(par, par->lcd_on && !blank);
}
-#endif
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && !blank)
+ if (machine_is(powermac) && !blank)
set_backlight_enable(1);
#endif /* CONFIG_PMAC_BACKLIGHT */
return 0;
/* in param: u32* backlight value: 0 to 15 */
#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
-static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
-#ifdef CONFIG_PMAC_PBOOK
struct aty128fb_par *par = info->par;
u32 value;
int rc;
case FBIO_ATY128_SET_MIRROR:
if (par->chip_gen != rage_M3)
return -EINVAL;
- rc = get_user(value, (__u32*)arg);
+ rc = get_user(value, (__u32 __user *)arg);
if (rc)
return rc;
par->lcd_on = (value & 0x01) != 0;
if (par->chip_gen != rage_M3)
return -EINVAL;
value = (par->crt_on << 1) | par->lcd_on;
- return put_user(value, (__u32*)arg);
+ return put_user(value, (__u32 __user *)arg);
}
-#endif
return -EINVAL;
}
}
}
-static int aty128_pci_suspend(struct pci_dev *pdev, u32 state)
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
* can properly take care of D3 ? Also, with swsusp, we
* know we'll be rebooted, ...
*/
-#ifdef CONFIG_PPC_PMAC
+#ifndef CONFIG_PPC_PMAC
/* HACK ALERT ! Once I find a proper way to say to each driver
* individually what will happen with it's PCI slot, I'll change
* that. On laptops, the AGP slot is just unclocked, so D2 is
* expected, while on desktops, the card is powered off
*/
- if (state >= 3)
- state = 2;
+ return 0;
#endif /* CONFIG_PPC_PMAC */
- if (state != 2 || state == pdev->dev.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
printk(KERN_DEBUG "aty128fb: suspending...\n");
par->asleep = 1;
par->lock_blank = 1;
+#ifdef CONFIG_PPC_PMAC
+ /* On powermac, we have hooks to properly suspend/resume AGP now,
+ * use them here. We'll ultimately need some generic support here,
+ * but the generic code isn't quite ready for that yet
+ */
+ pmac_suspend_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
/* We need a way to make sure the fbdev layer will _not_ touch the
* framebuffer before we put the chip to suspend state. On 2.4, I
* used dummy fb ops, 2.5 need proper support for this at the
* fbdev level
*/
- if (state == 2)
+ if (state.event != PM_EVENT_ON)
aty128_set_suspend(par, 1);
release_console_sem();
- pdev->dev.power_state = state;
+ pdev->dev.power.power_state = state;
return 0;
}
-static int aty128_pci_resume(struct pci_dev *pdev)
+static int aty128_do_resume(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
- if (pdev->dev.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
- acquire_console_sem();
-
/* Wakeup chip */
- if (pdev->dev.power_state == 2)
- aty128_set_suspend(par, 0);
+ aty128_set_suspend(par, 0);
par->asleep = 0;
/* Restore display & engine */
wait_for_idle(par);
aty128fb_set_par(info);
fb_pan_display(info, &info->var);
- fb_set_cmap(&info->cmap, 1, info);
+ fb_set_cmap(&info->cmap, info);
/* Refresh */
fb_set_suspend(info, 0);
par->lock_blank = 0;
aty128fb_blank(0, info);
- release_console_sem();
+#ifdef CONFIG_PPC_PMAC
+ /* On powermac, we have hooks to properly suspend/resume AGP now,
+ * use them here. We'll ultimately need some generic support here,
+ * but the generic code isn't quite ready for that yet
+ */
+ pmac_resume_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
- pdev->dev.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
printk(KERN_DEBUG "aty128fb: resumed !\n");
return 0;
}
-int __init aty128fb_init(void)
+static int aty128_pci_resume(struct pci_dev *pdev)
+{
+ int rc;
+
+ acquire_console_sem();
+ rc = aty128_do_resume(pdev);
+ release_console_sem();
+
+ return rc;
+}
+
+
+static int __init aty128fb_init(void)
{
- return pci_module_init(&aty128fb_driver);
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("aty128fb", &option))
+ return -ENODEV;
+ aty128fb_setup(option);
+#endif
+
+ return pci_register_driver(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
pci_unregister_driver(&aty128fb_driver);
}
-#ifdef MODULE
module_init(aty128fb_init);
+
module_exit(aty128fb_exit);
MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
MODULE_LICENSE("GPL");
module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
module_param_named(nomtrr, mtrr, invbool, 0);
-MODULE_PARM_DESC(mtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
-#endif
+MODULE_PARM_DESC(nomtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
#endif