X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Faty%2Faty128fb.c;h=f7bbff4ddc6afcb06dc82ef812c716fb1281d62a;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=276a21530b9527c4e5dbf1d4624ea116488f5163;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 276a21530..f7bbff4dd 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -46,12 +46,14 @@ */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -62,7 +64,6 @@ #include #include #include -#include #include #ifdef CONFIG_PPC_PMAC @@ -98,7 +99,7 @@ #ifndef CONFIG_PPC_PMAC /* default mode */ -static struct fb_var_screeninfo default_var __devinitdata = { +static struct fb_var_screeninfo default_var __initdata = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, @@ -121,7 +122,7 @@ static struct fb_var_screeninfo default_var = { /* default modedb mode */ /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ -static struct fb_videomode defaultmode __devinitdata = { +static struct fb_videomode defaultmode __initdata = { .refresh = 60, .xres = 640, .yres = 480, @@ -333,7 +334,7 @@ static const struct aty128_meminfo sdr_sgram = static const struct aty128_meminfo ddr_sgram = { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" }; -static struct fb_fix_screeninfo aty128fb_fix __devinitdata = { +static struct fb_fix_screeninfo aty128fb_fix __initdata = { .id = "ATY Rage128", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, @@ -343,15 +344,15 @@ static struct fb_fix_screeninfo aty128fb_fix __devinitdata = { .accel = FB_ACCEL_ATI_RAGE128, }; -static char *mode_option __devinitdata = NULL; +static char *mode_option __initdata = NULL; #ifdef CONFIG_PPC_PMAC -static int default_vmode __devinitdata = VMODE_1024_768_60; -static int default_cmode __devinitdata = CMODE_8; +static int default_vmode __initdata = VMODE_1024_768_60; +static int default_cmode __initdata = CMODE_8; #endif -static int default_crt_on __devinitdata = 0; -static int default_lcd_on __devinitdata = 1; +static int default_crt_on __initdata = 0; +static int default_lcd_on __initdata = 1; #ifdef CONFIG_MTRR static int mtrr = 1; @@ -443,9 +444,9 @@ static int aty128_encode_var(struct fb_var_screeninfo *var, static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par); #if 0 -static void __devinit aty128_get_pllinfo(struct aty128fb_par *par, +static void __init aty128_get_pllinfo(struct aty128fb_par *par, void __iomem *bios); -static void __devinit __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par); +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); @@ -456,10 +457,6 @@ static void wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_idle(struct aty128fb_par *par); static u32 depth_to_dst(u32 depth); -#ifdef CONFIG_FB_ATY128_BACKLIGHT -static void aty128_bl_set_power(struct fb_info *info, int power); -#endif - #define BIOS_IN8(v) (readb(bios + (v))) #define BIOS_IN16(v) (readb(bios + (v)) | \ (readb(bios + (v) + 1) << 8)) @@ -483,6 +480,16 @@ static struct fb_ops aty128fb_ops = { .fb_imageblit = cfb_imageblit, }; +#ifdef CONFIG_PMAC_BACKLIGHT +static int aty128_set_backlight_enable(int on, int level, void* data); +static int aty128_set_backlight_level(int level, void* data); + +static struct backlight_controller aty128_backlight_controller = { + aty128_set_backlight_enable, + aty128_set_backlight_level +}; +#endif /* CONFIG_PMAC_BACKLIGHT */ + /* * Functions to read from/write to the mmio registers * - endian conversions may possibly be avoided by @@ -575,7 +582,7 @@ static void aty_pll_writeupdate(const struct aty128fb_par *par) /* write to the scratch register to test r/w functionality */ -static int __devinit register_test(const struct aty128fb_par *par) +static int __init register_test(const struct aty128fb_par *par) { u32 val; int flag = 0; @@ -774,7 +781,7 @@ static u32 depth_to_dst(u32 depth) #ifndef __sparc__ -static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev) +static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev) { u16 dptr; u8 rom_type; @@ -858,7 +865,7 @@ static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, s return NULL; } -static void __devinit aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios) +static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios) { unsigned int bios_hdr; unsigned int bios_pll; @@ -905,7 +912,7 @@ static void __iomem * __devinit aty128_find_mem_vbios(struct aty128fb_par *par) #endif /* ndef(__sparc__) */ /* fill in known card constants if pll_block is not available */ -static void __devinit aty128_timings(struct aty128fb_par *par) +static void __init aty128_timings(struct aty128fb_par *par) { #ifdef CONFIG_PPC_OF /* instead of a table lookup, assume OF has properly @@ -1251,21 +1258,19 @@ static void aty128_set_crt_enable(struct aty128fb_par *par, int on) static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) { u32 reg; -#ifdef CONFIG_FB_ATY128_BACKLIGHT - struct fb_info *info = pci_get_drvdata(par->pdev); -#endif if (on) { reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; reg &= ~LVDS_DISPLAY_DIS; aty_st_le32(LVDS_GEN_CNTL, reg); -#ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_set_power(info, FB_BLANK_UNBLANK); +#ifdef CONFIG_PMAC_BACKLIGHT + aty128_set_backlight_enable(get_backlight_enable(), + get_backlight_level(), par); #endif } else { -#ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_set_power(info, FB_BLANK_POWERDOWN); +#ifdef CONFIG_PMAC_BACKLIGHT + aty128_set_backlight_enable(0, 0, par); #endif reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_DISPLAY_DIS; @@ -1633,7 +1638,7 @@ static int aty128fb_sync(struct fb_info *info) } #ifndef MODULE -static int __devinit aty128fb_setup(char *options) +static int __init aty128fb_setup(char *options) { char *this_opt; @@ -1686,211 +1691,6 @@ static int __devinit aty128fb_setup(char *options) } #endif /* MODULE */ -/* Backlight */ -#ifdef CONFIG_FB_ATY128_BACKLIGHT -#define MAX_LEVEL 0xFF - -static struct backlight_properties aty128_bl_data; - -/* Call with fb_info->bl_mutex held */ -static int aty128_bl_get_level_brightness(struct aty128fb_par *par, - int level) -{ - struct fb_info *info = pci_get_drvdata(par->pdev); - int atylevel; - - /* Get and convert the value */ - atylevel = MAX_LEVEL - - (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); - - if (atylevel < 0) - atylevel = 0; - else if (atylevel > MAX_LEVEL) - atylevel = MAX_LEVEL; - - return atylevel; -} - -/* We turn off the LCD completely instead of just dimming the backlight. - * This provides greater power saving and the display is useless without - * backlight anyway - */ -#define BACKLIGHT_LVDS_OFF -/* That one prevents proper CRT output with LCD off */ -#undef BACKLIGHT_DAC_OFF - -/* Call with fb_info->bl_mutex held */ -static int __aty128_bl_update_status(struct backlight_device *bd) -{ - struct aty128fb_par *par = class_get_devdata(&bd->class_dev); - unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); - int level; - - if (bd->props->power != FB_BLANK_UNBLANK || - bd->props->fb_blank != FB_BLANK_UNBLANK || - !par->lcd_on) - level = 0; - else - level = bd->props->brightness; - - reg |= LVDS_BL_MOD_EN | LVDS_BLON; - if (level > 0) { - reg |= LVDS_DIGION; - if (!(reg & LVDS_ON)) { - reg &= ~LVDS_BLON; - aty_st_le32(LVDS_GEN_CNTL, reg); - aty_ld_le32(LVDS_GEN_CNTL); - mdelay(10); - reg |= LVDS_BLON; - aty_st_le32(LVDS_GEN_CNTL, reg); - } - reg &= ~LVDS_BL_MOD_LEVEL_MASK; - reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT); -#ifdef BACKLIGHT_LVDS_OFF - reg |= LVDS_ON | LVDS_EN; - reg &= ~LVDS_DISPLAY_DIS; -#endif - aty_st_le32(LVDS_GEN_CNTL, reg); -#ifdef BACKLIGHT_DAC_OFF - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); -#endif - } else { - reg &= ~LVDS_BL_MOD_LEVEL_MASK; - reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT); -#ifdef BACKLIGHT_LVDS_OFF - reg |= LVDS_DISPLAY_DIS; - aty_st_le32(LVDS_GEN_CNTL, reg); - aty_ld_le32(LVDS_GEN_CNTL); - udelay(10); - reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); -#endif - aty_st_le32(LVDS_GEN_CNTL, reg); -#ifdef BACKLIGHT_DAC_OFF - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); -#endif - } - - return 0; -} - -static int aty128_bl_update_status(struct backlight_device *bd) -{ - struct aty128fb_par *par = class_get_devdata(&bd->class_dev); - struct fb_info *info = pci_get_drvdata(par->pdev); - int ret; - - mutex_lock(&info->bl_mutex); - ret = __aty128_bl_update_status(bd); - mutex_unlock(&info->bl_mutex); - - return ret; -} - -static int aty128_bl_get_brightness(struct backlight_device *bd) -{ - return bd->props->brightness; -} - -static struct backlight_properties aty128_bl_data = { - .owner = THIS_MODULE, - .get_brightness = aty128_bl_get_brightness, - .update_status = aty128_bl_update_status, - .max_brightness = (FB_BACKLIGHT_LEVELS - 1), -}; - -static void aty128_bl_set_power(struct fb_info *info, int power) -{ - mutex_lock(&info->bl_mutex); - - if (info->bl_dev) { - down(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty128_bl_update_status(info->bl_dev); - up(&info->bl_dev->sem); - } - - mutex_unlock(&info->bl_mutex); -} - -static void aty128_bl_init(struct aty128fb_par *par) -{ - struct fb_info *info = pci_get_drvdata(par->pdev); - struct backlight_device *bd; - char name[12]; - - /* Could be extended to Rage128Pro LVDS output too */ - if (par->chip_gen != rage_M3) - return; - -#ifdef CONFIG_PMAC_BACKLIGHT - if (!pmac_has_backlight_type("ati")) - return; -#endif - - snprintf(name, sizeof(name), "aty128bl%d", info->node); - - bd = backlight_device_register(name, par, &aty128_bl_data); - if (IS_ERR(bd)) { - info->bl_dev = NULL; - printk(KERN_WARNING "aty128: Backlight registration failed\n"); - goto error; - } - - mutex_lock(&info->bl_mutex); - info->bl_dev = bd; - fb_bl_default_curve(info, 0, - 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, - 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); - mutex_unlock(&info->bl_mutex); - - down(&bd->sem); - bd->props->brightness = aty128_bl_data.max_brightness; - bd->props->power = FB_BLANK_UNBLANK; - bd->props->update_status(bd); - up(&bd->sem); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); - if (!pmac_backlight) - pmac_backlight = bd; - mutex_unlock(&pmac_backlight_mutex); -#endif - - printk("aty128: Backlight initialized (%s)\n", name); - - return; - -error: - return; -} - -static void aty128_bl_exit(struct aty128fb_par *par) -{ - struct fb_info *info = pci_get_drvdata(par->pdev); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif - - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { -#ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == info->bl_dev) - pmac_backlight = NULL; -#endif - - backlight_device_unregister(info->bl_dev); - info->bl_dev = NULL; - - printk("aty128: Backlight unloaded\n"); - } - mutex_unlock(&info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif -} -#endif /* CONFIG_FB_ATY128_BACKLIGHT */ /* * Initialisation @@ -1908,7 +1708,7 @@ static void aty128_early_resume(void *data) } #endif /* CONFIG_PPC_PMAC */ -static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) { struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; @@ -1917,6 +1717,9 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u8 chip_rev; u32 dac; + if (!par->vram_size) /* may have already been probed */ + par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; @@ -2029,18 +1832,20 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_init_engine(par); + if (register_framebuffer(info) < 0) + return 0; + +#ifdef CONFIG_PMAC_BACKLIGHT + /* Could be extended to Rage128Pro LVDS output too */ + if (par->chip_gen == rage_M3) + register_backlight_controller(&aty128_backlight_controller, par, "ati"); +#endif /* CONFIG_PMAC_BACKLIGHT */ + par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; par->lock_blank = 0; - -#ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_init(par); -#endif - - if (register_framebuffer(info) < 0) - return 0; - + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); @@ -2049,7 +1854,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i #ifdef CONFIG_PCI /* register a card ++ajoshi */ -static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned long fb_addr, reg_addr; struct aty128fb_par *par; @@ -2090,6 +1895,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ par = info->par; info->pseudo_palette = par->pseudo_palette; + info->fix = aty128fb_fix; /* Virtualize mmio region */ info->fix.mmio_start = reg_addr; @@ -2175,10 +1981,6 @@ static void __devexit aty128_remove(struct pci_dev *pdev) par = info->par; -#ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_exit(par); -#endif - unregister_framebuffer(info); #ifdef CONFIG_MTRR if (par->mtrr.vram_valid) @@ -2209,10 +2011,10 @@ static int aty128fb_blank(int blank, struct fb_info *fb) if (par->lock_blank || par->asleep) return 0; -#ifdef CONFIG_FB_ATY128_BACKLIGHT +#ifdef CONFIG_PMAC_BACKLIGHT if (machine_is(powermac) && blank) - aty128_bl_set_power(fb, FB_BLANK_POWERDOWN); -#endif + set_backlight_enable(0); +#endif /* CONFIG_PMAC_BACKLIGHT */ if (blank & FB_BLANK_VSYNC_SUSPEND) state |= 2; @@ -2227,12 +2029,10 @@ static int aty128fb_blank(int blank, struct fb_info *fb) aty128_set_crt_enable(par, par->crt_on && !blank); aty128_set_lcd_enable(par, par->lcd_on && !blank); } - -#ifdef CONFIG_FB_ATY128_BACKLIGHT +#ifdef CONFIG_PMAC_BACKLIGHT if (machine_is(powermac) && !blank) - aty128_bl_set_power(fb, FB_BLANK_UNBLANK); -#endif - + set_backlight_enable(1); +#endif /* CONFIG_PMAC_BACKLIGHT */ return 0; } @@ -2338,6 +2138,73 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) return -EINVAL; } +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight_conv[] = { + 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, + 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 +}; + +/* We turn off the LCD completely instead of just dimming the backlight. + * This provides greater power saving and the display is useless without + * backlight anyway + */ +#define BACKLIGHT_LVDS_OFF +/* That one prevents proper CRT output with LCD off */ +#undef BACKLIGHT_DAC_OFF + +static int aty128_set_backlight_enable(int on, int level, void *data) +{ + struct aty128fb_par *par = data; + unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); + + if (!par->lcd_on) + on = 0; + reg |= LVDS_BL_MOD_EN | LVDS_BLON; + if (on && level > BACKLIGHT_OFF) { + reg |= LVDS_DIGION; + if (!(reg & LVDS_ON)) { + reg &= ~LVDS_BLON; + aty_st_le32(LVDS_GEN_CNTL, reg); + (void)aty_ld_le32(LVDS_GEN_CNTL); + mdelay(10); + reg |= LVDS_BLON; + aty_st_le32(LVDS_GEN_CNTL, reg); + } + reg &= ~LVDS_BL_MOD_LEVEL_MASK; + reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT); +#ifdef BACKLIGHT_LVDS_OFF + reg |= LVDS_ON | LVDS_EN; + reg &= ~LVDS_DISPLAY_DIS; +#endif + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef BACKLIGHT_DAC_OFF + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); +#endif + } else { + reg &= ~LVDS_BL_MOD_LEVEL_MASK; + reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT); +#ifdef BACKLIGHT_LVDS_OFF + reg |= LVDS_DISPLAY_DIS; + aty_st_le32(LVDS_GEN_CNTL, reg); + (void)aty_ld_le32(LVDS_GEN_CNTL); + udelay(10); + reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); +#endif + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef BACKLIGHT_DAC_OFF + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); +#endif + } + + return 0; +} + +static int aty128_set_backlight_level(int level, void* data) +{ + return aty128_set_backlight_enable(1, level, data); +} +#endif /* CONFIG_PMAC_BACKLIGHT */ + #if 0 /* * Accelerated functions @@ -2561,7 +2428,7 @@ static int aty128_pci_resume(struct pci_dev *pdev) } -static int __devinit aty128fb_init(void) +static int __init aty128fb_init(void) { #ifndef MODULE char *option = NULL;