X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Faty%2Faty128fb.c;h=f7bbff4ddc6afcb06dc82ef812c716fb1281d62a;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=b19eded6cb8b7c4f70e8b0584ea2bbf20c648f4a;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index b19eded6c..f7bbff4dd 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -67,6 +67,8 @@ #include #ifdef CONFIG_PPC_PMAC +#include +#include #include #include #include "../macmodes.h" @@ -165,8 +167,9 @@ static const char *r128_family[] __devinitdata = { 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[] = { @@ -348,10 +351,8 @@ static int default_vmode __initdata = VMODE_1024_768_60; 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; @@ -397,7 +398,7 @@ struct aty128fb_par { 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 */ @@ -423,11 +424,6 @@ struct aty128fb_par { #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); @@ -436,8 +432,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 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); /* @@ -450,9 +445,8 @@ static int aty128_decode_var(struct fb_var_screeninfo *var, 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); @@ -484,7 +478,6 @@ static struct fb_ops aty128fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PMAC_BACKLIGHT @@ -788,30 +781,12 @@ static u32 depth_to_dst(u32 depth) #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; @@ -821,30 +796,17 @@ static void * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_d 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; } @@ -899,11 +861,11 @@ static void * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_d 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; @@ -924,8 +886,8 @@ static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char *b } -#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 @@ -933,20 +895,20 @@ static void * __devinit aty128_find_mem_vbios(struct aty128fb_par *par) * 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 */ @@ -1284,7 +1246,6 @@ static int aty128_crtc_to_var(const struct aty128_crtc *crtc, return 0; } -#ifdef CONFIG_PMAC_PBOOK static void aty128_set_crt_enable(struct aty128fb_par *par, int on) { if (on) { @@ -1319,7 +1280,6 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int 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) { @@ -1367,7 +1327,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, 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 */ @@ -1381,15 +1341,16 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, /* 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; @@ -1526,12 +1487,10 @@ static int aty128fb_set_par(struct fb_info *info) 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); @@ -1678,7 +1637,8 @@ static int aty128fb_sync(struct fb_info *info) return 0; } -int __init aty128fb_setup(char *options) +#ifndef MODULE +static int __init aty128fb_setup(char *options) { char *this_opt; @@ -1686,7 +1646,6 @@ int __init aty128fb_setup(char *options) 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; @@ -1694,7 +1653,6 @@ int __init aty128fb_setup(char *options) default_crt_on = simple_strtoul(this_opt+4, NULL, 0); continue; } -#endif #ifdef CONFIG_MTRR if(!strncmp(this_opt, "nomtrr", 6)) { mtrr = 0; @@ -1731,12 +1689,25 @@ int __init aty128fb_setup(char *options) } 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); @@ -1755,9 +1726,9 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * 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); @@ -1773,14 +1744,19 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * 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; @@ -1885,7 +1861,7 @@ static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id struct fb_info *info; int err; #ifndef __sparc__ - void *bios = NULL; + void __iomem *bios = NULL; #endif /* Enable device in PCI config */ @@ -1950,7 +1926,7 @@ static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id #ifndef __sparc__ bios = aty128_map_ROM(par, pdev); -#ifdef __i386__ +#ifdef CONFIG_X86 if (bios == NULL) bios = aty128_find_mem_vbios(par); #endif @@ -1959,7 +1935,7 @@ static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id 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__ */ @@ -2016,8 +1992,6 @@ static void __devexit aty128_remove(struct pci_dev *pdev) 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); @@ -2038,27 +2012,25 @@ static int aty128fb_blank(int blank, struct fb_info *fb) 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; @@ -2137,10 +2109,8 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* 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; @@ -2149,7 +2119,7 @@ static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, 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; @@ -2163,9 +2133,8 @@ static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, 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; } @@ -2343,7 +2312,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) } } -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; @@ -2353,17 +2322,16 @@ static int aty128_pci_suspend(struct pci_dev *pdev, u32 state) * 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"); @@ -2384,34 +2352,39 @@ static int aty128_pci_suspend(struct pci_dev *pdev, u32 state) 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 */ @@ -2419,7 +2392,7 @@ static int aty128_pci_resume(struct pci_dev *pdev) 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); @@ -2428,18 +2401,44 @@ static int aty128_pci_resume(struct pci_dev *pdev) 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) @@ -2447,18 +2446,17 @@ 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 "); 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 \"x[-][@]\" "); +MODULE_PARM_DESC(mode_option, "Specify resolution as \"x[-][@]\" "); #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