diff options
Diffstat (limited to 'drivers/video')
114 files changed, 3648 insertions, 1717 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 702eb933cf8..4e83f01e894 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -53,6 +53,11 @@ config FB (e.g. an accelerated X server) and that are not frame buffer device-aware may cause unexpected results. If unsure, say N. +config FB_DDC + tristate + depends on FB && I2C && I2C_ALGOBIT + default n + config FB_CFB_FILLRECT tristate depends on FB @@ -183,7 +188,7 @@ config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC" help This is an implementation of the Sharp LQ035Q7DB02, a 3.5" - color QVGA, HRTFT panel. The LogicPD device includes an + color QVGA, HRTFT panel. The LogicPD device includes an integrated HRTFT controller IC. The native resolution is 240x320. @@ -398,7 +403,7 @@ config FB_ARC is based on the KS-108 lcd controller and is typically a matrix of 2*n chips. This driver was tested with a 128x64 panel. This driver supports it for use with x86 SBCs through a 16 bit GPIO - interface (8 bit data, 8 bit control). If you anticpate using + interface (8 bit data, 8 bit control). If you anticipate using this driver, say Y or M; otherwise say N. You must specify the GPIO IO address to be used for setting control and data. @@ -536,6 +541,7 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. @@ -546,6 +552,7 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VIDEO_SELECT help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -700,6 +707,7 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -734,10 +742,12 @@ config FB_RIVA depends on FB && PCI select I2C_ALGOBIT if FB_RIVA_I2C select I2C if FB_RIVA_I2C + select FB_DDC if FB_RIVA_I2C select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This driver supports graphics boards with the nVidia Riva/Geforce chips. @@ -764,7 +774,7 @@ config FB_RIVA_DEBUG default n help Say Y here if you want the Riva driver to output all sorts - of debugging informations to provide to the maintainer when + of debugging information to provide to the maintainer when something goes wrong. config FB_RIVA_BACKLIGHT @@ -822,33 +832,52 @@ config FB_I810_I2C depends on FB_I810 && FB_I810_GTF select I2C select I2C_ALGOBIT + select FB_DDC help config FB_INTEL - tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" + tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)" depends on FB && EXPERIMENTAL && PCI && X86 select AGP select AGP_INTEL + select I2C_ALGOBIT if FB_INTEL_I2C + select I2C if FB_INTEL_I2C select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT help This driver supports the on-board graphics built in to the Intel - 830M/845G/852GM/855GM/865G chipsets. + 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM chipsets. Say Y if you have and plan to use such a board. - To compile this driver as a module, choose M here: the + If you say Y here and want DDC/I2C support you must first say Y to + "I2C support" and "I2C bit-banging support" in the character devices + section. + + If you say M here then "I2C support" and "I2C bit-banging support" + can be build either as modules or built-in. + + To compile this driver as a module, choose M here: the module will be called intelfb. + For more information, please read <file:Documentation/fb/intelfb.txt> + config FB_INTEL_DEBUG - bool "Intel driver Debug Messages" + bool "Intel driver Debug Messages" depends on FB_INTEL ---help--- Say Y here if you want the Intel driver to output all sorts - of debugging informations to provide to the maintainer when + of debugging information to provide to the maintainer when something goes wrong. +config FB_INTEL_I2C + bool "DDC/I2C for Intel framebuffer support" + depends on FB_INTEL + default y + help + Say Y here if you want DDC/I2C support for your on-board Intel graphics. + config FB_MATROX tristate "Matrox acceleration" depends on FB && PCI @@ -994,6 +1023,7 @@ config FB_RADEON depends on FB && PCI select I2C_ALGOBIT if FB_RADEON_I2C select I2C if FB_RADEON_I2C + select FB_DDC if FB_RADEON_I2C select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -1035,7 +1065,7 @@ config FB_RADEON_DEBUG default n help Say Y here if you want the Radeon driver to output all sorts - of debugging informations to provide to the maintainer when + of debugging information to provide to the maintainer when something goes wrong. config FB_ATY128 @@ -1122,6 +1152,7 @@ config FB_SAVAGE depends on FB && PCI && EXPERIMENTAL select I2C_ALGOBIT if FB_SAVAGE_I2C select I2C if FB_SAVAGE_I2C + select FB_DDC if FB_SAVAGE_I2C select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -1584,6 +1615,16 @@ config FB_PNX4008_DUM_RGB ---help--- Say Y here to enable support for PNX4008 RGB Framebuffer +config FB_IBM_GXT4500 + tristate "Framebuffer support for IBM GXT4500P adaptor" + depends on PPC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Say Y here to enable support for the IBM GXT4500P display + adaptor, found on some IBM System P (pSeries) machines. + config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB @@ -1601,7 +1642,8 @@ config FB_VIRTUAL kernel option `video=vfb:'. To compile this driver as a module, choose M here: the - module will be called vfb. + module will be called vfb. In order to load it, you must use + the vfb_enable=1 option. If unsure, say N. if VT diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 481c6c9695f..309a26dd164 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o obj-$(CONFIG_FB_MACMODES) += macmodes.o +obj-$(CONFIG_FB_DDC) += fb_ddc.o # Hardware specific drivers go first obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o @@ -98,6 +99,7 @@ obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ +obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index 397005eb392..b3717c8f1bc 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -535,8 +535,11 @@ static void __init s3triofb_of_init(struct device_node *dp) #endif fb_info.flags = FBINFO_FLAG_DEFAULT; - if (register_framebuffer(&fb_info) < 0) - return; + if (register_framebuffer(&fb_info) < 0) { + iounmap(fb_info.screen_base); + fb_info.screen_base = NULL; + return; + } printk("fb%d: S3 Trio frame buffer device on %s\n", fb_info.node, dp->full_name); diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index f1ba54f4fc3..88a47845c4f 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1144,7 +1144,7 @@ static void amifb_deinit(void); */ static int flash_cursor(void); -static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp); +static irqreturn_t amifb_interrupt(int irq, void *dev_id); static u_long chipalloc(u_long size); static void chipfree(void); @@ -2407,10 +2407,10 @@ default_chipset: fb_info.fix.smem_len); if (!videomemory) { printk("amifb: WARNING! unable to map videomem cached writethrough\n"); - videomemory = ZTWO_VADDR(fb_info.fix.smem_start); - } + fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); + } else + fb_info.screen_base = (char *)videomemory; - fb_info.screen_base = (char *)videomemory; memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); /* @@ -2453,6 +2453,8 @@ static void amifb_deinit(void) { fb_dealloc_cmap(&fb_info.cmap); chipfree(); + if (videomemory) + iounmap((void*)videomemory); release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } @@ -2492,7 +2494,7 @@ static int flash_cursor(void) * VBlank Display Interrupt */ -static irqreturn_t amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t amifb_interrupt(int irq, void *dev_id) { if (do_vmode_pan || do_vmode_full) ami_update_display(); diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 70dd8115a4d..30a8369757e 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -218,8 +218,7 @@ static int arcfb_pan_display(struct fb_var_screeninfo *var, return -EINVAL; } -static irqreturn_t arcfb_interrupt(int vec, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t arcfb_interrupt(int vec, void *dev_instance) { struct fb_info *info = dev_instance; unsigned char ctl2status; @@ -455,7 +454,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou unsigned int xres; p = *ppos; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; fbidx = iminor(inode); info = registered_fb[fbidx]; diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 5831893bf7a..602db660bc7 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -1521,7 +1521,7 @@ static void falcon_set_par( struct atafb_par *par ) } -static irqreturn_t falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp ) +static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) { struct falcon_hw *hw = &f_new_mode; @@ -2804,8 +2804,19 @@ int __init atafb_init(void) atafb_set_disp(-1, &fb_info); do_install_cmap(0, &fb_info); - if (register_framebuffer(&fb_info) < 0) + if (register_framebuffer(&fb_info) < 0) { +#ifdef ATAFB_EXT + if (external_addr) { + iounmap(external_addr); + external_addr = NULL; + } + if (external_vgaiobase) { + iounmap((void*)external_vgaiobase); + external_vgaiobase = 0; + } +#endif return -EINVAL; + } printk("Determined %dx%d, depth %d\n", disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 276a21530b9..3feddf89d10 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1333,6 +1333,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, if (vclk * 12 < c.ppll_min) vclk = c.ppll_min/12; + pll->post_divider = -1; + /* now, find an acceptable divider */ for (i = 0; i < sizeof(post_dividers); i++) { output_freq = post_dividers[i] * vclk; @@ -1342,6 +1344,9 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, } } + if (pll->post_divider < 0) + return -EINVAL; + /* calculate feedback divider */ n = c.ref_divider * output_freq; d = c.ref_clk; diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 55fb8b04489..f72faff33c0 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -126,7 +126,6 @@ union aty_pll { */ struct atyfb_par { - struct aty_cmap_regs __iomem *aty_cmap_regs; struct { u8 red, green, blue; } palette[256]; const struct aty_dac_ops *dac_ops; const struct aty_pll_ops *pll_ops; @@ -186,6 +185,7 @@ struct atyfb_par { int mtrr_aper; int mtrr_reg; #endif + u32 mem_cntl; }; /* @@ -227,7 +227,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par) regindex -= 0x800; #ifdef CONFIG_ATARI - return in_le32((volatile u32 *)(par->ati_regbase + regindex)); + return in_le32(par->ati_regbase + regindex); #else return readl(par->ati_regbase + regindex); #endif @@ -240,7 +240,7 @@ static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *pa regindex -= 0x800; #ifdef CONFIG_ATARI - out_le32((volatile u32 *)(par->ati_regbase + regindex), val); + out_le32(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -253,7 +253,7 @@ static inline void aty_st_le16(int regindex, u16 val, if (regindex >= 0x400) regindex -= 0x800; #ifdef CONFIG_ATARI - out_le16((volatile u16 *)(par->ati_regbase + regindex), val); + out_le16(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -315,6 +315,7 @@ struct aty_pll_ops { void (*set_pll) (const struct fb_info * info, const union aty_pll * pll); void (*get_pll) (const struct fb_info *info, union aty_pll * pll); int (*init_pll) (const struct fb_info * info, union aty_pll * pll); + void (*resume_pll)(const struct fb_info *info, union aty_pll *pll); }; extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ @@ -355,5 +356,9 @@ static inline void wait_for_idle(struct atyfb_par *par) extern void aty_reset_engine(const struct atyfb_par *par); extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info); -extern void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par); extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par); + +void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); +void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); + diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 19a71f04578..176f9b85cdb 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -203,14 +203,6 @@ static void ATIReduceRatio(int *Numerator, int *Denominator) * The Hardware parameters for each card */ -struct aty_cmap_regs { - u8 windex; - u8 lut; - u8 mask; - u8 rindex; - u8 cntl; -}; - struct pci_mmap_map { unsigned long voff; unsigned long poff; @@ -240,9 +232,6 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); -extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); -extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); #ifdef __sparc__ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); #endif @@ -252,7 +241,8 @@ static int atyfb_sync(struct fb_info *info); * Internal routines */ -static int aty_init(struct fb_info *info, const char *name); +static int aty_init(struct fb_info *info); +static void aty_resume_chip(struct fb_info *info); #ifdef CONFIG_ATARI static int store_video_par(char *videopar, unsigned char m64_num); #endif @@ -409,7 +399,7 @@ static struct { { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 }, - { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, + { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 }, { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL }, @@ -1535,7 +1525,7 @@ static int atyfb_open(struct fb_info *info, int user) return (0); } -static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t aty_irq(int irq, void *dev_id) { struct atyfb_par *par = dev_id; int handled = 0; @@ -1940,17 +1930,14 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter) aty_st_8(DAC_CNTL, tmp, par); aty_st_8(DAC_MASK, 0xff, par); - writeb(i, &par->aty_cmap_regs->rindex); - atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut); - atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut); - atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut); - writeb(i, &par->aty_cmap_regs->windex); - writeb(atyfb_save.r[1 - enter][i], - &par->aty_cmap_regs->lut); - writeb(atyfb_save.g[1 - enter][i], - &par->aty_cmap_regs->lut); - writeb(atyfb_save.b[1 - enter][i], - &par->aty_cmap_regs->lut); + aty_st_8(DAC_R_INDEX, i, par); + atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par); + atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par); + atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par); + aty_st_8(DAC_W_INDEX, i, par); + aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par); + aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par); + aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par); } } @@ -1985,6 +1972,7 @@ static void atyfb_palette(int enter) #if defined(CONFIG_PM) && defined(CONFIG_PCI) +#ifdef CONFIG_PPC_PMAC /* Power management routines. Those are used for PowerBook sleep. */ static int aty_power_mgmt(int sleep, struct atyfb_par *par) @@ -2041,21 +2029,13 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) return timeout ? 0 : -EIO; } +#endif static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; -#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 - */ - return 0; -#endif /* CONFIG_PPC_PMAC */ - if (state.event == pdev->dev.power.power_state.event) return 0; @@ -2073,6 +2053,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; +#ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ if (aty_power_mgmt(1, par)) { par->asleep = 0; @@ -2082,6 +2063,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) release_console_sem(); return -EIO; } +#else + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +#endif release_console_sem(); @@ -2100,8 +2084,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); +#ifdef CONFIG_PPC_PMAC if (pdev->dev.power.power_state.event == 2) aty_power_mgmt(0, par); +#else + pci_set_power_state(pdev, PCI_D0); +#endif + + aty_resume_chip(info); + par->asleep = 0; /* Restore display */ @@ -2347,24 +2338,16 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par, } #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */ -static int __devinit aty_init(struct fb_info *info, const char *name) +static int __devinit aty_init(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; const char *ramname = NULL, *xtal; int gtb_memsize, has_var = 0; struct fb_var_screeninfo var; - u8 pll_ref_div; - u32 i; -#if defined(CONFIG_PPC) - int sense; -#endif init_waitqueue_head(&par->vblank.wait); spin_lock_init(&par->int_lock); - par->aty_cmap_regs = - (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0); - #ifdef CONFIG_PPC_PMAC /* The Apple iBook1 uses non-standard memory frequencies. We detect it * and set the frequency manually. */ @@ -2467,18 +2450,21 @@ static int __devinit aty_init(struct fb_info *info, const char *name) par->pll_limits.mclk = 63; } - if (M64_HAS(GTB_DSP) - && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) { - int diff1, diff2; - diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max; - diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max; - if (diff1 < 0) - diff1 = -diff1; - if (diff2 < 0) - diff2 = -diff2; - if (diff2 < diff1) { - par->ref_clk_per = 1000000000000ULL / 29498928; - xtal = "29.498928"; + if (M64_HAS(GTB_DSP)) { + u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par); + + if (pll_ref_div) { + int diff1, diff2; + diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max; + diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max; + if (diff1 < 0) + diff1 = -diff1; + if (diff2 < 0) + diff2 = -diff2; + if (diff2 < diff1) { + par->ref_clk_per = 1000000000000ULL / 29498928; + xtal = "29.498928"; + } } } #endif /* CONFIG_FB_ATY_CT */ @@ -2488,10 +2474,10 @@ static int __devinit aty_init(struct fb_info *info, const char *name) if(par->pll_ops->get_pll) par->pll_ops->get_pll(info, &saved_pll); - i = aty_ld_le32(MEM_CNTL, par); + par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); if (gtb_memsize) - switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2513,7 +2499,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) default: info->fix.smem_len = 0x80000; } else - switch (i & MEM_SIZE_ALIAS) { + switch (par->mem_cntl & MEM_SIZE_ALIAS) { case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2543,20 +2529,20 @@ static int __devinit aty_init(struct fb_info *info, const char *name) if (vram) { info->fix.smem_len = vram * 1024; - i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); + par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); if (info->fix.smem_len <= 0x80000) - i |= MEM_SIZE_512K; + par->mem_cntl |= MEM_SIZE_512K; else if (info->fix.smem_len <= 0x100000) - i |= MEM_SIZE_1M; + par->mem_cntl |= MEM_SIZE_1M; else if (info->fix.smem_len <= 0x200000) - i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; else if (info->fix.smem_len <= 0x400000) - i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; else if (info->fix.smem_len <= 0x600000) - i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; else - i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; - aty_st_le32(MEM_CNTL, i, par); + par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; + aty_st_le32(MEM_CNTL, par->mem_cntl, par); } /* @@ -2602,11 +2588,12 @@ static int __devinit aty_init(struct fb_info *info, const char *name) #endif if(par->pll_ops->init_pll) par->pll_ops->init_pll(info, &par->pll); + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); /* - * Last page of 8 MB (4 MB on ISA) aperture is MMIO - * FIXME: we should use the auxiliary aperture instead so we can access - * the full 8 MB of video RAM on 8 MB boards + * Last page of 8 MB (4 MB on ISA) aperture is MMIO, + * unless the auxiliary register aperture is used. */ if (!par->aux_start && @@ -2672,6 +2659,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) has_var = 1; } else { if (default_vmode == VMODE_CHOOSE) { + int sense; if (M64_HAS(G3_PB_1024x768)) /* G3 PowerBook with 1024x768 LCD */ default_vmode = VMODE_1024_768_60; @@ -2752,7 +2740,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) fb_list = info; PRINTKI("fb%d: %s frame buffer device on %s\n", - info->node, info->fix.id, name); + info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI"); return 0; aty_init_exit: @@ -2773,6 +2761,19 @@ aty_init_exit: return -1; } +static void aty_resume_chip(struct fb_info *info) +{ + struct atyfb_par *par = info->par; + + aty_st_le32(MEM_CNTL, par->mem_cntl, par); + + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); + + if (par->aux_start) + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); +} + #ifdef CONFIG_ATARI static int __devinit store_video_par(char *video_str, unsigned char m64_num) { @@ -2829,9 +2830,9 @@ static int atyfb_blank(int blank, struct fb_info *info) #endif gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); + gen_cntl &= ~0x400004c; switch (blank) { - case FB_BLANK_UNBLANK: - gen_cntl &= ~0x400004c; + case FB_BLANK_UNBLANK: break; case FB_BLANK_NORMAL: gen_cntl |= 0x4000040; @@ -2866,17 +2867,10 @@ static int atyfb_blank(int blank, struct fb_info *info) static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue, const struct atyfb_par *par) { -#ifdef CONFIG_ATARI - out_8(&par->aty_cmap_regs->windex, regno); - out_8(&par->aty_cmap_regs->lut, red); - out_8(&par->aty_cmap_regs->lut, green); - out_8(&par->aty_cmap_regs->lut, blue); -#else - writeb(regno, &par->aty_cmap_regs->windex); - writeb(red, &par->aty_cmap_regs->lut); - writeb(green, &par->aty_cmap_regs->lut); - writeb(blue, &par->aty_cmap_regs->lut); -#endif + aty_st_8(DAC_W_INDEX, regno, par); + aty_st_8(DAC_DATA, red, par); + aty_st_8(DAC_DATA, green, par); + aty_st_8(DAC_DATA, blue, par); } /* @@ -3185,7 +3179,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, #ifdef __i386__ #ifdef CONFIG_FB_ATY_GENERIC_LCD -static void aty_init_lcd(struct atyfb_par *par, u32 bios_base) +static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) { u32 driv_inf_tab, sig; u16 lcd_ofs; @@ -3530,6 +3524,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i atyfb_setup_generic_fail: iounmap(par->ati_regbase); par->ati_regbase = NULL; + if (info->screen_base) { + iounmap(info->screen_base); + info->screen_base = NULL; + } return ret; } @@ -3597,7 +3595,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi pci_set_drvdata(pdev, info); /* Init chip & register framebuffer */ - if (aty_init(info, "PCI")) + if (aty_init(info)) goto err_release_io; #ifdef __sparc__ @@ -3644,12 +3642,13 @@ err_release_mem: #ifdef CONFIG_ATARI -static int __devinit atyfb_atari_probe(void) +static int __init atyfb_atari_probe(void) { struct atyfb_par *par; struct fb_info *info; int m64_num; u32 clock_r; + int num_found = 0; for (m64_num = 0; m64_num < mach64_count; m64_num++) { if (!phys_vmembase[m64_num] || !phys_size[m64_num] || @@ -3697,16 +3696,34 @@ static int __devinit atyfb_atari_probe(void) break; } - if (aty_init(info, "ISA bus")) { + /* Fake pci_id for correct_chipset() */ + switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) { + case 0x00d7: + par->pci_id = PCI_CHIP_MACH64GX; + break; + case 0x0057: + par->pci_id = PCI_CHIP_MACH64CX; + break; + default: + break; + } + + if (correct_chipset(par) || aty_init(info)) { + iounmap(info->screen_base); + iounmap(par->ati_regbase); framebuffer_release(info); - /* This is insufficient! kernel_map has added two large chunks!! */ - return -ENXIO; + } else { + num_found++; } } + + return num_found ? 0 : -ENXIO; } #endif /* CONFIG_ATARI */ +#ifdef CONFIG_PCI + static void __devexit atyfb_remove(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -3754,7 +3771,6 @@ static void __devexit atyfb_remove(struct fb_info *info) framebuffer_release(info); } -#ifdef CONFIG_PCI static void __devexit atyfb_pci_remove(struct pci_dev *pdev) { @@ -3789,7 +3805,7 @@ static struct pci_driver atyfb_driver = { #endif /* CONFIG_PCI */ #ifndef MODULE -static int __devinit atyfb_setup(char *options) +static int __init atyfb_setup(char *options) { char *this_opt; @@ -3861,8 +3877,9 @@ static int __devinit atyfb_setup(char *options) } #endif /* MODULE */ -static int __devinit atyfb_init(void) +static int __init atyfb_init(void) { + int err1 = 1, err2 = 1; #ifndef MODULE char *option = NULL; @@ -3872,12 +3889,13 @@ static int __devinit atyfb_init(void) #endif #ifdef CONFIG_PCI - pci_register_driver(&atyfb_driver); + err1 = pci_register_driver(&atyfb_driver); #endif #ifdef CONFIG_ATARI - atyfb_atari_probe(); + err2 = atyfb_atari_probe(); #endif - return 0; + + return (err1 && err2) ? -ENODEV : 0; } static void __exit atyfb_exit(void) diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index e7056934c6a..f3b487b8710 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -27,7 +27,7 @@ u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par) return res; } -void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par) +static void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par) { /* write addr byte */ aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) | PLL_WR_EN, par); @@ -370,8 +370,8 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll) #endif } -static void __init aty_get_pll_ct(const struct fb_info *info, - union aty_pll *pll) +static void __devinit aty_get_pll_ct(const struct fb_info *info, + union aty_pll *pll) { struct atyfb_par *par = (struct atyfb_par *) info->par; u8 tmp, clock; @@ -394,12 +394,12 @@ static void __init aty_get_pll_ct(const struct fb_info *info, } } -static int __init aty_init_pll_ct(const struct fb_info *info, - union aty_pll *pll) +static int __devinit aty_init_pll_ct(const struct fb_info *info, + union aty_pll *pll) { struct atyfb_par *par = (struct atyfb_par *) info->par; - u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2; - u32 q, i, memcntl, trp; + u8 mpost_div, xpost_div, sclk_post_div_real; + u32 q, memcntl, trp; u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; #ifdef DEBUG int pllmclk, pllsclk; @@ -575,14 +575,30 @@ static int __init aty_init_pll_ct(const struct fb_info *info, mpost_div += (q < 32*8); } sclk_post_div_real = postdividers[mpost_div]; - sclk_fb_div = q * sclk_post_div_real / 8; - spll_cntl2 = mpost_div << 4; + pll->ct.sclk_fb_div = q * sclk_post_div_real / 8; + pll->ct.spll_cntl2 = mpost_div << 4; #ifdef DEBUG - pllsclk = (1000000 * 2 * sclk_fb_div) / + pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) / (par->ref_clk_per * pll->ct.pll_ref_div); printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n", __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real); #endif + } + + /* Disable the extra precision pixel clock controls since we do not use them. */ + pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par); + pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC); + + return 0; +} + +static void aty_resume_pll_ct(const struct fb_info *info, + union aty_pll *pll) +{ + struct atyfb_par *par = info->par; + + if (par->mclk_per != par->xclk_per) { + int i; /* * This disables the sclk, crashes the computer as reported: * aty_st_pll_ct(SPLL_CNTL2, 3, info); @@ -590,8 +606,8 @@ static int __init aty_init_pll_ct(const struct fb_info *info, * So it seems the sclk must be enabled before it is used; * so PLL_GEN_CNTL must be programmed *after* the sclk. */ - aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par); - aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par); + aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par); + aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par); /* * The sclk has been started. However, I believe the first clock * ticks it generates are not very stable. Hope this primitive loop @@ -605,11 +621,7 @@ static int __init aty_init_pll_ct(const struct fb_info *info, aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par); aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par); aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par); - /* Disable the extra precision pixel clock controls since we do not use them. */ - aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) & - ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par); - - return 0; + aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par); } static int dummy(void) @@ -626,5 +638,6 @@ const struct aty_pll_ops aty_pll_ct = { .pll_to_var = aty_pll_to_var_ct, .set_pll = aty_set_pll_ct, .get_pll = aty_get_pll_ct, - .init_pll = aty_init_pll_ct + .init_pll = aty_init_pll_ct, + .resume_pll = aty_resume_pll_ct, }; diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 9aaca58c074..e7c5b219ad1 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c @@ -16,8 +16,6 @@ #include "radeonfb.h" #include "../edid.h" -#define RADEON_DDC 0x50 - static void radeon_gpio_setscl(void* data, int state) { struct radeon_i2c_chan *chan = data; @@ -122,124 +120,32 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo) void radeon_delete_i2c_busses(struct radeonfb_info *rinfo) { if (rinfo->i2c[0].rinfo) - i2c_bit_del_bus(&rinfo->i2c[0].adapter); + i2c_del_adapter(&rinfo->i2c[0].adapter); rinfo->i2c[0].rinfo = NULL; if (rinfo->i2c[1].rinfo) - i2c_bit_del_bus(&rinfo->i2c[1].adapter); + i2c_del_adapter(&rinfo->i2c[1].adapter); rinfo->i2c[1].rinfo = NULL; if (rinfo->i2c[2].rinfo) - i2c_bit_del_bus(&rinfo->i2c[2].adapter); + i2c_del_adapter(&rinfo->i2c[2].adapter); rinfo->i2c[2].rinfo = NULL; if (rinfo->i2c[3].rinfo) - i2c_bit_del_bus(&rinfo->i2c[3].adapter); + i2c_del_adapter(&rinfo->i2c[3].adapter); rinfo->i2c[3].rinfo = NULL; } - -static u8 *radeon_do_probe_i2c_edid(struct radeon_i2c_chan *chan) -{ - u8 start = 0x0; - struct i2c_msg msgs[] = { - { - .addr = RADEON_DDC, - .len = 1, - .buf = &start, - }, { - .addr = RADEON_DDC, - .flags = I2C_M_RD, - .len = EDID_LENGTH, - }, - }; - u8 *buf; - - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (!buf) { - dev_warn(&chan->rinfo->pdev->dev, "Out of memory!\n"); - return NULL; - } - msgs[1].buf = buf; - - if (i2c_transfer(&chan->adapter, msgs, 2) == 2) - return buf; - dev_dbg(&chan->rinfo->pdev->dev, "Unable to read EDID block.\n"); - kfree(buf); - return NULL; -} - - -int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid) +int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, + u8 **out_edid) { u32 reg = rinfo->i2c[conn-1].ddc_reg; - u8 *edid = NULL; - int i, j; + u8 *edid; - OUTREG(reg, INREG(reg) & + OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT)); - OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN)); - (void)INREG(reg); - - for (i = 0; i < 3; i++) { - /* For some old monitors we need the - * following process to initialize/stop DDC - */ - OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUT_EN)); - (void)INREG(reg); - msleep(13); - - OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN)); - (void)INREG(reg); - for (j = 0; j < 5; j++) { - msleep(10); - if (INREG(reg) & VGA_DDC_CLK_INPUT) - break; - } - if (j == 5) - continue; - - OUTREG(reg, INREG(reg) | VGA_DDC_DATA_OUT_EN); - (void)INREG(reg); - msleep(15); - OUTREG(reg, INREG(reg) | VGA_DDC_CLK_OUT_EN); - (void)INREG(reg); - msleep(15); - OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUT_EN)); - (void)INREG(reg); - msleep(15); - - /* Do the real work */ - edid = radeon_do_probe_i2c_edid(&rinfo->i2c[conn-1]); - - OUTREG(reg, INREG(reg) | - (VGA_DDC_DATA_OUT_EN | VGA_DDC_CLK_OUT_EN)); - (void)INREG(reg); - msleep(15); - - OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN)); - (void)INREG(reg); - for (j = 0; j < 10; j++) { - msleep(10); - if (INREG(reg) & VGA_DDC_CLK_INPUT) - break; - } - - OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUT_EN)); - (void)INREG(reg); - msleep(15); - OUTREG(reg, INREG(reg) | - (VGA_DDC_DATA_OUT_EN | VGA_DDC_CLK_OUT_EN)); - (void)INREG(reg); - if (edid) - break; - } - /* Release the DDC lines when done or the Apple Cinema HD display - * will switch off - */ - OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN | VGA_DDC_DATA_OUT_EN)); - (void)INREG(reg); + edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter); if (out_edid) *out_edid = edid; diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c index ea531a6f45d..38c7dbf8c15 100644 --- a/drivers/video/aty/radeon_monitor.c +++ b/drivers/video/aty/radeon_monitor.c @@ -104,10 +104,9 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ if (pedid == NULL) return mt; - tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL); + tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); if (!tmp) return mt; - memcpy(tmp, pedid, EDID_LENGTH); *out_EDID = tmp; return mt; } diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 365de5dcc88..9a2b0d69b0a 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -86,6 +86,9 @@ static struct radeon_device_id radeon_workaround_list[] = { BUGFIX("Samsung P35", PCI_VENDOR_ID_SAMSUNG, 0xc00c, radeon_pm_off, radeon_reinitialize_M10), + BUGFIX("Acer Aspire 2010", + PCI_VENDOR_ID_AI, 0x0061, + radeon_pm_off, radeon_reinitialize_M10), { .ident = NULL } }; diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index f25d5d64833..ef5c16f7f5a 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -8,6 +8,7 @@ * <c.pellegrin@exadron.com> * * PM support added by Rodolfo Giometti <giometti@linux.it> + * Cursor enable/disable by Rodolfo Giometti <giometti@linux.it> * * Copyright 2002 MontaVista Software * Author: MontaVista Software, Inc. @@ -110,6 +111,10 @@ static struct fb_var_screeninfo au1100fb_var __initdata = { static struct au1100fb_drv_info drv_info; +static int nocursor = 0; +module_param(nocursor, int, 0644); +MODULE_PARM_DESC(nocursor, "cursor enable/disable"); + /* * Set hardware with var settings. This will enable the controller with a specific * mode, normally validated with the fb_check_var method @@ -422,6 +427,17 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) return 0; } +/* fb_cursor + * Used to disable cursor drawing... + */ +int au1100fb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + if (nocursor) + return 0; + else + return -EINVAL; /* just to force soft_cursor() call */ +} + static struct fb_ops au1100fb_ops = { .owner = THIS_MODULE, @@ -433,6 +449,7 @@ static struct fb_ops au1100fb_ops = .fb_imageblit = cfb_imageblit, .fb_rotate = au1100fb_fb_rotate, .fb_mmap = au1100fb_fb_mmap, + .fb_cursor = au1100fb_fb_cursor, }; @@ -677,7 +694,7 @@ int au1100fb_setup(char *options) if (options) { while ((this_opt = strsep(&options,",")) != NULL) { /* Panel option */ - if (!strncmp(this_opt, "panel:", 6)) { + if (!strncmp(this_opt, "panel:", 6)) { int i; this_opt += 6; for (i = 0; i < num_panels; i++) { @@ -685,13 +702,18 @@ int au1100fb_setup(char *options) known_lcd_panels[i].name, strlen(this_opt))) { panel_idx = i; - break; + break; + } } - } if (i >= num_panels) { print_warn("Panel %s not supported!", this_opt); } } + if (!strncmp(this_opt, "nocursor", 8)) { + this_opt += 8; + nocursor = 1; + print_info("Cursor disabled"); + } /* Mode option (only option that start with digit) */ else if (isdigit(this_opt[0])) { mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); @@ -700,7 +722,7 @@ int au1100fb_setup(char *options) /* Unsupported option */ else { print_warn("Unsupported option \"%s\"", this_opt); - } + } } } diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 2855534dc23..164fe2f231e 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h @@ -274,7 +274,7 @@ static struct au1100fb_panel known_lcd_panels[] = .bpp = 16, .control_base = 0x0004886A | LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF | - LCD_CONTROL_BPP_16, + LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4, .clkcontrol_base = 0x00020000, .horztiming = 0x005aff1f, .verttiming = 0x16000e57, diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index c6a5f0ccc10..dbf4ec3f6d5 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1545,7 +1545,7 @@ static struct fb_ops au1200fb_fb_ops = { /*-------------------------------------------------------------------------*/ -static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) +static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) { /* Nothing to do for now, just clear any pending interrupt */ lcd->intstatus = lcd->intstatus; diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 27597c576ef..db8c191b120 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -14,6 +14,59 @@ #include <linux/err.h> #include <linux/fb.h> + +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is, we're switching backlight power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct backlight_device *bd; + struct fb_event *evdata = data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + bd = container_of(self, struct backlight_device, fb_notif); + down(&bd->sem); + if (bd->props) + if (!bd->props->check_fb || + bd->props->check_fb(evdata->info)) { + bd->props->fb_blank = *(int *)evdata->data; + if (likely(bd->props && bd->props->update_status)) + bd->props->update_status(bd); + } + up(&bd->sem); + return 0; +} + +static int backlight_register_fb(struct backlight_device *bd) +{ + memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); + bd->fb_notif.notifier_call = fb_notifier_callback; + + return fb_register_client(&bd->fb_notif); +} + +static void backlight_unregister_fb(struct backlight_device *bd) +{ + fb_unregister_client(&bd->fb_notif); +} +#else +static inline int backlight_register_fb(struct backlight_device *bd) +{ + return 0; +} + +static inline void backlight_unregister_fb(struct backlight_device *bd) +{ +} +#endif /* CONFIG_FB */ + static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { int rc = -ENXIO; @@ -142,7 +195,7 @@ static struct class backlight_class = { .store = _store, \ } -static struct class_device_attribute bl_class_device_attributes[] = { +static const struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), @@ -151,33 +204,6 @@ static struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), }; -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching backlight power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct backlight_device *bd; - struct fb_event *evdata =(struct fb_event *)data; - - /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK) - return 0; - - bd = container_of(self, struct backlight_device, fb_notif); - down(&bd->sem); - if (bd->props) - if (!bd->props->check_fb || - bd->props->check_fb(evdata->info)) { - bd->props->fb_blank = *(int *)evdata->data; - if (likely(bd->props && bd->props->update_status)) - bd->props->update_status(bd); - } - up(&bd->sem); - return 0; -} - /** * backlight_device_register - create and register a new object of * backlight_device class. @@ -215,10 +241,7 @@ error: kfree(new_bd); return ERR_PTR(rc); } - memset(&new_bd->fb_notif, 0, sizeof(new_bd->fb_notif)); - new_bd->fb_notif.notifier_call = fb_notifier_callback; - - rc = fb_register_client(&new_bd->fb_notif); + rc = backlight_register_fb(new_bd); if (unlikely(rc)) goto error; @@ -259,16 +282,10 @@ void backlight_device_unregister(struct backlight_device *bd) &bl_class_device_attributes[i]); down(&bd->sem); - if (likely(bd->props && bd->props->update_status)) { - bd->props->brightness = 0; - bd->props->power = 0; - bd->props->update_status(bd); - } - bd->props = NULL; up(&bd->sem); - fb_unregister_client(&bd->fb_notif); + backlight_unregister_fb(bd); class_device_unregister(&bd->class_dev); } diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 2ebbfd95145..61587ca2cdb 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -111,7 +111,7 @@ static struct backlight_properties corgibl_data = { .update_status = corgibl_set_intensity, }; -static int __init corgibl_probe(struct platform_device *pdev) +static int corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; @@ -135,6 +135,10 @@ static int __init corgibl_probe(struct platform_device *pdev) static int corgibl_remove(struct platform_device *dev) { + corgibl_data.power = 0; + corgibl_data.brightness = 0; + corgibl_send_intensity(corgi_backlight_device); + backlight_device_unregister(corgi_backlight_device); printk("Corgi Backlight Driver Unloaded\n"); @@ -166,4 +170,4 @@ module_exit(corgibl_exit); MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); MODULE_DESCRIPTION("Corgi Backlight Driver"); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index ffc72ae3ada..1c569fb543a 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -19,8 +19,8 @@ #include <linux/backlight.h> #include <asm/cpu/dac.h> -#include <asm/hp6xx/hp6xx.h> -#include <asm/hd64461/hd64461.h> +#include <asm/hp6xx.h> +#include <asm/hd64461.h> #define HP680_MAX_INTENSITY 255 #define HP680_DEFAULT_INTENSITY 10 @@ -117,6 +117,10 @@ static int __init hp680bl_probe(struct platform_device *dev) static int hp680bl_remove(struct platform_device *dev) { + hp680bl_data.brightness = 0; + hp680bl_data.power = 0; + hp680bl_send_intensity(hp680_backlight_device); + backlight_device_unregister(hp680_backlight_device); return 0; @@ -163,6 +167,6 @@ static void __exit hp680bl_exit(void) module_init(hp680bl_init); module_exit(hp680bl_exit); -MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>"); +MODULE_AUTHOR("Andriy Skulysh <askulysh@gmail.com>"); MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index bc8ab005a3f..f6e041627ed 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -14,6 +14,53 @@ #include <linux/err.h> #include <linux/fb.h> +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is, we're switching lcd power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct lcd_device *ld; + struct fb_event *evdata = data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + ld = container_of(self, struct lcd_device, fb_notif); + down(&ld->sem); + if (ld->props) + if (!ld->props->check_fb || ld->props->check_fb(evdata->info)) + ld->props->set_power(ld, *(int *)evdata->data); + up(&ld->sem); + return 0; +} + +static int lcd_register_fb(struct lcd_device *ld) +{ + memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif)); + ld->fb_notif.notifier_call = fb_notifier_callback; + return fb_register_client(&ld->fb_notif); +} + +static void lcd_unregister_fb(struct lcd_device *ld) +{ + fb_unregister_client(&ld->fb_notif); +} +#else +static int lcd_register_fb(struct lcd_device *ld) +{ + return 0; +} + +static inline void lcd_unregister_fb(struct lcd_device *ld) +{ +} +#endif /* CONFIG_FB */ + static ssize_t lcd_show_power(struct class_device *cdev, char *buf) { int rc; @@ -121,35 +168,12 @@ static struct class lcd_class = { .store = _store, \ } -static struct class_device_attribute lcd_class_device_attributes[] = { +static const struct class_device_attribute lcd_class_device_attributes[] = { DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power), DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), }; -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching lcd power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct lcd_device *ld; - struct fb_event *evdata =(struct fb_event *)data; - - /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK) - return 0; - - ld = container_of(self, struct lcd_device, fb_notif); - down(&ld->sem); - if (ld->props) - if (!ld->props->check_fb || ld->props->check_fb(evdata->info)) - ld->props->set_power(ld, *(int *)evdata->data); - up(&ld->sem); - return 0; -} - /** * lcd_device_register - register a new object of lcd_device class. * @name: the name of the new object(must be the same as the name of the @@ -186,10 +210,8 @@ error: kfree(new_ld); return ERR_PTR(rc); } - memset(&new_ld->fb_notif, 0, sizeof(new_ld->fb_notif)); - new_ld->fb_notif.notifier_call = fb_notifier_callback; + rc = lcd_register_fb(new_ld); - rc = fb_register_client(&new_ld->fb_notif); if (unlikely(rc)) goto error; @@ -232,9 +254,7 @@ void lcd_device_unregister(struct lcd_device *ld) down(&ld->sem); ld->props = NULL; up(&ld->sem); - - fb_unregister_client(&ld->fb_notif); - + lcd_unregister_fb(ld); class_device_unregister(&ld->class_dev); } EXPORT_SYMBOL(lcd_device_unregister); diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index caf1eca199b..2d7905410b2 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -33,19 +33,19 @@ static unsigned long locomolcd_flags; static void locomolcd_on(int comadj) { - locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1); + locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 1); mdelay(2); - locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1); + locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 1); mdelay(2); locomo_m62332_senddata(locomolcd_dev, comadj, 0); mdelay(5); - locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1); + locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 1); mdelay(10); /* TFTCRST | CPSOUT=0 | CPSEN */ @@ -58,8 +58,8 @@ static void locomolcd_on(int comadj) locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC); mdelay(10); - locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1); + locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 1); } static void locomolcd_off(int comadj) @@ -68,16 +68,16 @@ static void locomolcd_off(int comadj) locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC); mdelay(1); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0); mdelay(110); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0); mdelay(700); /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */ locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0); - locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0); + locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0); } void locomolcd_power(int on) @@ -167,14 +167,14 @@ static int locomolcd_resume(struct locomo_dev *dev) #define locomolcd_resume NULL #endif -static int locomolcd_probe(struct locomo_dev *dev) +static int locomolcd_probe(struct locomo_dev *ldev) { unsigned long flags; local_irq_save(flags); - locomolcd_dev = dev; + locomolcd_dev = ldev; - locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0); + locomo_gpio_set_dir(ldev->dev.parent, LOCOMO_GPIO_FL_VR, 0); /* the poodle_lcd_power function is called for the first time * from fs_initcall, which is before locomo is activated. @@ -200,6 +200,10 @@ static int locomolcd_remove(struct locomo_dev *dev) { unsigned long flags; + locomobl_data.brightness = 0; + locomobl_data.power = 0; + locomolcd_set_intensity(locomolcd_bl_device); + backlight_device_unregister(locomolcd_bl_device); local_irq_save(flags); locomolcd_dev = NULL; diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 51d35386a94..261004473c8 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -42,7 +42,7 @@ #define DPRINTK(fmt, args...) #endif -static u32 cfb_tab8[] = { +static const u32 cfb_tab8[] = { #if defined(__BIG_ENDIAN) 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, @@ -58,7 +58,7 @@ static u32 cfb_tab8[] = { #endif }; -static u32 cfb_tab16[] = { +static const u32 cfb_tab16[] = { #if defined(__BIG_ENDIAN) 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff #elif defined(__LITTLE_ENDIAN) @@ -68,7 +68,7 @@ static u32 cfb_tab16[] = { #endif }; -static u32 cfb_tab32[] = { +static const u32 cfb_tab32[] = { 0x00000000, 0xffffffff }; @@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * u32 bit_mask, end_mask, eorx, shift; const char *s = image->data, *src; u32 __iomem *dst; - u32 *tab = NULL; + const u32 *tab = NULL; int i, j, k; switch (bpp) { diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index daf43f535a0..2c4bc620573 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2442,7 +2442,10 @@ static int cirrusfb_pci_register (struct pci_dev *pdev, printk ("Cirrus Logic chipset on PCI bus\n"); pci_set_drvdata(pdev, info); - return cirrusfb_register(cinfo); + ret = cirrusfb_register(cinfo); + if (ret) + iounmap(cinfo->fbmem); + return ret; err_release_legacy: if (release_io_ports) @@ -2574,7 +2577,15 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); zorro_set_drvdata(z, info); - return cirrusfb_register(cinfo); + ret = cirrusfb_register(cinfo); + if (ret) { + if (btype == BT_PICASSO4) { + iounmap(cinfo->fbmem); + iounmap(cinfo->regbase - 0x600000); + } else if (board_addr > 0x01000000) + iounmap(cinfo->fbmem); + } + return ret; err_unmap_regbase: /* Parental advisory: explicit hack */ diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 4444bef68fb..aa3935df852 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -6,7 +6,7 @@ menu "Console display driver support" config VGA_CONSOLE bool "VGA text console" if EMBEDDED || !X86 - depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 1b4f75d1f8a..31f476a6479 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -133,6 +133,7 @@ static int info_idx = -1; /* console rotation */ static int rotate; +static int fbcon_has_sysfs; static const struct consw fb_con; @@ -203,7 +204,7 @@ static struct class_device *fbcon_class_device; */ static int vbl_detected; -static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) +static irqreturn_t fb_vbl_detect(int irq, void *dummy) { vbl_detected++; return IRQ_HANDLED; @@ -382,9 +383,9 @@ static void fbcon_update_softback(struct vc_data *vc) softback_top = 0; } -static void fb_flashcursor(void *private) +static void fb_flashcursor(struct work_struct *work) { - struct fb_info *info = private; + struct fb_info *info = container_of(work, struct fb_info, queue); struct fbcon_ops *ops = info->fbcon_par; struct display *p; struct vc_data *vc = NULL; @@ -396,9 +397,8 @@ static void fb_flashcursor(void *private) vc = vc_cons[ops->currcon].d; if (!vc || !CON_IS_VISIBLE(vc) || - fbcon_is_inactive(vc, info) || registered_fb[con2fb_map[vc->vc_num]] != info || - vc_cons[ops->currcon].d->vc_deccm != 1) { + vc->vc_deccm != 1) { release_console_sem(); return; } @@ -414,7 +414,7 @@ static void fb_flashcursor(void *private) #if defined(CONFIG_ATARI) || defined(CONFIG_MAC) static int cursor_blink_rate; -static irqreturn_t fb_vbl_handler(int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t fb_vbl_handler(int irq, void *dev_id) { struct fb_info *info = dev_id; @@ -442,7 +442,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info) if ((!info->queue.func || info->queue.func == fb_flashcursor) && !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) { if (!info->queue.func) - INIT_WORK(&info->queue, fb_flashcursor, info); + INIT_WORK(&info->queue, fb_flashcursor); init_timer(&ops->cursor_timer); ops->cursor_timer.function = cursor_timer_handler; @@ -2166,7 +2166,12 @@ static int fbcon_switch(struct vc_data *vc) fbcon_del_cursor_timer(old_info); } - fbcon_add_cursor_timer(info); + if (fbcon_is_inactive(vc, info) || + ops->blank_state != FB_BLANK_UNBLANK) + fbcon_del_cursor_timer(info); + else + fbcon_add_cursor_timer(info); + set_blitting_type(vc, info); ops->cursor_reset = 1; @@ -2276,10 +2281,11 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) update_screen(vc); } - if (!blank) - fbcon_add_cursor_timer(info); - else + if (fbcon_is_inactive(vc, info) || + ops->blank_state != FB_BLANK_UNBLANK) fbcon_del_cursor_timer(info); + else + fbcon_add_cursor_timer(info); return 0; } @@ -3161,11 +3167,26 @@ static struct class_device_attribute class_device_attrs[] = { static int fbcon_init_class_device(void) { - int i; + int i, error = 0; + + fbcon_has_sysfs = 1; + + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { + error = class_device_create_file(fbcon_class_device, + &class_device_attrs[i]); + + if (error) + break; + } + + if (error) { + while (--i >= 0) + class_device_remove_file(fbcon_class_device, + &class_device_attrs[i]); + + fbcon_has_sysfs = 0; + } - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_create_file(fbcon_class_device, - &class_device_attrs[i]); return 0; } @@ -3225,7 +3246,10 @@ static void fbcon_exit(void) module_put(info->fbops->owner); if (info->fbcon_par) { + struct fbcon_ops *ops = info->fbcon_par; + fbcon_del_cursor_timer(info); + kfree(ops->cursor_src); kfree(info->fbcon_par); info->fbcon_par = NULL; } @@ -3271,9 +3295,13 @@ static void __exit fbcon_deinit_class_device(void) { int i; - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_remove_file(fbcon_class_device, - &class_device_attrs[i]); + if (fbcon_has_sysfs) { + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) + class_device_remove_file(fbcon_class_device, + &class_device_attrs[i]); + + fbcon_has_sysfs = 0; + } } static void __exit fb_console_exit(void) diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index f244ad066d6..b9386d168c0 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -80,6 +80,8 @@ struct fbcon_ops { char *cursor_data; u8 *fontbuffer; u8 *fontdata; + u8 *cursor_src; + u32 cursor_size; u32 fd_size; }; /* diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 4481c80b8b2..825e6d6972a 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c @@ -391,7 +391,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->cursor_reset = 0; } -int ccw_update_start(struct fb_info *info) +static int ccw_update_start(struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; u32 yoffset; diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 7f92c06afea..c637e631880 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c @@ -375,7 +375,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->cursor_reset = 0; } -int cw_update_start(struct fb_info *info) +static int cw_update_start(struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; u32 vxres = GETVXRES(ops->p->scrollmode, info); diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index ab91005e64d..1473506df5d 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c @@ -415,7 +415,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->cursor_reset = 0; } -int ud_update_start(struct fb_info *info) +static int ud_update_start(struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; int xoffset, yoffset; diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c index 557c563e4ae..f577bd80e02 100644 --- a/drivers/video/console/softcursor.c +++ b/drivers/video/console/softcursor.c @@ -1,11 +1,13 @@ /* - * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * linux/drivers/video/softcursor.c + * + * Generic software cursor for frame buffer devices * * Created 14 Nov 2002 by James Simmons * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. */ #include <linux/module.h> @@ -20,11 +22,12 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) { + struct fbcon_ops *ops = info->fbcon_par; unsigned int scan_align = info->pixmap.scan_align - 1; unsigned int buf_align = info->pixmap.buf_align - 1; unsigned int i, size, dsize, s_pitch, d_pitch; struct fb_image *image; - u8 *dst, *src; + u8 *src, *dst; if (info->state != FBINFO_STATE_RUNNING) return 0; @@ -32,11 +35,20 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) s_pitch = (cursor->image.width + 7) >> 3; dsize = s_pitch * cursor->image.height; - src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); - if (!src) - return -ENOMEM; + if (dsize + sizeof(struct fb_image) != ops->cursor_size) { + if (ops->cursor_src != NULL) + kfree(ops->cursor_src); + ops->cursor_size = dsize + sizeof(struct fb_image); + + ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC); + if (!ops->cursor_src) { + ops->cursor_size = 0; + return -ENOMEM; + } + } - image = (struct fb_image *) (src + dsize); + src = ops->cursor_src + sizeof(struct fb_image); + image = (struct fb_image *)ops->cursor_src; *image = cursor->image; d_pitch = (s_pitch + scan_align) & ~scan_align; @@ -62,7 +74,6 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); image->data = dst; info->fbops->fb_imageblit(info, image); - kfree(src); return 0; } diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 45586aaabd1..57b21e53303 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -345,7 +345,7 @@ static void sticon_save_screen(struct vc_data *conp) { } -static struct consw sti_con = { +static const struct consw sti_con = { .owner = THIS_MODULE, .con_startup = sticon_startup, .con_init = sticon_init, diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0a2c10a1abf..4a9bde2c839 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -93,27 +93,27 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static unsigned long vgacon_uni_pagedir[2]; /* Description of the hardware situation */ -static unsigned long vga_vram_base; /* Base of video memory */ -static unsigned long vga_vram_end; /* End of video memory */ -static int vga_vram_size; /* Size of video memory */ -static u16 vga_video_port_reg; /* Video register select port */ -static u16 vga_video_port_val; /* Video register value port */ -static unsigned int vga_video_num_columns; /* Number of text columns */ -static unsigned int vga_video_num_lines; /* Number of text lines */ -static int vga_can_do_color = 0; /* Do we support colors? */ -static unsigned int vga_default_font_height;/* Height of default screen font */ -static unsigned char vga_video_type; /* Card type */ -static unsigned char vga_hardscroll_enabled; -static unsigned char vga_hardscroll_user_enable = 1; +static int vga_init_done __read_mostly; +static unsigned long vga_vram_base __read_mostly; /* Base of video memory */ +static unsigned long vga_vram_end __read_mostly; /* End of video memory */ +static unsigned int vga_vram_size __read_mostly; /* Size of video memory */ +static u16 vga_video_port_reg __read_mostly; /* Video register select port */ +static u16 vga_video_port_val __read_mostly; /* Video register value port */ +static unsigned int vga_video_num_columns; /* Number of text columns */ +static unsigned int vga_video_num_lines; /* Number of text lines */ +static int vga_can_do_color __read_mostly; /* Do we support colors? */ +static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ +static unsigned char vga_video_type __read_mostly; /* Card type */ +static unsigned char vga_hardscroll_enabled __read_mostly; +static unsigned char vga_hardscroll_user_enable __read_mostly = 1; static unsigned char vga_font_is_default = 1; static int vga_vesa_blanked; static int vga_palette_blanked; static int vga_is_gfx; static int vga_512_chars; static int vga_video_font_height; -static int vga_scan_lines; -static unsigned int vga_rolled_over = 0; -static int vga_init_done; +static int vga_scan_lines __read_mostly; +static unsigned int vga_rolled_over; static int __init no_scroll(char *str) { diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 8cc6c0e2d27..04c6d928189 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -415,13 +415,15 @@ static int __init init_control(struct fb_info_control *p) full = p->total_vram == 0x400000; /* Try to pick a video mode out of NVRAM if we have one. */ +#ifdef CONFIG_NVRAM if (default_cmode == CMODE_NVRAM){ cmode = nvram_read_byte(NV_CMODE); if(cmode < CMODE_8 || cmode > CMODE_32) cmode = CMODE_8; } else +#endif cmode=default_cmode; - +#ifdef CONFIG_NVRAM if (default_vmode == VMODE_NVRAM) { vmode = nvram_read_byte(NV_VMODE); if (vmode < 1 || vmode > VMODE_MAX || @@ -432,7 +434,9 @@ static int __init init_control(struct fb_info_control *p) if (control_mac_modes[vmode - 1].m[full] < cmode) vmode = VMODE_640_480_60; } - } else { + } else +#endif + { vmode=default_vmode; if (control_mac_modes[vmode - 1].m[full] < cmode) { if (cmode > CMODE_8) diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index c40e72dafb0..0b8d5b12115 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -109,8 +109,6 @@ static void cv64_dump(void); #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat) #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg)) -#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat) - struct cyberfb_par { struct fb_var_screeninfo var; __u32 type; @@ -1055,6 +1053,8 @@ int __init cyberfb_init(void) if (register_framebuffer(&fb_info) < 0) { DPRINTK("EXIT - register_framebuffer failed\n"); + if (CyberBase) + iounmap(CyberBase); release_mem_region(CyberMem_phys, 0x400000); release_mem_region(CyberRegs_phys, 0x10000); return -EINVAL; diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 737257d278f..29e07c10988 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -405,7 +405,7 @@ static inline unsigned long copy_to_user16(void *to, const void *from, static ssize_t epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; @@ -437,7 +437,7 @@ static ssize_t epson1355fb_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c new file mode 100644 index 00000000000..f836137a0ed --- /dev/null +++ b/drivers/video/fb_ddc.c @@ -0,0 +1,116 @@ +/* + * driver/vide/fb_ddc.c - DDC/EDID read support. + * + * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/fb.h> +#include <linux/i2c-algo-bit.h> + +#include "edid.h" + +#define DDC_ADDR 0x50 + +static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter) +{ + unsigned char start = 0x0; + unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL); + struct i2c_msg msgs[] = { + { + .addr = DDC_ADDR, + .flags = 0, + .len = 1, + .buf = &start, + }, { + .addr = DDC_ADDR, + .flags = I2C_M_RD, + .len = EDID_LENGTH, + .buf = buf, + } + }; + + if (!buf) { + dev_warn(&adapter->dev, "unable to allocate memory for EDID " + "block.\n"); + return NULL; + } + + if (i2c_transfer(adapter, msgs, 2) == 2) + return buf; + + dev_warn(&adapter->dev, "unable to read EDID block.\n"); + kfree(buf); + return NULL; +} + +unsigned char *fb_ddc_read(struct i2c_adapter *adapter) +{ + struct i2c_algo_bit_data *algo_data = adapter->algo_data; + unsigned char *edid = NULL; + int i, j; + + algo_data->setscl(algo_data->data, 1); + algo_data->setscl(algo_data->data, 0); + + for (i = 0; i < 3; i++) { + /* For some old monitors we need the + * following process to initialize/stop DDC + */ + algo_data->setsda(algo_data->data, 0); + msleep(13); + + algo_data->setscl(algo_data->data, 1); + for (j = 0; j < 5; j++) { + msleep(10); + if (algo_data->getscl(algo_data->data)) + break; + } + if (j == 5) + continue; + + algo_data->setsda(algo_data->data, 0); + msleep(15); + algo_data->setscl(algo_data->data, 0); + msleep(15); + algo_data->setsda(algo_data->data, 1); + msleep(15); + + /* Do the real work */ + edid = fb_do_probe_ddc_edid(adapter); + algo_data->setsda(algo_data->data, 0); + algo_data->setscl(algo_data->data, 0); + msleep(15); + + algo_data->setscl(algo_data->data, 1); + for (j = 0; j < 10; j++) { + msleep(10); + if (algo_data->getscl(algo_data->data)) + break; + } + + algo_data->setsda(algo_data->data, 1); + msleep(15); + algo_data->setscl(algo_data->data, 0); + if (edid) + break; + } + /* Release the DDC lines when done or the Apple Cinema HD display + * will switch off + */ + algo_data->setsda(algo_data->data, 0); + algo_data->setscl(algo_data->data, 0); + + return edid; +} + +EXPORT_SYMBOL_GPL(fb_ddc_read); + +MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>"); +MODULE_DESCRIPTION("DDC/EDID reading support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index e8b135f3d80..148108afdd5 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -18,63 +18,64 @@ #include <asm/uaccess.h> -static u16 red2[] = { +static u16 red2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 green2[] = { +static u16 green2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 blue2[] = { +static u16 blue2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 red4[] = { +static u16 red4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 green4[] = { +static u16 green4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 blue4[] = { +static u16 blue4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 red8[] = { +static u16 red8[] __read_mostly = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa }; -static u16 green8[] = { +static u16 green8[] __read_mostly = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa }; -static u16 blue8[] = { +static u16 blue8[] __read_mostly = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa }; -static u16 red16[] = { +static u16 red16[] __read_mostly = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff }; -static u16 green16[] = { +static u16 green16[] __read_mostly = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff }; -static u16 blue16[] = { +static u16 blue16[] __read_mostly = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff }; -static struct fb_cmap default_2_colors = { - 0, 2, red2, green2, blue2, NULL +static const struct fb_cmap default_2_colors = { + .len=2, .red=red2, .green=green2, .blue=blue2 }; -static struct fb_cmap default_8_colors = { - 0, 8, red8, green8, blue8, NULL +static const struct fb_cmap default_8_colors = { + .len=8, .red=red8, .green=green8, .blue=blue8 }; -static struct fb_cmap default_4_colors = { - 0, 4, red4, green4, blue4, NULL +static const struct fb_cmap default_4_colors = { + .len=4, .red=red4, .green=green4, .blue=blue4 }; -static struct fb_cmap default_16_colors = { - 0, 16, red16, green16, blue16, NULL +static const struct fb_cmap default_16_colors = { + .len=16, .red=red16, .green=green16, .blue=blue16 }; + /** * fb_alloc_cmap - allocate a colormap * @cmap: frame buffer colormap structure @@ -146,7 +147,7 @@ void fb_dealloc_cmap(struct fb_cmap *cmap) * Copy contents of colormap from @from to @to. */ -int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to) +int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) { int tooff = 0, fromoff = 0; int size; @@ -170,7 +171,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to) return 0; } -int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to) +int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) { int tooff = 0, fromoff = 0; int size; @@ -282,7 +283,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) * */ -struct fb_cmap *fb_default_cmap(int len) +const struct fb_cmap *fb_default_cmap(int len) { if (len <= 2) return &default_2_colors; @@ -305,22 +306,22 @@ void fb_invert_cmaps(void) { u_int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < ARRAY_SIZE(red2); i++) { red2[i] = ~red2[i]; green2[i] = ~green2[i]; blue2[i] = ~blue2[i]; } - for (i = 0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(red4); i++) { red4[i] = ~red4[i]; green4[i] = ~green4[i]; blue4[i] = ~blue4[i]; } - for (i = 0; i < 8; i++) { + for (i = 0; i < ARRAY_SIZE(red8); i++) { red8[i] = ~red8[i]; green8[i] = ~green8[i]; blue8[i] = ~blue8[i]; } - for (i = 0; i < 16; i++) { + for (i = 0; i < ARRAY_SIZE(red16); i++) { red16[i] = ~red16[i]; green16[i] = ~green16[i]; blue16[i] = ~blue16[i]; diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c index b5498999c4e..0847c5e72cb 100644 --- a/drivers/video/fbcvt.c +++ b/drivers/video/fbcvt.c @@ -57,7 +57,7 @@ struct fb_cvt_data { u32 status; }; -static int fb_cvt_vbi_tab[] = { +static const unsigned char fb_cvt_vbi_tab[] = { 4, /* 4:3 */ 5, /* 16:9 */ 6, /* 16:10 */ diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 17961e3ecaa..3cfea315a48 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -52,8 +52,8 @@ #define FBPIXMAPSIZE (1024 * 8) -struct fb_info *registered_fb[FB_MAX]; -int num_registered_fb; +struct fb_info *registered_fb[FB_MAX] __read_mostly; +int num_registered_fb __read_mostly; /* * Helpers @@ -202,7 +202,7 @@ static void fb_set_logo_truepalette(struct fb_info *info, const struct linux_logo *logo, u32 *palette) { - unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; + static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; unsigned char redmask, greenmask, bluemask; int redshift, greenshift, blueshift; int i; @@ -317,7 +317,7 @@ static struct logo_data { int needs_truepalette; int needs_cmapreset; const struct linux_logo *logo; -} fb_logo; +} fb_logo __read_mostly; static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) { @@ -554,7 +554,8 @@ static int fbmem_read_proc(char *buf, char **start, off_t offset, int clen; clen = 0; - for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && len < 4000; fi++) + for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && clen < 4000; + fi++) if (*fi) clen += sprintf(buf + clen, "%d %s\n", (*fi)->node, @@ -571,7 +572,7 @@ static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *dst; @@ -646,7 +647,7 @@ static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *src; @@ -1080,7 +1081,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; @@ -1120,7 +1121,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static int fb_mmap(struct file *file, struct vm_area_struct * vma) { - int fbidx = iminor(file->f_dentry->d_inode); + int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; unsigned long off; @@ -1252,7 +1253,7 @@ fb_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations fb_fops = { +static const struct file_operations fb_fops = { .owner = THIS_MODULE, .read = fb_read, .write = fb_write, @@ -1295,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info) break; fb_info->node = i; - fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i), - fb_info->device, "fb%d", i); - if (IS_ERR(fb_info->class_device)) { + fb_info->dev = device_create(fb_class, fb_info->device, + MKDEV(FB_MAJOR, i), "fb%d", i); + if (IS_ERR(fb_info->dev)) { /* Not fatal */ - printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device)); - fb_info->class_device = NULL; + printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); + fb_info->dev = NULL; } else - fb_init_class_device(fb_info); + fb_init_device(fb_info); if (fb_info->pixmap.addr == NULL) { fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); @@ -1355,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info) fb_destroy_modelist(&fb_info->modelist); registered_fb[i]=NULL; num_registered_fb--; - fb_cleanup_class_device(fb_info); - class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); + fb_cleanup_device(fb_info); + device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); return 0; @@ -1458,8 +1459,8 @@ int fb_new_modelist(struct fb_info *info) return err; } -static char *video_options[FB_MAX]; -static int ofonly; +static char *video_options[FB_MAX] __read_mostly; +static int ofonly __read_mostly; extern const char *global_mode_option; diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index de93139ccbb..6b385c39b8b 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -58,7 +58,7 @@ struct broken_edid { u32 fix; }; -static struct broken_edid brokendb[] = { +static const struct broken_edid brokendb[] = { /* DEC FR-PCXAV-YZ */ { .manufacturer = "DEC", diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index c151dcf6878..323bdf6fc7d 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -20,6 +20,8 @@ #include <linux/console.h> #include <linux/module.h> +#define FB_SYSFS_FLAG_ATTR 1 + /** * framebuffer_alloc - creates a new frame buffer info structure * @@ -71,7 +73,7 @@ EXPORT_SYMBOL(framebuffer_alloc); * * @info: frame buffer info structure * - * Drop the reference count of the class_device embedded in the + * Drop the reference count of the device embedded in the * framebuffer info structure. * */ @@ -118,10 +120,10 @@ static int mode_string(char *buf, unsigned int offset, m, mode->xres, mode->yres, v, mode->refresh); } -static ssize_t store_mode(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_mode(struct device *device, struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); char mstr[100]; struct fb_var_screeninfo var; struct fb_modelist *modelist; @@ -149,9 +151,10 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf, return -EINVAL; } -static ssize_t show_mode(struct class_device *class_device, char *buf) +static ssize_t show_mode(struct device *device, struct device_attribute *attr, + char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); if (!fb_info->mode) return 0; @@ -159,10 +162,11 @@ static ssize_t show_mode(struct class_device *class_device, char *buf) return mode_string(buf, 0, fb_info->mode); } -static ssize_t store_modes(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_modes(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); LIST_HEAD(old_list); int i = count / sizeof(struct fb_videomode); @@ -184,9 +188,10 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf, return 0; } -static ssize_t show_modes(struct class_device *class_device, char *buf) +static ssize_t show_modes(struct device *device, struct device_attribute *attr, + char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); unsigned int i; struct list_head *pos; struct fb_modelist *modelist; @@ -201,10 +206,10 @@ static ssize_t show_modes(struct class_device *class_device, char *buf) return i; } -static ssize_t store_bpp(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_bpp(struct device *device, struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char ** last = NULL; int err; @@ -216,16 +221,18 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf, return count; } -static ssize_t show_bpp(struct class_device *class_device, char *buf) +static ssize_t show_bpp(struct device *device, struct device_attribute *attr, + char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } -static ssize_t store_rotate(struct class_device *class_device, const char *buf, - size_t count) +static ssize_t store_rotate(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char **last = NULL; int err; @@ -240,17 +247,19 @@ static ssize_t store_rotate(struct class_device *class_device, const char *buf, } -static ssize_t show_rotate(struct class_device *class_device, char *buf) +static ssize_t show_rotate(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); } -static ssize_t store_virtual(struct class_device *class_device, - const char * buf, size_t count) +static ssize_t store_virtual(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char *last = NULL; int err; @@ -267,23 +276,26 @@ static ssize_t store_virtual(struct class_device *class_device, return count; } -static ssize_t show_virtual(struct class_device *class_device, char *buf) +static ssize_t show_virtual(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual, fb_info->var.yres_virtual); } -static ssize_t show_stride(struct class_device *class_device, char *buf) +static ssize_t show_stride(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length); } -static ssize_t store_blank(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_blank(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); char *last = NULL; int err; @@ -297,42 +309,48 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf, return count; } -static ssize_t show_blank(struct class_device *class_device, char *buf) +static ssize_t show_blank(struct device *device, + struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t store_console(struct class_device *class_device, - const char * buf, size_t count) +static ssize_t store_console(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t show_console(struct class_device *class_device, char *buf) +static ssize_t show_console(struct device *device, + struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t store_cursor(struct class_device *class_device, - const char * buf, size_t count) +static ssize_t store_cursor(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t show_cursor(struct class_device *class_device, char *buf) +static ssize_t show_cursor(struct device *device, + struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t store_pan(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_pan(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char *last = NULL; int err; @@ -353,24 +371,27 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf, return count; } -static ssize_t show_pan(struct class_device *class_device, char *buf) +static ssize_t show_pan(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset, fb_info->var.xoffset); } -static ssize_t show_name(struct class_device *class_device, char *buf) +static ssize_t show_name(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id); } -static ssize_t store_fbstate(struct class_device *class_device, - const char *buf, size_t count) +static ssize_t store_fbstate(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); u32 state; char *last = NULL; @@ -383,17 +404,19 @@ static ssize_t store_fbstate(struct class_device *class_device, return count; } -static ssize_t show_fbstate(struct class_device *class_device, char *buf) +static ssize_t show_fbstate(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); } #ifdef CONFIG_FB_BACKLIGHT -static ssize_t store_bl_curve(struct class_device *class_device, - const char *buf, size_t count) +static ssize_t store_bl_curve(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); u8 tmp_curve[FB_BACKLIGHT_LEVELS]; unsigned int i; @@ -430,9 +453,10 @@ static ssize_t store_bl_curve(struct class_device *class_device, return count; } -static ssize_t show_bl_curve(struct class_device *class_device, char *buf) +static ssize_t show_bl_curve(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); ssize_t len = 0; unsigned int i; @@ -463,7 +487,7 @@ static ssize_t show_bl_curve(struct class_device *class_device, char *buf) /* When cmap is added back in it should be a binary attribute * not a text one. Consideration should also be given to converting * fbdev to use configfs instead of sysfs */ -static struct class_device_attribute class_device_attrs[] = { +static struct device_attribute device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console), @@ -481,24 +505,40 @@ static struct class_device_attribute class_device_attrs[] = { #endif }; -int fb_init_class_device(struct fb_info *fb_info) +int fb_init_device(struct fb_info *fb_info) { - unsigned int i; - class_set_devdata(fb_info->class_device, fb_info); + int i, error = 0; + + dev_set_drvdata(fb_info->dev, fb_info); + + fb_info->class_flag |= FB_SYSFS_FLAG_ATTR; + + for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { + error = device_create_file(fb_info->dev, &device_attrs[i]); + + if (error) + break; + } + + if (error) { + while (--i >= 0) + device_remove_file(fb_info->dev, &device_attrs[i]); + fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; + } - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_create_file(fb_info->class_device, - &class_device_attrs[i]); return 0; } -void fb_cleanup_class_device(struct fb_info *fb_info) +void fb_cleanup_device(struct fb_info *fb_info) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_remove_file(fb_info->class_device, - &class_device_attrs[i]); + if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) { + for (i = 0; i < ARRAY_SIZE(device_attrs); i++) + device_remove_file(fb_info->dev, &device_attrs[i]); + + fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; + } } #ifdef CONFIG_FB_BACKLIGHT diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 2a0e8210d39..949141bd44d 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -968,6 +968,8 @@ static int ffb_init_one(struct of_device *op) if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { printk(KERN_ERR "ffb: Could not allocate color map.\n"); + of_iounmap(all->par.fbc, sizeof(struct ffb_fbc)); + of_iounmap(all->par.dac, sizeof(struct ffb_dac)); kfree(all); return -ENOMEM; } @@ -978,6 +980,8 @@ static int ffb_init_one(struct of_device *op) if (err < 0) { printk(KERN_ERR "ffb: Could not register framebuffer.\n"); fb_dealloc_cmap(&all->info.cmap); + of_iounmap(all->par.fbc, sizeof(struct ffb_fbc)); + of_iounmap(all->par.dac, sizeof(struct ffb_dac)); kfree(all); return err; } diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 998374cfae6..70ff55b1459 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -283,6 +283,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z, if (register_framebuffer(info) < 0) { fb_dealloc_cmap(&info->cmap); + iounmap(info->screen_base); framebuffer_release(info); zorro_release_device(z); return -EINVAL; diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 4e173ef20a7..a814b6c2605 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -23,6 +23,26 @@ config FB_GEODE_GX If unsure, say N. +config FB_GEODE_GX_SET_FBSIZE + bool "Manually specify the Geode GX framebuffer size" + depends on FB_GEODE_GX + default n + ---help--- + If you want to manually specify the size of your GX framebuffer, + say Y here, otherwise say N to dynamically probe it. + + Say N unless you know what you are doing. + +config FB_GEODE_GX_FBSIZE + hex "Size of the GX framebuffer, in bytes" + depends on FB_GEODE_GX_SET_FBSIZE + default "0x1600000" + ---help--- + Specify the size of the GX framebuffer. Normally, you will + want this to be MB aligned. Common values are 0x80000 (8MB) + and 0x1600000 (16MB). Don't change this unless you know what + you are doing + config FB_GEODE_GX1 tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" depends on FB && FB_GEODE && EXPERIMENTAL diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c index 825c3405f5c..0f16e4bffc6 100644 --- a/drivers/video/geode/display_gx.c +++ b/drivers/video/geode/display_gx.c @@ -21,11 +21,27 @@ #include "geodefb.h" #include "display_gx.h" -int gx_frame_buffer_size(void) +#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE +unsigned int gx_frame_buffer_size(void) { - /* Assuming 16 MiB. */ - return 16*1024*1024; + return CONFIG_FB_GEODE_GX_FBSIZE; } +#else +unsigned int gx_frame_buffer_size(void) +{ + unsigned int val; + + /* FB size is reported by a virtual register */ + /* Virtual register class = 0x02 */ + /* VG_MEM_SIZE(512Kb units) = 0x00 */ + + outw(0xFC53, 0xAC1C); + outw(0x0200, 0xAC1C); + + val = (unsigned int)(inw(0xAC1E)) & 0xFFl; + return (val << 19); +} +#endif int gx_line_delta(int xres, int bpp) { @@ -81,6 +97,7 @@ static void gx_set_mode(struct fb_info *info) writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, par->dc_regs + DC_LINE_SIZE); + /* Enable graphics and video data and unmask address lines. */ dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h index 86c62336130..0af33f329e8 100644 --- a/drivers/video/geode/display_gx.h +++ b/drivers/video/geode/display_gx.h @@ -11,11 +11,15 @@ #ifndef __DISPLAY_GX_H__ #define __DISPLAY_GX_H__ -int gx_frame_buffer_size(void); +unsigned int gx_frame_buffer_size(void); int gx_line_delta(int xres, int bpp); extern struct geode_dc_ops gx_dc_ops; +/* MSR that tells us if a TFT or CRT is attached */ +#define GLD_MSR_CONFIG 0xC0002001 +#define GLD_MSR_CONFIG_DM_FP 0x40 + /* Display controller registers */ #define DC_UNLOCK 0x00 @@ -93,4 +97,5 @@ extern struct geode_dc_ops gx_dc_ops; #define DC_PAL_ADDRESS 0x70 #define DC_PAL_DATA 0x74 +#define DC_GLIU0_MEM_OFFSET 0x84 #endif /* !__DISPLAY_GX1_H__ */ diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 0d3643fc629..cf841efa229 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c @@ -35,10 +35,10 @@ #include "display_gx.h" #include "video_gx.h" -static char mode_option[32] = "640x480-16@60"; +static char *mode_option; /* Modes relevant to the GX (taken from modedb.c) */ -static const struct fb_videomode __initdata gx_modedb[] = { +static const struct fb_videomode gx_modedb[] __initdata = { /* 640x480-60 VESA */ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -240,6 +240,12 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de if (!info->screen_base) return -ENOMEM; + /* Set the 16MB aligned base address of the graphics memory region + * in the display controller */ + + writel(info->fix.smem_start & 0xFF000000, + par->dc_regs + DC_GLIU0_MEM_OFFSET); + dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", info->fix.smem_len / 1024, info->fix.smem_start); @@ -302,6 +308,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i struct geodefb_par *par; struct fb_info *info; int ret; + unsigned long val; info = gxfb_init_fbinfo(&pdev->dev); if (!info) @@ -317,6 +324,15 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i goto err; } + /* Figure out if this is a TFT or CRT part */ + + rdmsrl(GLD_MSR_CONFIG, val); + + if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP) + par->enable_crt = 0; + else + par->enable_crt = 1; + ret = fb_find_mode(&info->var, info, mode_option, gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); if (ret == 0 || ret == 4) { @@ -325,7 +341,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i goto err; } - /* Clear the frame buffer of garbage. */ + + /* Clear the frame buffer of garbage. */ memset_io(info->screen_base, 0, info->fix.smem_len); gxfb_check_var(&info->var, info); @@ -380,7 +397,7 @@ static void gxfb_remove(struct pci_dev *pdev) } static struct pci_device_id gxfb_id_table[] = { - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO, + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 }, { 0, } @@ -395,11 +412,35 @@ static struct pci_driver gxfb_driver = { .remove = gxfb_remove, }; +#ifndef MODULE +static int __init gxfb_setup(char *options) +{ + + char *opt; + + if (!options || !*options) + return 0; + + while ((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + + mode_option = opt; + } + + return 0; +} +#endif + static int __init gxfb_init(void) { #ifndef MODULE - if (fb_get_options("gxfb", NULL)) + char *option = NULL; + + if (fb_get_options("gxfb", &option)) return -ENODEV; + + gxfb_setup(option); #endif return pci_register_driver(&gxfb_driver); } @@ -412,8 +453,8 @@ static void __exit gxfb_cleanup(void) module_init(gxfb_init); module_exit(gxfb_cleanup); -module_param_string(mode, mode_option, sizeof(mode_option), 0444); -MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index 2b2a7880ea7..7f3f18d0671 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c @@ -175,13 +175,88 @@ static void gx_set_dclk_frequency(struct fb_info *info) } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); } +static void +gx_configure_tft(struct fb_info *info) +{ + struct geodefb_par *par = info->par; + unsigned long val; + unsigned long fp; + + /* Set up the DF pad select MSR */ + + rdmsrl(GX_VP_MSR_PAD_SELECT, val); + val &= ~GX_VP_PAD_SELECT_MASK; + val |= GX_VP_PAD_SELECT_TFT; + wrmsrl(GX_VP_MSR_PAD_SELECT, val); + + /* Turn off the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp &= ~GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); + + /* Set timing 1 */ + + fp = readl(par->vid_regs + GX_FP_PT1); + fp &= GX_FP_PT1_VSIZE_MASK; + fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT; + writel(fp, par->vid_regs + GX_FP_PT1); + + /* Timing 2 */ + /* Set bits that are always on for TFT */ + + fp = 0x0F100000; + + /* Add sync polarity */ + + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + fp |= GX_FP_PT2_VSP; + + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + fp |= GX_FP_PT2_HSP; + + writel(fp, par->vid_regs + GX_FP_PT2); + + /* Set the dither control */ + writel(0x70, par->vid_regs + GX_FP_DFC); + + /* Enable the FP data and power (in case the BIOS didn't) */ + + fp = readl(par->vid_regs + GX_DCFG); + fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN; + writel(fp, par->vid_regs + GX_DCFG); + + /* Unblank the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp |= GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); +} + static void gx_configure_display(struct fb_info *info) { struct geodefb_par *par = info->par; - u32 dcfg, fp_pm; + u32 dcfg, misc; + + /* Set up the MISC register */ + + misc = readl(par->vid_regs + GX_MISC); + + /* Power up the DAC */ + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN); + + /* Disable gamma correction */ + misc |= GX_MISC_GAM_EN; + + writel(misc, par->vid_regs + GX_MISC); + /* Write the display configuration */ dcfg = readl(par->vid_regs + GX_DCFG); + /* Disable hsync and vsync */ + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); + writel(dcfg, par->vid_regs + GX_DCFG); + /* Clear bits from existing mode. */ dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL @@ -199,12 +274,19 @@ static void gx_configure_display(struct fb_info *info) if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) dcfg |= GX_DCFG_CRT_VSYNC_POL; + /* Enable the display logic */ + /* Set up the DACS to blank normally */ + + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN; + + /* Enable the external DAC VREF? */ + writel(dcfg, par->vid_regs + GX_DCFG); - /* Power on flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + /* Set up the flat panel (if it is enabled) */ + + if (par->enable_crt == 0) + gx_configure_tft(info); } static int gx_blank_display(struct fb_info *info, int blank_mode) @@ -245,12 +327,15 @@ static int gx_blank_display(struct fb_info *info, int blank_mode) writel(dcfg, par->vid_regs + GX_DCFG); /* Power on/off flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - if (blank_mode == FB_BLANK_POWERDOWN) - fp_pm &= ~GX_FP_PM_P; - else - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + + if (par->enable_crt == 0) { + fp_pm = readl(par->vid_regs + GX_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~GX_FP_PM_P; + else + fp_pm |= GX_FP_PM_P; + writel(fp_pm, par->vid_regs + GX_FP_PM); + } return 0; } diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h index 2d9211f3ed8..ce28d8f382d 100644 --- a/drivers/video/geode/video_gx.h +++ b/drivers/video/geode/video_gx.h @@ -13,6 +13,11 @@ extern struct geode_vid_ops gx_vid_ops; +/* GX Flatpanel control MSR */ +#define GX_VP_MSR_PAD_SELECT 0xC0002011 +#define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF +#define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF + /* Geode GX video processor registers */ #define GX_DCFG 0x0008 @@ -20,6 +25,8 @@ extern struct geode_vid_ops gx_vid_ops; # define GX_DCFG_HSYNC_EN 0x00000002 # define GX_DCFG_VSYNC_EN 0x00000004 # define GX_DCFG_DAC_BL_EN 0x00000008 +# define GX_DCFG_FP_PWR_EN 0x00000040 +# define GX_DCFG_FP_DATA_EN 0x00000080 # define GX_DCFG_CRT_HSYNC_POL 0x00000100 # define GX_DCFG_CRT_VSYNC_POL 0x00000200 # define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 @@ -28,10 +35,28 @@ extern struct geode_vid_ops gx_vid_ops; # define GX_DCFG_GV_GAM 0x00200000 # define GX_DCFG_DAC_VREF 0x04000000 +/* Geode GX MISC video configuration */ + +#define GX_MISC 0x50 +#define GX_MISC_GAM_EN 0x00000001 +#define GX_MISC_DAC_PWRDN 0x00000400 +#define GX_MISC_A_PWRDN 0x00000800 + /* Geode GX flat panel display control registers */ + +#define GX_FP_PT1 0x0400 +#define GX_FP_PT1_VSIZE_MASK 0x7FF0000 +#define GX_FP_PT1_VSIZE_SHIFT 16 + +#define GX_FP_PT2 0x408 +#define GX_FP_PT2_VSP (1 << 23) +#define GX_FP_PT2_HSP (1 << 22) + #define GX_FP_PM 0x410 # define GX_FP_PM_P 0x01000000 +#define GX_FP_DFC 0x418 + /* Geode GX clock control MSRs */ #define MSR_GLCP_SYS_RSTPLL 0x4c000014 diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c new file mode 100644 index 00000000000..3adf6ab0768 --- /dev/null +++ b/drivers/video/gxt4500.c @@ -0,0 +1,741 @@ +/* + * Frame buffer device for IBM GXT4500P display adaptor + * + * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/fb.h> +#include <linux/console.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/delay.h> + +#define PCI_DEVICE_ID_IBM_GXT4500P 0x21c + +/* GXT4500P registers */ + +/* Registers in PCI config space */ +#define CFG_ENDIAN0 0x40 + +/* Misc control/status registers */ +#define STATUS 0x1000 +#define CTRL_REG0 0x1004 +#define CR0_HALT_DMA 0x4 +#define CR0_RASTER_RESET 0x8 +#define CR0_GEOM_RESET 0x10 +#define CR0_MEM_CTRLER_RESET 0x20 + +/* Framebuffer control registers */ +#define FB_AB_CTRL 0x1100 +#define FB_CD_CTRL 0x1104 +#define FB_WID_CTRL 0x1108 +#define FB_Z_CTRL 0x110c +#define FB_VGA_CTRL 0x1110 +#define REFRESH_AB_CTRL 0x1114 +#define REFRESH_CD_CTRL 0x1118 +#define FB_OVL_CTRL 0x111c +#define FB_CTRL_TYPE 0x80000000 +#define FB_CTRL_WIDTH_MASK 0x007f0000 +#define FB_CTRL_WIDTH_SHIFT 16 +#define FB_CTRL_START_SEG_MASK 0x00003fff + +#define REFRESH_START 0x1098 +#define REFRESH_SIZE 0x109c + +/* "Direct" framebuffer access registers */ +#define DFA_FB_A 0x11e0 +#define DFA_FB_B 0x11e4 +#define DFA_FB_C 0x11e8 +#define DFA_FB_D 0x11ec +#define DFA_FB_ENABLE 0x80000000 +#define DFA_FB_BASE_MASK 0x03f00000 +#define DFA_FB_STRIDE_1k 0x00000000 +#define DFA_FB_STRIDE_2k 0x00000010 +#define DFA_FB_STRIDE_4k 0x00000020 +#define DFA_PIX_8BIT 0x00000000 +#define DFA_PIX_16BIT_565 0x00000001 +#define DFA_PIX_16BIT_1555 0x00000002 +#define DFA_PIX_24BIT 0x00000004 +#define DFA_PIX_32BIT 0x00000005 + +/* maps DFA_PIX_* to pixel size in bytes */ +static const unsigned char pixsize[] = { + 1, 2, 2, 2, 4, 4 +}; + +/* Display timing generator registers */ +#define DTG_CONTROL 0x1900 +#define DTG_CTL_SCREEN_REFRESH 2 +#define DTG_CTL_ENABLE 1 +#define DTG_HORIZ_EXTENT 0x1904 +#define DTG_HORIZ_DISPLAY 0x1908 +#define DTG_HSYNC_START 0x190c +#define DTG_HSYNC_END 0x1910 +#define DTG_HSYNC_END_COMP 0x1914 +#define DTG_VERT_EXTENT 0x1918 +#define DTG_VERT_DISPLAY 0x191c +#define DTG_VSYNC_START 0x1920 +#define DTG_VSYNC_END 0x1924 +#define DTG_VERT_SHORT 0x1928 + +/* PLL/RAMDAC registers */ +#define DISP_CTL 0x402c +#define DISP_CTL_OFF 2 +#define SYNC_CTL 0x4034 +#define SYNC_CTL_SYNC_ON_RGB 1 +#define SYNC_CTL_SYNC_OFF 2 +#define SYNC_CTL_HSYNC_INV 8 +#define SYNC_CTL_VSYNC_INV 0x10 +#define SYNC_CTL_HSYNC_OFF 0x20 +#define SYNC_CTL_VSYNC_OFF 0x40 + +#define PLL_M 0x4040 +#define PLL_N 0x4044 +#define PLL_POSTDIV 0x4048 + +/* Hardware cursor */ +#define CURSOR_X 0x4078 +#define CURSOR_Y 0x407c +#define CURSOR_HOTSPOT 0x4080 +#define CURSOR_MODE 0x4084 +#define CURSOR_MODE_OFF 0 +#define CURSOR_MODE_4BPP 1 +#define CURSOR_PIXMAP 0x5000 +#define CURSOR_CMAP 0x7400 + +/* Window attribute table */ +#define WAT_FMT 0x4100 +#define WAT_FMT_24BIT 0 +#define WAT_FMT_16BIT_565 1 +#define WAT_FMT_16BIT_1555 2 +#define WAT_FMT_32BIT 3 /* 0 vs. 3 is a guess */ +#define WAT_FMT_8BIT_332 9 +#define WAT_FMT_8BIT 0xa +#define WAT_FMT_NO_CMAP 4 /* ORd in to other values */ +#define WAT_CMAP_OFFSET 0x4104 /* 4-bit value gets << 6 */ +#define WAT_CTRL 0x4108 +#define WAT_CTRL_SEL_B 1 /* select B buffer if 1 */ +#define WAT_CTRL_NO_INC 2 +#define WAT_GAMMA_CTRL 0x410c +#define WAT_GAMMA_DISABLE 1 /* disables gamma cmap */ +#define WAT_OVL_CTRL 0x430c /* controls overlay */ + +/* Indexed by DFA_PIX_* values */ +static const unsigned char watfmt[] = { + WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0, + WAT_FMT_24BIT, WAT_FMT_32BIT +}; + +/* Colormap array; 1k entries of 4 bytes each */ +#define CMAP 0x6000 + +#define readreg(par, reg) readl((par)->regs + (reg)) +#define writereg(par, reg, val) writel((val), (par)->regs + (reg)) + +struct gxt4500_par { + void __iomem *regs; + + int pixfmt; /* pixel format, see DFA_PIX_* values */ + + /* PLL parameters */ + int pll_m; /* ref clock divisor */ + int pll_n; /* VCO divisor */ + int pll_pd1; /* first post-divisor */ + int pll_pd2; /* second post-divisor */ + + u32 pseudo_palette[16]; /* used in color blits */ +}; + +/* mode requested by user */ +static char *mode_option; + +/* default mode: 1280x1024 @ 60 Hz, 8 bpp */ +static const struct fb_videomode defaultmode __devinitdata = { + .refresh = 60, + .xres = 1280, + .yres = 1024, + .pixclock = 9295, + .left_margin = 248, + .right_margin = 48, + .upper_margin = 38, + .lower_margin = 1, + .hsync_len = 112, + .vsync_len = 3, + .vmode = FB_VMODE_NONINTERLACED +}; + +/* + * The refclk and VCO dividers appear to use a linear feedback shift + * register, which gets reloaded when it reaches a terminal value, at + * which point the divider output is toggled. Thus one can obtain + * whatever divisor is required by putting the appropriate value into + * the reload register. For a divisor of N, one puts the value from + * the LFSR sequence that comes N-1 places before the terminal value + * into the reload register. + */ + +static const unsigned char mdivtab[] = { +/* 1 */ 0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a, +/* 10 */ 0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11, +/* 20 */ 0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d, +/* 30 */ 0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02, +/* 40 */ 0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e, +/* 50 */ 0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e, +/* 60 */ 0x1f, 0x0f, 0x07, 0x03, 0x01, +}; + +static const unsigned char ndivtab[] = { +/* 2 */ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e, +/* 10 */ 0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e, +/* 20 */ 0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf, +/* 30 */ 0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc, +/* 40 */ 0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8, +/* 50 */ 0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6, +/* 60 */ 0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62, +/* 70 */ 0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57, +/* 80 */ 0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94, +/* 90 */ 0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79, +/* 100 */ 0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24, +/* 110 */ 0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45, +/* 120 */ 0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d, +/* 130 */ 0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e, +/* 140 */ 0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98, +/* 150 */ 0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2, +/* 160 */ 0x69, 0xb4, 0xda, 0xed, 0x76, 0xbb, 0x5d, 0xae, 0xd7, 0x6b, +/* 170 */ 0xb5, 0x5a, 0xad, 0x56, 0xab, 0xd5, 0x6a, 0x35, 0x1a, 0x8d, +/* 180 */ 0x46, 0x23, 0x11, 0x88, 0x44, 0x22, 0x91, 0xc8, 0x64, 0x32, +/* 190 */ 0x19, 0x0c, 0x86, 0x43, 0x21, 0x10, 0x08, 0x04, 0x02, 0x81, +/* 200 */ 0x40, 0xa0, 0xd0, 0x68, 0x34, 0x9a, 0xcd, 0x66, 0x33, 0x99, +/* 210 */ 0x4c, 0xa6, 0x53, 0xa9, 0xd4, 0xea, 0x75, 0x3a, 0x9d, 0xce, +/* 220 */ 0xe7, 0xf3, 0xf9, 0x7c, 0x3e, 0x1f, 0x8f, 0x47, 0xa3, 0x51, +/* 230 */ 0xa8, 0x54, 0xaa, 0x55, 0x2a, 0x15, 0x0a, 0x05, 0x82, 0xc1, +/* 240 */ 0x60, 0xb0, 0x58, 0xac, 0xd6, 0xeb, 0xf5, 0x7a, 0xbd, 0xde, +/* 250 */ 0x6f, 0x37, 0x1b, 0x0d, 0x06, 0x03, 0x01, +}; + +#define REF_PERIOD_PS 9259 /* period of reference clock in ps */ + +static int calc_pll(int period_ps, struct gxt4500_par *par) +{ + int m, n, pdiv1, pdiv2, postdiv; + int pll_period, best_error, t; + + /* only deal with range 1MHz - 400MHz */ + if (period_ps < 2500 || period_ps > 1000000) + return -1; + + best_error = 1000000; + for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) { + for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) { + postdiv = pdiv1 * pdiv2; + pll_period = (period_ps + postdiv - 1) / postdiv; + /* keep pll in range 500..1250 MHz */ + if (pll_period < 800 || pll_period > 2000) + continue; + for (m = 3; m <= 40; ++m) { + n = REF_PERIOD_PS * m * postdiv / period_ps; + if (n < 5 || n > 256) + continue; + t = REF_PERIOD_PS * m * postdiv / n; + t -= period_ps; + if (t >= 0 && t < best_error) { + par->pll_m = m; + par->pll_n = n; + par->pll_pd1 = pdiv1; + par->pll_pd2 = pdiv2; + best_error = t; + } + } + } + } + if (best_error == 1000000) + return -1; + return 0; +} + +static int calc_pixclock(struct gxt4500_par *par) +{ + return REF_PERIOD_PS * par->pll_m * par->pll_pd1 * par->pll_pd2 + / par->pll_n; +} + +static int gxt4500_var_to_par(struct fb_var_screeninfo *var, + struct gxt4500_par *par) +{ + if (var->xres + var->xoffset > var->xres_virtual || + var->yres + var->yoffset > var->yres_virtual || + var->xres_virtual > 4096) + return -EINVAL; + if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + return -EINVAL; + + if (calc_pll(var->pixclock, par) < 0) + return -EINVAL; + + switch (var->bits_per_pixel) { + case 32: + if (var->transp.length) + par->pixfmt = DFA_PIX_32BIT; + else + par->pixfmt = DFA_PIX_24BIT; + break; + case 24: + par->pixfmt = DFA_PIX_24BIT; + break; + case 16: + if (var->green.length == 5) + par->pixfmt = DFA_PIX_16BIT_1555; + else + par->pixfmt = DFA_PIX_16BIT_565; + break; + case 8: + par->pixfmt = DFA_PIX_8BIT; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct fb_bitfield eightbits = {0, 8}; +static const struct fb_bitfield nobits = {0, 0}; + +static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var, + int pixfmt) +{ + var->bits_per_pixel = pixsize[pixfmt] * 8; + var->red = eightbits; + var->green = eightbits; + var->blue = eightbits; + var->transp = nobits; + + switch (pixfmt) { + case DFA_PIX_16BIT_565: + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + break; + case DFA_PIX_16BIT_1555: + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.length = 1; + break; + case DFA_PIX_32BIT: + var->transp.length = 8; + break; + } + if (pixfmt != DFA_PIX_8BIT) { + var->green.offset = var->red.length; + var->blue.offset = var->green.offset + var->green.length; + if (var->transp.length) + var->transp.offset = + var->blue.offset + var->blue.length; + } +} + +static int gxt4500_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct gxt4500_par par; + int err; + + par = *(struct gxt4500_par *)info->par; + err = gxt4500_var_to_par(var, &par); + if (!err) { + var->pixclock = calc_pixclock(&par); + gxt4500_unpack_pixfmt(var, par.pixfmt); + } + return err; +} + +static int gxt4500_set_par(struct fb_info *info) +{ + struct gxt4500_par *par = info->par; + struct fb_var_screeninfo *var = &info->var; + int err; + u32 ctrlreg; + unsigned int dfa_ctl, pixfmt, stride; + unsigned int wid_tiles, i; + unsigned int prefetch_pix, htot; + struct gxt4500_par save_par; + + save_par = *par; + err = gxt4500_var_to_par(var, par); + if (err) { + *par = save_par; + return err; + } + + /* turn off DTG for now */ + ctrlreg = readreg(par, DTG_CONTROL); + ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH); + writereg(par, DTG_CONTROL, ctrlreg); + + /* set PLL registers */ + writereg(par, PLL_M, mdivtab[par->pll_m - 1]); + writereg(par, PLL_N, ndivtab[par->pll_n - 2]); + writereg(par, PLL_POSTDIV, + ((8 - par->pll_pd1) << 3) | (8 - par->pll_pd2)); + msleep(20); + + /* turn off hardware cursor */ + writereg(par, CURSOR_MODE, CURSOR_MODE_OFF); + + /* reset raster engine */ + writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16)); + udelay(10); + writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16); + + /* set display timing generator registers */ + htot = var->xres + var->left_margin + var->right_margin + + var->hsync_len; + writereg(par, DTG_HORIZ_EXTENT, htot - 1); + writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1); + writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1); + writereg(par, DTG_HSYNC_END, + var->xres + var->right_margin + var->hsync_len - 1); + writereg(par, DTG_HSYNC_END_COMP, + var->xres + var->right_margin + var->hsync_len - 1); + writereg(par, DTG_VERT_EXTENT, + var->yres + var->upper_margin + var->lower_margin + + var->vsync_len - 1); + writereg(par, DTG_VERT_DISPLAY, var->yres - 1); + writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1); + writereg(par, DTG_VSYNC_END, + var->yres + var->lower_margin + var->vsync_len - 1); + prefetch_pix = 3300000 / var->pixclock; + if (prefetch_pix >= htot) + prefetch_pix = htot - 1; + writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1); + ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH; + writereg(par, DTG_CONTROL, ctrlreg); + + /* calculate stride in DFA aperture */ + if (var->xres_virtual > 2048) { + stride = 4096; + dfa_ctl = DFA_FB_STRIDE_4k; + } else if (var->xres_virtual > 1024) { + stride = 2048; + dfa_ctl = DFA_FB_STRIDE_2k; + } else { + stride = 1024; + dfa_ctl = DFA_FB_STRIDE_1k; + } + + /* Set up framebuffer definition */ + wid_tiles = (var->xres_virtual + 63) >> 6; + + /* XXX add proper FB allocation here someday */ + writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); + writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); + writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); + writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); + writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); + writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres); + + /* Set up framebuffer access by CPU */ + + pixfmt = par->pixfmt; + dfa_ctl |= DFA_FB_ENABLE | pixfmt; + writereg(par, DFA_FB_A, dfa_ctl); + + /* + * Set up window attribute table. + * We set all WAT entries the same so it doesn't matter what the + * window ID (WID) plane contains. + */ + for (i = 0; i < 32; ++i) { + writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]); + writereg(par, WAT_CMAP_OFFSET + (i << 4), 0); + writereg(par, WAT_CTRL + (i << 4), 0); + writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE); + } + + /* Set sync polarity etc. */ + ctrlreg = readreg(par, SYNC_CTL) & + ~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV | + SYNC_CTL_VSYNC_INV); + if (var->sync & FB_SYNC_ON_GREEN) + ctrlreg |= SYNC_CTL_SYNC_ON_RGB; + if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) + ctrlreg |= SYNC_CTL_HSYNC_INV; + if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) + ctrlreg |= SYNC_CTL_VSYNC_INV; + writereg(par, SYNC_CTL, ctrlreg); + + info->fix.line_length = stride * pixsize[pixfmt]; + info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR: + FB_VISUAL_DIRECTCOLOR; + + return 0; +} + +static int gxt4500_setcolreg(unsigned int reg, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) +{ + u32 cmap_entry; + struct gxt4500_par *par = info->par; + + if (reg > 1023) + return 1; + cmap_entry = ((transp & 0xff00) << 16) | ((blue & 0xff00) << 8) | + (green & 0xff00) | (red >> 8); + writereg(par, CMAP + reg * 4, cmap_entry); + + if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) { + u32 *pal = info->pseudo_palette; + u32 val = reg; + switch (par->pixfmt) { + case DFA_PIX_16BIT_565: + val |= (reg << 11) | (reg << 6); + break; + case DFA_PIX_16BIT_1555: + val |= (reg << 10) | (reg << 5); + break; + case DFA_PIX_32BIT: + val |= (reg << 24); + /* fall through */ + case DFA_PIX_24BIT: + val |= (reg << 16) | (reg << 8); + break; + } + pal[reg] = val; + } + + return 0; +} + +static int gxt4500_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct gxt4500_par *par = info->par; + + if (var->xoffset & 7) + return -EINVAL; + if (var->xoffset + var->xres > var->xres_virtual || + var->yoffset + var->yres > var->yres_virtual) + return -EINVAL; + + writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); + return 0; +} + +static int gxt4500_blank(int blank, struct fb_info *info) +{ + struct gxt4500_par *par = info->par; + int ctrl, dctl; + + ctrl = readreg(par, SYNC_CTL); + ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF); + dctl = readreg(par, DISP_CTL); + dctl |= DISP_CTL_OFF; + switch (blank) { + case FB_BLANK_UNBLANK: + dctl &= ~DISP_CTL_OFF; + break; + case FB_BLANK_POWERDOWN: + ctrl |= SYNC_CTL_SYNC_OFF; + break; + case FB_BLANK_HSYNC_SUSPEND: + ctrl |= SYNC_CTL_HSYNC_OFF; + break; + case FB_BLANK_VSYNC_SUSPEND: + ctrl |= SYNC_CTL_VSYNC_OFF; + break; + default: ; + } + writereg(par, SYNC_CTL, ctrl); + writereg(par, DISP_CTL, dctl); + + return 0; +} + +static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = { + .id = "IBM GXT4500P", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 8, + .ypanstep = 1, + .mmio_len = 0x20000, +}; + +static struct fb_ops gxt4500_ops = { + .owner = THIS_MODULE, + .fb_check_var = gxt4500_check_var, + .fb_set_par = gxt4500_set_par, + .fb_setcolreg = gxt4500_setcolreg, + .fb_pan_display = gxt4500_pan_display, + .fb_blank = gxt4500_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +/* PCI functions */ +static int __devinit gxt4500_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int err; + unsigned long reg_phys, fb_phys; + struct gxt4500_par *par; + struct fb_info *info; + struct fb_var_screeninfo var; + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n", + err); + return err; + } + + reg_phys = pci_resource_start(pdev, 0); + if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0), + "gxt4500 regs")) { + dev_err(&pdev->dev, "gxt4500: cannot get registers\n"); + goto err_nodev; + } + + fb_phys = pci_resource_start(pdev, 1); + if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1), + "gxt4500 FB")) { + dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n"); + goto err_free_regs; + } + + info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev); + if (!info) { + dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record"); + goto err_free_fb; + } + par = info->par; + info->fix = gxt4500_fix; + info->pseudo_palette = par->pseudo_palette; + + info->fix.mmio_start = reg_phys; + par->regs = ioremap(reg_phys, pci_resource_len(pdev, 0)); + if (!par->regs) { + dev_err(&pdev->dev, "gxt4500: cannot map registers\n"); + goto err_free_all; + } + + info->fix.smem_start = fb_phys; + info->fix.smem_len = pci_resource_len(pdev, 1); + info->screen_base = ioremap(fb_phys, pci_resource_len(pdev, 1)); + if (!info->screen_base) { + dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n"); + goto err_unmap_regs; + } + + pci_set_drvdata(pdev, info); + + /* Set byte-swapping for DFA aperture for all pixel sizes */ + pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300); + + info->fbops = &gxt4500_ops; + info->flags = FBINFO_FLAG_DEFAULT; + + err = fb_alloc_cmap(&info->cmap, 256, 0); + if (err) { + dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n"); + goto err_unmap_all; + } + + gxt4500_blank(FB_BLANK_UNBLANK, info); + + if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) { + dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n"); + goto err_free_cmap; + } + info->var = var; + if (gxt4500_set_par(info)) { + printk(KERN_ERR "gxt4500: cannot set video mode\n"); + goto err_free_cmap; + } + + if (register_framebuffer(info) < 0) { + dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n"); + goto err_free_cmap; + } + printk(KERN_INFO "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + + return 0; + + err_free_cmap: + fb_dealloc_cmap(&info->cmap); + err_unmap_all: + iounmap(info->screen_base); + err_unmap_regs: + iounmap(par->regs); + err_free_all: + framebuffer_release(info); + err_free_fb: + release_mem_region(fb_phys, pci_resource_len(pdev, 1)); + err_free_regs: + release_mem_region(reg_phys, pci_resource_len(pdev, 0)); + err_nodev: + return -ENODEV; +} + +static void __devexit gxt4500_remove(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct gxt4500_par *par; + + if (!info) + return; + par = info->par; + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + iounmap(par->regs); + iounmap(info->screen_base); + 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)); + framebuffer_release(info); +} + +/* supported chipsets */ +static const struct pci_device_id gxt4500_pci_tbl[] = { + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl); + +static struct pci_driver gxt4500_driver = { + .name = "gxt4500", + .id_table = gxt4500_pci_tbl, + .probe = gxt4500_probe, + .remove = __devexit_p(gxt4500_remove), +}; + +static int __devinit gxt4500_init(void) +{ +#ifndef MODULE + if (fb_get_options("gxt4500", &mode_option)) + return -ENODEV; +#endif + + return pci_register_driver(&gxt4500_driver); +} +module_init(gxt4500_init); + +static void __exit gxt4500_exit(void) +{ + pci_unregister_driver(&gxt4500_driver); +} +module_exit(gxt4500_exit); + +MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); +MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P"); +MODULE_LICENSE("GPL"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\""); diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 4cc6b454265..3dc49424dc7 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -4,7 +4,7 @@ * (C) 1999 Mihai Spatar * (C) 2000 YAEGASHI Takeshi * (C) 2003, 2004 Paul Mundt - * (C) 2003, 2004 Andriy Skulysh + * (C) 2003, 2004, 2006 Andriy Skulysh * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -20,18 +20,15 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/platform_device.h> #include <linux/fb.h> #include <asm/machvec.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> -#include <asm/hd64461/hd64461.h> - -#ifdef MACH_HP600 +#include <asm/hd64461.h> #include <asm/cpu/dac.h> -#include <asm/hp6xx/hp6xx.h> -#endif #define WIDTH 640 @@ -45,7 +42,6 @@ static struct fb_var_screeninfo hitfb_var __initdata = { static struct fb_fix_screeninfo hitfb_fix __initdata = { .id = "Hitachi HD64461", .type = FB_TYPE_PACKED_PIXELS, - .ypanstep = 8, .accel = FB_ACCEL_NONE, }; @@ -73,26 +69,14 @@ static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy, if (truecolor) saddr <<= 1; - fb_writew(width, HD64461_BBTDWR); - fb_writew(height, HD64461_BBTDHR); + fb_writew(width-1, HD64461_BBTDWR); + fb_writew(height-1, HD64461_BBTDHR); fb_writew(saddr & 0xffff, HD64461_BBTDSARL); fb_writew(saddr >> 16, HD64461_BBTDSARH); } -static inline void hitfb_accel_solidfill(int truecolor, u16 dx, u16 dy, - u16 width, u16 height, u16 color) -{ - hitfb_accel_set_dest(truecolor, dx, dy, width, height); - - fb_writew(0x00f0, HD64461_BBTROPR); - fb_writew(16, HD64461_BBTMDR); - fb_writew(color, HD64461_GRSCR); - - hitfb_accel_start(truecolor); -} - static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx, u16 dy, u16 width, u16 height, u16 rop, u32 mask_addr) @@ -100,6 +84,8 @@ static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx, u32 saddr, daddr; u32 maddr = 0; + height--; + width--; fb_writew(rop, HD64461_BBTROPR); if ((sy < dy) || ((sy == dy) && (sx <= dx))) { saddr = WIDTH * (sy + height) + sx + width; @@ -146,6 +132,7 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) if (rect->rop != ROP_COPY) cfb_fillrect(p, rect); else { + hitfb_accel_wait(); fb_writew(0x00f0, HD64461_BBTROPR); fb_writew(16, HD64461_BBTMDR); @@ -161,16 +148,15 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) rect->height); hitfb_accel_start(0); } - hitfb_accel_wait(); } } static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) { + hitfb_accel_wait(); hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy, area->dx, area->dy, area->width, area->height, 0x00cc, 0); - hitfb_accel_wait(); } static int hitfb_pan_display(struct fb_var_screeninfo *var, @@ -182,7 +168,7 @@ static int hitfb_pan_display(struct fb_var_screeninfo *var, if (xoffset != 0) return -EINVAL; - fb_writew(yoffset, HD64461_LCDCBAR); + fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR); return 0; } @@ -192,12 +178,6 @@ int hitfb_blank(int blank_mode, struct fb_info *info) unsigned short v; if (blank_mode) { -#ifdef MACH_HP600 - sh_dac_disable(DAC_LCD_BRIGHTNESS); - v = fb_readw(HD64461_GPBDR); - v |= HD64461_GPBDR_LCDOFF; - fb_writew(v, HD64461_GPBDR); -#endif v = fb_readw(HD64461_LDR1); v &= ~HD64461_LDR1_DON; fb_writew(v, HD64461_LDR1); @@ -213,19 +193,18 @@ int hitfb_blank(int blank_mode, struct fb_info *info) v = fb_readw(HD64461_STBCR); v &= ~HD64461_STBCR_SLCDST; fb_writew(v, HD64461_STBCR); -#ifdef MACH_HP600 - sh_dac_enable(DAC_LCD_BRIGHTNESS); - v = fb_readw(HD64461_GPBDR); - v &= ~HD64461_GPBDR_LCDOFF; - fb_writew(v, HD64461_GPBDR); -#endif - v = fb_readw(HD64461_LDR1); - v |= HD64461_LDR1_DON; - fb_writew(v, HD64461_LDR1); v = fb_readw(HD64461_LCDCCR); - v &= ~HD64461_LCDCCR_MOFF; + v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ); fb_writew(v, HD64461_LCDCCR); + + do { + v = fb_readw(HD64461_LCDCCR); + } while(v&HD64461_LCDCCR_STBACK); + + v = fb_readw(HD64461_LDR1); + v |= HD64461_LDR1_DON; + fb_writew(v, HD64461_LDR1); } return 0; } @@ -233,7 +212,7 @@ int hitfb_blank(int blank_mode, struct fb_info *info) static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - if (regno >= info->cmap.len) + if (regno >= 256) return 1; switch (info->var.bits_per_pixel) { @@ -244,6 +223,8 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green, fb_writew(blue >> 10, HD64461_CPTWDR); break; case 16: + if (regno >= 16) + return 1; ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); @@ -252,26 +233,113 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green, return 0; } +static int hitfb_sync(struct fb_info *info) +{ + hitfb_accel_wait(); + + return 0; +} + +static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + int maxy; + + var->xres = info->var.xres; + var->xres_virtual = info->var.xres; + var->yres = info->var.yres; + + if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16)) + var->bits_per_pixel = info->var.bits_per_pixel; + + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + maxy = info->fix.smem_len / var->xres; + + if (var->bits_per_pixel == 16) + maxy /= 2; + + if (var->yres_virtual > maxy) + var->yres_virtual = maxy; + + var->xoffset = 0; + var->yoffset = 0; + + switch (var->bits_per_pixel) { + case 8: + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 16: /* RGB 565 */ + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; + } + + return 0; +} + +static int hitfb_set_par(struct fb_info *info) +{ + unsigned short ldr3; + + switch (info->var.bits_per_pixel) { + case 8: + info->fix.line_length = info->var.xres; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->fix.ypanstep = 16; + break; + case 16: + info->fix.line_length = info->var.xres*2; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.ypanstep = 8; + break; + } + + fb_writew(info->fix.line_length, HD64461_LCDCLOR); + ldr3 = fb_readw(HD64461_LDR3); + ldr3 &= ~15; + ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8; + fb_writew(ldr3, HD64461_LDR3); + return 0; +} + static struct fb_ops hitfb_ops = { .owner = THIS_MODULE, + .fb_check_var = hitfb_check_var, + .fb_set_par = hitfb_set_par, .fb_setcolreg = hitfb_setcolreg, .fb_blank = hitfb_blank, + .fb_sync = hitfb_sync, .fb_pan_display = hitfb_pan_display, .fb_fillrect = hitfb_fillrect, .fb_copyarea = hitfb_copyarea, .fb_imageblit = cfb_imageblit, }; -int __init hitfb_init(void) +static int __init hitfb_probe(struct platform_device *dev) { unsigned short lcdclor, ldr3, ldvndr; - int size; if (fb_get_options("hitfb", NULL)) return -ENODEV; + hitfb_fix.mmio_start = CONFIG_HD64461_IOBASE+0x1000; + hitfb_fix.mmio_len = 0x1000; hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000; - hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024; + hitfb_fix.smem_len = 512 * 1024; lcdclor = fb_readw(HD64461_LCDCLOR); ldvndr = fb_readw(HD64461_LDVNDR); @@ -321,12 +389,12 @@ int __init hitfb_init(void) fb_info.var = hitfb_var; fb_info.fix = hitfb_fix; fb_info.pseudo_palette = pseudo_palette; - fb_info.flags = FBINFO_DEFAULT; + fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | + FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; fb_info.screen_base = (void *)hitfb_fix.smem_start; - size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16; - fb_alloc_cmap(&fb_info.cmap, size, 0); + fb_alloc_cmap(&fb_info.cmap, 256, 0); if (register_framebuffer(&fb_info) < 0) return -EINVAL; @@ -336,9 +404,75 @@ int __init hitfb_init(void) return 0; } +static int __devexit hitfb_remove(struct platform_device *dev) +{ + return unregister_framebuffer(&fb_info); +} + +#ifdef CONFIG_PM +static int hitfb_suspend(struct platform_device *dev, pm_message_t state) +{ + u16 v; + + hitfb_blank(1,0); + v = fb_readw(HD64461_STBCR); + v |= HD64461_STBCR_SLCKE_IST; + fb_writew(v, HD64461_STBCR); + + return 0; +} + +static int hitfb_resume(struct platform_device *dev) +{ + u16 v; + + v = fb_readw(HD64461_STBCR); + v &= ~HD64461_STBCR_SLCKE_OST; + msleep(100); + v = fb_readw(HD64461_STBCR); + v &= ~HD64461_STBCR_SLCKE_IST; + fb_writew(v, HD64461_STBCR); + hitfb_blank(0,0); + + return 0; +} +#endif + +static struct platform_driver hitfb_driver = { + .probe = hitfb_probe, + .remove = __devexit_p(hitfb_remove), +#ifdef CONFIG_PM + .suspend = hitfb_suspend, + .resume = hitfb_resume, +#endif + .driver = { + .name = "hitfb", + }, +}; + +static struct platform_device hitfb_device = { + .name = "hitfb", + .id = -1, +}; + +static int __init hitfb_init(void) +{ + int ret; + + ret = platform_driver_register(&hitfb_driver); + if (!ret) { + ret = platform_device_register(&hitfb_device); + if (ret) + platform_driver_unregister(&hitfb_driver); + } + return ret; +} + + static void __exit hitfb_exit(void) { - unregister_framebuffer(&fb_info); + platform_device_unregister(&hitfb_device); + platform_driver_unregister(&hitfb_driver); } module_init(hitfb_init); diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index 91cf3b577d1..9ab9b839a0f 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -295,6 +295,8 @@ static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base if (register_framebuffer(&fb_info) < 0) { fb_dealloc_cmap(&fb_info.cmap); + iounmap(fb_info.screen_base); + fb_info.screen_base = NULL; return 1; } diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index c1f7b49975d..961f4d40446 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -19,7 +19,6 @@ #include "i810_main.h" #include "../edid.h" -#define I810_DDC 0x50 /* bit locations in the registers */ #define SCL_DIR_MASK 0x0001 #define SCL_DIR 0x0002 @@ -98,7 +97,6 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) chan->algo.getsda = i810i2c_getsda; chan->algo.getscl = i810i2c_getscl; chan->algo.udelay = 10; - chan->algo.mdelay = 10; chan->algo.timeout = (HZ/2); chan->algo.data = chan; @@ -139,73 +137,32 @@ void i810_create_i2c_busses(struct i810fb_par *par) void i810_delete_i2c_busses(struct i810fb_par *par) { if (par->chan[0].par) - i2c_bit_del_bus(&par->chan[0].adapter); + i2c_del_adapter(&par->chan[0].adapter); par->chan[0].par = NULL; if (par->chan[1].par) - i2c_bit_del_bus(&par->chan[1].adapter); + i2c_del_adapter(&par->chan[1].adapter); par->chan[1].par = NULL; if (par->chan[2].par) - i2c_bit_del_bus(&par->chan[2].adapter); + i2c_del_adapter(&par->chan[2].adapter); par->chan[2].par = NULL; } -static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) -{ - u8 start = 0x0; - struct i2c_msg msgs[] = { - { - .addr = I810_DDC, - .len = 1, - .buf = &start, - }, { - .addr = I810_DDC, - .flags = I2C_M_RD, - .len = EDID_LENGTH, - }, - }; - u8 *buf; - - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (!buf) { - DPRINTK("i810-i2c: Failed to allocate memory\n"); - return NULL; - } - msgs[1].buf = buf; - - if (i2c_transfer(&chan->adapter, msgs, 2) == 2) { - DPRINTK("i810-i2c: I2C Transfer successful\n"); - return buf; - } - - DPRINTK("i810-i2c: Unable to read EDID block.\n"); - kfree(buf); - return NULL; -} - int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) { struct i810fb_par *par = info->par; u8 *edid = NULL; - int i; DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1); if (conn < par->ddc_num) { - for (i = 0; i < 3; i++) { - /* Do the real work */ - edid = i810_do_probe_i2c_edid(&par->chan[conn]); - if (edid) - break; - } + edid = fb_ddc_read(&par->chan[conn].adapter); } else { const u8 *e = fb_firmware_edid(info->device); if (e != NULL) { DPRINTK("i810-i2c: Getting EDID from BIOS\n"); - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } } diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index d42edaccb84..b55a12d95eb 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1602,7 +1602,10 @@ static int i810fb_resume(struct pci_dev *dev) acquire_console_sem(); pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); - pci_enable_device(dev); + + if (pci_enable_device(dev)) + goto fail; + pci_set_master(dev); agp_bind_memory(par->i810_gtt.i810_fb_memory, par->fb.offset); @@ -1611,6 +1614,7 @@ static int i810fb_resume(struct pci_dev *dev) i810fb_set_par(info); fb_set_suspend (info, 0); info->fbops->fb_blank(VESA_NO_BLANKING, info); +fail: release_console_sem(); return 0; } diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index 67f384f8675..655ae0fa99c 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -384,19 +384,21 @@ int __init igafb_init(void) if (!con_is_present()) return -ENXIO; - pdev = pci_find_device(PCI_VENDOR_ID_INTERG, + pdev = pci_get_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0); if (pdev == NULL) { /* * XXX We tried to use cyber2000fb.c for IGS 2000. * But it does not initialize the chip in JavaStation-E, alas. */ - pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); + pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); if(pdev == NULL) { return -ENXIO; } iga2000 = 1; } + /* We leak a reference here but as it cannot be unloaded this is + fine. If you write unload code remember to free it in unload */ size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16; @@ -573,3 +575,10 @@ int __init igafb_setup(char *options) module_init(igafb_init); MODULE_LICENSE("GPL"); +static struct pci_device_id igafb_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; + +MODULE_DEVICE_TABLE(pci, igafb_pci_tbl); diff --git a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile index 722d21d6e5c..6c782d3ae1b 100644 --- a/drivers/video/intelfb/Makefile +++ b/drivers/video/intelfb/Makefile @@ -1,6 +1,8 @@ obj-$(CONFIG_FB_INTEL) += intelfb.o -intelfb-objs := intelfbdrv.o intelfbhw.o +intelfb-y := intelfbdrv.o intelfbhw.o +intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o +intelfb-objs := $(intelfb-y) ifdef CONFIG_FB_INTEL_DEBUG #EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index e290d7460e1..80b94c19a9f 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h @@ -6,6 +6,10 @@ #include <linux/agp_backend.h> #include <linux/fb.h> +#ifdef CONFIG_FB_INTEL_I2C +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> +#endif /*** Version/name ***/ #define INTELFB_VERSION "0.9.4" @@ -115,6 +119,29 @@ /* Intel agpgart driver */ #define AGP_PHYSICAL_MEMORY 2 +/* store information about an Ixxx DVO */ +/* The i830->i865 use multiple DVOs with multiple i2cs */ +/* the i915, i945 have a single sDVO i2c bus - which is different */ +#define MAX_OUTPUTS 6 + +/* these are outputs from the chip - integrated only + external chips are via DVO or SDVO output */ +#define INTELFB_OUTPUT_UNUSED 0 +#define INTELFB_OUTPUT_ANALOG 1 +#define INTELFB_OUTPUT_DVO 2 +#define INTELFB_OUTPUT_SDVO 3 +#define INTELFB_OUTPUT_LVDS 4 +#define INTELFB_OUTPUT_TVOUT 5 + +#define INTELFB_DVO_CHIP_NONE 0 +#define INTELFB_DVO_CHIP_LVDS 1 +#define INTELFB_DVO_CHIP_TMDS 2 +#define INTELFB_DVO_CHIP_TVOUT 4 + +#define INTELFB_OUTPUT_PIPE_NC 0 +#define INTELFB_OUTPUT_PIPE_A 1 +#define INTELFB_OUTPUT_PIPE_B 2 + /*** Data Types ***/ /* supported chipsets */ @@ -195,6 +222,10 @@ struct intelfb_hwstate { u32 mem_mode; u32 fw_blc_0; u32 fw_blc_1; + u16 hwstam; + u16 ier; + u16 iir; + u16 imr; }; struct intelfb_heap_data { @@ -204,6 +235,33 @@ struct intelfb_heap_data { u32 size; // in bytes }; +#ifdef CONFIG_FB_INTEL_I2C +struct intelfb_i2c_chan { + struct intelfb_info *dinfo; + u32 reg; + struct i2c_adapter adapter; + struct i2c_algo_bit_data algo; +}; +#endif + +struct intelfb_output_rec { + int type; + int pipe; + int flags; + +#ifdef CONFIG_FB_INTEL_I2C + struct intelfb_i2c_chan i2c_bus; + struct intelfb_i2c_chan ddc_bus; +#endif +}; + +struct intelfb_vsync { + wait_queue_head_t wait; + unsigned int count; + int pan_display; + u32 pan_offset; +}; + struct intelfb_info { struct fb_info *info; struct fb_ops *fbops; @@ -220,7 +278,7 @@ struct intelfb_info { u8 fbmem_gart; /* mtrr support */ - u32 mtrr_reg; + int mtrr_reg; u32 has_mtrr; /* heap data */ @@ -267,6 +325,12 @@ struct intelfb_info { int fixed_mode; int ring_active; int flag; + unsigned long irq_flags; + int open; + + /* vsync */ + struct intelfb_vsync vsync; + spinlock_t int_lock; /* hw cursor */ int cursor_on; @@ -285,12 +349,25 @@ struct intelfb_info { /* index into plls */ int pll_index; + + /* outputs */ + int num_outputs; + struct intelfb_output_rec output[MAX_OUTPUTS]; }; #define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM)) +#ifndef FBIO_WAITFORVSYNC +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#endif + /*** function prototypes ***/ extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); +#ifdef CONFIG_FB_INTEL_I2C +extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo); +extern void intelfb_delete_i2c_busses(struct intelfb_info *dinfo); +#endif + #endif /* _INTELFB_H */ diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c new file mode 100644 index 00000000000..33bc41f5054 --- /dev/null +++ b/drivers/video/intelfb/intelfb_i2c.c @@ -0,0 +1,199 @@ +/************************************************************************** + + Copyright 2006 Dave Airlie <airlied@linux.ie> + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/fb.h> + +#include <linux/i2c.h> +#include <linux/i2c-id.h> +#include <linux/i2c-algo-bit.h> + +#include <asm/io.h> + +#include "intelfb.h" +#include "intelfbhw.h" + +/* bit locations in the registers */ +#define SCL_DIR_MASK 0x0001 +#define SCL_DIR 0x0002 +#define SCL_VAL_MASK 0x0004 +#define SCL_VAL_OUT 0x0008 +#define SCL_VAL_IN 0x0010 +#define SDA_DIR_MASK 0x0100 +#define SDA_DIR 0x0200 +#define SDA_VAL_MASK 0x0400 +#define SDA_VAL_OUT 0x0800 +#define SDA_VAL_IN 0x1000 + +static void intelfb_gpio_setscl(void *data, int state) +{ + struct intelfb_i2c_chan *chan = data; + struct intelfb_info *dinfo = chan->dinfo; + u32 val; + + OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); + val = INREG(chan->reg); +} + +static void intelfb_gpio_setsda(void *data, int state) +{ + struct intelfb_i2c_chan *chan = data; + struct intelfb_info *dinfo = chan->dinfo; + u32 val; + + OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); + val = INREG(chan->reg); +} + +static int intelfb_gpio_getscl(void *data) +{ + struct intelfb_i2c_chan *chan = data; + struct intelfb_info *dinfo = chan->dinfo; + u32 val; + + OUTREG(chan->reg, SCL_DIR_MASK); + OUTREG(chan->reg, 0); + val = INREG(chan->reg); + return ((val & SCL_VAL_IN) != 0); +} + +static int intelfb_gpio_getsda(void *data) +{ + struct intelfb_i2c_chan *chan = data; + struct intelfb_info *dinfo = chan->dinfo; + u32 val; + + OUTREG(chan->reg, SDA_DIR_MASK); + OUTREG(chan->reg, 0); + val = INREG(chan->reg); + return ((val & SDA_VAL_IN) != 0); +} + +static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, + struct intelfb_i2c_chan *chan, + const u32 reg, const char *name) +{ + int rc; + + chan->dinfo = dinfo; + chan->reg = reg; + snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name); + chan->adapter.owner = THIS_MODULE; + chan->adapter.id = I2C_HW_B_INTELFB; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->dinfo->pdev->dev; + chan->algo.setsda = intelfb_gpio_setsda; + chan->algo.setscl = intelfb_gpio_setscl; + chan->algo.getsda = intelfb_gpio_getsda; + chan->algo.getscl = intelfb_gpio_getscl; + chan->algo.udelay = 40; + chan->algo.timeout = 20; + chan->algo.data = chan; + + i2c_set_adapdata(&chan->adapter, chan); + + /* Raise SCL and SDA */ + intelfb_gpio_setsda(chan, 1); + intelfb_gpio_setscl(chan, 1); + udelay(20); + + rc = i2c_bit_add_bus(&chan->adapter); + if (rc == 0) + DBG_MSG("I2C bus %s registered.\n", name); + else + WRN_MSG("Failed to register I2C bus %s.\n", name); + return rc; +} + +void intelfb_create_i2c_busses(struct intelfb_info *dinfo) +{ + int i = 0; + + /* everyone has at least a single analog output */ + dinfo->num_outputs = 1; + dinfo->output[i].type = INTELFB_OUTPUT_ANALOG; + + /* setup the DDC bus for analog output */ + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, "CRTDDC_A"); + i++; + + /* need to add the output busses for each device + - this function is very incomplete + - i915GM has LVDS and TVOUT for example + */ + switch(dinfo->chipset) { + case INTEL_830M: + case INTEL_845G: + case INTEL_855GM: + case INTEL_865G: + dinfo->output[i].type = INTELFB_OUTPUT_DVO; + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOD, "DVODDC_D"); + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "DVOI2C_E"); + i++; + break; + case INTEL_915G: + case INTEL_915GM: + /* has some LVDS + tv-out */ + case INTEL_945G: + case INTEL_945GM: + /* SDVO ports have a single control bus - 2 devices */ + dinfo->output[i].type = INTELFB_OUTPUT_SDVO; + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "SDVOCTRL_E"); + /* TODO: initialize the SDVO */ +// I830SDVOInit(pScrn, i, DVOB); + i++; + + /* set up SDVOC */ + dinfo->output[i].type = INTELFB_OUTPUT_SDVO; + dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus; + /* TODO: initialize the SDVO */ +// I830SDVOInit(pScrn, i, DVOC); + i++; + break; + } + dinfo->num_outputs = i; +} + +void intelfb_delete_i2c_busses(struct intelfb_info *dinfo) +{ + int i; + + for (i = 0; i < MAX_OUTPUTS; i++) { + if (dinfo->output[i].i2c_bus.dinfo) { + i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter); + dinfo->output[i].i2c_bus.dinfo = NULL; + } + if (dinfo->output[i].ddc_bus.dinfo) { + i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter); + dinfo->output[i].ddc_bus.dinfo = NULL; + } + } +} diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 06af89d44a0..664fc5cf962 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -136,6 +136,8 @@ static void __devinit get_initial_mode(struct intelfb_info *dinfo); static void update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var); +static int intelfb_open(struct fb_info *info, int user); +static int intelfb_release(struct fb_info *info, int user); static int intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); static int intelfb_set_par(struct fb_info *info); @@ -194,6 +196,8 @@ static int num_registered = 0; /* fb ops */ static struct fb_ops intel_fb_ops = { .owner = THIS_MODULE, + .fb_open = intelfb_open, + .fb_release = intelfb_release, .fb_check_var = intelfb_check_var, .fb_set_par = intelfb_set_par, .fb_setcolreg = intelfb_setcolreg, @@ -446,6 +450,8 @@ cleanup(struct intelfb_info *dinfo) if (!dinfo) return; + intelfbhw_disable_irq(dinfo); + fb_dealloc_cmap(&dinfo->info->cmap); kfree(dinfo->info->pixmap.addr); @@ -467,6 +473,11 @@ cleanup(struct intelfb_info *dinfo) agp_free_memory(dinfo->gtt_ring_mem); } +#ifdef CONFIG_FB_INTEL_I2C + /* un-register I2C bus */ + intelfb_delete_i2c_busses(dinfo); +#endif + if (dinfo->mmio_base) iounmap((void __iomem *)dinfo->mmio_base); if (dinfo->aperture.virtual) @@ -844,6 +855,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) if (bailearly == 5) bailout(dinfo); +#ifdef CONFIG_FB_INTEL_I2C + /* register I2C bus */ + intelfb_create_i2c_busses(dinfo); +#endif + if (bailearly == 6) bailout(dinfo); @@ -888,6 +904,13 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) } dinfo->registered = 1; + dinfo->open = 0; + + init_waitqueue_head(&dinfo->vsync.wait); + spin_lock_init(&dinfo->int_lock); + dinfo->irq_flags = 0; + dinfo->vsync.pan_display = 0; + dinfo->vsync.pan_offset = 0; return 0; @@ -1035,10 +1058,9 @@ intelfb_init_var(struct intelfb_info *dinfo) u8 *edid_d = NULL; if (edid_s) { - edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL); + edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL); if (edid_d) { - memcpy(edid_d, edid_s, EDID_LENGTH); fb_edid_to_monspecs(edid_d, &dinfo->info->monspecs); kfree(edid_d); @@ -1188,6 +1210,34 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var) ***************************************************************/ static int +intelfb_open(struct fb_info *info, int user) +{ + struct intelfb_info *dinfo = GET_DINFO(info); + + if (user) { + dinfo->open++; + } + + return 0; +} + +static int +intelfb_release(struct fb_info *info, int user) +{ + struct intelfb_info *dinfo = GET_DINFO(info); + + if (user) { + dinfo->open--; + msleep(1); + if (!dinfo->open) { + intelfbhw_disable_irq(dinfo); + } + } + + return 0; +} + +static int intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int change_var = 0; @@ -1433,6 +1483,19 @@ static int intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { int retval = 0; + struct intelfb_info *dinfo = GET_DINFO(info); + u32 pipe = 0; + + switch (cmd) { + case FBIO_WAITFORVSYNC: + if (get_user(pipe, (__u32 __user *)arg)) + return -EFAULT; + + retval = intelfbhw_wait_for_vsync(dinfo, pipe); + break; + default: + break; + } return retval; } diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 2a9322f9cfd..a95836839e1 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -32,6 +32,7 @@ #include <linux/pci.h> #include <linux/vmalloc.h> #include <linux/pagemap.h> +#include <linux/interrupt.h> #include <asm/io.h> @@ -160,7 +161,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, return 1; /* Find the bridge device. It is always 0:0.0 */ - if (!(bridge_dev = pci_find_slot(0, PCI_DEVFN(0, 0)))) { + if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) { ERR_MSG("cannot find bridge device\n"); return 1; } @@ -168,6 +169,8 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, /* Get the fb aperture size and "stolen" memory amount. */ tmp = 0; pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); + pci_dev_put(bridge_dev); + switch (pdev->device) { case PCI_DEVICE_ID_INTEL_915G: case PCI_DEVICE_ID_INTEL_915GM: @@ -368,7 +371,13 @@ intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) offset += dinfo->fb.offset << 12; - OUTREG(DSPABASE, offset); + dinfo->vsync.pan_offset = offset; + if ((var->activate & FB_ACTIVATE_VBL) && !intelfbhw_enable_irq(dinfo, 0)) { + dinfo->vsync.pan_display = 1; + } else { + dinfo->vsync.pan_display = 0; + OUTREG(DSPABASE, offset); + } return 0; } @@ -585,6 +594,11 @@ intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, hw->fw_blc_0 = INREG(FW_BLC_0); hw->fw_blc_1 = INREG(FW_BLC_1); + hw->hwstam = INREG16(HWSTAM); + hw->ier = INREG16(IER); + hw->iir = INREG16(IIR); + hw->imr = INREG16(IMR); + return 0; } @@ -613,6 +627,7 @@ static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvd return vco / p; } +#if REGDUMP static void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2) { @@ -638,6 +653,7 @@ intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2) *o_p1 = p1; *o_p2 = p2; } +#endif void @@ -648,7 +664,7 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) int index = dinfo->pll_index; DBG_MSG("intelfbhw_print_hw_state\n"); - if (!hw || !dinfo) + if (!hw) return; /* Read in as much of the HW state as possible. */ printk("hw state dump start\n"); @@ -794,6 +810,10 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) printk(" FW_BLC_0 0x%08x\n", hw->fw_blc_0); printk(" FW_BLC_1 0x%08x\n", hw->fw_blc_1); + printk(" HWSTAM 0x%04x\n", hw->hwstam); + printk(" IER 0x%04x\n", hw->ier); + printk(" IIR 0x%04x\n", hw->iir); + printk(" IMR 0x%04x\n", hw->imr); printk("hw state dump end\n"); #endif } @@ -1932,3 +1952,119 @@ intelfbhw_cursor_reset(struct intelfb_info *dinfo) { addr += 16; } } + +static irqreturn_t +intelfbhw_irq(int irq, void *dev_id) { + int handled = 0; + u16 tmp; + struct intelfb_info *dinfo = (struct intelfb_info *)dev_id; + + spin_lock(&dinfo->int_lock); + + tmp = INREG16(IIR); + tmp &= VSYNC_PIPE_A_INTERRUPT; + + if (tmp == 0) { + spin_unlock(&dinfo->int_lock); + return IRQ_RETVAL(handled); + } + + OUTREG16(IIR, tmp); + + if (tmp & VSYNC_PIPE_A_INTERRUPT) { + dinfo->vsync.count++; + if (dinfo->vsync.pan_display) { + dinfo->vsync.pan_display = 0; + OUTREG(DSPABASE, dinfo->vsync.pan_offset); + } + wake_up_interruptible(&dinfo->vsync.wait); + handled = 1; + } + + spin_unlock(&dinfo->int_lock); + + return IRQ_RETVAL(handled); +} + +int +intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) { + + if (!test_and_set_bit(0, &dinfo->irq_flags)) { + if (request_irq(dinfo->pdev->irq, intelfbhw_irq, SA_SHIRQ, "intelfb", dinfo)) { + clear_bit(0, &dinfo->irq_flags); + return -EINVAL; + } + + spin_lock_irq(&dinfo->int_lock); + OUTREG16(HWSTAM, 0xfffe); + OUTREG16(IMR, 0x0); + OUTREG16(IER, VSYNC_PIPE_A_INTERRUPT); + spin_unlock_irq(&dinfo->int_lock); + } else if (reenable) { + u16 ier; + + spin_lock_irq(&dinfo->int_lock); + ier = INREG16(IER); + if ((ier & VSYNC_PIPE_A_INTERRUPT)) { + DBG_MSG("someone disabled the IRQ [%08X]\n", ier); + OUTREG(IER, VSYNC_PIPE_A_INTERRUPT); + } + spin_unlock_irq(&dinfo->int_lock); + } + return 0; +} + +void +intelfbhw_disable_irq(struct intelfb_info *dinfo) { + u16 tmp; + + if (test_and_clear_bit(0, &dinfo->irq_flags)) { + if (dinfo->vsync.pan_display) { + dinfo->vsync.pan_display = 0; + OUTREG(DSPABASE, dinfo->vsync.pan_offset); + } + spin_lock_irq(&dinfo->int_lock); + OUTREG16(HWSTAM, 0xffff); + OUTREG16(IMR, 0xffff); + OUTREG16(IER, 0x0); + + tmp = INREG16(IIR); + OUTREG16(IIR, tmp); + spin_unlock_irq(&dinfo->int_lock); + + free_irq(dinfo->pdev->irq, dinfo); + } +} + +int +intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe) { + struct intelfb_vsync *vsync; + unsigned int count; + int ret; + + switch (pipe) { + case 0: + vsync = &dinfo->vsync; + break; + default: + return -ENODEV; + } + + ret = intelfbhw_enable_irq(dinfo, 0); + if (ret) { + return ret; + } + + count = vsync->count; + ret = wait_event_interruptible_timeout(vsync->wait, count != vsync->count, HZ/10); + if (ret < 0) { + return ret; + } + if (ret == 0) { + intelfbhw_enable_irq(dinfo, 1); + DBG_MSG("wait_for_vsync timed out!\n"); + return -ETIMEDOUT; + } + + return 0; +} diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h index 10acda098b7..8c54ba8fbdd 100644 --- a/drivers/video/intelfb/intelfbhw.h +++ b/drivers/video/intelfb/intelfbhw.h @@ -88,6 +88,19 @@ #define INSTDONE 0x2090 #define PRI_RING_EMPTY 1 +#define HWSTAM 0x2098 +#define IER 0x20A0 +#define IIR 0x20A4 +#define IMR 0x20A8 +#define VSYNC_PIPE_A_INTERRUPT (1 << 7) +#define PIPE_A_EVENT_INTERRUPT (1 << 4) +#define VSYNC_PIPE_B_INTERRUPT (1 << 5) +#define PIPE_B_EVENT_INTERRUPT (1 << 4) +#define HOST_PORT_EVENT_INTERRUPT (1 << 3) +#define CAPTURE_EVENT_INTERRUPT (1 << 2) +#define USER_DEFINED_INTERRUPT (1 << 1) +#define BREAKPOINT_INTERRUPT 1 + #define INSTPM 0x20c0 #define SYNC_FLUSH_ENABLE (1 << 5) @@ -113,6 +126,12 @@ #define FW_DISPC_BL_SHIFT 8 #define FW_DISPC_BL_MASK 0x7 +#define GPIOA 0x5010 +#define GPIOB 0x5014 +#define GPIOC 0x5018 // this may be external DDC on i830 +#define GPIOD 0x501C // this is DVO DDC +#define GPIOE 0x5020 // this is DVO i2C +#define GPIOF 0x5024 /* PLL registers */ #define VGA0_DIVISOR 0x06000 @@ -468,9 +487,12 @@ /* I/O macros */ #define INREG8(addr) readb((u8 __iomem *)(dinfo->mmio_base + (addr))) +#define INREG16(addr) readw((u16 __iomem *)(dinfo->mmio_base + (addr))) #define INREG(addr) readl((u32 __iomem *)(dinfo->mmio_base + (addr))) #define OUTREG8(addr, val) writeb((val),(u8 __iomem *)(dinfo->mmio_base + \ (addr))) +#define OUTREG16(addr, val) writew((val),(u16 __iomem *)(dinfo->mmio_base + \ + (addr))) #define OUTREG(addr, val) writel((val),(u32 __iomem *)(dinfo->mmio_base + \ (addr))) @@ -545,5 +567,8 @@ extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height, u8 *data); extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo); +extern int intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable); +extern void intelfbhw_disable_irq(struct intelfb_info *dinfo); +extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe); #endif /* _INTELFBHW_H */ diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 80a04380716..180d94c2b4d 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -608,6 +608,22 @@ void __init macfb_setup(char *options) } } +static void __init iounmap_macfb(void) +{ + if (valkyrie_cmap_regs) + iounmap(valkyrie_cmap_regs); + if (dafb_cmap_regs) + iounmap(dafb_cmap_regs); + if (v8_brazil_cmap_regs) + iounmap(v8_brazil_cmap_regs); + if (rbv_cmap_regs) + iounmap(rbv_cmap_regs); + if (civic_cmap_regs) + iounmap(civic_cmap_regs); + if (csc_cmap_regs) + iounmap(csc_cmap_regs); +} + static int __init macfb_init(void) { int video_cmap_len, video_is_nubus = 0; @@ -962,6 +978,10 @@ static int __init macfb_init(void) if (!err) printk("fb%d: %s frame buffer device\n", fb_info.node, fb_info.fix.id); + else { + iounmap(fb_info.screen_base); + iounmap_macfb(); + } return err; } diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 57abbae5520..797b42305b0 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c @@ -95,12 +95,12 @@ static struct i2c_adapter matrox_i2c_adapter_template = static struct i2c_algo_bit_data matrox_i2c_algo_template = { - NULL, - matroxfb_gpio_setsda, - matroxfb_gpio_setscl, - matroxfb_gpio_getsda, - matroxfb_gpio_getscl, - 10, 10, 100, + .setsda = matroxfb_gpio_setsda, + .setscl = matroxfb_gpio_setscl, + .getsda = matroxfb_gpio_getsda, + .getscl = matroxfb_gpio_getscl, + .udelay = 10, + .timeout = 100, }; static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, @@ -124,7 +124,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, static void i2c_bit_bus_del(struct i2c_bit_adapter* b) { if (b->initialized) { - i2c_bit_del_bus(&b->adapter); + i2c_del_adapter(&b->adapter); b->initialized = 0; } } diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 4a57dabb77d..e9b4115fcad 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -198,7 +198,7 @@ static void matroxfb_crtc1_panpos(WPMINFO2) { } } -static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t matrox_irq(int irq, void *dev_id) { u_int32_t status; int handled = 0; @@ -2277,10 +2277,13 @@ static void __init matroxfb_init_params(void) { } } -static void __init matrox_init(void) { +static int __init matrox_init(void) { + int err; + matroxfb_init_params(); - pci_register_driver(&matroxfb_driver); + err = pci_register_driver(&matroxfb_driver); dev = -1; /* accept all new devices... */ + return err; } /* **************************** exit-time only **************************** */ @@ -2437,6 +2440,7 @@ static int __initdata initialized = 0; static int __init matroxfb_init(void) { char *option = NULL; + int err = 0; DBG(__FUNCTION__) @@ -2448,11 +2452,11 @@ static int __init matroxfb_init(void) return -ENXIO; if (!initialized) { initialized = 1; - matrox_init(); + err = matrox_init(); } hotplug = 1; /* never return failure, user can hotplug matrox later... */ - return 0; + return err; } module_init(matroxfb_init); diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c index 84aab3ad024..472a3ca3d92 100644 --- a/drivers/video/mbx/mbxdebugfs.c +++ b/drivers/video/mbx/mbxdebugfs.c @@ -10,6 +10,8 @@ struct mbxfb_debugfs_data { struct dentry *clock; struct dentry *display; struct dentry *gsctl; + struct dentry *sdram; + struct dentry *misc; }; static int open_file_generic(struct inode *inode, struct file *file) @@ -29,11 +31,11 @@ static ssize_t sysconf_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); - s += sprintf(s, "PFBASE = %08lx\n", PFBASE); - s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); - s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); - s += sprintf(s, "SYSRST = %08lx\n", SYSRST); + s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG)); + s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE)); + s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL)); + s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG)); + s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -45,24 +47,24 @@ static ssize_t gsctl_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); - s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); - s += sprintf(s, "GBBASE = %08lx\n", GBBASE); - s += sprintf(s, "VBBASE = %08lx\n", VBBASE); - s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); - s += sprintf(s, "VCMSK = %08lx\n", VCMSK); - s += sprintf(s, "GSCADR = %08lx\n", GSCADR); - s += sprintf(s, "VSCADR = %08lx\n", VSCADR); - s += sprintf(s, "VUBASE = %08lx\n", VUBASE); - s += sprintf(s, "VVBASE = %08lx\n", VVBASE); - s += sprintf(s, "GSADR = %08lx\n", GSADR); - s += sprintf(s, "VSADR = %08lx\n", VSADR); - s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); - s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); - s += sprintf(s, "HCPOS = %08lx\n", HCPOS); - s += sprintf(s, "HCBADR = %08lx\n", HCBADR); - s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); - s += sprintf(s, "GPLUT = %08lx\n", GPLUT); + s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL)); + s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL)); + s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE)); + s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE)); + s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL)); + s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK)); + s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR)); + s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR)); + s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE)); + s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE)); + s += sprintf(s, "GSADR = %08x\n", readl(GSADR)); + s += sprintf(s, "VSADR = %08x\n", readl(VSADR)); + s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL)); + s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE)); + s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS)); + s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR)); + s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK)); + s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -73,36 +75,36 @@ static ssize_t display_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); - s += sprintf(s, "DHT01 = %08lx\n", DHT01); - s += sprintf(s, "DHT02 = %08lx\n", DHT02); - s += sprintf(s, "DHT03 = %08lx\n", DHT03); - s += sprintf(s, "DVT01 = %08lx\n", DVT01); - s += sprintf(s, "DVT02 = %08lx\n", DVT02); - s += sprintf(s, "DVT03 = %08lx\n", DVT03); - s += sprintf(s, "DBCOL = %08lx\n", DBCOL); - s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); - s += sprintf(s, "DINTRS = %08lx\n", DINTRS); - s += sprintf(s, "DINTRE = %08lx\n", DINTRE); - s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); - s += sprintf(s, "DSIG = %08lx\n", DSIG); - s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); - s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); - s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); - s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); - s += sprintf(s, "DLSTS = %08lx\n", DLSTS); - s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); - s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); - s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); - s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); - s += sprintf(s, "DHDET = %08lx\n", DHDET); - s += sprintf(s, "DVDET = %08lx\n", DVDET); - s += sprintf(s, "DODMSK = %08lx\n", DODMSK); - s += sprintf(s, "CSC01 = %08lx\n", CSC01); - s += sprintf(s, "CSC02 = %08lx\n", CSC02); - s += sprintf(s, "CSC03 = %08lx\n", CSC03); - s += sprintf(s, "CSC04 = %08lx\n", CSC04); - s += sprintf(s, "CSC05 = %08lx\n", CSC05); + s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL)); + s += sprintf(s, "DHT01 = %08x\n", readl(DHT01)); + s += sprintf(s, "DHT02 = %08x\n", readl(DHT02)); + s += sprintf(s, "DHT03 = %08x\n", readl(DHT03)); + s += sprintf(s, "DVT01 = %08x\n", readl(DVT01)); + s += sprintf(s, "DVT02 = %08x\n", readl(DVT02)); + s += sprintf(s, "DVT03 = %08x\n", readl(DVT03)); + s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL)); + s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR)); + s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS)); + s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE)); + s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT)); + s += sprintf(s, "DSIG = %08x\n", readl(DSIG)); + s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL)); + s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL)); + s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL)); + s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL)); + s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS)); + s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL)); + s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM)); + s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL)); + s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL)); + s += sprintf(s, "DHDET = %08x\n", readl(DHDET)); + s += sprintf(s, "DVDET = %08x\n", readl(DVDET)); + s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK)); + s += sprintf(s, "CSC01 = %08x\n", readl(CSC01)); + s += sprintf(s, "CSC02 = %08x\n", readl(CSC02)); + s += sprintf(s, "CSC03 = %08x\n", readl(CSC03)); + s += sprintf(s, "CSC04 = %08x\n", readl(CSC04)); + s += sprintf(s, "CSC05 = %08x\n", readl(CSC05)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -113,24 +115,61 @@ static ssize_t clock_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); - s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); - s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); - s += sprintf(s, "COREPLL = %08lx\n", COREPLL); - s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); - s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); - s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); - s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); - s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); - s += sprintf(s, "M24CLK = %08lx\n", M24CLK); - s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); - s += sprintf(s, "SDCLK = %08lx\n", SDCLK); - s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); + s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC)); + s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC)); + s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP)); + s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL)); + s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL)); + s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT)); + s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK)); + s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK)); + s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK)); + s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK)); + s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK)); + s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK)); + s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); } +static ssize_t sdram_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "LMRST = %08x\n", readl(LMRST)); + s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG)); + s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR)); + s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT)); + s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR)); + s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE)); + s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM)); + s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH)); + s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN)); + s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX)); + s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG)); + s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR)); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + +static ssize_t misc_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG)); + s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR)); + s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT)); + s += sprintf(s, "ID = %08x\n", readl(ID)); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + + static struct file_operations sysconf_fops = { .read = sysconf_read_file, .write = write_file_dummy, @@ -155,6 +194,17 @@ static struct file_operations gsctl_fops = { .open = open_file_generic, }; +static struct file_operations sdram_fops = { + .read = sdram_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations misc_fops = { + .read = misc_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) { @@ -173,6 +223,10 @@ static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) fbi, &display_fops); dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir, fbi, &gsctl_fops); + dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir, + fbi, &sdram_fops); + dbg->misc = debugfs_create_file("misc", 0444, dbg->dir, + fbi, &misc_fops); } static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) @@ -180,6 +234,8 @@ static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) struct mbxfb_info *mfbi = fbi->par; struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data; + debugfs_remove(dbg->misc); + debugfs_remove(dbg->sdram); debugfs_remove(dbg->gsctl); debugfs_remove(dbg->display); debugfs_remove(dbg->clock); diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 6849ab75d40..980d5f62390 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -1,8 +1,14 @@ /* * linux/drivers/video/mbx/mbxfb.c * + * Copyright (C) 2006 8D Technologies inc + * Raphael Assenat <raph@8d.com> + * - Added video overlay support + * - Various improvements + * * Copyright (C) 2006 Compulab, Ltd. * Mike Rapoport <mike@compulab.co.il> + * - Creation of driver * * Based on pxafb.c * @@ -19,6 +25,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/uaccess.h> #include <asm/io.h> @@ -29,6 +36,14 @@ static unsigned long virt_base_2700; +#define write_reg(val, reg) do { writel((val), (reg)); } while(0) + +/* Without this delay, the graphics appears somehow scaled and + * there is a lot of jitter in scanlines. This delay is probably + * needed only after setting some specific register(s) somewhere, + * not all over the place... */ +#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0) + #define MIN_XRES 16 #define MIN_YRES 16 #define MAX_XRES 2048 @@ -118,8 +133,19 @@ static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps, /* convert pixclock to KHz */ pixclock = PICOS2KHZ(pixclock_ps); + /* PLL output freq = (ref_clk * M) / (N * 2^P) + * + * M: 1 to 63 + * N: 1 to 7 + * P: 0 to 7 + */ + + /* RAPH: When N==1, the resulting pixel clock appears to + * get divided by 2. Preventing N=1 by starting the following + * loop at 2 prevents this. Is this a bug with my chip + * revision or something I dont understand? */ for (m = 1; m < 64; m++) { - for (n = 1; n < 8; n++) { + for (n = 2; n < 8; n++) { for (p = 0; p < 8; p++) { clk = (ref_clk * m) / (n * (1 << p)); err = (clk > pixclock) ? (clk - pixclock) : @@ -244,21 +270,19 @@ static int mbxfb_set_par(struct fb_info *info) /* setup resolution */ gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); - gsctrl |= Gsctrl_Width(info->var.xres - 1) | - Gsctrl_Height(info->var.yres - 1); - writel(gsctrl, GSCTRL); - udelay(1000); + gsctrl |= Gsctrl_Width(info->var.xres) | + Gsctrl_Height(info->var.yres); + write_reg_dly(gsctrl, GSCTRL); gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / (8 * 16) - 1); - writel(gsadr, GSADR); - udelay(1000); + write_reg_dly(gsadr, GSADR); /* setup timings */ var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); - writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | + write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); hbps = var->hsync_len; @@ -271,18 +295,20 @@ static int mbxfb_set_par(struct fb_info *info) vfps = vas + var->yres; vt = vfps + var->lower_margin; - writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); - writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); - writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); - writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); + write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); + write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); + write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); + write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); - writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); - writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); - writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); - writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); - writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); + write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); + write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); + write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); + write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); + write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + + write_reg_dly(DINTRE_VEVENT0_EN, DINTRE); return 0; } @@ -294,23 +320,203 @@ static int mbxfb_blank(int blank, struct fb_info *info) case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_NORMAL: - writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); - udelay(1000); - writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); - udelay(1000); - writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); - udelay(1000); + write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); + write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); break; case FB_BLANK_UNBLANK: - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); - udelay(1000); - writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK); - udelay(1000); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK); break; } return 0; } +static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set) +{ + u32 vsctrl, vbbase, vscadr, vsadr; + u32 sssize, spoctrl, svctrl, shctrl; + u32 vubase, vvbase; + u32 vovrclk; + + if (set->scaled_width==0 || set->scaled_height==0) + return -EINVAL; + + /* read registers which have reserved bits + * so we can write them back as-is. */ + vovrclk = readl(VOVRCLK); + vsctrl = readl(VSCTRL); + vscadr = readl(VSCADR); + vubase = readl(VUBASE); + vvbase = readl(VVBASE); + + spoctrl = readl(SPOCTRL); + sssize = readl(SSSIZE); + + + vbbase = Vbbase_Glalpha(set->alpha); + + vsctrl &= ~( FMsk(VSCTRL_VSWIDTH) | + FMsk(VSCTRL_VSHEIGHT) | + FMsk(VSCTRL_VPIXFMT) | + VSCTRL_GAMMA_EN | VSCTRL_CSC_EN | + VSCTRL_COSITED ); + vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) | + VSCTRL_CSC_EN; + + vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC | + FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) | + FMsk(VSCADR_VBASE_ADR) ); + vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR)); + vvbase &= ~(FMsk(VVBASE_VBASE_ADR)); + + switch (set->fmt) + { + case MBXFB_FMT_YUV12: + vsctrl |= VSCTRL_VPIXFMT_YUV12; + + set->Y_stride = ((set->width) + 0xf ) & ~0xf; + + break; + case MBXFB_FMT_UY0VY1: + vsctrl |= VSCTRL_VPIXFMT_UY0VY1; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_VY0UY1: + vsctrl |= VSCTRL_VPIXFMT_VY0UY1; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_Y0UY1V: + vsctrl |= VSCTRL_VPIXFMT_Y0UY1V; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_Y0VY1U: + vsctrl |= VSCTRL_VPIXFMT_Y0VY1U; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + default: + return -EINVAL; + } + + /* VSCTRL has the bits which sets the Video Pixel Format. + * When passing from a packed to planar format, + * if we write VSCTRL first, VVBASE and VUBASE would + * be zero if we would not set them here. (And then, + * the chips hangs and only a reset seems to fix it). + * + * If course, the values calculated here have no meaning + * for packed formats. + */ + set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7; + set->U_offset = set->height * set->Y_stride; + set->V_offset = set->U_offset + + set->height * set->UV_stride; + vubase |= Vubase_Ubase_Adr( + (0x60000 + set->mem_offset + set->U_offset)>>3); + vvbase |= Vvbase_Vbase_Adr( + (0x60000 + set->mem_offset + set->V_offset)>>3); + + + vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB | + Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4); + + if (set->enable) + vscadr |= VSCADR_STR_EN; + + + vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) | + Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y); + + sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT)); + sssize = Sssize_Sc_Width(set->scaled_width-1) | + Sssize_Sc_Height(set->scaled_height-1); + + spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | + SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C | + FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH)); + spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height) + | SPOCTRL_VORDER_2TAP; + + /* Bypass horiz/vert scaler when same size */ + if (set->scaled_width == set->width) + spoctrl |= SPOCTRL_H_SC_BP; + if (set->scaled_height == set->height) + spoctrl |= SPOCTRL_V_SC_BP; + + svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10); + + shctrl = Shctrl_Hinitial(4<<11) + | Shctrl_Hpitch((set->width<<11)/set->scaled_width); + + /* Video plane registers */ + write_reg(vsctrl, VSCTRL); + write_reg(vbbase, VBBASE); + write_reg(vscadr, VSCADR); + write_reg(vubase, VUBASE); + write_reg(vvbase, VVBASE); + write_reg(vsadr, VSADR); + + /* Video scaler registers */ + write_reg(sssize, SSSIZE); + write_reg(spoctrl, SPOCTRL); + write_reg(svctrl, SVCTRL); + write_reg(shctrl, SHCTRL); + + /* RAPH: Using those coefficients, the scaled + * image is quite blurry. I dont know how + * to improve them ; The chip documentation + * was not helpful.. */ + write_reg(0x21212121, VSCOEFF0); + write_reg(0x21212121, VSCOEFF1); + write_reg(0x21212121, VSCOEFF2); + write_reg(0x21212121, VSCOEFF3); + write_reg(0x21212121, VSCOEFF4); + write_reg(0x00000000, HSCOEFF0); + write_reg(0x00000000, HSCOEFF1); + write_reg(0x00000000, HSCOEFF2); + write_reg(0x03020201, HSCOEFF3); + write_reg(0x09070604, HSCOEFF4); + write_reg(0x0f0e0c0a, HSCOEFF5); + write_reg(0x15141211, HSCOEFF6); + write_reg(0x19181716, HSCOEFF7); + write_reg(0x00000019, HSCOEFF8); + + /* Clock */ + if (set->enable) + vovrclk |= 1; + else + vovrclk &= ~1; + + write_reg(vovrclk, VOVRCLK); + + return 0; +} + +static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct mbxfb_overlaySetup setup; + int res; + + if (cmd == MBXFB_IOCX_OVERLAY) + { + if (copy_from_user(&setup, (void __user*)arg, + sizeof(struct mbxfb_overlaySetup))) + return -EFAULT; + + res = mbxfb_setupOverlay(&setup); + if (res) + return res; + + if (copy_to_user((void __user*)arg, &setup, + sizeof(struct mbxfb_overlaySetup))) + return -EFAULT; + + return 0; + } + return -EINVAL; +} + static struct fb_ops mbxfb_ops = { .owner = THIS_MODULE, .fb_check_var = mbxfb_check_var, @@ -320,6 +526,7 @@ static struct fb_ops mbxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = mbxfb_blank, + .fb_ioctl = mbxfb_ioctl, }; /* @@ -328,36 +535,29 @@ static struct fb_ops mbxfb_ops = { */ static void __devinit setup_memc(struct fb_info *fbi) { - struct mbxfb_info *mfbi = fbi->par; unsigned long tmp; int i; /* FIXME: use platfrom specific parameters */ /* setup SDRAM controller */ - writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | + write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS), LMCFG); - udelay(1000); - writel(LMPWR_MC_PWR_ACT, LMPWR); - udelay(1000); + write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); /* setup SDRAM timings */ - writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | + write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | Lmtim_Trc(9) | Lmtim_Tdpl(2)), LMTIM); - udelay(1000); /* setup SDRAM refresh rate */ - writel(0xc2b, LMREFRESH); - udelay(1000); + write_reg_dly(0xc2b, LMREFRESH); /* setup SDRAM type parameters */ - writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | + write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | LMTYPE_COLSZ_8), LMTYPE); - udelay(1000); /* enable memory controller */ - writel(LMPWR_MC_PWR_ACT, LMPWR); - udelay(1000); + write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); /* perform dummy reads */ for ( i = 0; i < 16; i++ ) { @@ -368,42 +568,38 @@ static void __devinit setup_memc(struct fb_info *fbi) static void enable_clocks(struct fb_info *fbi) { /* enable clocks */ - writel(SYSCLKSRC_PLL_2, SYSCLKSRC); - udelay(1000); - writel(PIXCLKSRC_PLL_1, PIXCLKSRC); - udelay(1000); - writel(0x00000000, CLKSLEEP); - udelay(1000); - writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | + write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC); + write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC); + write_reg_dly(0x00000000, CLKSLEEP); + + /* PLL output = (Frefclk * M) / (N * 2^P ) + * + * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz! + * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz + * */ + write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) | CORE_PLL_EN), COREPLL); - udelay(1000); - writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | + + write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | DISP_PLL_EN), DISPPLL); - writel(0x00000000, VOVRCLK); - udelay(1000); - writel(PIXCLK_EN, PIXCLK); - udelay(1000); - writel(MEMCLK_EN, MEMCLK); - udelay(1000); - writel(0x00000006, M24CLK); - udelay(1000); - writel(0x00000006, MBXCLK); - udelay(1000); - writel(SDCLK_EN, SDCLK); - udelay(1000); - writel(0x00000001, PIXCLKDIV); - udelay(1000); + write_reg_dly(0x00000000, VOVRCLK); + write_reg_dly(PIXCLK_EN, PIXCLK); + write_reg_dly(MEMCLK_EN, MEMCLK); + write_reg_dly(0x00000006, M24CLK); + write_reg_dly(0x00000006, MBXCLK); + write_reg_dly(SDCLK_EN, SDCLK); + write_reg_dly(0x00000001, PIXCLKDIV); } static void __devinit setup_graphics(struct fb_info *fbi) { unsigned long gsctrl; - gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres - 1) | - Gsctrl_Height(fbi->var.yres - 1); + gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres) | + Gsctrl_Height(fbi->var.yres); switch (fbi->var.bits_per_pixel) { case 16: if (fbi->var.green.length == 5) @@ -419,16 +615,11 @@ static void __devinit setup_graphics(struct fb_info *fbi) break; } - writel(gsctrl, GSCTRL); - udelay(1000); - writel(0x00000000, GBBASE); - udelay(1000); - writel(0x00ffffff, GDRCTRL); - udelay(1000); - writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); - udelay(1000); - writel(0x00000000, GPLUT); - udelay(1000); + write_reg_dly(gsctrl, GSCTRL); + write_reg_dly(0x00000000, GBBASE); + write_reg_dly(0x00ffffff, GDRCTRL); + write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); + write_reg_dly(0x00000000, GPLUT); } static void __devinit setup_display(struct fb_info *fbi) @@ -440,17 +631,14 @@ static void __devinit setup_display(struct fb_info *fbi) dsctrl |= DSCTRL_HS_POL; if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) dsctrl |= DSCTRL_VS_POL; - writel(dsctrl, DSCTRL); - udelay(1000); - writel(0xd0303010, DMCTRL); - udelay(1000); - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly(dsctrl, DSCTRL); + write_reg_dly(0xd0303010, DMCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); } static void __devinit enable_controller(struct fb_info *fbi) { - writel(SYSRST_RST, SYSRST); - udelay(1000); + write_reg_dly(SYSRST_RST, SYSRST); enable_clocks(fbi); @@ -467,12 +655,12 @@ static void __devinit enable_controller(struct fb_info *fbi) static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) { /* make frame buffer memory enter self-refresh mode */ - writel(LMPWR_MC_PWR_SRM, LMPWR); + write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR); while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) ; /* empty statement */ /* reset the device, since it's initial state is 'mostly sleeping' */ - writel(SYSRST_RST, SYSRST); + write_reg_dly(SYSRST_RST, SYSRST); return 0; } @@ -484,7 +672,7 @@ static int mbxfb_resume(struct platform_device *dev) /* setup_graphics(fbi); */ /* setup_display(fbi); */ - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); return 0; } #else @@ -509,6 +697,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev) dev_dbg(dev, "mbxfb_probe\n"); + pdata = dev->dev.platform_data; + if (!pdata) { + dev_err(&dev->dev, "platform data is required\n"); + return -EINVAL; + } + fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); if (fbi == NULL) { dev_err(&dev->dev, "framebuffer_alloc failed\n"); @@ -517,7 +711,8 @@ static int __devinit mbxfb_probe(struct platform_device *dev) mfbi = fbi->par; fbi->pseudo_palette = mfbi->pseudo_palette; - pdata = dev->dev.platform_data; + + if (pdata->probe) mfbi->platform_probe = pdata->probe; if (pdata->remove) @@ -567,16 +762,16 @@ static int __devinit mbxfb_probe(struct platform_device *dev) goto err4; } - /* FIXME: get from platform */ fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); - fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */ + fbi->screen_size = pdata->memsize; fbi->fbops = &mbxfb_ops; fbi->var = mbxfb_default; fbi->fix = mbxfb_fix; fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; - fbi->fix.smem_len = 8 * 1024 * 1024; - fbi->fix.line_length = 640 * 2; + fbi->fix.smem_len = pdata->memsize; + fbi->fix.line_length = mbxfb_default.xres_virtual * + mbxfb_default.bits_per_pixel / 8; ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret < 0) { @@ -625,8 +820,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev) { struct fb_info *fbi = platform_get_drvdata(dev); - writel(SYSRST_RST, SYSRST); - udelay(1000); + write_reg_dly(SYSRST_RST, SYSRST); mbxfb_debugfs_remove(fbi); diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h index c226a8e4531..9a24fb0c7d4 100644 --- a/drivers/video/mbx/reg_bits.h +++ b/drivers/video/mbx/reg_bits.h @@ -242,6 +242,67 @@ #define GPLUT_LUTDATA Fld(24,0) #define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) +/* VSCTRL - Video Surface Control Register */ +#define VSCTRL_VPIXFMT Fld(4,27) +#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_GAMMA_EN (1 << 26) +#define VSCTRL_CSC_EN (1 << 25) +#define VSCTRL_COSITED (1 << 22) +#define VSCTRL_VSWIDTH Fld(11,11) +#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \ + (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH)) +#define VSCTRL_VSHEIGHT Fld(11,0) +#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \ + (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT)) + +/* VBBASE - Video Blending Base Register */ +#define VBBASE_GLALPHA Fld(8,24) +#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA)) + +#define VBBASE_COLKEY Fld(24,0) +#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY)) + +/* VCMSK - Video Color Key Mask Register */ +#define VCMSK_COLKEY_M Fld(24,0) +#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M)) + +/* VSCADR - Video Stream Control Rddress Register */ +#define VSCADR_STR_EN (1 << 31) +#define VSCADR_COLKEY_EN (1 << 30) +#define VSCADR_COLKEYSRC (1 << 29) +#define VSCADR_BLEND_M Fld(2,27) +#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_POS Fld(2,24) +#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_VBASE_ADR Fld(23,0) +#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR)) + +/* VUBASE - Video U Base Register */ +#define VUBASE_UVHALFSTR (1 << 31) +#define VUBASE_UBASE_ADR Fld(24,0) +#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR)) + +/* VVBASE - Video V Base Register */ +#define VVBASE_VBASE_ADR Fld(24,0) +#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR)) + +/* VSADR - Video Stride Address Register */ +#define VSADR_SRCSTRIDE Fld(10,22) +#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE)) +#define VSADR_XSTART Fld(11,11) +#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART)) +#define VSADR_YSTART Fld(11,0) +#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART)) + /* HCCTRL - Hardware Cursor Register fields */ #define HCCTRL_CUR_EN (1 << 31) #define HCCTRL_COLKEY_EN (1 << 29) @@ -394,6 +455,30 @@ #define DMCTRL_BURSTLEN Fld(6,0) #define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) +/* DINTRS - Display Interrupt Status Register */ +#define DINTRS_CUR_OR_S (1 << 18) +#define DINTRS_STR2_OR_S (1 << 17) +#define DINTRS_STR1_OR_S (1 << 16) +#define DINTRS_CUR_UR_S (1 << 6) +#define DINTRS_STR2_UR_S (1 << 5) +#define DINTRS_STR1_UR_S (1 << 4) +#define DINTRS_VEVENT1_S (1 << 3) +#define DINTRS_VEVENT0_S (1 << 2) +#define DINTRS_HBLNK1_S (1 << 1) +#define DINTRS_HBLNK0_S (1 << 0) + +/* DINTRE - Display Interrupt Enable Register */ +#define DINTRE_CUR_OR_EN (1 << 18) +#define DINTRE_STR2_OR_EN (1 << 17) +#define DINTRE_STR1_OR_EN (1 << 16) +#define DINTRE_CUR_UR_EN (1 << 6) +#define DINTRE_STR2_UR_EN (1 << 5) +#define DINTRE_STR1_UR_EN (1 << 4) +#define DINTRE_VEVENT1_EN (1 << 3) +#define DINTRE_VEVENT0_EN (1 << 2) +#define DINTRE_HBLNK1_EN (1 << 1) +#define DINTRE_HBLNK0_EN (1 << 0) + /* DLSTS - display load status register */ #define DLSTS_RLD_ADONE (1 << 23) @@ -403,16 +488,41 @@ #define DLLCTRL_RLD_ADRLN Fld(8,24) #define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) +/* CLIPCTRL - Clipping Control Register */ +#define CLIPCTRL_HSKIP Fld(11,16) +#define Clipctrl_Hskip ((x) << FShft(CLIPCTRL_HSKIP)) +#define CLIPCTRL_VSKIP Fld(11,0) +#define Clipctrl_Vskip ((x) << FShft(CLIPCTRL_VSKIP)) + /* SPOCTRL - Scale Pitch/Order Control Register */ #define SPOCTRL_H_SC_BP (1 << 31) #define SPOCTRL_V_SC_BP (1 << 30) #define SPOCTRL_HV_SC_OR (1 << 29) #define SPOCTRL_VS_UR_C (1 << 27) -#define SPOCTRL_VORDER Fld(2,16) +#define SPOCTRL_VORDER Fld(2,16) #define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) #define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) #define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) -#define SPOCTRL_VPITCH Fld(16,0) +#define SPOCTRL_VPITCH Fld(16,0) #define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) +/* SVCTRL - Scale Vertical Control Register */ +#define SVCTRL_INITIAL1 Fld(16,16) +#define Svctrl_Initial1(x) ((x) << FShft(SVCTRL_INITIAL1)) +#define SVCTRL_INITIAL2 Fld(16,0) +#define Svctrl_Initial2(x) ((x) << FShft(SVCTRL_INITIAL2)) + +/* SHCTRL - Scale Horizontal Control Register */ +#define SHCTRL_HINITIAL Fld(16,16) +#define Shctrl_Hinitial(x) ((x) << FShft(SHCTRL_HINITIAL)) +#define SHCTRL_HDECIM (1 << 15) +#define SHCTRL_HPITCH Fld(15,0) +#define Shctrl_Hpitch(x) ((x) << FShft(SHCTRL_HPITCH)) + +/* SSSIZE - Scale Surface Size Register */ +#define SSSIZE_SC_WIDTH Fld(11,16) +#define Sssize_Sc_Width(x) ((x) << FShft(SSSIZE_SC_WIDTH)) +#define SSSIZE_SC_HEIGHT Fld(11,0) +#define Sssize_Sc_Height(x) ((x) << FShft(SSSIZE_SC_HEIGHT)) + #endif /* __REG_BITS_2700G_ */ diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h index ad20be07666..a7c63d865aa 100644 --- a/drivers/video/mbx/regs.h +++ b/drivers/video/mbx/regs.h @@ -127,7 +127,7 @@ #define HSCOEFF0 __REG_2700G(0x000021b4) #define HSCOEFF1 __REG_2700G(0x000021b8) #define HSCOEFF2 __REG_2700G(0x000021bc) -#define HSCOEFF3 __REG_2700G(0x000021b0) +#define HSCOEFF3 __REG_2700G(0x000021c0) #define HSCOEFF4 __REG_2700G(0x000021c4) #define HSCOEFF5 __REG_2700G(0x000021c8) #define HSCOEFF6 __REG_2700G(0x000021cc) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index d1267904c28..5df41f6f2b8 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -34,8 +34,6 @@ const char *global_mode_option; * Standard video mode definitions (taken from XFree86) */ -#define DEFAULT_MODEDB_INDEX 0 - static const struct fb_videomode modedb[] = { { /* 640x400 @ 70 Hz, 31.5 kHz hsync */ @@ -505,8 +503,10 @@ int fb_find_mode(struct fb_var_screeninfo *var, db = modedb; dbsize = ARRAY_SIZE(modedb); } + if (!default_mode) - default_mode = &modedb[DEFAULT_MODEDB_INDEX]; + default_mode = &db[0]; + if (!default_bpp) default_bpp = 8; diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 59a6f5fa5ae..deaf820cb38 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1932,7 +1932,7 @@ static int __devinit neo_init_hw(struct fb_info *info) printk(KERN_DEBUG "--- Neo extended register dump ---\n"); for (int w = 0; w < 0x85; w++) printk(KERN_DEBUG "CR %p: %p\n", (void *) w, - (void *) vga_rcrt(NULL, w); + (void *) vga_rcrt(NULL, w)); for (int w = 0; w < 0xC7; w++) printk(KERN_DEBUG "GR %p: %p\n", (void *) w, (void *) vga_rgfx(NULL, w)); diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c index 4aefb8f4163..9efb8a3854e 100644 --- a/drivers/video/nvidia/nv_accel.c +++ b/drivers/video/nvidia/nv_accel.c @@ -261,41 +261,6 @@ void NVResetGraphics(struct fb_info *info) NVDmaKickoff(par); } -u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - int nvidiafb_sync(struct fb_info *info) { struct nvidia_par *par = info->par; diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index 9ed640d3572..ea426115c6f 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -145,12 +145,18 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk, if (par->Architecture >= NV_ARCH_40) { pll = NV_RD32(par->PMC, 0x4020); - P = (pll >> 16) & 0x03; + P = (pll >> 16) & 0x07; pll = NV_RD32(par->PMC, 0x4024); M = pll & 0xFF; N = (pll >> 8) & 0xFF; - MB = (pll >> 16) & 0xFF; - NB = (pll >> 24) & 0xFF; + if (((par->Chipset & 0xfff0) == 0x0290) || + ((par->Chipset & 0xfff0) == 0x0390)) { + MB = 1; + NB = 1; + } else { + MB = (pll >> 16) & 0xFF; + NB = (pll >> 24) & 0xFF; + } *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; pll = NV_RD32(par->PMC, 0x4000); diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index 19eef3a0902..8454adf2d17 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c @@ -147,15 +147,15 @@ void nvidia_create_i2c_busses(struct nvidia_par *par) void nvidia_delete_i2c_busses(struct nvidia_par *par) { if (par->chan[0].par) - i2c_bit_del_bus(&par->chan[0].adapter); + i2c_del_adapter(&par->chan[0].adapter); par->chan[0].par = NULL; if (par->chan[1].par) - i2c_bit_del_bus(&par->chan[1].adapter); + i2c_del_adapter(&par->chan[1].adapter); par->chan[1].par = NULL; if (par->chan[2].par) - i2c_bit_del_bus(&par->chan[2].adapter); + i2c_del_adapter(&par->chan[2].adapter); par->chan[2].par = NULL; } @@ -210,11 +210,8 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) /* try to get from firmware */ const u8 *e = fb_firmware_edid(info->device); - if (e != NULL) { - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); - } + if (e != NULL) + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } *out_edid = edid; diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h index 4243d7fae97..e009d242ea1 100644 --- a/drivers/video/nvidia/nv_local.h +++ b/drivers/video/nvidia/nv_local.h @@ -96,13 +96,16 @@ #define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2) #ifdef __LITTLE_ENDIAN + +#include <linux/bitrev.h> + #define reverse_order(l) \ do { \ u8 *a = (u8 *)(l); \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a]; \ + a[0] = bitrev8(a[0]); \ + a[1] = bitrev8(a[1]); \ + a[2] = bitrev8(a[2]); \ + a[3] = bitrev8(a[3]); \ } while(0) #else #define reverse_order(l) do { } while(0) diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c index d9af88c2b58..181875fe35c 100644 --- a/drivers/video/nvidia/nv_of.c +++ b/drivers/video/nvidia/nv_of.c @@ -72,10 +72,9 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) } } if (pedid) { - *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + *out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); if (*out_edid == NULL) return -1; - memcpy(*out_edid, pedid, EDID_LENGTH); printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); return 0; } diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index 86127101765..43058d0cf5b 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -62,7 +62,6 @@ extern void nvidiafb_fillrect(struct fb_info *info, extern void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image); extern int nvidiafb_sync(struct fb_info *info); -extern u8 byte_rev[256]; /* in nv_backlight.h */ #ifdef CONFIG_FB_NVIDIA_BACKLIGHT diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index a18a9aebf05..eab3e282a4d 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -262,7 +262,7 @@ static void nv10GetConfig(struct nvidia_par *par) #endif dev = pci_find_slot(0, 1); - if ((par->Chipset && 0xffff) == 0x01a0) { + if ((par->Chipset & 0xffff) == 0x01a0) { int amt = 0; pci_read_config_dword(dev, 0x7c, &amt); @@ -359,6 +359,7 @@ int NVCommonSetup(struct fb_info *info) case 0x0186: case 0x0187: case 0x018D: + case 0x0228: case 0x0286: case 0x028C: case 0x0316: @@ -382,6 +383,10 @@ int NVCommonSetup(struct fb_info *info) case 0x034C: case 0x0160: case 0x0166: + case 0x0169: + case 0x016B: + case 0x016C: + case 0x016D: case 0x00C8: case 0x00CC: case 0x0144: @@ -639,12 +644,23 @@ int NVCommonSetup(struct fb_info *info) par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1; par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033; - printk("Panel size is %i x %i\n", par->fpWidth, par->fpHeight); + printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight); } if (monA) info->monspecs = *monA; + if (!par->FlatPanel || !par->twoHeads) + par->FPDither = 0; + + par->LVDS = 0; + if (par->FlatPanel && par->twoHeads) { + NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004); + if (par->PRAMDAC0[0x08b4] & 1) + par->LVDS = 1; + printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS"); + } + kfree(edidA); kfree(edidB); done: diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index acdc2669340..86e65dea60d 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h @@ -129,6 +129,7 @@ struct nvidia_par { int fpHeight; int PanelTweak; int paneltweak; + int LVDS; int pm_state; u32 crtcSync_read; u32 fpSyncs; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index f8cd4c519ae..538e947610e 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -28,6 +28,9 @@ #include <asm/prom.h> #include <asm/pci-bridge.h> #endif +#ifdef CONFIG_BOOTX_TEXT +#include <asm/btext.h> +#endif #include "nv_local.h" #include "nv_type.h" @@ -681,6 +684,13 @@ static int nvidiafb_set_par(struct fb_info *info) nvidia_vga_protect(par, 0); +#ifdef CONFIG_BOOTX_TEXT + /* Update debug text engine */ + btext_update_display(info->fix.smem_start, + info->var.xres, info->var.yres, + info->var.bits_per_pixel, info->fix.line_length); +#endif + NVTRACE_LEAVE(); return 0; } @@ -984,7 +994,10 @@ static int nvidiafb_resume(struct pci_dev *dev) if (par->pm_state != PM_EVENT_FREEZE) { pci_restore_state(dev); - pci_enable_device(dev); + + if (pci_enable_device(dev)) + goto fail; + pci_set_master(dev); } @@ -993,6 +1006,7 @@ static int nvidiafb_resume(struct pci_dev *dev) fb_set_suspend (info, 0); nvidiafb_blank(FB_BLANK_UNBLANK, info); +fail: release_console_sem(); return 0; } @@ -1146,20 +1160,20 @@ static u32 __devinit nvidia_get_arch(struct fb_info *info) case 0x0340: /* GeForceFX 5700 */ arch = NV_ARCH_30; break; - case 0x0040: - case 0x00C0: - case 0x0120: + case 0x0040: /* GeForce 6800 */ + case 0x00C0: /* GeForce 6800 */ + case 0x0120: /* GeForce 6800 */ case 0x0130: - case 0x0140: - case 0x0160: - case 0x01D0: - case 0x0090: - case 0x0210: - case 0x0220: + case 0x0140: /* GeForce 6600 */ + case 0x0160: /* GeForce 6200 */ + case 0x01D0: /* GeForce 7200, 7300, 7400 */ + case 0x0090: /* GeForce 7800 */ + case 0x0210: /* GeForce 6800 */ + case 0x0220: /* GeForce 6200 */ case 0x0230: - case 0x0240: - case 0x0290: - case 0x0390: + case 0x0240: /* GeForce 6100 */ + case 0x0290: /* GeForce 7900 */ + case 0x0390: /* GeForce 7600 */ arch = NV_ARCH_40; break; case 0x0020: /* TNT, TNT2 */ diff --git a/drivers/video/offb.c b/drivers/video/offb.c index bad0e98fb3b..9576a55eaf1 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -157,7 +157,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue)); break; case cmap_gxt2000: - out_le32((unsigned __iomem *) par->cmap_adr + regno, + out_le32(((unsigned __iomem *) par->cmap_adr) + regno, (red << 16 | green << 8 | blue)); break; } @@ -213,7 +213,7 @@ static int offb_blank(int blank, struct fb_info *info) out_le32(par->cmap_adr + 0xb4, 0); break; case cmap_gxt2000: - out_le32((unsigned __iomem *) par->cmap_adr + i, + out_le32(((unsigned __iomem *) par->cmap_adr) + i, 0); break; } @@ -226,13 +226,23 @@ static int offb_blank(int blank, struct fb_info *info) static void __iomem *offb_map_reg(struct device_node *np, int index, unsigned long offset, unsigned long size) { - struct resource r; - - if (of_address_to_resource(np, index, &r)) - return 0; - if ((r.start + offset + size) > r.end) - return 0; - return ioremap(r.start + offset, size); + const u32 *addrp; + u64 asize, taddr; + unsigned int flags; + + addrp = of_get_pci_address(np, index, &asize, &flags); + if (addrp == NULL) + addrp = of_get_address(np, index, &asize, &flags); + if (addrp == NULL) + return NULL; + if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) + return NULL; + if ((offset + size) > asize) + return NULL; + taddr = of_translate_address(np, addrp); + if (taddr == OF_BAD_ADDR) + return NULL; + return ioremap(taddr + offset, size); } static void __init offb_init_fb(const char *name, const char *full_name, @@ -289,7 +299,6 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_type = cmap_unknown; if (depth == 8) { - /* Palette hacks disabled for now */ if (dp && !strncmp(name, "ATY,Rage128", 11)) { par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); if (par->cmap_adr) @@ -313,7 +322,8 @@ static void __init offb_init_fb(const char *name, const char *full_name, ioremap(base + 0x7ff000, 0x1000) + 0xcc0; par->cmap_data = par->cmap_adr + 1; par->cmap_type = cmap_m64; - } else if (dp && device_is_compatible(dp, "pci1014,b7")) { + } else if (dp && (device_is_compatible(dp, "pci1014,b7") || + device_is_compatible(dp, "pci1014,21c"))) { par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); if (par->cmap_adr) par->cmap_type = cmap_gxt2000; @@ -392,6 +402,9 @@ static void __init offb_init_fb(const char *name, const char *full_name, fb_alloc_cmap(&info->cmap, 256, 0); if (register_framebuffer(info) < 0) { + iounmap(par->cmap_adr); + par->cmap_adr = NULL; + iounmap(info->screen_base); kfree(info); release_mem_region(res_start, res_size); return; @@ -433,7 +446,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) pp = get_property(dp, "linux,bootx-linebytes", &len); if (pp == NULL) pp = get_property(dp, "linebytes", &len); - if (pp && len == sizeof(u32)) + if (pp && len == sizeof(u32) && (*pp != 0xffffffffu)) pitch = *pp; else pitch = width * ((depth + 7) / 8); @@ -496,7 +509,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) offb_init_fb(no_real_node ? "bootx" : dp->name, no_real_node ? "display" : dp->full_name, width, height, depth, pitch, address, - no_real_node ? dp : NULL); + no_real_node ? NULL : dp); } } diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 983be3ec234..23387165582 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -34,6 +34,7 @@ #include <asm/prom.h> #include <asm/pgtable.h> #include <asm/of_device.h> +#include <asm/of_platform.h> #include "macmodes.h" #include "platinumfb.h" @@ -339,11 +340,12 @@ static int __devinit platinum_init_fb(struct fb_info *info) sense = read_platinum_sense(pinfo); printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense); - if (default_vmode == VMODE_NVRAM) { +#ifdef CONFIG_NVRAM default_vmode = nvram_read_byte(NV_VMODE); if (default_vmode <= 0 || default_vmode > VMODE_MAX || !platinum_reg_init[default_vmode-1]) +#endif default_vmode = VMODE_CHOOSE; } if (default_vmode == VMODE_CHOOSE) { @@ -351,8 +353,10 @@ static int __devinit platinum_init_fb(struct fb_info *info) } 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; /* @@ -623,6 +627,9 @@ static int __devinit platinumfb_probe(struct of_device* odev, rc = platinum_init_fb(info); if (rc != 0) { + iounmap(pinfo->frame_buffer); + iounmap(pinfo->platinum_regs); + iounmap(pinfo->cmap_regs); dev_set_drvdata(&odev->dev, NULL); framebuffer_release(info); } @@ -679,14 +686,14 @@ static int __init platinumfb_init(void) return -ENODEV; platinumfb_setup(option); #endif - of_register_driver(&platinum_driver); + of_register_platform_driver(&platinum_driver); return 0; } static void __exit platinumfb_exit(void) { - of_unregister_driver(&platinum_driver); + of_unregister_platform_driver(&platinum_driver); } MODULE_LICENSE("GPL"); diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 73e2d7d1660..a06a064ad75 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -186,7 +186,7 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info) static void __init pmagbbfb_osc_setup(struct fb_info *info) { static unsigned int pmagbbfb_freqs[] __initdata = { - 130808, 119843, 104000, 92980, 74367, 72800, + 130808, 119843, 104000, 92980, 74370, 72800, 69197, 66000, 65000, 50350, 36000, 32000, 25175 }; struct pmagbbfb_par *par = info->par; diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c index 7d9453c91a4..f29e66e2d77 100644 --- a/drivers/video/pnx4008/pnxrgbfb.c +++ b/drivers/video/pnx4008/pnxrgbfb.c @@ -154,7 +154,8 @@ static int __devinit rgbfb_probe(struct platform_device *pdev) goto err1; } - if (!fb_get_options("pnxrgbfb", &option) && !strcmp(option, "nocursor")) + if (!fb_get_options("pnxrgbfb", &option) && option && + !strcmp(option, "nocursor")) rgbfb_ops.fb_cursor = no_cursor; info->node = -1; @@ -191,7 +192,7 @@ err: static struct platform_driver rgbfb_driver = { .driver = { - .name = "rgbfb", + .name = "pnx4008-rgbfb", }, .probe = rgbfb_probe, .remove = rgbfb_remove, diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c index 51f0ecc2a51..d23bf0d659b 100644 --- a/drivers/video/pnx4008/sdum.c +++ b/drivers/video/pnx4008/sdum.c @@ -848,7 +848,7 @@ static int sdum_remove(struct platform_device *pdev) static struct platform_driver sdum_driver = { .driver = { - .name = "sdum", + .name = "pnx4008-sdum", }, .probe = sdum_probe, .remove = sdum_remove, diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 940ba2be55e..a93618bc9d2 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -187,7 +187,7 @@ static short do_blank = 0; /* (Un)Blank the screen */ static unsigned int is_blanked = 0; /* Is the screen blanked? */ #ifdef CONFIG_SH_STORE_QUEUES -static struct sq_mapping *pvr2fb_map; +static unsigned long pvr2fb_map; #endif #ifdef CONFIG_SH_DMA @@ -209,19 +209,21 @@ static int pvr2fb_set_par(struct fb_info *info); static void pvr2_update_display(struct fb_info *info); static void pvr2_init_display(struct fb_info *info); static void pvr2_do_blank(void); -static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp); +static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id); static int pvr2_init_cable(void); static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, int size); +#ifdef CONFIG_SH_DMA static ssize_t pvr2fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos); +#endif static struct fb_ops pvr2fb_ops = { - .owner = THIS_MODULE, - .fb_setcolreg = pvr2fb_setcolreg, - .fb_blank = pvr2fb_blank, - .fb_check_var = pvr2fb_check_var, - .fb_set_par = pvr2fb_set_par, + .owner = THIS_MODULE, + .fb_setcolreg = pvr2fb_setcolreg, + .fb_blank = pvr2fb_blank, + .fb_check_var = pvr2fb_check_var, + .fb_set_par = pvr2fb_set_par, #ifdef CONFIG_SH_DMA .fb_write = pvr2fb_write, #endif @@ -624,7 +626,7 @@ static void pvr2_do_blank(void) is_blanked = do_blank > 0 ? do_blank : 0; } -static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id) { struct fb_info *info = dev_id; @@ -783,7 +785,7 @@ static int __init pvr2fb_common_init(void) goto out_err; } - fb_memset((unsigned long)fb_info->screen_base, 0, pvr2_fix.smem_len); + fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len); pvr2_fix.ypanstep = nopan ? 0 : 1; pvr2_fix.ywrapstep = nowrap ? 0 : 1; @@ -820,7 +822,7 @@ static int __init pvr2fb_common_init(void) modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10)); printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", fb_info->node, fb_info->var.xres, fb_info->var.yres, - fb_info->var.bits_per_pixel, + fb_info->var.bits_per_pixel, get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), (char *)pvr2_get_param(cables, NULL, cable_type, 3), (char *)pvr2_get_param(outputs, NULL, video_output, 3)); @@ -829,10 +831,10 @@ static int __init pvr2fb_common_init(void) printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node); pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len, - fb_info->fix.id); + fb_info->fix.id, pgprot_val(PAGE_SHARED)); printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n", - fb_info->node, pvr2fb_map->sq_addr); + fb_info->node, pvr2fb_map); #endif return 0; @@ -903,6 +905,15 @@ static int __init pvr2fb_dc_init(void) static void pvr2fb_dc_exit(void) { + if (fb_info->screen_base) { + iounmap(fb_info->screen_base); + fb_info->screen_base = NULL; + } + if (currentpar->mmio_base) { + iounmap((void *)currentpar->mmio_base); + currentpar->mmio_base = 0; + } + free_irq(HW_EVENT_VSYNC, 0); #ifdef CONFIG_SH_DMA free_dma(pvr2dma); @@ -944,6 +955,15 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev, static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev) { + if (fb_info->screen_base) { + iounmap(fb_info->screen_base); + fb_info->screen_base = NULL; + } + if (currentpar->mmio_base) { + iounmap((void *)currentpar->mmio_base); + currentpar->mmio_base = 0; + } + pci_release_regions(pdev); } diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index bbb07106cd5..38eb0b69c2d 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -59,7 +59,7 @@ #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP) static void (*pxafb_backlight_power)(int); -static void (*pxafb_lcd_power)(int); +static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *); static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *); static void set_ctrlr_state(struct pxafb_info *fbi, u_int state); @@ -214,6 +214,48 @@ extern unsigned int get_clk_frequency_khz(int info); #endif /* + * Select the smallest mode that allows the desired resolution to be + * displayed. If desired parameters can be rounded up. + */ +static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach, struct fb_var_screeninfo *var) +{ + struct pxafb_mode_info *mode = NULL; + struct pxafb_mode_info *modelist = mach->modes; + unsigned int best_x = 0xffffffff, best_y = 0xffffffff; + unsigned int i; + + for (i = 0 ; i < mach->num_modes ; i++) { + if (modelist[i].xres >= var->xres && modelist[i].yres >= var->yres && + modelist[i].xres < best_x && modelist[i].yres < best_y && + modelist[i].bpp >= var->bits_per_pixel ) { + best_x = modelist[i].xres; + best_y = modelist[i].yres; + mode = &modelist[i]; + } + } + + return mode; +} + +static void pxafb_setmode(struct fb_var_screeninfo *var, struct pxafb_mode_info *mode) +{ + var->xres = mode->xres; + var->yres = mode->yres; + var->bits_per_pixel = mode->bpp; + var->pixclock = mode->pixclock; + var->hsync_len = mode->hsync_len; + var->left_margin = mode->left_margin; + var->right_margin = mode->right_margin; + var->vsync_len = mode->vsync_len; + var->upper_margin = mode->upper_margin; + var->lower_margin = mode->lower_margin; + var->sync = mode->sync; + var->grayscale = mode->cmap_greyscale; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; +} + +/* * pxafb_check_var(): * Get the video params out of 'var'. If a value doesn't fit, round it up, * if it's too big, return -EINVAL. @@ -225,15 +267,29 @@ extern unsigned int get_clk_frequency_khz(int info); static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct pxafb_info *fbi = (struct pxafb_info *)info; + struct pxafb_mach_info *inf = fbi->dev->platform_data; if (var->xres < MIN_XRES) var->xres = MIN_XRES; if (var->yres < MIN_YRES) var->yres = MIN_YRES; - if (var->xres > fbi->max_xres) - return -EINVAL; - if (var->yres > fbi->max_yres) - return -EINVAL; + + if (inf->fixed_modes) { + struct pxafb_mode_info *mode; + + mode = pxafb_getmode(inf, var); + if (!mode) + return -EINVAL; + pxafb_setmode(var, mode); + } else { + if (var->xres > inf->modes->xres) + return -EINVAL; + if (var->yres > inf->modes->yres) + return -EINVAL; + if (var->bits_per_pixel > inf->modes->bpp) + return -EINVAL; + } + var->xres_virtual = max(var->xres_virtual, var->xres); var->yres_virtual = @@ -693,7 +749,7 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on) pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff"); if (pxafb_lcd_power) - pxafb_lcd_power(on); + pxafb_lcd_power(on, &fbi->fb.var); } static void pxafb_setup_gpio(struct pxafb_info *fbi) @@ -790,7 +846,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) /* * pxafb_handle_irq: Handle 'LCD DONE' interrupts. */ -static irqreturn_t pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pxafb_handle_irq(int irq, void *dev_id) { struct pxafb_info *fbi = dev_id; unsigned int lcsr = LCSR; @@ -869,9 +925,11 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) * registers. */ if (old_state == C_ENABLE) { + __pxafb_lcd_power(fbi, 0); pxafb_disable_controller(fbi); pxafb_setup_gpio(fbi); pxafb_enable_controller(fbi); + __pxafb_lcd_power(fbi, 1); } break; @@ -906,9 +964,10 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) * Our LCD controller task (which is called when we blank or unblank) * via keventd. */ -static void pxafb_task(void *dummy) +static void pxafb_task(struct work_struct *work) { - struct pxafb_info *fbi = dummy; + struct pxafb_info *fbi = + container_of(work, struct pxafb_info, task); u_int state = xchg(&fbi->task_state, -1); set_ctrlr_state(fbi, state); @@ -1049,6 +1108,8 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) struct pxafb_info *fbi; void *addr; struct pxafb_mach_info *inf = dev->platform_data; + struct pxafb_mode_info *mode = inf->modes; + int i, smemlen; /* Alloc the pxafb_info and pseudo_palette in one step */ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL); @@ -1082,34 +1143,24 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) addr = addr + sizeof(struct pxafb_info); fbi->fb.pseudo_palette = addr; - fbi->max_xres = inf->xres; - fbi->fb.var.xres = inf->xres; - fbi->fb.var.xres_virtual = inf->xres; - fbi->max_yres = inf->yres; - fbi->fb.var.yres = inf->yres; - fbi->fb.var.yres_virtual = inf->yres; - fbi->max_bpp = inf->bpp; - fbi->fb.var.bits_per_pixel = inf->bpp; - fbi->fb.var.pixclock = inf->pixclock; - fbi->fb.var.hsync_len = inf->hsync_len; - fbi->fb.var.left_margin = inf->left_margin; - fbi->fb.var.right_margin = inf->right_margin; - fbi->fb.var.vsync_len = inf->vsync_len; - fbi->fb.var.upper_margin = inf->upper_margin; - fbi->fb.var.lower_margin = inf->lower_margin; - fbi->fb.var.sync = inf->sync; - fbi->fb.var.grayscale = inf->cmap_greyscale; + pxafb_setmode(&fbi->fb.var, mode); + fbi->cmap_inverse = inf->cmap_inverse; fbi->cmap_static = inf->cmap_static; + fbi->lccr0 = inf->lccr0; fbi->lccr3 = inf->lccr3; fbi->state = C_STARTUP; fbi->task_state = (u_char)-1; - fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * - fbi->max_bpp / 8; + + for (i = 0; i < inf->num_modes; i++) { + smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8; + if (smemlen > fbi->fb.fix.smem_len) + fbi->fb.fix.smem_len = smemlen; + } init_waitqueue_head(&fbi->ctrlr_wait); - INIT_WORK(&fbi->task, pxafb_task, fbi); + INIT_WORK(&fbi->task, pxafb_task); init_MUTEX(&fbi->ctrlr_sem); return fbi; @@ -1307,12 +1358,12 @@ int __init pxafb_probe(struct platform_device *dev) (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) dev_warn(&dev->dev, "Dual panel only valid in passive mode\n"); if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && - (inf->upper_margin || inf->lower_margin)) + (inf->modes->upper_margin || inf->modes->lower_margin)) dev_warn(&dev->dev, "Upper and lower margins must be 0 in passive mode\n"); #endif - dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->xres, inf->yres, inf->bpp); - if (inf->xres == 0 || inf->yres == 0 || inf->bpp == 0) { + dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->modes->xres, inf->modes->yres, inf->modes->bpp); + if (inf->modes->xres == 0 || inf->modes->yres == 0 || inf->modes->bpp == 0) { dev_err(&dev->dev, "Invalid resolution or bit depth\n"); ret = -EINVAL; goto failed; diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 47f41f70db7..7499a1c4bf7 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h @@ -41,10 +41,6 @@ struct pxafb_info { struct fb_info fb; struct device *dev; - u_int max_bpp; - u_int max_xres; - u_int max_yres; - /* * These are the addresses we mapped * the framebuffer memory region to. diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index cf41ff17764..bc7ffc84e18 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -1423,8 +1423,10 @@ int __init retz3fb_init(void) do_install_cmap(0, fb_info); - if (register_framebuffer(fb_info) < 0) + if (register_framebuffer(fb_info) < 0) { + iounmap(zinfo->base); return -EINVAL; + } printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of " "video memory\n", fb_info->node, diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 4acde4f7dbf..345e8b1c1af 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -40,6 +40,7 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/backlight.h> +#include <linux/bitrev.h> #ifdef CONFIG_MTRR #include <asm/mtrr.h> #endif @@ -393,8 +394,8 @@ static void riva_bl_init(struct riva_par *par) mutex_lock(&info->bl_mutex); info->bl_dev = bd; fb_bl_default_curve(info, 0, - 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, - 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); + MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL, + FB_BACKLIGHT_MAX); mutex_unlock(&info->bl_mutex); down(&bd->sem); @@ -521,48 +522,13 @@ static inline unsigned char MISCin(struct riva_par *par) return (VGA_RD08(par->riva.PVIO, 0x3cc)); } -static u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - static inline void reverse_order(u32 *l) { u8 *a = (u8 *)l; - *a = byte_rev[*a], a++; - *a = byte_rev[*a], a++; - *a = byte_rev[*a], a++; - *a = byte_rev[*a]; + a[0] = bitrev8(a[0]); + a[1] = bitrev8(a[1]); + a[2] = bitrev8(a[2]); + a[3] = bitrev8(a[3]); } /* ------------------------------------------------------------------------- * @@ -774,17 +740,18 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs) * CALLED FROM: * rivafb_set_par() */ -static void riva_load_video_mode(struct fb_info *info) +static int riva_load_video_mode(struct fb_info *info) { int bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd; + int rc; struct riva_par *par = info->par; struct riva_regs newmode; NVTRACE_ENTER(); /* time to calculate */ - rivafb_blank(1, info); + rivafb_blank(FB_BLANK_NORMAL, info); bpp = info->var.bits_per_pixel; if (bpp == 16 && info->var.green.length == 5) @@ -884,8 +851,10 @@ static void riva_load_video_mode(struct fb_info *info) else newmode.misc_output |= 0x80; - par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, - hDisplaySize, height, dotClock); + rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width, + hDisplaySize, height, dotClock); + if (rc) + goto out; newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) & 0xfff000ff; @@ -917,8 +886,12 @@ static void riva_load_video_mode(struct fb_info *info) par->current_state = newmode; riva_load_state(par, &par->current_state); par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */ - rivafb_blank(0, info); + +out: + rivafb_blank(FB_BLANK_UNBLANK, info); NVTRACE_LEAVE(); + + return rc; } static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb) @@ -1286,12 +1259,15 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int rivafb_set_par(struct fb_info *info) { struct riva_par *par = info->par; + int rc = 0; NVTRACE_ENTER(); /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); - riva_load_video_mode(info); + rc = riva_load_video_mode(info); + if (rc) + goto out; if(!(info->flags & FBINFO_HWACCEL_DISABLED)) riva_setup_accel(info); @@ -1304,8 +1280,10 @@ static int rivafb_set_par(struct fb_info *info) info->pixmap.scan_align = 1; else info->pixmap.scan_align = 4; + +out: NVTRACE_LEAVE(); - return 0; + return rc; } /** @@ -1843,7 +1821,7 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) for (i = 0; propnames[i] != NULL; ++i) { pedid = get_property(dp, propnames[i], NULL); if (pedid != NULL) { - par->EDID = pedid; + par->EDID = (unsigned char *)pedid; NVTRACE("LCD found.\n"); return 1; } diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c index b6f8690b96c..e0b8c521cc9 100644 --- a/drivers/video/riva/riva_hw.c +++ b/drivers/video/riva/riva_hw.c @@ -1227,7 +1227,7 @@ static int CalcVClock * Calculate extended mode parameters (SVGA) and save in a * mode state structure. */ -static void CalcStateExt +int CalcStateExt ( RIVA_HW_INST *chip, RIVA_HW_STATE *state, @@ -1249,7 +1249,8 @@ static void CalcStateExt * Extended RIVA registers. */ pixelDepth = (bpp + 1)/8; - CalcVClock(dotClock, &VClk, &m, &n, &p, chip); + if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip)) + return -EINVAL; switch (chip->Architecture) { @@ -1327,6 +1328,8 @@ static void CalcStateExt state->pitch1 = state->pitch2 = state->pitch3 = pixelDepth * width; + + return 0; } /* * Load fixed function state and pre-calculated/stored state. @@ -2026,7 +2029,6 @@ static void nv3GetConfig */ chip->Busy = nv3Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress3; @@ -2084,7 +2086,6 @@ static void nv4GetConfig */ chip->Busy = nv4Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress; @@ -2186,7 +2187,6 @@ static void nv10GetConfig */ chip->Busy = nv10Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress; diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h index a1e71a626df..c2769f73e0b 100644 --- a/drivers/video/riva/riva_hw.h +++ b/drivers/video/riva/riva_hw.h @@ -463,7 +463,6 @@ typedef struct _riva_hw_inst * Common chip functions. */ int (*Busy)(struct _riva_hw_inst *); - void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int); void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*SetStartAddress)(struct _riva_hw_inst *,U032); @@ -528,6 +527,22 @@ typedef struct _riva_hw_state U032 pitch2; U032 pitch3; } RIVA_HW_STATE; + +/* + * function prototypes + */ + +extern int CalcStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state, + int bpp, + int width, + int hDisplaySize, + int height, + int dotClock +); + /* * External routines. */ diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c index 9751c37c0bf..01b85e3b0ae 100644 --- a/drivers/video/riva/rivafb-i2c.c +++ b/drivers/video/riva/rivafb-i2c.c @@ -25,8 +25,6 @@ #include "rivafb.h" #include "../edid.h" -#define RIVA_DDC 0x50 - static void riva_gpio_setscl(void* data, int state) { struct riva_i2c_chan *chan = data; @@ -146,62 +144,24 @@ void riva_create_i2c_busses(struct riva_par *par) void riva_delete_i2c_busses(struct riva_par *par) { if (par->chan[0].par) - i2c_bit_del_bus(&par->chan[0].adapter); + i2c_del_adapter(&par->chan[0].adapter); par->chan[0].par = NULL; if (par->chan[1].par) - i2c_bit_del_bus(&par->chan[1].adapter); + i2c_del_adapter(&par->chan[1].adapter); par->chan[1].par = NULL; if (par->chan[2].par) - i2c_bit_del_bus(&par->chan[2].adapter); + i2c_del_adapter(&par->chan[2].adapter); par->chan[2].par = NULL; } -static u8 *riva_do_probe_i2c_edid(struct riva_i2c_chan *chan) -{ - u8 start = 0x0; - struct i2c_msg msgs[] = { - { - .addr = RIVA_DDC, - .len = 1, - .buf = &start, - }, { - .addr = RIVA_DDC, - .flags = I2C_M_RD, - .len = EDID_LENGTH, - }, - }; - u8 *buf; - - if (!chan->par) - return NULL; - - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (!buf) { - dev_warn(&chan->par->pdev->dev, "Out of memory!\n"); - return NULL; - } - msgs[1].buf = buf; - - if (i2c_transfer(&chan->adapter, msgs, 2) == 2) - return buf; - dev_dbg(&chan->par->pdev->dev, "Unable to read EDID block.\n"); - kfree(buf); - return NULL; -} - int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid) { u8 *edid = NULL; - int i; - for (i = 0; i < 3; i++) { - /* Do the real work */ - edid = riva_do_probe_i2c_edid(&par->chan[conn-1]); - if (edid) - break; - } + edid = fb_ddc_read(&par->chan[conn-1].adapter); + if (out_edid) *out_edid = edid; if (!edid) diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index ad3bdd6f1ac..ccef56d0c15 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -131,7 +131,7 @@ static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi) saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8; saddr2>>= 1; - saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres); + saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff); dprintk("LCDSADDR1 = 0x%08lx\n", saddr1); dprintk("LCDSADDR2 = 0x%08lx\n", saddr2); @@ -199,28 +199,86 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, var->bits_per_pixel = fbi->mach_info->bpp.min; /* set r/g/b positions */ + switch (var->bits_per_pixel) { + case 1: + case 2: + case 4: + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 8: + if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) { + /* 8 bpp 332 */ + var->red.length = 3; + var->red.offset = 5; + var->green.length = 3; + var->green.offset = 2; + var->blue.length = 2; + var->blue.offset = 0; + var->transp.length = 0; + } else { + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 0; + } + break; + case 12: + /* 12 bpp 444 */ + var->red.length = 4; + var->red.offset = 8; + var->green.length = 4; + var->green.offset = 4; + var->blue.length = 4; + var->blue.offset = 0; + var->transp.length = 0; + break; + + default: + case 16: + if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) { + /* 16 bpp, 565 format */ + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->transp.length = 0; + } else { + /* 16 bpp, 5551 format */ + var->red.offset = 11; + var->green.offset = 6; + var->blue.offset = 1; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.length = 0; + } + break; + case 24: + /* 24 bpp 888 */ + var->red.length = 8; + var->red.offset = 16; + var->green.length = 8; + var->green.offset = 8; + var->blue.length = 8; + var->blue.offset = 0; + var->transp.length = 0; + break; - if (var->bits_per_pixel == 16) { - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - var->transp.length = 0; - } else { - var->red.length = var->bits_per_pixel; - var->red.offset = 0; - var->green.length = var->bits_per_pixel; - var->green.offset = 0; - var->blue.length = var->bits_per_pixel; - var->blue.offset = 0; - var->transp.length = 0; - } + } return 0; } + /* s3c2410fb_activate_var * * activate (set) the controller from the given framebuffer @@ -230,29 +288,61 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, struct fb_var_screeninfo *var) { + int hs; + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT; dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres); dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres); dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel); - switch (var->bits_per_pixel) { - case 1: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; - break; - case 2: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; - break; - case 4: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; - break; - case 8: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; - break; - case 16: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; - break; - } + fbi->regs.lcdcon1 |= fbi->mach_info->type; + + if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) + switch (var->bits_per_pixel) { + case 1: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; + break; + case 2: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; + break; + case 4: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; + break; + case 8: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; + break; + case 16: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; + break; + + default: + /* invalid pixel depth */ + dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel); + } + else + switch (var->bits_per_pixel) { + case 1: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP; + break; + case 2: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY; + break; + case 4: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY; + break; + case 8: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP; + break; + case 12: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP; + break; + + default: + /* invalid pixel depth */ + dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel); + } /* check to see if we need to update sync/borders */ @@ -283,15 +373,44 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff); fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1); + switch(fbi->mach_info->type) { + case S3C2410_LCDCON1_DSCAN4: + case S3C2410_LCDCON1_STN8: + hs = var->xres / 8; + break; + case S3C2410_LCDCON1_STN4: + hs = var->xres / 4; + break; + default: + case S3C2410_LCDCON1_TFT: + hs = var->xres; + break; + + } + + /* Special cases : STN color displays */ + if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \ + || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) { + hs = hs * 3; + } + + fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff); - fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1); + fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(hs - 1); if (var->pixclock > 0) { int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); - clkdiv = (clkdiv / 2) -1; - if (clkdiv < 0) - clkdiv = 0; + if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) { + clkdiv = (clkdiv / 2) -1; + if (clkdiv < 0) + clkdiv = 0; + } + else { + clkdiv = (clkdiv / 2); + if (clkdiv < 2) + clkdiv = 2; + } fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff); fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv); @@ -329,10 +448,18 @@ static int s3c2410fb_set_par(struct fb_info *info) struct s3c2410fb_info *fbi = info->par; struct fb_var_screeninfo *var = &info->var; - if (var->bits_per_pixel == 16) - fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; - else - fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; + switch (var->bits_per_pixel) + { + case 16: + fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + fbi->fb->fix.visual = FB_VISUAL_MONO01; + break; + default: + fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + } fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8; @@ -614,7 +741,7 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) } } -static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r) +static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) { struct s3c2410fb_info *fbi = dev_id; unsigned long lcdirq = readl(S3C2410_LCDINTPND); diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index be40968f899..f3f8a8e1501 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h @@ -1,5 +1,5 @@ /* - * linux/drivers/s3c2410fb.h + * linux/drivers/video/s3c2410fb.h * Copyright (c) Arnaud Patard * * This file is subject to the terms and conditions of the GNU General Public diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index a2e6e7205d7..cd10b18150b 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1085,7 +1085,7 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) /* * sa1100fb_handle_irq: Handle 'LCD DONE' interrupts. */ -static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id) { struct sa1100fb_info *fbi = dev_id; unsigned int lcsr = LCSR; diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index e83befd16d6..1411f3b6a00 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -148,7 +148,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &chan->par->pcidev->dev; chan->algo.udelay = 40; - chan->algo.mdelay = 5; chan->algo.timeout = 20; chan->algo.data = chan; @@ -209,67 +208,27 @@ void savagefb_delete_i2c_busses(struct fb_info *info) struct savagefb_par *par = info->par; if (par->chan.par) - i2c_bit_del_bus(&par->chan.adapter); + i2c_del_adapter(&par->chan.adapter); par->chan.par = NULL; } -static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan) -{ - u8 start = 0x0; - struct i2c_msg msgs[] = { - { - .addr = SAVAGE_DDC, - .len = 1, - .buf = &start, - }, { - .addr = SAVAGE_DDC, - .flags = I2C_M_RD, - .len = EDID_LENGTH, - }, - }; - u8 *buf = NULL; - - if (chan->par) { - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); - - if (buf) { - msgs[1].buf = buf; - - if (i2c_transfer(&chan->adapter, msgs, 2) != 2) { - dev_dbg(&chan->par->pcidev->dev, - "Unable to read EDID block.\n"); - kfree(buf); - buf = NULL; - } - } - } - - return buf; -} - int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) { struct savagefb_par *par = info->par; - u8 *edid = NULL; - int i; - - for (i = 0; i < 3; i++) { - /* Do the real work */ - edid = savage_do_probe_i2c_edid(&par->chan); - if (edid) - break; - } + u8 *edid; + + if (par->chan.par) + edid = fb_ddc_read(&par->chan.adapter); + else + edid = NULL; if (!edid) { /* try to get from firmware */ const u8 *e = fb_firmware_edid(info->device); - if (e) { - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); - } + if (e) + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } *out_edid = edid; diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h index 7ecab87cef0..59d12844b4d 100644 --- a/drivers/video/sis/init.h +++ b/drivers/video/sis/init.h @@ -77,16 +77,9 @@ #include <linux/types.h> #include <asm/io.h> #include <linux/fb.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <video/fbcon.h> -#endif #include "sis.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <linux/sisfb.h> -#else #include <video/sisfb.h> #endif -#endif /* Mode numbers */ static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f}; diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c index f13faddc618..47e1896cffe 100644 --- a/drivers/video/sis/init301.c +++ b/drivers/video/sis/init301.c @@ -445,11 +445,8 @@ SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr) void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime) { - unsigned int i, j; - - for(i = 0; i < delaytime; i++) { - j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); - } + while (delaytime-- > 0) + SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05); } #if defined(SIS300) || defined(SIS315H) diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h index bc321dc57e9..4f3a28699d3 100644 --- a/drivers/video/sis/init301.h +++ b/drivers/video/sis/init301.h @@ -71,16 +71,9 @@ #include <linux/types.h> #include <asm/io.h> #include <linux/fb.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <video/fbcon.h> -#endif #include "sis.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <linux/sisfb.h> -#else #include <video/sisfb.h> #endif -#endif static const unsigned char SiS_YPbPrTable[3][64] = { { diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c index 09f5d758b6c..c3884a29f4c 100644 --- a/drivers/video/sis/initextlfb.c +++ b/drivers/video/sis/initextlfb.c @@ -34,12 +34,10 @@ #include <linux/types.h> #include <linux/fb.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno, unsigned char rateindex); int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno, unsigned char rateindex, struct fb_var_screeninfo *var); -#endif BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex); @@ -49,7 +47,6 @@ extern BOOLEAN SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *Mode extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres, int yres, struct fb_var_screeninfo *var, BOOLEAN writeres); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno, unsigned char rateindex) @@ -177,7 +174,6 @@ sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno, return 1; } -#endif /* Linux >= 2.5 */ BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal, diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h index f59568020eb..d048bd39961 100644 --- a/drivers/video/sis/osdef.h +++ b/drivers/video/sis/osdef.h @@ -100,11 +100,7 @@ #define SIS315H #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #define SIS_LINUX_KERNEL_26 -#else -#define SIS_LINUX_KERNEL_24 -#endif #if !defined(SIS300) && !defined(SIS315H) #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c index 3b7ce032e2e..7addf91d2fe 100644 --- a/drivers/video/sis/sis_accel.c +++ b/drivers/video/sis/sis_accel.c @@ -32,22 +32,10 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/fb.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <linux/console.h> -#endif #include <linux/ioport.h> #include <linux/types.h> - #include <asm/io.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> -#endif - #include "sis.h" #include "sis_accel.h" @@ -91,11 +79,9 @@ static const u8 sisPatALUConv[] = 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) static const int myrops[] = { 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; -#endif /* 300 series ----------------------------------------------------- */ #ifdef CONFIG_FB_SIS_300 @@ -315,8 +301,6 @@ void sisfb_syncaccel(struct sis_video_info *ivideo) } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* --------------- 2.5 --------------- */ - int fbcon_sis_sync(struct fb_info *info) { struct sis_video_info *ivideo = (struct sis_video_info *)info->par; @@ -438,13 +422,3 @@ void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area) sisfb_syncaccel(ivideo); } - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */ - -#include "sisfb_accel_2_4.h" - -#endif /* KERNEL VERSION */ - - diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h index 046e2c4a8e0..30e03cdf6b8 100644 --- a/drivers/video/sis/sis_accel.h +++ b/drivers/video/sis/sis_accel.h @@ -390,25 +390,11 @@ MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \ CmdQueLen -= 2; - int sisfb_initaccel(struct sis_video_info *ivideo); void sisfb_syncaccel(struct sis_video_info *ivideo); -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) -void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty, - int dstx, int height, int width); -void fbcon_sis_revc(struct display *p, int srcy, int srcx); -void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy, - int srcx, int height, int width); -void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy, - int srcx, int height, int width); -void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy, - int srcx, int height, int width); -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) int fbcon_sis_sync(struct fb_info *info); void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect); void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area); -#endif #endif diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 895ebda7d9e..baaf495a0a6 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -35,9 +35,7 @@ #include <linux/version.h> #include <linux/module.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #include <linux/moduleparam.h> -#endif #include <linux/kernel.h> #include <linux/smp_lock.h> #include <linux/spinlock.h> @@ -58,9 +56,6 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/vmalloc.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <linux/vt_kern.h> -#endif #include <linux/capability.h> #include <linux/fs.h> #include <linux/types.h> @@ -70,35 +65,9 @@ #include <asm/mtrr.h> #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> -#endif - #include "sis.h" #include "sis_main.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -#error "This version of sisfb requires at least 2.6.3" -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#ifdef FBCON_HAS_CFB8 -extern struct display_switch fbcon_sis8; -#endif -#ifdef FBCON_HAS_CFB16 -extern struct display_switch fbcon_sis16; -#endif -#ifdef FBCON_HAS_CFB32 -extern struct display_switch fbcon_sis32; -#endif -#endif - static void sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command); @@ -114,17 +83,7 @@ sisfb_setdefaultparms(void) sisfb_max = -1; sisfb_userom = -1; sisfb_useoem = -1; -#ifdef MODULE - /* Module: "None" for 2.4, default mode for 2.5+ */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - sisfb_mode_idx = -1; -#else - sisfb_mode_idx = MODE_INDEX_NONE; -#endif -#else - /* Static: Default mode */ sisfb_mode_idx = -1; -#endif sisfb_parm_rate = -1; sisfb_crt1off = 0; sisfb_forcecrt1 = -1; @@ -142,10 +101,6 @@ sisfb_setdefaultparms(void) sisfb_tvxposoffset = 0; sisfb_tvyposoffset = 0; sisfb_nocrt2rate = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - sisfb_inverse = 0; - sisfb_fontname[0] = 0; -#endif #if !defined(__i386__) && !defined(__x86_64__) sisfb_resetcard = 0; sisfb_videoram = 0; @@ -162,14 +117,11 @@ sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet) /* We don't know the hardware specs yet and there is no ivideo */ if(vesamode == 0) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - sisfb_mode_idx = MODE_INDEX_NONE; -#else if(!quiet) printk(KERN_ERR "sisfb: Invalid mode. Using default.\n"); sisfb_mode_idx = DEFAULT_MODE; -#endif + return; } @@ -215,7 +167,6 @@ sisfb_search_mode(char *name, BOOLEAN quiet) return; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { if(!quiet) printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); @@ -223,7 +174,7 @@ sisfb_search_mode(char *name, BOOLEAN quiet) sisfb_mode_idx = DEFAULT_MODE; return; } -#endif + if(strlen(name) <= 19) { strcpy(strbuf1, name); for(i = 0; i < strlen(strbuf1); i++) { @@ -1315,20 +1266,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in ivideo->refresh_rate = 60; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - if(ivideo->sisfb_thismonitor.datavalid) { - if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, - ivideo->rate_idx, ivideo->refresh_rate)) { - printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); - } - } -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) { -#else if(isactive) { -#endif /* If acceleration to be used? Need to know * before pre/post_set_mode() */ @@ -1367,9 +1305,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in ivideo->current_linelength = ivideo->video_linelength; ivideo->current_pixclock = var->pixclock; ivideo->current_refresh_rate = ivideo->refresh_rate; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate; -#endif } return 0; @@ -1435,18 +1371,6 @@ sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) return 0; } -/* ------------ FBDev related routines for 2.4 series ----------- */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - -#include "sisfb_fbdev_2_4.h" - -#endif - -/* ------------ FBDev related routines for 2.6 series ----------- */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - static int sisfb_open(struct fb_info *info, int user) { @@ -1744,8 +1668,6 @@ sisfb_blank(int blank, struct fb_info *info) return sisfb_myblank(ivideo, blank); } -#endif - /* ----------- FBDev related routines for all series ---------- */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) @@ -1969,20 +1891,6 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) /* ---------------- fb_ops structures ----------------- */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -static struct fb_ops sisfb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = sisfb_get_fix, - .fb_get_var = sisfb_get_var, - .fb_set_var = sisfb_set_var, - .fb_get_cmap = sisfb_get_cmap, - .fb_set_cmap = sisfb_set_cmap, - .fb_pan_display = sisfb_pan_display, - .fb_ioctl = sisfb_ioctl -}; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) static struct fb_ops sisfb_ops = { .owner = THIS_MODULE, .fb_open = sisfb_open, @@ -2004,7 +1912,6 @@ static struct fb_ops sisfb_ops = { #endif .fb_ioctl = sisfb_ioctl }; -#endif /* ---------------- Chip generation dependent routines ---------------- */ @@ -4100,16 +4007,6 @@ sisfb_setup(char *options) sisfb_search_mode(this_opt + 5, FALSE); } else if(!strnicmp(this_opt, "vesa:", 5)) { sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - } else if(!strnicmp(this_opt, "inverse", 7)) { - sisfb_inverse = 1; - /* fb_invert_cmaps(); */ - } else if(!strnicmp(this_opt, "font:", 5)) { - if(strlen(this_opt + 5) < 40) { - strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1); - sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0'; - } -#endif } else if(!strnicmp(this_opt, "rate:", 5)) { sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { @@ -5870,17 +5767,9 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if(sisfb_off) return -ENXIO; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); if(!sis_fb_info) return -ENOMEM; -#else - sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL); - if(!sis_fb_info) - return -ENOMEM; - memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo)); - sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info)); -#endif ivideo = (struct sis_video_info *)sis_fb_info->par; ivideo->memyselfandi = sis_fb_info; @@ -5970,10 +5859,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ivideo->tvxpos = sisfb_tvxposoffset; ivideo->tvypos = sisfb_tvyposoffset; ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - ivideo->sisfb_inverse = sisfb_inverse; -#endif - ivideo->refresh_rate = 0; if(ivideo->sisfb_parm_rate != -1) { ivideo->refresh_rate = ivideo->sisfb_parm_rate; @@ -6049,10 +5934,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - strcpy(sis_fb_info->modename, ivideo->myid); -#endif - ivideo->SiS_Pr.ChipType = ivideo->chip; ivideo->SiS_Pr.ivideo = (void *)ivideo; @@ -6134,20 +6015,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #endif } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#ifdef MODULE - if((reg & 0x80) && (reg != 0xff)) { - if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) - != 0xFF) { - printk(KERN_INFO "sisfb: Cannot initialize display mode, " - "X server is active\n"); - ret = -EBUSY; - goto error_4; - } - } -#endif -#endif - /* Search and copy ROM image */ ivideo->bios_abase = NULL; ivideo->SiS_Pr.VirtualRomBase = NULL; @@ -6281,9 +6148,6 @@ error_0: iounmap(ivideo->video_vbase); error_1: release_mem_region(ivideo->video_base, ivideo->video_size); error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size); error_3: vfree(ivideo->bios_abase); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -error_4: -#endif if(ivideo->lpcdev) SIS_PCI_PUT_DEVICE(ivideo->lpcdev); if(ivideo->nbridge) @@ -6586,7 +6450,6 @@ error_4: sis_fb_info->fix = ivideo->sisfb_fix; sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; sis_fb_info->fbops = &sisfb_ops; - sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); sis_fb_info->pseudo_palette = ivideo->pseudo_palette; @@ -6603,10 +6466,6 @@ error_4: } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - vc_resize_con(1, 1, 0); -#endif - if(register_framebuffer(sis_fb_info) < 0) { printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n"); ret = -EINVAL; @@ -6653,12 +6512,7 @@ error_4: printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n", -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - GET_FB_IDX(sis_fb_info->node), -#else - sis_fb_info->node, -#endif - ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); + sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n"); @@ -6732,11 +6586,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev) /* Unregister the framebuffer */ if(ivideo->registered) { unregister_framebuffer(sis_fb_info); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) framebuffer_release(sis_fb_info); -#else - kfree(sis_fb_info); -#endif } /* OK, our ivideo is gone for good from here. */ @@ -6762,7 +6612,6 @@ static struct pci_driver sisfb_driver = { SISINITSTATIC int __init sisfb_init(void) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) #ifndef MODULE char *options = NULL; @@ -6771,15 +6620,12 @@ SISINITSTATIC int __init sisfb_init(void) sisfb_setup(options); #endif -#endif return pci_register_driver(&sisfb_driver); } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) #ifndef MODULE module_init(sisfb_init); #endif -#endif /*****************************************************/ /* MODULE */ @@ -6799,9 +6645,6 @@ static int pdc1 = -1; static int noaccel = -1; static int noypan = -1; static int nomax = -1; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -static int inverse = 0; -#endif static int userom = -1; static int useoem = -1; static char *tvstandard = NULL; @@ -6861,10 +6704,6 @@ static int __init sisfb_init_module(void) else if(nomax == 0) sisfb_max = 1; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - if(inverse) sisfb_inverse = 1; -#endif - if(mem) sisfb_parm_mem = mem; @@ -6913,35 +6752,6 @@ MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3X MODULE_LICENSE("GPL"); MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -MODULE_PARM(mem, "i"); -MODULE_PARM(noaccel, "i"); -MODULE_PARM(noypan, "i"); -MODULE_PARM(nomax, "i"); -MODULE_PARM(userom, "i"); -MODULE_PARM(useoem, "i"); -MODULE_PARM(mode, "s"); -MODULE_PARM(vesa, "i"); -MODULE_PARM(rate, "i"); -MODULE_PARM(forcecrt1, "i"); -MODULE_PARM(forcecrt2type, "s"); -MODULE_PARM(scalelcd, "i"); -MODULE_PARM(pdc, "i"); -MODULE_PARM(pdc1, "i"); -MODULE_PARM(specialtiming, "s"); -MODULE_PARM(lvdshl, "i"); -MODULE_PARM(tvstandard, "s"); -MODULE_PARM(tvxposoffset, "i"); -MODULE_PARM(tvyposoffset, "i"); -MODULE_PARM(nocrt2rate, "i"); -MODULE_PARM(inverse, "i"); -#if !defined(__i386__) && !defined(__x86_64__) -MODULE_PARM(resetcard, "i"); -MODULE_PARM(videoram, "i"); -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) module_param(mem, int, 0); module_param(noaccel, int, 0); module_param(noypan, int, 0); @@ -6966,18 +6776,7 @@ module_param(nocrt2rate, int, 0); module_param(resetcard, int, 0); module_param(videoram, int, 0); #endif -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -MODULE_PARM_DESC(mem, - "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" - "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" - "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" - "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" - "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n" - "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" - "for XFree86 4.x/X.org 6.7 and later.\n"); -#else MODULE_PARM_DESC(mem, "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" @@ -6985,7 +6784,6 @@ MODULE_PARM_DESC(mem, "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n" "The value is to be specified without 'KB'.\n"); -#endif MODULE_PARM_DESC(noaccel, "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" @@ -7002,23 +6800,6 @@ MODULE_PARM_DESC(nomax, "enable the user to positively specify a virtual Y size of the screen using\n" "fbset. (default: 0)\n"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -MODULE_PARM_DESC(mode, - "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n" - "1024x768x16. Other formats supported include XxY-Depth and\n" - "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" - "number, it will be interpreted as a VESA mode number. (default: none if\n" - "sisfb is a module; this leaves the console untouched and the driver will\n" - "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n" - "is in the kernel)\n"); -MODULE_PARM_DESC(vesa, - "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n" - "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n" - "and the driver will only do the video memory management for eg. DRM/DRI;\n" - "0x0103 if sisfb is in the kernel)\n"); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) MODULE_PARM_DESC(mode, "\nSelects the desired default display mode in the format XxYxDepth,\n" "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" @@ -7028,7 +6809,6 @@ MODULE_PARM_DESC(mode, MODULE_PARM_DESC(vesa, "\nSelects the desired default display mode by VESA defined mode number, eg.\n" "0x117 (default: 0x0103)\n"); -#endif MODULE_PARM_DESC(rate, "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n" @@ -7094,12 +6874,6 @@ MODULE_PARM_DESC(nocrt2rate, "\nSetting this to 1 will force the driver to use the default refresh rate for\n" "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -MODULE_PARM_DESC(inverse, - "\nSetting this to anything but 0 should invert the display colors, but this\n" - "does not seem to work. (default: 0)\n"); -#endif - #if !defined(__i386__) && !defined(__x86_64__) #ifdef CONFIG_FB_SIS_300 MODULE_PARM_DESC(resetcard, diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h index 70b6df371b8..88e4f1e4147 100644 --- a/drivers/video/sis/sis_main.h +++ b/drivers/video/sis/sis_main.h @@ -67,15 +67,7 @@ static int sisfb_ypan = -1; static int sisfb_max = -1; static int sisfb_userom = 1; static int sisfb_useoem = -1; -#ifdef MODULE -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -static int sisfb_mode_idx = -1; -#else -static int sisfb_mode_idx = MODE_INDEX_NONE; /* Don't use a mode by default if we are a module */ -#endif -#else static int sisfb_mode_idx = -1; /* Use a default mode if we are inside the kernel */ -#endif static int sisfb_parm_rate = -1; static int sisfb_crt1off = 0; static int sisfb_forcecrt1 = -1; @@ -93,10 +85,6 @@ static int sisfb_tvstd = -1; static int sisfb_tvxposoffset = 0; static int sisfb_tvyposoffset = 0; static int sisfb_nocrt2rate = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -static int sisfb_inverse = 0; -static char sisfb_fontname[40]; -#endif #if !defined(__i386__) && !defined(__x86_64__) static int sisfb_resetcard = 0; static int sisfb_videoram = 0; @@ -687,54 +675,8 @@ SISINITSTATIC int sisfb_init(void); static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -static int sisfb_get_fix(struct fb_fix_screeninfo *fix, - int con, - struct fb_info *info); -static int sisfb_get_var(struct fb_var_screeninfo *var, - int con, - struct fb_info *info); -static int sisfb_set_var(struct fb_var_screeninfo *var, - int con, - struct fb_info *info); -static void sisfb_crtc_to_var(struct sis_video_info *ivideo, - struct fb_var_screeninfo *var); -static int sisfb_get_cmap(struct fb_cmap *cmap, - int kspc, - int con, - struct fb_info *info); -static int sisfb_set_cmap(struct fb_cmap *cmap, - int kspc, - int con, - struct fb_info *info); -static int sisfb_update_var(int con, - struct fb_info *info); -static int sisfb_switch(int con, - struct fb_info *info); -static void sisfb_blank(int blank, - struct fb_info *info); -static void sisfb_set_disp(int con, - struct fb_var_screeninfo *var, - struct fb_info *info); -static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *fb_info); -static void sisfb_do_install_cmap(int con, - struct fb_info *info); -static int sisfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, int con, - struct fb_info *info); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); -#else -static int sisfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info); -#endif static int sisfb_set_par(struct fb_info *info); static int sisfb_blank(int blank, struct fb_info *info); @@ -743,7 +685,6 @@ extern void fbcon_sis_fillrect(struct fb_info *info, extern void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern int fbcon_sis_sync(struct fb_info *info); -#endif /* Internal 2D accelerator functions */ extern int sisfb_initaccel(struct sis_video_info *ivideo); @@ -811,16 +752,10 @@ extern BOOLEAN SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr); extern BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) extern int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno, unsigned char rateindex); extern int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno, unsigned char rateindex, struct fb_var_screeninfo *var); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres, - int yres, struct fb_var_screeninfo *var, BOOLEAN writeres); -#endif /* Chrontel TV, DDC and DPMS functions */ extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg); diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h index 831b9f42264..05d08b7889a 100644 --- a/drivers/video/sis/vgatypes.h +++ b/drivers/video/sis/vgatypes.h @@ -73,12 +73,10 @@ typedef unsigned int BOOLEAN; #ifdef SIS_LINUX_KERNEL typedef unsigned long SISIOADDRESS; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) #include <linux/types.h> /* Need __iomem */ #undef SISIOMEMTYPE #define SISIOMEMTYPE __iomem #endif -#endif #ifdef SIS_XORG_XF86 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0) diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index dad54e73147..711cb11d6eb 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -17,7 +17,10 @@ * (port driver to new frambuffer infrastructure) * 01/2003 Helge Deller <deller@gmx.de> * (initial work on fb hardware acceleration for voodoo2) - * + * 08/2006 Alan Cox <alan@redhat.com> + * Remove never finished and bogus 24/32bit support + * Clean up macro abuse + * Minor tidying for format. */ /* @@ -40,6 +43,7 @@ through the fifo. warning: issuing a nop command seems to need pci_fifo -FIXME: in case of failure in the init sequence, be sure we return to a safe state. +- FIXME: Use accelerator for 2D scroll -FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20) */ @@ -67,9 +71,6 @@ #undef SST_DEBUG -/* enable 24/32 bpp functions ? (completely untested!) */ -#undef EN_24_32_BPP - /* Default video mode . 0 800x600@60 took from glide @@ -377,7 +378,11 @@ static void sstfb_clear_screen(struct fb_info *info) * sstfb_check_var - Optional function. Validates a var passed in. * @var: frame buffer variable screen structure * @info: frame buffer structure that represents a single frame buffer + * + * Limit to the abilities of a single chip as SLI is not supported + * by this driver. */ + static int sstfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -390,7 +395,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, unsigned int freq; if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) { - eprintk("Pixclock at %ld KHZ out of range\n", + printk(KERN_ERR "sstfb: Pixclock at %ld KHZ out of range\n", PICOS2KHZ(var->pixclock)); return -EINVAL; } @@ -409,27 +414,15 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, case 0 ... 16 : var->bits_per_pixel = 16; break; -#ifdef EN_24_32_BPP - case 17 ... 24 : - var->bits_per_pixel = 24; - break; - case 25 ... 32 : - var->bits_per_pixel = 32; - break; -#endif default : - eprintk("Unsupported bpp %d\n", var->bits_per_pixel); + printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel); return -EINVAL; } /* validity tests */ - if ((var->xres <= 1) || (yDim <= 0 ) - || (var->hsync_len <= 1) - || (hSyncOff <= 1) - || (var->left_margin <= 2) - || (vSyncOn <= 0) - || (vSyncOff <= 0) - || (vBackPorch <= 0)) { + if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1 || + hSyncOff <= 1 || var->left_margin <= 2 || vSyncOn <= 0 || + vSyncOff <= 0 || vBackPorch <= 0) { return -EINVAL; } @@ -437,21 +430,17 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, /* Voodoo 2 limits */ tiles_in_X = (var->xres + 63 ) / 64 * 2; - if (((var->xres - 1) >= POW2(11)) || (yDim >= POW2(11))) { - eprintk("Unsupported resolution %dx%d\n", + if (var->xres > POW2(11) || yDim >= POW2(11)) { + printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n", var->xres, var->yres); return -EINVAL; } - if (((var->hsync_len-1) >= POW2(9)) - || ((hSyncOff-1) >= POW2(11)) - || ((var->left_margin - 2) >= POW2(9)) - || (vSyncOn >= POW2(13)) - || (vSyncOff >= POW2(13)) - || (vBackPorch >= POW2(9)) - || (tiles_in_X >= POW2(6)) - || (tiles_in_X <= 0)) { - eprintk("Unsupported Timings\n"); + if (var->hsync_len > POW2(9) || hSyncOff > POW2(11) || + var->left_margin - 2 >= POW2(9) || vSyncOn >= POW2(13) || + vSyncOff >= POW2(13) || vBackPorch >= POW2(9) || + tiles_in_X >= POW2(6) || tiles_in_X <= 0) { + printk(KERN_ERR "sstfb: Unsupported timings\n"); return -EINVAL; } } else { @@ -459,24 +448,20 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, tiles_in_X = (var->xres + 63 ) / 64; if (var->vmode) { - eprintk("Interlace/Doublescan not supported %#x\n", + printk(KERN_ERR "sstfb: Interlace/doublescan not supported %#x\n", var->vmode); return -EINVAL; } - if (((var->xres - 1) >= POW2(10)) || (var->yres >= POW2(10))) { - eprintk("Unsupported resolution %dx%d\n", + if (var->xres > POW2(10) || var->yres >= POW2(10)) { + printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n", var->xres, var->yres); return -EINVAL; } - if (((var->hsync_len - 1) >= POW2(8)) - || ((hSyncOff-1) >= POW2(10)) - || ((var->left_margin - 2) >= POW2(8)) - || (vSyncOn >= POW2(12)) - || (vSyncOff >= POW2(12)) - || (vBackPorch >= POW2(8)) - || (tiles_in_X >= POW2(4)) - || (tiles_in_X <= 0)) { - eprintk("Unsupported Timings\n"); + if (var->hsync_len > POW2(8) || hSyncOff - 1 > POW2(10) || + var->left_margin - 2 >= POW2(8) || vSyncOn >= POW2(12) || + vSyncOff >= POW2(12) || vBackPorch >= POW2(8) || + tiles_in_X >= POW2(4) || tiles_in_X <= 0) { + printk(KERN_ERR "sstfb: Unsupported timings\n"); return -EINVAL; } } @@ -486,8 +471,8 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, real_length = tiles_in_X * (IS_VOODOO2(par) ? 32 : 64 ) * ((var->bits_per_pixel == 16) ? 2 : 4); - if ((real_length * yDim) > info->fix.smem_len) { - eprintk("Not enough video memory\n"); + if (real_length * yDim > info->fix.smem_len) { + printk(KERN_ERR "sstfb: Not enough video memory\n"); return -ENOMEM; } @@ -515,20 +500,6 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, var->blue.offset = 0; var->transp.offset = 0; break; -#ifdef EN_24_32_BPP - case 24: /* RGB 888 LfbMode 4 */ - case 32: /* ARGB 8888 LfbMode 5 */ - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - var->transp.length = 0; - - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->transp.offset = 0; /* in 24bpp we fake a 32 bpp mode */ - break; -#endif default: return -EINVAL; } @@ -653,13 +624,6 @@ static int sstfb_set_par(struct fb_info *info) case 16: fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL; break; -#ifdef EN_24_32_BPP - case 24: - case 32: - /* sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP);*/ - fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP; - break; -#endif default: return -EINVAL; } @@ -690,14 +654,6 @@ static int sstfb_set_par(struct fb_info *info) case 16: lfbmode = LFB_565; break; -#ifdef EN_24_32_BPP - case 24: - lfbmode = LFB_888; - break; - case 32: - lfbmode = LFB_8888; - break; -#endif default: return -EINVAL; } @@ -789,8 +745,7 @@ static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) return -EFAULT; if (val > info->fix.smem_len) val = info->fix.smem_len; - printk("filling %#x \n", val); - for (p=0 ; p<val; p+=2) + for (p = 0 ; p < val; p += 2) writew(p >> 6, info->screen_base + p); return 0; @@ -802,13 +757,10 @@ static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp | PCI_EN_INIT_WR ); fbiinit0 = sst_read (FBIINIT0); - if (val) { + if (val) sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH); - iprintk("Disabling VGA pass-through\n"); - } else { + else sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH); - iprintk("Enabling VGA pass-through\n"); - } pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); return 0; @@ -884,9 +836,9 @@ static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize) u8 __iomem *fbbase_virt = info->screen_base; /* force memsize */ - if ((mem >= 1 ) && (mem <= 4)) { + if (mem >= 1 && mem <= 4) { *memsize = (mem * 0x100000); - iprintk("supplied memsize: %#x\n", *memsize); + printk(KERN_INFO "supplied memsize: %#x\n", *memsize); return 1; } @@ -927,7 +879,7 @@ static int __devinit sst_detect_att(struct fb_info *info) struct sstfb_par *par = info->par; int i, mir, dir; - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) { sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); @@ -940,7 +892,7 @@ static int __devinit sst_detect_att(struct fb_info *info) /*the 7th, device ID register */ dir = sst_dac_read(DACREG_RMR); f_ddprintk("mir: %#x, dir: %#x\n", mir, dir); - if ((mir == DACREG_MIR_ATT ) && (dir == DACREG_DIR_ATT)) { + if (mir == DACREG_MIR_ATT && dir == DACREG_DIR_ATT) { return 1; } } @@ -1134,12 +1086,6 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp) case 16: sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP); break; -#ifdef EN_24_32_BPP - case 24: - case 32: - sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_24BPP); - break; -#endif default: dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp); break; @@ -1154,12 +1100,6 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp) case 16: sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP); break; -#ifdef EN_24_32_BPP - case 24: - case 32: - sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_24BPP); - break; -#endif default: dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp); break; @@ -1250,7 +1190,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) PCI_EN_INIT_WR | PCI_REMAP_DAC ); /* detect dac type */ if (!sst_detect_dactype(info, par)) { - eprintk("Unknown dac type\n"); + printk(KERN_ERR "sstfb: unknown dac type.\n"); //FIXME watch it: we are not in a safe state, bad bad bad. return 0; } @@ -1258,10 +1198,10 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) /* set graphic clock */ par->gfx_clock = spec->default_gfx_clock; if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) { - iprintk("Using supplied graphic freq : %dMHz\n", gfxclk); + printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk); par->gfx_clock = gfxclk *1000; } else if (gfxclk) { - wprintk ("%dMhz is way out of spec! Using default\n", gfxclk); + printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk); } sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings); @@ -1396,7 +1336,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, /* Enable device in PCI config. */ if ((err=pci_enable_device(pdev))) { - eprintk("cannot enable device\n"); + printk(KERN_ERR "cannot enable device\n"); return err; } @@ -1422,39 +1362,39 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, fix->smem_start = fix->mmio_start + 0x400000; if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) { - eprintk("cannot reserve mmio memory\n"); + printk(KERN_ERR "sstfb: cannot reserve mmio memory\n"); goto fail_mmio_mem; } if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) { - eprintk("cannot reserve fb memory\n"); + printk(KERN_ERR "sstfb: cannot reserve fb memory\n"); goto fail_fb_mem; } par->mmio_vbase = ioremap_nocache(fix->mmio_start, fix->mmio_len); if (!par->mmio_vbase) { - eprintk("cannot remap register area %#lx\n", + printk(KERN_ERR "sstfb: cannot remap register area %#lx\n", fix->mmio_start); goto fail_mmio_remap; } info->screen_base = ioremap_nocache(fix->smem_start, 0x400000); if (!info->screen_base) { - eprintk("cannot remap framebuffer %#lx\n", + printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n", fix->smem_start); goto fail_fb_remap; } if (!sst_init(info, par)) { - eprintk("Init failed\n"); + printk(KERN_ERR "sstfb: Init failed\n"); goto fail; } sst_get_memsize(info, &fix->smem_len); strlcpy(fix->id, spec->name, sizeof(fix->id)); - iprintk("%s (revision %d) with %s dac\n", + printk(KERN_INFO "%s (revision %d) with %s dac\n", fix->id, par->revision, par->dac_sw.name); - iprintk("framebuffer at %#lx, mapped to 0x%p, size %dMB\n", + printk(KERN_INFO "framebuffer at %#lx, mapped to 0x%p, size %dMB\n", fix->smem_start, info->screen_base, fix->smem_len >> 20); @@ -1471,24 +1411,25 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, fix->accel = FB_ACCEL_NONE; /* FIXME */ /* * According to the specs, the linelength must be of 1024 *pixels* - * and the 24bpp mode is in fact a 32 bpp mode. + * and the 24bpp mode is in fact a 32 bpp mode (and both are in + * fact dithered to 16bit). */ fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */ if ( mode_option && fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) { - eprintk("can't set supplied video mode. Using default\n"); + printk(KERN_ERR "sstfb: can't set supplied video mode. Using default\n"); info->var = sstfb_default; } else info->var = sstfb_default; if (sstfb_check_var(&info->var, info)) { - eprintk("invalid default video mode.\n"); + printk(KERN_ERR "sstfb: invalid default video mode.\n"); goto fail; } if (sstfb_set_par(info)) { - eprintk("can't set default video mode.\n"); + printk(KERN_ERR "sstfb: can't set default video mode.\n"); goto fail; } @@ -1497,7 +1438,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, /* register fb */ info->device = &pdev->dev; if (register_framebuffer(info) < 0) { - eprintk("can't register framebuffer.\n"); + printk(KERN_ERR "sstfb: can't register framebuffer.\n"); goto fail; } @@ -1711,4 +1652,3 @@ module_param(gfxclk, int, 0); MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)"); module_param(slowpci, bool, 0); MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)"); - diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 3e16e2d9d55..69f3b264a22 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1291,6 +1291,7 @@ out_err3: out_err2: release_mem_region(fix->smem_start, fix->smem_len); out_err1: + iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); out_err0: kfree(fb); @@ -1364,6 +1365,8 @@ stifb_cleanup(void) unregister_framebuffer(sti->info); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); release_mem_region(info->fix.smem_start, info->fix.smem_len); + if (info->screen_base) + iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); kfree(info); } diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 94fde625a6c..4b88fab83b7 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -23,6 +23,7 @@ #include <linux/fb.h> #include <linux/pci.h> #include <linux/selection.h> +#include <linux/bitrev.h> #include <asm/io.h> #include <video/tgafb.h> @@ -517,41 +518,6 @@ tgafb_blank(int blank, struct fb_info *info) static void tgafb_imageblit(struct fb_info *info, const struct fb_image *image) { - static unsigned char const bitrev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff - }; - struct tga_par *par = (struct tga_par *) info->par; u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask; unsigned long rincr, line_length, shift, pos, is8bpp; @@ -649,7 +615,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) /* The image data is bit big endian; we need little endian. */ for (j = 0; j < bwidth; ++j) - mask |= bitrev[data[j]] << (j * 8); + mask |= bitrev8(data[j]) << (j * 8); __raw_writel(mask << shift, fb_base + pos); @@ -676,10 +642,10 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) for (i = 0; i < height; ++i) { for (j = 0; j < bwidth; j += 4) { u32 mask = 0; - mask |= bitrev[data[j+0]] << (0 * 8); - mask |= bitrev[data[j+1]] << (1 * 8); - mask |= bitrev[data[j+2]] << (2 * 8); - mask |= bitrev[data[j+3]] << (3 * 8); + mask |= bitrev8(data[j+0]) << (0 * 8); + mask |= bitrev8(data[j+1]) << (1 * 8); + mask |= bitrev8(data[j+2]) << (2 * 8); + mask |= bitrev8(data[j+3]) << (3 * 8); __raw_writel(mask, fb_base + pos + j*bincr); } pos += line_length; @@ -699,7 +665,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) for (i = 0; i < height; ++i) { u32 mask = 0; for (j = 0; j < bwidth; ++j) - mask |= bitrev[data[j]] << (j * 8); + mask |= bitrev8(data[j]) << (j * 8); __raw_writel(mask, fb_base + pos); pos += line_length; data += rincr; @@ -726,8 +692,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) for (i = 0; i < height; ++i) { for (j = 0; j < bwidth; j += 2) { u32 mask = 0; - mask |= bitrev[data[j+0]] << (0 * 8); - mask |= bitrev[data[j+1]] << (1 * 8); + mask |= bitrev8(data[j+0]) << (0 * 8); + mask |= bitrev8(data[j+1]) << (1 * 8); mask <<= shift; __raw_writel(mask, fb_base + pos + j*bincr); } @@ -746,9 +712,9 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) bwidth = (width & 15) > 8; for (i = 0; i < height; ++i) { - u32 mask = bitrev[data[0]]; + u32 mask = bitrev8(data[0]); if (bwidth) - mask |= bitrev[data[1]] << 8; + mask |= bitrev8(data[1]) << 8; mask <<= shift; __raw_writel(mask, fb_base + pos); pos += line_length; @@ -1473,6 +1439,8 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err1: + if (mem_base) + iounmap(mem_base); release_mem_region(bar0_start, bar0_len); err0: kfree(all); diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 14175cdb9c9..55e8aa450bf 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1130,7 +1130,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { debug("request_mem_region failed!\n"); - return -1; + err = -1; + goto out_unmap; } fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start, @@ -1139,7 +1140,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de if (!fb_info.screen_base) { release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); debug("ioremap failed\n"); - return -1; + err = -1; + goto out_unmap; } output("%s board found\n", pci_name(dev)); @@ -1162,8 +1164,10 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de #endif fb_info.pseudo_palette = pseudo_pal; - if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) - return -EINVAL; + if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) { + err = -EINVAL; + goto out_unmap; + } fb_alloc_cmap(&fb_info.cmap,256,0); if (defaultaccel && acc) default_var.accel_flags |= FB_ACCELF_TEXT; @@ -1174,12 +1178,20 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de fb_info.device = &dev->dev; if (register_framebuffer(&fb_info) < 0) { printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n"); - return -EINVAL; + err = -EINVAL; + goto out_unmap; } output("fb%d: %s frame buffer device %dx%d-%dbpp\n", fb_info.node, fb_info.fix.id,default_var.xres, default_var.yres,default_var.bits_per_pixel); return 0; + +out_unmap: + if (default_par.io_virt) + iounmap(default_par.io_virt); + if (fb_info.screen_base) + iounmap(fb_info.screen_base); + return err; } static void __devexit trident_pci_remove(struct pci_dev * dev) diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 47f27924a7d..06fc19a6119 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -284,7 +284,7 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p) printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense); /* Try to pick a video mode out of NVRAM if we have one. */ -#ifndef CONFIG_MAC +#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM) if (default_vmode == VMODE_NVRAM) { default_vmode = nvram_read_byte(NV_VMODE); if (default_vmode <= 0 @@ -297,7 +297,7 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p) default_vmode = mac_map_monitor_sense(p->sense); if (!valkyrie_reg_init[default_vmode - 1]) default_vmode = VMODE_640_480_67; -#ifndef CONFIG_MAC +#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM) if (default_cmode == CMODE_NVRAM) default_cmode = nvram_read_byte(NV_CMODE); #endif diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 2196448396e..e16322d157d 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -47,17 +47,16 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = { .accel = FB_ACCEL_NONE, }; -static int inverse = 0; -static int mtrr = 0; /* disable mtrr */ -static int vram_remap __initdata = 0; /* Set amount of memory to be used */ -static int vram_total __initdata = 0; /* Set total amount of memory */ -static int pmi_setpal = 1; /* pmi for palette changes ??? */ -static int ypan = 0; /* 0..nothing, 1..ypan, 2..ywrap */ -static unsigned short *pmi_base = NULL; -static void (*pmi_start)(void); -static void (*pmi_pal)(void); -static int depth; -static int vga_compat; +static int inverse __read_mostly; +static int mtrr __read_mostly; /* disable mtrr */ +static int vram_remap __initdata; /* Set amount of memory to be used */ +static int vram_total __initdata; /* Set total amount of memory */ +static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */ +static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */ +static void (*pmi_start)(void) __read_mostly; +static void (*pmi_pal) (void) __read_mostly; +static int depth __read_mostly; +static int vga_compat __read_mostly; /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -312,6 +311,7 @@ static int __init vesafb_probe(struct platform_device *dev) ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */ if (ypan || pmi_setpal) { + unsigned short *pmi_base; pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); pmi_start = (void*)((char*)pmi_base + pmi_base[1]); pmi_pal = (void*)((char*)pmi_base + pmi_base[2]); @@ -456,6 +456,8 @@ static int __init vesafb_probe(struct platform_device *dev) info->node, info->fix.id); return 0; err: + if (info->screen_base) + iounmap(info->screen_base); framebuffer_release(info); release_mem_region(vesafb_fix.smem_start, size_total); return err; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 43d5a6d9c4a..6aff63d5b29 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -264,7 +264,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, const struct fb_info *info, int mul, int div) { - static struct { + static const struct { u32 pixclock; u8 misc; u8 seq_clock_mode; @@ -652,7 +652,7 @@ static int vga16fb_set_par(struct fb_info *info) static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) { - static unsigned char map[] = { 000, 001, 010, 011 }; + static const unsigned char map[] = { 000, 001, 010, 011 }; int val; if (regno >= 16) @@ -1139,23 +1139,19 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are } } -#ifdef __LITTLE_ENDIAN -static unsigned int transl_l[] = -{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; -static unsigned int transl_h[] = -{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, - 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; -#else -#ifdef __BIG_ENDIAN -static unsigned int transl_h[] = -{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; -static unsigned int transl_l[] = -{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, - 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; +#define TRANS_MASK_LOW {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF} +#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \ + 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00} + +#if defined(__LITTLE_ENDIAN) +static const u16 transl_l[] = TRANS_MASK_LOW; +static const u16 transl_h[] = TRANS_MASK_HIGH; +#elif defined(__BIG_ENDIAN) +static const u16 transl_l[] = TRANS_MASK_HIGH; +static const u16 transl_h[] = TRANS_MASK_LOW; #else #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes" #endif -#endif static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image) { diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index 64378959dd7..b9fb6fb3600 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -1799,7 +1799,7 @@ int __init virgefb_init(void) #warning release resources printk(KERN_ERR "virgefb.c: register_framebuffer failed\n"); DPRINTK("EXIT\n"); - return -EINVAL; + goto out_unmap; } printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n", @@ -1809,6 +1809,21 @@ int __init virgefb_init(void) DPRINTK("EXIT\n"); return 0; + +out_unmap: + if (board_addr >= 0x01000000) { + if (v_ram) + iounmap((void*)v_ram); + if (vgaio_regs) + iounmap(vgaio_regs); + if (mmio_regs) + iounmap(mmio_regs); + if (vcode_switch_base) + iounmap((void*)vcode_switch_base); + v_ram = vcode_switch_base = 0; + vgaio_regs = mmio_regs = NULL; + } + return -EINVAL; } |