diff options
Diffstat (limited to 'drivers/video')
71 files changed, 2455 insertions, 2200 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index cc8e3bf5001..3e153d313bb 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -993,12 +993,6 @@ config FB_ATY_GENERIC_LCD Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility, Rage XC, or Rage XL chipset. -config FB_ATY_XL_INIT - bool "Rage XL No-BIOS Init support" - depends on FB_ATY_CT - help - Say Y here to support booting a Rage XL without BIOS support. - config FB_ATY_GX bool "Mach64 GX support" if PCI depends on FB_ATY @@ -1151,7 +1145,7 @@ config FB_VOODOO1 config FB_CYBLA tristate "Cyberblade/i1 support" - depends on FB && PCI + depends on FB && PCI && X86_32 && !64BIT select FB_CFB_IMAGEBLIT select VIDEO_SELECT ---help--- @@ -1376,7 +1370,7 @@ config FB_PXA This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The - module will be called vfb. If you want to compile it as a module, + module will be called pxafb. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. If unsure, say N. @@ -1409,7 +1403,7 @@ config FB_W100 This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The - module will be called vfb. If you want to compile it as a module, + module will be called w100fb. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. If unsure, say N. diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index a3c2c45e29e..0da4083ba90 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -21,12 +21,11 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/list.h> +#include <linux/amba/bus.h> +#include <linux/amba/clcd.h> +#include <linux/clk.h> #include <asm/sizes.h> -#include <asm/hardware/amba.h> -#include <asm/hardware/clock.h> - -#include <asm/hardware/amba_clcd.h> #define to_clcd(info) container_of(info, struct clcd_fb, fb) @@ -346,10 +345,6 @@ static int clcdfb_register(struct clcd_fb *fb) goto out; } - ret = clk_use(fb->clk); - if (ret) - goto free_clk; - fb->fb.fix.mmio_start = fb->dev->res.start; fb->fb.fix.mmio_len = SZ_4K; @@ -357,7 +352,7 @@ static int clcdfb_register(struct clcd_fb *fb) if (!fb->regs) { printk(KERN_ERR "CLCD: unable to remap registers\n"); ret = -ENOMEM; - goto unuse_clk; + goto free_clk; } fb->fb.fbops = &clcdfb_ops; @@ -427,8 +422,6 @@ static int clcdfb_register(struct clcd_fb *fb) printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret); iounmap(fb->regs); - unuse_clk: - clk_unuse(fb->clk); free_clk: clk_put(fb->clk); out: @@ -489,7 +482,6 @@ static int clcdfb_remove(struct amba_device *dev) clcdfb_disable(fb); unregister_framebuffer(&fb->fb); iounmap(fb->regs); - clk_unuse(fb->clk); clk_put(fb->clk); fb->board->remove(fb); diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 2784f0a9d69..89060b2db8e 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -366,7 +366,8 @@ static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx, } } -void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +static void arcfb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) { struct arcfb_par *par = info->par; @@ -376,7 +377,8 @@ void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height); } -void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +static void arcfb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) { struct arcfb_par *par = info->par; @@ -386,7 +388,7 @@ void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height); } -void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) +static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) { struct arcfb_par *par = info->par; diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index c64de59398f..69f75547865 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -549,7 +549,7 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) if (!request_mem_region(addr, size, "asiliantfb")) return -EBUSY; - p = framebuffer_alloc(sizeof(u32) * 256, &dp->dev); + p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev); if (!p) { release_mem_region(addr, size); return -ENOMEM; diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile index 9dec96249ff..18521397a6e 100644 --- a/drivers/video/aty/Makefile +++ b/drivers/video/aty/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_FB_RADEON) += radeonfb.o atyfb-y := atyfb_base.o mach64_accel.o mach64_cursor.o atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o -atyfb-$(CONFIG_FB_ATY_XL_INIT) += xlinit.o atyfb-objs := $(atyfb-y) diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 09de173c116..e9b7a64c1ac 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -50,6 +50,7 @@ struct pll_info { int sclk, mclk, mclk_pm, xclk; int ref_div; int ref_clk; + int ecp_max; }; typedef struct { @@ -354,6 +355,5 @@ 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 int atyfb_xl_init(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); diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 3fefdb0cbf0..e370125e4fb 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -109,9 +109,18 @@ #define GUI_RESERVE (1 * PAGE_SIZE) /* FIXME: remove the FAIL definition */ -#define FAIL(msg) do { printk(KERN_CRIT "atyfb: " msg "\n"); return -EINVAL; } while (0) -#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0) - +#define FAIL(msg) do { \ + if (!(var->activate & FB_ACTIVATE_TEST)) \ + printk(KERN_CRIT "atyfb: " msg "\n"); \ + return -EINVAL; \ +} while (0) +#define FAIL_MAX(msg, x, _max_) do { \ + if (x > _max_) { \ + if (!(var->activate & FB_ACTIVATE_TEST)) \ + printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \ + return -EINVAL; \ + } \ +} while (0) #ifdef DEBUG #define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args) #else @@ -340,6 +349,7 @@ static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, }; #define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL) #define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP) +/* FIXME what is this chip? */ #define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP) /* make sets shorter */ @@ -359,58 +369,60 @@ static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, }; static struct { u16 pci_id; const char *name; - int pll, mclk, xclk; + int pll, mclk, xclk, ecp_max; u32 features; } aty_chips[] __devinitdata = { #ifdef CONFIG_FB_ATY_GX /* Mach64 GX */ - { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX }, - { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, ATI_CHIP_88800CX }, + { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX }, + { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX }, #endif /* CONFIG_FB_ATY_GX */ #ifdef CONFIG_FB_ATY_CT - { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, ATI_CHIP_264CT }, - { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, ATI_CHIP_264ET }, - { PCI_CHIP_MACH64VT, "ATI264VT? (Mach64 VT)", 170, 67, 67, ATI_CHIP_264VT }, - { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, ATI_CHIP_264GT }, - /* FIXME { ...ATI_264GU, maybe ATI_CHIP_264GTDVD }, */ - { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GTB)", 200, 67, 67, ATI_CHIP_264GTB }, - { PCI_CHIP_MACH64VU, "ATI264VTB (Mach64 VU)", 200, 67, 67, ATI_CHIP_264VT3 }, - - { PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT }, - /* FIXME chipset maybe ATI_CHIP_264LTPRO ? */ - { PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 }, - - { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 }, - - { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, ATI_CHIP_264GT2C }, - { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, ATI_CHIP_264GT2C }, - { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, ATI_CHIP_264GT2C }, - { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, ATI_CHIP_264GT2C }, - - { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, ATI_CHIP_264GTPRO }, - { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, ATI_CHIP_264GTPRO }, - { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE }, - { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO }, - { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, ATI_CHIP_264GTPRO }, - - { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, ATI_CHIP_264LTPRO }, - { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, ATI_CHIP_264LTPRO }, - { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 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, ATI_CHIP_264LTPRO }, - { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO }, - - { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL }, - { PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL }, - { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL }, - { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 235, 83, 63, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL }, - { PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL }, - { PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL }, - - { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY }, - { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY }, - { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY }, - { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY }, + { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT }, + { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET }, + + /* FIXME what is this chip? */ + { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT }, + + { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT }, + { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT }, + + { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 }, + { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB }, + + { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 }, + + { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 }, + + { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, + { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, + { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, + { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, + + { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, + { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, + { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE }, + { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, + { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, + + { 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_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 }, + { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL }, + { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL }, + { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL }, + { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL }, + { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL }, + + { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, + { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, + { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, + { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, #endif /* CONFIG_FB_ATY_CT */ }; @@ -431,6 +443,7 @@ static int __devinit correct_chipset(struct atyfb_par *par) par->pll_limits.pll_max = aty_chips[i].pll; par->pll_limits.mclk = aty_chips[i].mclk; par->pll_limits.xclk = aty_chips[i].xclk; + par->pll_limits.ecp_max = aty_chips[i].ecp_max; par->features = aty_chips[i].features; chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); @@ -450,39 +463,63 @@ static int __devinit correct_chipset(struct atyfb_par *par) #endif #ifdef CONFIG_FB_ATY_CT case PCI_CHIP_MACH64VT: - rev &= 0xc7; - if(rev == 0x00) { - name = "ATI264VTA3 (Mach64 VT)"; - par->pll_limits.pll_max = 170; - par->pll_limits.mclk = 67; - par->pll_limits.xclk = 67; - par->features = ATI_CHIP_264VT; - } else if(rev == 0x40) { - name = "ATI264VTA4 (Mach64 VT)"; + switch (rev & 0x07) { + case 0x00: + switch (rev & 0xc0) { + case 0x00: + name = "ATI264VT (A3) (Mach64 VT)"; + par->pll_limits.pll_max = 170; + par->pll_limits.mclk = 67; + par->pll_limits.xclk = 67; + par->pll_limits.ecp_max = 80; + par->features = ATI_CHIP_264VT; + break; + case 0x40: + name = "ATI264VT2 (A4) (Mach64 VT)"; + par->pll_limits.pll_max = 200; + par->pll_limits.mclk = 67; + par->pll_limits.xclk = 67; + par->pll_limits.ecp_max = 80; + par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV; + break; + } + break; + case 0x01: + name = "ATI264VT3 (B1) (Mach64 VT)"; par->pll_limits.pll_max = 200; par->pll_limits.mclk = 67; par->pll_limits.xclk = 67; - par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV; - } else { - name = "ATI264VTB (Mach64 VT)"; + par->pll_limits.ecp_max = 80; + par->features = ATI_CHIP_264VTB; + break; + case 0x02: + name = "ATI264VT3 (B2) (Mach64 VT)"; par->pll_limits.pll_max = 200; par->pll_limits.mclk = 67; par->pll_limits.xclk = 67; - par->features = ATI_CHIP_264VTB; + par->pll_limits.ecp_max = 80; + par->features = ATI_CHIP_264VT3; + break; } break; case PCI_CHIP_MACH64GT: - rev &= 0x07; - if(rev == 0x01) { + switch (rev & 0x07) { + case 0x01: + name = "3D RAGE II (Mach64 GT)"; par->pll_limits.pll_max = 170; par->pll_limits.mclk = 67; par->pll_limits.xclk = 67; + par->pll_limits.ecp_max = 80; par->features = ATI_CHIP_264GTB; - } else if(rev == 0x02) { + break; + case 0x02: + name = "3D RAGE II+ (Mach64 GT)"; par->pll_limits.pll_max = 200; par->pll_limits.mclk = 67; par->pll_limits.xclk = 67; + par->pll_limits.ecp_max = 100; par->features = ATI_CHIP_264GTB; + break; } break; #endif @@ -692,7 +729,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | (SHADOW_EN | SHADOW_RW_EN), par); - DPRINTK("set secondary CRT to %ix%i %c%c\n", + DPRINTK("set shadow CRT to %ix%i %c%c\n", ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1), (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P'); @@ -840,11 +877,14 @@ static int aty_var_to_crtc(const struct fb_info *info, know if one is connected. So it's better to fail then. */ if (crtc->lcd_gen_cntl & CRT_ON) { - PRINTKI("Disable lcd panel, because video mode does not fit.\n"); + if (!(var->activate & FB_ACTIVATE_TEST)) + PRINTKI("Disable LCD panel, because video mode does not fit.\n"); crtc->lcd_gen_cntl &= ~LCD_ON; /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/ } else { - FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode."); + if (!(var->activate & FB_ACTIVATE_TEST)) + PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n"); + return -EINVAL; } } } @@ -858,9 +898,9 @@ static int aty_var_to_crtc(const struct fb_info *info, vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED); /* This is horror! When we simulate, say 640x480 on an 800x600 - lcd monitor, the CRTC should be programmed 800x600 values for + LCD monitor, the CRTC should be programmed 800x600 values for the non visible part, but 640x480 for the visible part. - This code has been tested on a laptop with it's 1400x1050 lcd + This code has been tested on a laptop with it's 1400x1050 LCD monitor and a conventional monitor both switched on. Tested modes: 1280x1024, 1152x864, 1024x768, 800x600, works with little glitches also with DOUBLESCAN modes @@ -955,16 +995,6 @@ static int aty_var_to_crtc(const struct fb_info *info, vdisplay = yres; if(vmode & FB_VMODE_DOUBLE) vdisplay <<= 1; - if(vmode & FB_VMODE_INTERLACED) { - vdisplay >>= 1; - - /* The prefered mode for the lcd is not interlaced, so disable it if - it was enabled. For doublescan there is no problem, because we can - compensate for it in the hardware stretching (we stretch half as much) - */ - vmode &= ~FB_VMODE_INTERLACED; - /*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/ - } crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH); crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/ @@ -980,7 +1010,7 @@ static int aty_var_to_crtc(const struct fb_info *info, crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | HORZ_STRETCH_MODE | HORZ_STRETCH_EN); - if (xres < par->lcd_width) { + if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) { do { /* * The horizontal blender misbehaves when HDisplay is less than a @@ -1042,7 +1072,7 @@ static int aty_var_to_crtc(const struct fb_info *info, } while (0); } - if (vdisplay < par->lcd_height) { + if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) { crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN | (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0)); @@ -1065,9 +1095,8 @@ static int aty_var_to_crtc(const struct fb_info *info, #endif /* CONFIG_FB_ATY_GENERIC_LCD */ if (M64_HAS(MAGIC_FIFO)) { - /* Not VTB/GTB */ - /* FIXME: magic FIFO values */ - crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH); + /* FIXME: display FIFO low watermark values */ + crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM); } crtc->dp_pix_width = dp_pix_width; crtc->dp_chain_mask = dp_chain_mask; @@ -1184,7 +1213,8 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va var->transp.length = 8; break; default: - FAIL("Invalid pixel width"); + PRINTKE("Invalid pixel width\n"); + return -EINVAL; } /* output */ @@ -1241,7 +1271,8 @@ static int atyfb_set_par(struct fb_info *info) pixclock = atyfb_get_pixclock(var, par); if (pixclock == 0) { - FAIL("Invalid pixclock"); + PRINTKE("Invalid pixclock\n"); + return -EINVAL; } else { if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll))) return err; @@ -1446,7 +1477,9 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) pixclock = atyfb_get_pixclock(var, par); if (pixclock == 0) { - FAIL("Invalid pixclock"); + if (!(var->activate & FB_ACTIVATE_TEST)) + PRINTKE("Invalid pixclock\n"); + return -EINVAL; } else { if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll))) return err; @@ -2291,10 +2324,6 @@ static int __init aty_init(struct fb_info *info, const char *name) par->dac_ops = &aty_dac_ct; par->pll_ops = &aty_pll_ct; par->bus_type = PCI; -#ifdef CONFIG_FB_ATY_XL_INIT - if (IS_XL(par->pci_id)) - atyfb_xl_init(info); -#endif par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07); ramname = aty_ct_ram[par->ram_type]; /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ @@ -2638,16 +2667,16 @@ static int __init store_video_par(char *video_str, unsigned char m64_num) static int atyfb_blank(int blank, struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; - u8 gen_cntl; + u32 gen_cntl; if (par->lock_blank || par->asleep) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank) + if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL) set_backlight_enable(0); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) - if (par->lcd_table && blank && + if (par->lcd_table && blank > FB_BLANK_NORMAL && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); pm &= ~PWR_BLON; @@ -2655,31 +2684,31 @@ static int atyfb_blank(int blank, struct fb_info *info) } #endif - gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par); + gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); switch (blank) { case FB_BLANK_UNBLANK: - gen_cntl &= ~(0x4c); + gen_cntl &= ~0x400004c; break; case FB_BLANK_NORMAL: - gen_cntl |= 0x40; + gen_cntl |= 0x4000040; break; case FB_BLANK_VSYNC_SUSPEND: - gen_cntl |= 0x8; + gen_cntl |= 0x4000048; break; case FB_BLANK_HSYNC_SUSPEND: - gen_cntl |= 0x4; + gen_cntl |= 0x4000044; break; case FB_BLANK_POWERDOWN: - gen_cntl |= 0x4c; + gen_cntl |= 0x400004c; break; } - aty_st_8(CRTC_GEN_CNTL, gen_cntl, par); + aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && !blank) + if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL) set_backlight_enable(1); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) - if (par->lcd_table && !blank && + if (par->lcd_table && blank <= FB_BLANK_NORMAL && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); pm |= PWR_BLON; @@ -3157,15 +3186,15 @@ static void aty_init_lcd(struct atyfb_par *par, u32 bios_base) refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]); par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate]; /* We now need to determine the crtc parameters for the - * lcd monitor. This is tricky, because they are not stored + * LCD monitor. This is tricky, because they are not stored * individually in the BIOS. Instead, the BIOS contains a * table of display modes that work for this monitor. * * The idea is that we search for a mode of the same dimensions - * as the dimensions of the lcd monitor. Say our lcd monitor + * as the dimensions of the LCD monitor. Say our LCD monitor * is 800x600 pixels, we search for a 800x600 monitor. * The CRTC parameters we find here are the ones that we need - * to use to simulate other resolutions on the lcd screen. + * to use to simulate other resolutions on the LCD screen. */ lcdmodeptr = (u16 *)(par->lcd_table + 64); while (*lcdmodeptr != 0) { @@ -3692,9 +3721,7 @@ static int __init atyfb_init(void) atyfb_setup(option); #endif -#ifdef CONFIG_PCI pci_register_driver(&atyfb_driver); -#endif #ifdef CONFIG_ATARI atyfb_atari_probe(); #endif @@ -3703,9 +3730,7 @@ static int __init atyfb_init(void) static void __exit atyfb_exit(void) { -#ifdef CONFIG_PCI pci_unregister_driver(&atyfb_driver); -#endif } module_init(atyfb_init); diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index 9bdb2aab01a..e7056934c6a 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -206,9 +206,7 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll { u32 q; struct atyfb_par *par = (struct atyfb_par *) info->par; -#ifdef DEBUG int pllvclk; -#endif /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */ q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per; @@ -223,13 +221,26 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll pll->vclk_post_div_real = postdividers[pll->vclk_post_div]; // pll->vclk_post_div <<= 6; pll->vclk_fb_div = q * pll->vclk_post_div_real / 8; -#ifdef DEBUG pllvclk = (1000000 * 2 * pll->vclk_fb_div) / (par->ref_clk_per * pll->pll_ref_div); +#ifdef DEBUG printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n", __FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real); #endif pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ + + /* Set ECP (scaler/overlay clock) divider */ + if (par->pll_limits.ecp_max) { + int ecp = pllvclk / pll->vclk_post_div_real; + int ecp_div = 0; + + while (ecp > par->pll_limits.ecp_max && ecp_div < 2) { + ecp >>= 1; + ecp_div++; + } + pll->pll_vclk_cntl |= ecp_div << 4; + } + return 0; } diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c index ea7c8630691..7f9838dceab 100644 --- a/drivers/video/aty/radeon_monitor.c +++ b/drivers/video/aty/radeon_monitor.c @@ -423,7 +423,7 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo, /* * Probe display on both primary and secondary card's connector (if any) * by various available techniques (i2c, OF device tree, BIOS, ...) and - * try to retreive EDID. The algorithm here comes from XFree's radeon + * try to retrieve EDID. The algorithm here comes from XFree's radeon * driver */ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo, diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c deleted file mode 100644 index a085cbf74ec..00000000000 --- a/drivers/video/aty/xlinit.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * ATI Rage XL Initialization. Support for Xpert98 and Victoria - * PCI cards. - * - * Copyright (C) 2002 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * stevel@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <asm/io.h> -#include <video/mach64.h> -#include "atyfb.h" - -#define MPLL_GAIN 0xad -#define VPLL_GAIN 0xd5 - -enum { - VICTORIA = 0, - XPERT98, - NUM_XL_CARDS -}; - -extern const struct aty_pll_ops aty_pll_ct; - -#define DEFAULT_CARD XPERT98 -static int xl_card = DEFAULT_CARD; - -static const struct xl_card_cfg_t { - int ref_crystal; // 10^4 Hz - int mem_type; - int mem_size; - u32 mem_cntl; - u32 ext_mem_cntl; - u32 mem_addr_config; - u32 bus_cntl; - u32 dac_cntl; - u32 hw_debug; - u32 custom_macro_cntl; - u8 dll2_cntl; - u8 pll_yclk_cntl; -} card_cfg[NUM_XL_CARDS] = { - // VICTORIA - { 2700, SDRAM, 0x800000, - 0x10757A3B, 0x64000C81, 0x00110202, 0x7b33A040, - 0x82010102, 0x48803800, 0x005E0179, - 0x50, 0x25 - }, - // XPERT98 - { 1432, WRAM, 0x800000, - 0x00165A2B, 0xE0000CF1, 0x00200213, 0x7333A001, - 0x8000000A, 0x48833800, 0x007F0779, - 0x10, 0x19 - } -}; - -typedef struct { - u8 lcd_reg; - u32 val; -} lcd_tbl_t; - -static const lcd_tbl_t lcd_tbl[] = { - { 0x01, 0x000520C0 }, - { 0x08, 0x02000408 }, - { 0x03, 0x00000F00 }, - { 0x00, 0x00000000 }, - { 0x02, 0x00000000 }, - { 0x04, 0x00000000 }, - { 0x05, 0x00000000 }, - { 0x06, 0x00000000 }, - { 0x33, 0x00000000 }, - { 0x34, 0x00000000 }, - { 0x35, 0x00000000 }, - { 0x36, 0x00000000 }, - { 0x37, 0x00000000 } -}; - -static void reset_gui(struct atyfb_par *par) -{ - aty_st_8(GEN_TEST_CNTL+1, 0x01, par); - aty_st_8(GEN_TEST_CNTL+1, 0x00, par); - aty_st_8(GEN_TEST_CNTL+1, 0x02, par); - mdelay(5); -} - -static void reset_sdram(struct atyfb_par *par) -{ - u8 temp; - - temp = aty_ld_8(EXT_MEM_CNTL, par); - temp |= 0x02; - aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_RESET = 1b - temp |= 0x08; - aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 10b - temp |= 0x0c; - aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 11b - mdelay(5); - temp &= 0xf3; - aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 00b - temp &= 0xfd; - aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_REST = 0b - mdelay(5); -} - -static void init_dll(struct atyfb_par *par) -{ - // enable DLL - aty_st_pll_ct(PLL_GEN_CNTL, - aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f, - par); - - // reset DLL - aty_st_pll_ct(DLL_CNTL, 0x82, par); - aty_st_pll_ct(DLL_CNTL, 0xE2, par); - mdelay(5); - aty_st_pll_ct(DLL_CNTL, 0x82, par); - mdelay(6); -} - -static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll, - int hsync_enb) -{ - reset_gui(par); - aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par); - aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par); - - mdelay(15); - init_dll(par); - aty_st_8(GEN_TEST_CNTL+1, 0x00, par); - mdelay(5); - aty_st_8(CRTC_GEN_CNTL+3, 0x04, par); - mdelay(6); - reset_sdram(par); - aty_st_8(CRTC_GEN_CNTL+3, - hsync_enb ? 0x00 : 0x04, par); - - aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par); - aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par); - aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par); -} - -int atyfb_xl_init(struct fb_info *info) -{ - const struct xl_card_cfg_t * card = &card_cfg[xl_card]; - struct atyfb_par *par = (struct atyfb_par *) info->par; - union aty_pll pll; - int err; - u32 temp; - - aty_st_8(CONFIG_STAT0, 0x85, par); - mdelay(10); - - /* - * The following needs to be set before the call - * to var_to_pll() below. They'll be re-set again - * to the same values in aty_init(). - */ - par->ref_clk_per = 100000000UL/card->ref_crystal; - par->ram_type = card->mem_type; - info->fix.smem_len = card->mem_size; - if (xl_card == VICTORIA) { - // the MCLK, XCLK are 120MHz on victoria card - par->mclk_per = 1000000/120; - par->xclk_per = 1000000/120; - par->features &= ~M64F_MFB_FORCE_4; - } - - /* - * Calculate mclk and xclk dividers, etc. The passed - * pixclock and bpp values don't matter yet, the vclk - * isn't programmed until later. - */ - if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll))) - return err; - - aty_st_pll_ct(LVDS_CNTL0, 0x00, par); - aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par); - aty_st_pll_ct(V2PLL_CNTL, 0x10, par); - aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par); - aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par); - aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par); - aty_st_pll_ct(VFC_CNTL, 0x1B, par); - aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par); - aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par); - aty_st_pll_ct(SPLL_CNTL2, 0x03, par); - aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par); - - reset_clocks(par, &pll.ct, 0); - mdelay(10); - - aty_st_pll_ct(VCLK_POST_DIV, 0x03, par); - aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par); - aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par); - aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par); - aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par); - aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par); - aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par); - aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par); - aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par); - aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par); - - aty_st_8(BUS_CNTL, 0x01, par); - aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par); - - aty_st_le32(CRTC_GEN_CNTL, 0x04000200, par); - aty_st_le16(CONFIG_STAT0, 0x0020, par); - aty_st_le32(MEM_CNTL, 0x10151A33, par); - aty_st_le32(EXT_MEM_CNTL, 0xE0000C01, par); - aty_st_le16(CRTC_GEN_CNTL+2, 0x0000, par); - aty_st_le32(DAC_CNTL, card->dac_cntl, par); - aty_st_le16(GEN_TEST_CNTL, 0x0100, par); - aty_st_le32(CUSTOM_MACRO_CNTL, 0x003C0171, par); - aty_st_le32(MEM_BUF_CNTL, 0x00382848, par); - - aty_st_le32(HW_DEBUG, card->hw_debug, par); - aty_st_le16(MEM_ADDR_CONFIG, 0x0000, par); - aty_st_le16(GP_IO+2, 0x0000, par); - aty_st_le16(GEN_TEST_CNTL, 0x0000, par); - aty_st_le16(EXT_DAC_REGS+2, 0x0000, par); - aty_st_le32(CRTC_INT_CNTL, 0x00000000, par); - aty_st_le32(TIMER_CONFIG, 0x00000000, par); - aty_st_le32(0xEC, 0x00000000, par); - aty_st_le32(0xFC, 0x00000000, par); - -#if defined (CONFIG_FB_ATY_GENERIC_LCD) - { - int i; - - for (i = 0; i < ARRAY_SIZE(lcd_tbl); i++) - aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par); - } -#endif - - aty_st_le16(CONFIG_STAT0, 0x00A4, par); - mdelay(10); - - aty_st_8(BUS_CNTL+1, 0xA0, par); - mdelay(10); - - reset_clocks(par, &pll.ct, 1); - mdelay(10); - - // something about power management - aty_st_8(LCD_INDEX, 0x08, par); - aty_st_8(LCD_DATA, 0x0A, par); - aty_st_8(LCD_INDEX, 0x08, par); - aty_st_8(LCD_DATA+3, 0x02, par); - aty_st_8(LCD_INDEX, 0x08, par); - aty_st_8(LCD_DATA, 0x0B, par); - mdelay(2); - - // enable display requests, enable CRTC - aty_st_8(CRTC_GEN_CNTL+3, 0x02, par); - // disable display - aty_st_8(CRTC_GEN_CNTL, 0x40, par); - // disable display requests, disable CRTC - aty_st_8(CRTC_GEN_CNTL+3, 0x04, par); - mdelay(10); - - aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par); - - aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par); - aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par); - aty_st_le16(CUSTOM_MACRO_CNTL+2, card->custom_macro_cntl>>16, par); - aty_st_8(CUSTOM_MACRO_CNTL+1, - (card->custom_macro_cntl>>8) & 0xff, par); - - aty_st_le32(MEM_ADDR_CONFIG, card->mem_addr_config, par); - aty_st_le32(MEM_CNTL, card->mem_cntl, par); - aty_st_le32(EXT_MEM_CNTL, card->ext_mem_cntl, par); - - aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par); - - aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par); - mdelay(15); - aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par); - mdelay(1); - - reset_clocks(par, &pll.ct, 0); - mdelay(50); - reset_clocks(par, &pll.ct, 0); - mdelay(50); - - // enable extended register block - aty_st_8(BUS_CNTL+3, 0x7B, par); - mdelay(1); - // disable extended register block - aty_st_8(BUS_CNTL+3, 0x73, par); - - aty_st_8(CONFIG_STAT0, 0x80 | card->mem_type, par); - - // disable display requests, disable CRTC - aty_st_8(CRTC_GEN_CNTL+3, 0x04, par); - // disable mapping registers in VGA aperture - aty_st_8(CONFIG_CNTL, aty_ld_8(CONFIG_CNTL, par) & ~0x04, par); - mdelay(50); - // enable display requests, enable CRTC - aty_st_8(CRTC_GEN_CNTL+3, 0x02, par); - - // make GPIO's 14,15,16 all inputs - aty_st_8(LCD_INDEX, 0x07, par); - aty_st_8(LCD_DATA+3, 0x00, par); - - // enable the display - aty_st_8(CRTC_GEN_CNTL, 0x00, par); - mdelay(17); - // reset the memory controller - aty_st_8(GEN_TEST_CNTL+1, 0x02, par); - mdelay(15); - aty_st_8(GEN_TEST_CNTL+1, 0x00, par); - mdelay(30); - - // enable extended register block - aty_st_8(BUS_CNTL+3, - (u8)(aty_ld_8(BUS_CNTL+3, par) | 0x08), - par); - // set FIFO size to 512 (PIO) - aty_st_le32(GUI_CNTL, - aty_ld_le32(GUI_CNTL, par) & ~0x3, - par); - - // enable CRT and disable lcd - aty_st_8(LCD_INDEX, 0x01, par); - temp = aty_ld_le32(LCD_DATA, par); - temp = (temp | 0x01) & ~0x02; - aty_st_le32(LCD_DATA, temp, par); - return 0; -} - diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 6a219b2c77e..d0aaf450e8c 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -20,6 +20,7 @@ #include <linux/backlight.h> #include <asm/arch/sharpsl.h> +#include <asm/hardware/sharpsl_pm.h> #define CORGI_DEFAULT_INTENSITY 0x1f #define CORGI_LIMIT_MASK 0x0b diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index a5d09e159cd..6ee449858a5 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 && !ARCH_VERSATILE + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index e65fc3ef763..eea422eb1ab 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -234,14 +234,14 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, } } -static void bit_cursor(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, int fg, int bg) +static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.width + 7) >> 3, c; - int y = real_y(p, vc->vc_y); + int y = real_y(ops->p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1; char *src; @@ -310,7 +310,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != p->cursor_shape || + vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); @@ -323,10 +323,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, kfree(ops->cursor_state.mask); ops->cursor_state.mask = mask; - p->cursor_shape = vc->vc_cursor_type; + ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (p->cursor_shape & CUR_HWMASK) { + switch (ops->p->cursor_shape & CUR_HWMASK) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3660e51b261..041d0698786 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -209,13 +209,13 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) #endif #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION -static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +static inline void fbcon_set_rotation(struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; if (!(info->flags & FBINFO_MISC_TILEBLITTING) && - p->con_rotate < 4) - ops->rotate = p->con_rotate; + ops->p->con_rotate < 4) + ops->rotate = ops->p->con_rotate; else ops->rotate = 0; } @@ -265,7 +265,7 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate) fbcon_set_all_vcs(info); } #else -static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +static inline void fbcon_set_rotation(struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -402,7 +402,7 @@ static void fb_flashcursor(void *private) c = scr_readw((u16 *) vc->vc_pos); mode = (!ops->cursor_flash || ops->cursor_state.enable) ? CM_ERASE : CM_DRAW; - ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1), + ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1), get_color(vc, info, c, 0)); release_console_sem(); } @@ -647,29 +647,27 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, } #ifdef CONFIG_FB_TILEBLITTING -static void set_blitting_type(struct vc_data *vc, struct fb_info *info, - struct display *p) +static void set_blitting_type(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; - ops->p = (p) ? p : &fb_display[vc->vc_num]; + ops->p = &fb_display[vc->vc_num]; if ((info->flags & FBINFO_MISC_TILEBLITTING)) - fbcon_set_tileops(vc, info, p, ops); + fbcon_set_tileops(vc, info); else { - fbcon_set_rotation(info, ops->p); + fbcon_set_rotation(info); fbcon_set_bitops(ops); } } #else -static void set_blitting_type(struct vc_data *vc, struct fb_info *info, - struct display *p) +static void set_blitting_type(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; info->flags &= ~FBINFO_MISC_TILEBLITTING; - ops->p = (p) ? p : &fb_display[vc->vc_num]; - fbcon_set_rotation(info, ops->p); + ops->p = &fb_display[vc->vc_num]; + fbcon_set_rotation(info); fbcon_set_bitops(ops); } #endif /* CONFIG_MISC_TILEBLITTING */ @@ -689,15 +687,14 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info, err = -ENODEV; if (!err) { - ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL); + ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL); if (!ops) err = -ENOMEM; } if (!err) { - memset(ops, 0, sizeof(struct fbcon_ops)); info->fbcon_par = ops; - set_blitting_type(vc, info, NULL); + set_blitting_type(vc, info); } if (err) { @@ -921,19 +918,18 @@ static const char *fbcon_startup(void) return NULL; } - ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL); + ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL); if (!ops) { module_put(owner); return NULL; } - memset(ops, 0, sizeof(struct fbcon_ops)); ops->currcon = -1; ops->graphics = 1; ops->cur_rotate = -1; info->fbcon_par = ops; p->con_rotate = rotate; - set_blitting_type(vc, info, NULL); + set_blitting_type(vc, info); if (info->fix.type != FB_TYPE_TEXT) { if (fbcon_softback_size) { @@ -1093,7 +1089,7 @@ static void fbcon_init(struct vc_data *vc, int init) ops = info->fbcon_par; p->con_rotate = rotate; - set_blitting_type(vc, info, NULL); + set_blitting_type(vc, info); cols = vc->vc_cols; rows = vc->vc_rows; @@ -1110,7 +1106,7 @@ static void fbcon_init(struct vc_data *vc, int init) * * We need to do it in fbcon_init() to prevent screen corruption. */ - if (CON_IS_VISIBLE(vc)) { + if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) info->fbops->fb_set_par(info); @@ -1141,9 +1137,9 @@ static void fbcon_init(struct vc_data *vc, int init) if (vc == svc && softback_buf) fbcon_update_softback(vc); - if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + if (ops->rotate_font && ops->rotate_font(info, vc)) { ops->rotate = FB_ROTATE_UR; - set_blitting_type(vc, info, p); + set_blitting_type(vc, info); } } @@ -1243,7 +1239,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; - struct display *p = &fb_display[vc->vc_num]; int y; int c = scr_readw((u16 *) vc->vc_pos); @@ -1260,7 +1255,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) y = 0; } - ops->cursor(vc, info, p, mode, y, get_color(vc, info, c, 1), + ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1), get_color(vc, info, c, 0)); vbl_cursor_cnt = CURSOR_DRAW_DELAY; } @@ -1411,16 +1406,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; - int redraw = 0; p->yscroll += count; + if (p->yscroll > p->vrows - vc->vc_rows) { p->yscroll -= p->vrows - vc->vc_rows; - redraw = 1; - } - - if (redraw) fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); + } ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; @@ -1462,16 +1454,13 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; - int redraw = 0; p->yscroll -= count; + if (p->yscroll < 0) { p->yscroll += p->vrows - vc->vc_rows; - redraw = 1; - } - - if (redraw) fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); + } ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; @@ -1968,7 +1957,8 @@ static __inline__ void updatescrollmode(struct display *p, divides(ypan, vc->vc_font.height) && vyres > yres; int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && divides(ywrap, vc->vc_font.height) && - divides(vc->vc_font.height, vyres); + divides(vc->vc_font.height, vyres) && + divides(vc->vc_font.height, yres); int reading_fast = cap & FBINFO_READS_FAST; int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED); @@ -2107,16 +2097,19 @@ static int fbcon_switch(struct vc_data *vc) info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { if (info->fbops->fb_set_par) info->fbops->fb_set_par(info); - fbcon_del_cursor_timer(old_info); - fbcon_add_cursor_timer(info); + + if (old_info != info) { + fbcon_del_cursor_timer(old_info); + fbcon_add_cursor_timer(info); + } } - set_blitting_type(vc, info, p); + set_blitting_type(vc, info); ops->cursor_reset = 1; - if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + if (ops->rotate_font && ops->rotate_font(info, vc)) { ops->rotate = FB_ROTATE_UR; - set_blitting_type(vc, info, p); + set_blitting_type(vc, info); } vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); @@ -2739,7 +2732,7 @@ static void fbcon_modechanged(struct fb_info *info) return; p = &fb_display[vc->vc_num]; - set_blitting_type(vc, info, p); + set_blitting_type(vc, info); if (CON_IS_VISIBLE(vc)) { var_to_display(p, &info->var, info); @@ -2781,7 +2774,7 @@ static void fbcon_set_all_vcs(struct fb_info *info) continue; p = &fb_display[vc->vc_num]; - set_blitting_type(vc, info, p); + set_blitting_type(vc, info); var_to_display(p, &info->var, info); cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); @@ -2806,6 +2799,8 @@ static void fbcon_set_all_vcs(struct fb_info *info) fbcon_update_softback(vc); } } + + ops->p = &fb_display[ops->currcon]; } static int fbcon_mode_deleted(struct fb_info *info, diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 6892e7ff34d..c38c3d8e7a7 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -62,12 +62,10 @@ struct fbcon_ops { int fg, int bg); void (*clear_margins)(struct vc_data *vc, struct fb_info *info, int bottom_only); - void (*cursor)(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, - int fg, int bg); + void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg); int (*update_start)(struct fb_info *info); - int (*rotate_font)(struct fb_info *info, struct vc_data *vc, - struct display *p); + int (*rotate_font)(struct fb_info *info, struct vc_data *vc); struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ struct timer_list cursor_timer; /* Cursor timer */ struct fb_cursor cursor_state; @@ -173,8 +171,7 @@ struct fbcon_ops { #define SCROLL_PAN_REDRAW 0x005 #ifdef CONFIG_FB_TILEBLITTING -extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, - struct display *p, struct fbcon_ops *ops); +extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 4952b66ae20..990289a69b7 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c @@ -219,19 +219,18 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, } } -static void ccw_cursor(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, - int fg, int bg) +static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(p, vc->vc_y); + int y = real_y(ops->p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1, dx, dy; char *src; - u32 vyres = GETVYRES(p->scrollmode, info); + u32 vyres = GETVYRES(ops->p->scrollmode, info); if (!ops->fontbuffer) return; @@ -303,7 +302,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != p->cursor_shape || + vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); @@ -323,10 +322,10 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, kfree(ops->cursor_state.mask); ops->cursor_state.mask = mask; - p->cursor_shape = vc->vc_cursor_type; + ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (p->cursor_shape & CUR_HWMASK) { + switch (ops->p->cursor_shape & CUR_HWMASK) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 6d92b845620..d44c5fa515f 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c @@ -203,19 +203,18 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, } } -static void cw_cursor(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, - int fg, int bg) +static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(p, vc->vc_y); + int y = real_y(ops->p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1, dx, dy; char *src; - u32 vxres = GETVXRES(p->scrollmode, info); + u32 vxres = GETVXRES(ops->p->scrollmode, info); if (!ops->fontbuffer) return; @@ -287,7 +286,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != p->cursor_shape || + vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); @@ -307,10 +306,10 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, kfree(ops->cursor_state.mask); ops->cursor_state.mask = mask; - p->cursor_shape = vc->vc_cursor_type; + ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (p->cursor_shape & CUR_HWMASK) { + switch (ops->p->cursor_shape & CUR_HWMASK) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c index ec0dd8fe241..2dc091fbd5c 100644 --- a/drivers/video/console/fbcon_rotate.c +++ b/drivers/video/console/fbcon_rotate.c @@ -18,8 +18,7 @@ #include "fbcon.h" #include "fbcon_rotate.h" -static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc, - struct display *p) +static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) { struct fbcon_ops *ops = info->fbcon_par; int len, err = 0; @@ -28,12 +27,12 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc, u8 *dst; if (vc->vc_font.data == ops->fontdata && - p->con_rotate == ops->cur_rotate) + ops->p->con_rotate == ops->cur_rotate) goto finished; src = ops->fontdata = vc->vc_font.data; - ops->cur_rotate = p->con_rotate; - len = (!p->userfont) ? 256 : FNTCHARCNT(src); + ops->cur_rotate = ops->p->con_rotate; + len = (!ops->p->userfont) ? 256 : FNTCHARCNT(src); s_cellsize = ((vc->vc_font.width + 7)/8) * vc->vc_font.height; d_cellsize = s_cellsize; diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h index 1b8f92fdc6a..75be5ce53dc 100644 --- a/drivers/video/console/fbcon_rotate.h +++ b/drivers/video/console/fbcon_rotate.h @@ -11,8 +11,6 @@ #ifndef _FBCON_ROTATE_H #define _FBCON_ROTATE_H -#define FNTCHARCNT(fd) (((int *)(fd))[-3]) - #define GETVYRES(s,i) ({ \ (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \ (i)->var.yres : (i)->var.yres_virtual; }) diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 9dd059e8b64..f56ed068a5b 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c @@ -249,20 +249,19 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, } } -static void ud_cursor(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, - int fg, int bg) +static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.width + 7) >> 3, c; - int y = real_y(p, vc->vc_y); + int y = real_y(ops->p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1, dx, dy; char *src; - u32 vyres = GETVYRES(p->scrollmode, info); - u32 vxres = GETVXRES(p->scrollmode, info); + u32 vyres = GETVYRES(ops->p->scrollmode, info); + u32 vxres = GETVXRES(ops->p->scrollmode, info); if (!ops->fontbuffer) return; @@ -334,7 +333,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != p->cursor_shape || + vc->vc_cursor_type != ops->p->cursor_shape || ops->cursor_state.mask == NULL || ops->cursor_reset) { char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); @@ -347,10 +346,10 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, kfree(ops->cursor_state.mask); ops->cursor_state.mask = mask; - p->cursor_shape = vc->vc_cursor_type; + ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (p->cursor_shape & CUR_HWMASK) { + switch (ops->p->cursor_shape & CUR_HWMASK) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c index 8529bf08db2..3957fc7523e 100644 --- a/drivers/video/console/softcursor.c +++ b/drivers/video/console/softcursor.c @@ -17,6 +17,8 @@ #include <asm/uaccess.h> #include <asm/io.h> +#include "fbcon.h" + int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) { unsigned int scan_align = info->pixmap.scan_align - 1; diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index cb25324a563..153352ca946 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c @@ -80,9 +80,8 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info, return; } -static void tile_cursor(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, - int fg, int bg) +static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int softback_lines, int fg, int bg) { struct fb_tilecursor cursor; int use_sw = (vc->vc_cursor_type & 0x01); @@ -130,10 +129,10 @@ static int tile_update_start(struct fb_info *info) return err; } -void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, - struct display *p, struct fbcon_ops *ops) +void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info) { struct fb_tilemap map; + struct fbcon_ops *ops = info->fbcon_par; ops->bmove = tile_bmove; ops->clear = tile_clear; @@ -142,13 +141,13 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, ops->cursor = tile_cursor; ops->update_start = tile_update_start; - if (p) { + if (ops->p) { map.width = vc->vc_font.width; map.height = vc->vc_font.height; map.depth = 1; - map.length = (p->userfont) ? - FNTCHARCNT(p->fontdata) : 256; - map.data = p->fontdata; + map.length = (ops->p->userfont) ? + FNTCHARCNT(ops->p->fontdata) : 256; + map.data = ops->p->fontdata; info->tileops->fb_settile(info, &map); } } diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 167de397e4b..12d9329d140 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -56,6 +56,8 @@ static DEFINE_SPINLOCK(vga_lock); static int cursor_size_lastfrom; static int cursor_size_lastto; +static u32 vgacon_xres; +static u32 vgacon_yres; static struct vgastate state; #define BLANK 0x0020 @@ -69,7 +71,7 @@ static struct vgastate state; * appear. */ #undef TRIDENT_GLITCH - +#define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */ /* * Interface used by the world */ @@ -325,6 +327,10 @@ static const char __init *vgacon_startup(void) vga_scan_lines = vga_video_font_height * vga_video_num_lines; } + + vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; + vgacon_yres = vga_scan_lines; + return display_desc; } @@ -503,10 +509,18 @@ static int vgacon_doresize(struct vc_data *c, { unsigned long flags; unsigned int scanlines = height * c->vc_font.height; - u8 scanlines_lo, r7, vsync_end, mode; + u8 scanlines_lo, r7, vsync_end, mode, max_scan; spin_lock_irqsave(&vga_lock, flags); + outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg); + max_scan = inb_p(vga_video_port_val); + + if (max_scan & 0x80) + scanlines <<= 1; + + vgacon_xres = width * VGA_FONTWIDTH; + vgacon_yres = height * c->vc_font.height; outb_p(VGA_CRTC_MODE, vga_video_port_reg); mode = inb_p(vga_video_port_val); @@ -551,6 +565,10 @@ static int vgacon_doresize(struct vc_data *c, static int vgacon_switch(struct vc_data *c) { + int x = c->vc_cols * VGA_FONTWIDTH; + int y = c->vc_rows * c->vc_font.height; + int rows = ORIG_VIDEO_LINES * vga_default_font_height/ + c->vc_font.height; /* * We need to save screen size here as it's the only way * we can spot the screen has been resized and we need to @@ -566,10 +584,11 @@ static int vgacon_switch(struct vc_data *c) scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); - if (!(vga_video_num_columns % 2) && - vga_video_num_columns <= ORIG_VIDEO_COLS && - vga_video_num_lines <= (ORIG_VIDEO_LINES * - vga_default_font_height) / c->vc_font.height) + + if ((vgacon_xres != x || vgacon_yres != y) && + (!(vga_video_num_columns % 2) && + vga_video_num_columns <= ORIG_VIDEO_COLS && + vga_video_num_lines <= rows)) vgacon_doresize(c, c->vc_cols, c->vc_rows); } @@ -993,7 +1012,8 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne if (vga_video_type < VIDEO_TYPE_EGAM) return -EINVAL; - if (font->width != 8 || (charcount != 256 && charcount != 512)) + if (font->width != VGA_FONTWIDTH || + (charcount != 256 && charcount != 512)) return -EINVAL; rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512); @@ -1010,7 +1030,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) if (vga_video_type < VIDEO_TYPE_EGAM) return -EINVAL; - font->width = 8; + font->width = VGA_FONTWIDTH; font->height = c->vc_font.height; font->charcount = vga_512_chars ? 512 : 256; if (!font->data) diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 403d17377f8..03798e9c882 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -133,12 +133,6 @@ static int controlfb_mmap(struct fb_info *info, struct file *file, static int controlfb_set_par (struct fb_info *info); static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); -/* - * inititialization - */ -int control_init(void); -void control_setup(char *); - /******************** Prototypes for internal functions **********************/ static void set_control_clock(unsigned char *params); @@ -550,9 +544,46 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro /* - * Called from fbmem.c for probing & initializing + * Parse user speficied options (`video=controlfb:') */ -int __init control_init(void) +static void __init control_setup(char *options) +{ + char *this_opt; + + if (!options || !*options) + return; + + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!strncmp(this_opt, "vmode:", 6)) { + int vmode = simple_strtoul(this_opt+6, NULL, 0); + if (vmode > 0 && vmode <= VMODE_MAX && + control_mac_modes[vmode - 1].m[1] >= 0) + default_vmode = vmode; + } else if (!strncmp(this_opt, "cmode:", 6)) { + int depth = simple_strtoul(this_opt+6, NULL, 0); + switch (depth) { + case CMODE_8: + case CMODE_16: + case CMODE_32: + default_cmode = depth; + break; + case 8: + default_cmode = CMODE_8; + break; + case 15: + case 16: + default_cmode = CMODE_16; + break; + case 24: + case 32: + default_cmode = CMODE_32; + break; + } + } + } +} + +static int __init control_init(void) { struct device_node *dp; char *option = NULL; @@ -651,15 +682,16 @@ static void __init find_vram_size(struct fb_info_control *p) static int __init control_of_init(struct device_node *dp) { struct fb_info_control *p; - unsigned long addr; - int i; + struct resource fb_res, reg_res; if (control_fb) { printk(KERN_ERR "controlfb: only one control is supported\n"); return -ENXIO; } - if(dp->n_addrs != 2) { - printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs); + + if (of_pci_address_to_resource(dp, 2, &fb_res) || + of_pci_address_to_resource(dp, 1, ®_res)) { + printk(KERN_ERR "can't get 2 addresses for control\n"); return -ENXIO; } p = kmalloc(sizeof(*p), GFP_KERNEL); @@ -669,18 +701,12 @@ static int __init control_of_init(struct device_node *dp) memset(p, 0, sizeof(*p)); /* Map in frame buffer and registers */ - for (i = 0; i < dp->n_addrs; ++i) { - addr = dp->addrs[i].address; - if (dp->addrs[i].size >= 0x800000) { - p->fb_orig_base = addr; - p->fb_orig_size = dp->addrs[i].size; - /* use the big-endian aperture (??) */ - p->frame_buffer_phys = addr + 0x800000; - } else { - p->control_regs_phys = addr; - p->control_regs_size = dp->addrs[i].size; - } - } + p->fb_orig_base = fb_res.start; + p->fb_orig_size = fb_res.end - fb_res.start + 1; + /* use the big-endian aperture (??) */ + p->frame_buffer_phys = fb_res.start + 0x800000; + p->control_regs_phys = reg_res.start; + p->control_regs_size = reg_res.end - reg_res.start + 1; if (!p->fb_orig_base || !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) { @@ -1059,43 +1085,3 @@ static void control_cleanup(void) } -/* - * Parse user speficied options (`video=controlfb:') - */ -void __init control_setup(char *options) -{ - char *this_opt; - - if (!options || !*options) - return; - - while ((this_opt = strsep(&options, ",")) != NULL) { - if (!strncmp(this_opt, "vmode:", 6)) { - int vmode = simple_strtoul(this_opt+6, NULL, 0); - if (vmode > 0 && vmode <= VMODE_MAX && - control_mac_modes[vmode - 1].m[1] >= 0) - default_vmode = vmode; - } else if (!strncmp(this_opt, "cmode:", 6)) { - int depth = simple_strtoul(this_opt+6, NULL, 0); - switch (depth) { - case CMODE_8: - case CMODE_16: - case CMODE_32: - default_cmode = depth; - break; - case 8: - default_cmode = CMODE_8; - break; - case 15: - case 16: - default_cmode = CMODE_16; - break; - case 24: - case 32: - default_cmode = CMODE_32; - break; - } - } - } -} - diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index a9300f930ef..55a3514157e 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -50,7 +50,6 @@ #include <linux/init.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/pgtable.h> #include <asm/system.h> #include <asm/uaccess.h> diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index 03fbe83d71a..2b972461a03 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -7,11 +7,12 @@ * tridentfb.c by Jani Monoses * see files above for further credits * - * TODO: - * */ #define CYBLAFB_DEBUG 0 +#define CYBLAFB_KD_GRAPHICS_QUIRK 1 + +#define CYBLAFB_PIXMAPSIZE 8192 #include <linux/config.h> #include <linux/module.h> @@ -22,7 +23,7 @@ #include <asm/types.h> #include <video/cyblafb.h> -#define VERSION "0.54" +#define VERSION "0.62" struct cyblafb_par { u32 pseudo_pal[16]; @@ -32,7 +33,9 @@ struct cyblafb_par { static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { .id = "CyBla", .type = FB_TYPE_PACKED_PIXELS, + .xpanstep = 1, .ypanstep = 1, + .ywrapstep = 1, .visual = FB_VISUAL_PSEUDOCOLOR, .accel = FB_ACCEL_NONE, }; @@ -43,8 +46,9 @@ static int ref __devinitdata = 75; static int fp __devinitdata; static int crt __devinitdata; static int memsize __devinitdata; -static int vesafb __devinitdata; +static int basestride; +static int vesafb; static int nativex; static int center; static int stretch; @@ -52,26 +56,50 @@ static int pciwb = 1; static int pcirb = 1; static int pciwr = 1; static int pcirr = 1; +static int disabled; static int verbosity; static int displaytype; -static void __iomem * io_virt; // iospace virtual memory address - -module_param(mode,charp,0); -module_param(bpp,int,0); -module_param(ref,int,0); -module_param(fp,int,0); -module_param(crt,int,0); -module_param(nativex,int,0); -module_param(center,int,0); -module_param(stretch,int,0); -module_param(pciwb,int,0); -module_param(pcirb,int,0); -module_param(pciwr,int,0); -module_param(pcirr,int,0); -module_param(memsize,int,0); -module_param(verbosity,int,0); -module_param(vesafb,int,0); +static void __iomem *io_virt; // iospace virtual memory address + +module_param(mode, charp, 0); +module_param(bpp, int, 0); +module_param(ref, int, 0); +module_param(fp, int, 0); +module_param(crt, int, 0); +module_param(nativex, int, 0); +module_param(center, int, 0); +module_param(stretch, int, 0); +module_param(pciwb, int, 0); +module_param(pcirb, int, 0); +module_param(pciwr, int, 0); +module_param(pcirr, int, 0); +module_param(memsize, int, 0); +module_param(verbosity, int, 0); + +//========================================= +// +// Well, we have to fix the upper layers. +// Until this has been done, we work around +// the bugs. +// +//========================================= + +#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG) + if (disabled) { \ + printk("********\n");\ + dump_stack();\ + return val;\ + } + +#elif CYBLAFB_KD_GRAPHICS_QUIRK +#define KD_GRAPHICS_RETURN(val)\ + if (disabled) {\ + return val;\ + } +#else +#define KD_GRAPHICS_RETURN(val) +#endif //========================================= // @@ -79,10 +107,10 @@ module_param(vesafb,int,0); // //========================================= -#define out8(r,v) writeb(v,io_virt+r) -#define out32(r,v) writel(v,io_virt+r) -#define in8(r) readb(io_virt+r) -#define in32(r) readl(io_virt+r) +#define out8(r, v) writeb(v, io_virt + r) +#define out32(r, v) writel(v, io_virt + r) +#define in8(r) readb(io_virt + r) +#define in32(r) readl(io_virt + r) //====================================== // @@ -90,47 +118,47 @@ module_param(vesafb,int,0); // //====================================== -static inline unsigned char read3X4(int reg) +static inline u8 read3X4(u32 reg) { - out8(0x3D4,reg); + out8(0x3D4, reg); return in8(0x3D5); } -static inline unsigned char read3C4(int reg) +static inline u8 read3C4(u32 reg) { - out8(0x3C4,reg); + out8(0x3C4, reg); return in8(0x3C5); } -static inline unsigned char read3CE(int reg) +static inline u8 read3CE(u32 reg) { - out8(0x3CE,reg); + out8(0x3CE, reg); return in8(0x3CF); } -static inline void write3X4(int reg,unsigned char val) +static inline void write3X4(u32 reg, u8 val) { - out8(0x3D4,reg); - out8(0x3D5,val); + out8(0x3D4, reg); + out8(0x3D5, val); } -static inline void write3C4(int reg,unsigned char val) +static inline void write3C4(u32 reg, u8 val) { - out8(0x3C4,reg); - out8(0x3C5,val); + out8(0x3C4, reg); + out8(0x3C5, val); } -static inline void write3CE(int reg,unsigned char val) +static inline void write3CE(u32 reg, u8 val) { - out8(0x3CE,reg); - out8(0x3CF,val); + out8(0x3CE, reg); + out8(0x3CF, val); } -static inline void write3C0(int reg,unsigned char val) +static inline void write3C0(u32 reg, u8 val) { - in8(0x3DA); // read to reset index - out8(0x3C0,reg); - out8(0x3C0,val); + in8(0x3DA); // read to reset index + out8(0x3C0, reg); + out8(0x3C0, val); } //================================================= @@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val) // //================================================= -static inline void enable_mmio(void) +static void enable_mmio(void) { - int tmp; + u8 tmp; - outb(0x0B,0x3C4); + outb(0x0B, 0x3C4); inb(0x3C5); // Set NEW mode - outb(SR0E,0x3C4); // write enable a lot of extended ports - outb(0x80,0x3C5); + outb(SR0E, 0x3C4); // write enable a lot of extended ports + outb(0x80, 0x3C5); - outb(SR11,0x3C4); // write enable those extended ports that - outb(0x87,0x3C5); // are not affected by SR0E_New + outb(SR11, 0x3C4); // write enable those extended ports that + outb(0x87, 0x3C5); // are not affected by SR0E_New - outb(CR1E,0x3d4); // clear write protect bit for port 0x3c2 - tmp=inb(0x3d5) & 0xBF; - outb(CR1E,0x3d4); - outb(tmp,0x3d5); + outb(CR1E, 0x3d4); // clear write protect bit for port 0x3c2 + tmp = inb(0x3d5) & 0xBF; + outb(CR1E, 0x3d4); + outb(tmp, 0x3d5); - outb(CR39,0x3D4); - outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched + outb(CR39, 0x3D4); + outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio } //================================================= // // Set pixel clock VCLK1 -// - multipliers set elswhere -// - freq in units of 0.01 MHz +// - multipliers set elswhere +// - freq in units of 0.01 MHz +// +// Hardware bug: SR18 >= 250 is broken for the +// cyberblade/i1 // //================================================= static void set_vclk(struct cyblafb_par *par, int freq) { - u32 m,n,k; - int f,fi,d,di; - u8 lo=0,hi=0; + u32 m, n, k; + int f, fi, d, di; + u8 lo = 0, hi = 0; d = 2000; k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3; - for(m = 0;m<64;m++) - for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 ! - fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12); - if ((di = abs(fi - freq)) < d) { - d = di; - f = fi; - lo = (u8) n; - hi = (u8) ((k<<6) | m); + for (m = 0; m < 64; m++) + for (n = 0; n < 250; n++) { + fi = (int)(((5864727 * (n + 8)) / + ((m + 2) * (1 << k))) >> 12); + if ((di = abs(fi - freq)) < d) { + d = di; + f = fi; + lo = (u8) n; + hi = (u8) ((k << 6) | m); + } } - } - write3C4(SR19,hi); - write3C4(SR18,lo); - if(verbosity > 1) + write3C4(SR19, hi); + write3C4(SR18, lo); + if (verbosity > 0) output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n", - freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo); + freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo); } //================================================ @@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq) // //================================================ -static void cyblafb_setup_GE(int pitch,int bpp) +static void cyblafb_setup_GE(int pitch, int bpp) { - int base = (pitch>>3)<<20; + KD_GRAPHICS_RETURN(); switch (bpp) { - case 8: base |= (0<<29); break; - case 15: base |= (5<<29); break; - case 16: base |= (1<<29); break; - case 24: - case 32: base |= (2<<29); break; + case 8: + basestride = ((pitch >> 3) << 20) | (0 << 29); + break; + case 15: + basestride = ((pitch >> 3) << 20) | (5 << 29); + break; + case 16: + basestride = ((pitch >> 3) << 20) | (1 << 29); + break; + case 24: + case 32: + basestride = ((pitch >> 3) << 20) | (2 << 29); + break; } - write3X4(CR36,0x90); // reset GE - write3X4(CR36,0x80); // enable GE - - out32(GE24,1<<7); // reset all GE pointers - out32(GE24,0); - - write3X4(CR2D,0x00); // GE Timinigs, no delays - - out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133 - out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133 - out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133 - out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133 - out32(GEC8,base); // Source Stride / Buffer Base 0, p 133 - out32(GECC,base); // Source Stride / Buffer Base 1, p 133 - out32(GED0,base); // Source Stride / Buffer Base 2, p 133 - out32(GED4,base); // Source Stride / Buffer Base 3, p 133 - out32(GE6C,0); // Pattern and Style, p 129, ok + write3X4(CR36, 0x90); // reset GE + write3X4(CR36, 0x80); // enable GE + out32(GE24, 1 << 7); // reset all GE pointers by toggling + out32(GE24, 0); // d7 of GE24 + write3X4(CR2D, 0x00); // GE Timinigs, no delays + out32(GE6C, 0); // Pattern and Style, p 129, ok } //===================================================================== // -// Although this is a .fb_sync function that could be enabled in -// cyblafb_ops, we do not include it there. We sync immediately before -// new GE operations to improve performance. +// Cyberblade specific syncing +// +// A timeout might be caused by disabled mmio. +// Cause: +// - bit CR39 & 1 == 0 upon return, X trident driver bug +// - kdm bug (KD_GRAPHICS not set on first switch) +// - kernel design flaw (it believes in the correctness +// of kdm/X +// First we try to sync ignoring that problem, as most of the +// time that will succeed immediately and the enable_mmio() +// would only degrade performance. // //===================================================================== static int cyblafb_sync(struct fb_info *info) { - int status, i=100000; - while( ((status=in32(GE20)) & 0xFA800000) && i != 0) + u32 status, i = 100000; + + KD_GRAPHICS_RETURN(0); + + while (((status = in32(GE20)) & 0xFe800000) && i != 0) i--; if (i == 0) { - // The timeout might be caused by disabled mmio. - // Cause: - // - bit CR39 & 1 == 0 upon return, X trident driver bug - // - kdm bug (KD_GRAPHICS not set on first switch) - // - kernel design flaw (it believes in the correctness - // of kdm/X - // So we make sure that mmio is enabled first ... enable_mmio(); -// show_trace(NULL,&status); - i=1000000; - while( ((status=in32(GE20)) & 0xFA800000) && i != 0) + i = 1000000; + while (((status = in32(GE20)) & 0xFA800000) && i != 0) i--; if (i == 0) { - output("GE Timeout, status: %x\n",status); - if(status & 0x80000000) + output("GE Timeout, status: %x\n", status); + if (status & 0x80000000) output("Bresenham Engine : Busy\n"); - if(status & 0x40000000) + if (status & 0x40000000) output("Setup Engine : Busy\n"); - if(status & 0x20000000) + if (status & 0x20000000) output("SP / DPE : Busy\n"); - if(status & 0x10000000) + if (status & 0x10000000) output("Memory Interface : Busy\n"); - if(status & 0x08000000) + if (status & 0x08000000) output("Com Lst Proc : Busy\n"); - if(status & 0x04000000) + if (status & 0x04000000) output("Block Write : Busy\n"); - if(status & 0x02000000) + if (status & 0x02000000) output("Command Buffer : Full\n"); - if(status & 0x01000000) + if (status & 0x01000000) output("RESERVED : Busy\n"); - if(status & 0x00800000) + if (status & 0x00800000) output("PCI Write Buffer : Busy\n"); cyblafb_setup_GE(info->var.xres, info->var.bits_per_pixel); @@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info) // //============================== -static void cyblafb_fillrect(struct fb_info * info, - const struct fb_fillrect *fr) +static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr) { - int bpp = info->var.bits_per_pixel; - int col; + u32 bpp = info->var.bits_per_pixel, col, desty, height; + + KD_GRAPHICS_RETURN(); switch (bpp) { - default: - case 8: col = fr->color; - col |= col <<8; - col |= col <<16; - break; - case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; - col |= col <<16; - break; - case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; - break; + default: + case 8: + col = fr->color; + col |= col << 8; + col |= col << 16; + break; + case 16: + col = ((u32 *) (info->pseudo_palette))[fr->color]; + col |= col << 16; + break; + case 32: + col = ((u32 *) (info->pseudo_palette))[fr->color]; + break; } - cyblafb_sync(info); - - out32(GE60,col); - out32(GE48,fr->rop ? 0x66:ROP_S); - out32(GE44,0x20000000|1<<19|1<<4|2<<2); - out32(GE08,point(fr->dx,fr->dy)); - out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1)); - + desty = fr->dy; + height = fr->height; + while (height) { + out32(GEB8, basestride | ((desty * info->var.xres_virtual * + bpp) >> 6)); + out32(GE60, col); + out32(GE48, fr->rop ? 0x66 : ROP_S); + out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); + out32(GE08, point(fr->dx, 0)); + out32(GE0C, point(fr->dx + fr->width - 1, + height > 4096 ? 4095 : height - 1)); + if (likely(height <= 4096)) + return; + desty += 4096; + height -= 4096; + } } -//============================== +//================================================ // // Cyberblade specific copyarea // -//============================== +// This function silently assumes that it never +// will be called with width or height exceeding +// 4096. +// +//================================================ -static void cyblafb_copyarea(struct fb_info *info, - const struct fb_copyarea *ca) +static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca) { - __u32 s1,s2,d1,d2; - int direction; + u32 s1, s2, d1, d2, direction; + + KD_GRAPHICS_RETURN(); + + s1 = point(ca->sx, 0); + s2 = point(ca->sx + ca->width - 1, ca->height - 1); + d1 = point(ca->dx, 0); + d2 = point(ca->dx + ca->width - 1, ca->height - 1); - s1 = point(ca->sx,ca->sy); - s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1); - d1 = point(ca->dx,ca->dy); - d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1); if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx))) direction = 0; else direction = 2; - cyblafb_sync(info); - - out32(GE44,0xa0000000|1<<19|1<<2|direction); - out32(GE00,direction?s2:s1); - out32(GE04,direction?s1:s2); - out32(GE08,direction?d2:d1); - out32(GE0C,direction?d1:d2); - + out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual * + info->var.bits_per_pixel) >> 6)); + out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual * + info->var.bits_per_pixel) >> 6)); + out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction); + out32(GE00, direction ? s2 : s1); + out32(GE04, direction ? s1 : s2); + out32(GE08, direction ? d2 : d1); + out32(GE0C, direction ? d1 : d2); } //======================================================================= // // Cyberblade specific imageblit // -// Accelerated for the most usual case, blitting 1-bit deep character -// character images. Everything else is passed to the generic imageblit. +// Accelerated for the most usual case, blitting 1 - bit deep +// character images. Everything else is passed to the generic imageblit +// unless it is so insane that it is better to printk an alert. +// +// Hardware bug: _Never_ blit across pixel column 2048, that will lock +// the system. We split those blit requests into three blitting +// operations. // //======================================================================= static void cyblafb_imageblit(struct fb_info *info, const struct fb_image *image) { - u32 fgcol, bgcol; + u32 *pd = (u32 *) image->data; + u32 bpp = info->var.bits_per_pixel; - int i; - int bpp = info->var.bits_per_pixel; - int index = 0; - int index_end=image->height * image->width / 8; - int width_dds=image->width / 32; - int width_dbs=image->width % 32; - - if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 || - image->width % 8 != 0 || image->width == 0 || image->height == 0) { - cfb_imageblit(info,image); + KD_GRAPHICS_RETURN(); + + // Used only for drawing the penguine (image->depth > 1) + if (image->depth != 1) { + cfb_imageblit(info, image); + return; + } + // That should never happen, but it would be fatal + if (image->width == 0 || image->height == 0) { + output("imageblit: width/height 0 detected\n"); return; } if (info->fix.visual == FB_VISUAL_TRUECOLOR || info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcol = ((u32*)(info->pseudo_palette))[image->fg_color]; - bgcol = ((u32*)(info->pseudo_palette))[image->bg_color]; + fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color]; + bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color]; } else { fgcol = image->fg_color; bgcol = image->bg_color; } switch (bpp) { - case 8: - fgcol |= fgcol <<8; fgcol |= fgcol <<16; - bgcol |= bgcol <<8; bgcol |= bgcol <<16; - break; - case 16: - fgcol |= fgcol <<16; - bgcol |= bgcol <<16; - break; - default: - break; + case 8: + fgcol |= fgcol << 8; + bgcol |= bgcol << 8; + case 16: + fgcol |= fgcol << 16; + bgcol |= bgcol << 16; + default: + break; } - cyblafb_sync(info); - - out32(GE60,fgcol); - out32(GE64,bgcol); - out32(GE44,0xa0000000 | 1<<20 | 1<<19); - out32(GE08,point(image->dx,image->dy)); - out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1)); + out32(GEB8, basestride | ((image->dy * info->var.xres_virtual * + bpp) >> 6)); + out32(GE60, fgcol); + out32(GE64, bgcol); + + if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) { + u32 dds = ((image->width + 31) >> 5) * image->height; + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(image->dx, 0)); + out32(GE0C, point(image->dx + image->width - 1, + image->height - 1)); + while (dds--) + out32(GE9C, *pd++); + } else { + int i, j; + u32 ddstotal = (image->width + 31) >> 5; + u32 ddsleft = (2048 - image->dx + 31) >> 5; + u32 skipleft = ddstotal - ddsleft; + + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(image->dx, 0)); + out32(GE0C, point(2048 - 1, image->height - 1)); + for (i = 0; i < image->height; i++) { + for (j = 0; j < ddsleft; j++) + out32(GE9C, *pd++); + pd += skipleft; + } - while(index < index_end) { - const char *p = image->data + index; - for(i=0;i<width_dds;i++) { - out32(GE9C,*(u32*)p); - p+=4; - index+=4; + if (image->dx % 32) { + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(2048, 0)); + if (image->width > ddsleft << 5) + out32(GE0C, point(image->dx + (ddsleft << 5) - + 1, image->height - 1)); + else + out32(GE0C, point(image->dx + image->width - 1, + image->height - 1)); + pd = ((u32 *) image->data) + ddstotal - skipleft - 1; + for (i = 0; i < image->height; i++) { + out32(GE9C, swab32(swab32(*pd) << ((32 - + (image->dx & 31)) & 31))); + pd += ddstotal; + } } - switch(width_dbs) { - case 0: break; - case 8: out32(GE9C,*(u8*)p); - index+=1; - break; - case 16: out32(GE9C,*(u16*)p); - index+=2; - break; - case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16); - index+=3; - break; + + if (skipleft) { + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(image->dx + (ddsleft << 5), 0)); + out32(GE0C, point(image->dx + image->width - 1, + image->height - 1)); + pd = (u32 *) image->data; + for (i = 0; i < image->height; i++) { + pd += ddsleft; + for (j = 0; j < skipleft; j++) + out32(GE9C, *pd++); + } } } } @@ -443,7 +526,6 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int bpp = var->bits_per_pixel; - int s,t,maxvyres; // // we try to support 8, 16, 24 and 32 bpp modes, @@ -453,9 +535,9 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, // (This is what tridentfb does ... will be changed in the future) // // - if ( bpp % 8 != 0 || bpp < 8 || bpp >32) + if (bpp % 8 != 0 || bpp < 8 || bpp > 32) bpp = 8; - if (bpp == 24 ) + if (bpp == 24) bpp = var->bits_per_pixel = 32; // @@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, return -EINVAL; // - // xres != xres_virtual is broken, fail if such an - // unusual mode is requested + // we do not allow vclk to exceed 230 MHz. If the requested + // vclk is too high, we default to 200 MHz // - if (var->xres != var->xres_virtual) - return -EINVAL; + if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000) + var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000; // - // we do not allow vclk to exceed 230 MHz + // enforce (h|v)sync_len limits // - if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000) - return -EINVAL; + var->hsync_len &= ~7; + if(var->hsync_len > 248) + var->hsync_len = 248; + + var->vsync_len &= 15; // - // calc max yres_virtual that would fit in memory - // and max yres_virtual that could be used for scrolling - // and use minimum of the results as maxvyres - // - // adjust vyres_virtual to maxvyres if necessary - // fail if requested yres is bigger than maxvyres + // Enforce horizontal and vertical hardware limits. + // 1600x1200 is mentioned as a maximum, but higher resolutions could + // work with slow refresh, small margins and short sync. // - s = (0x1fffff / (var->xres * bpp/8)) + var->yres; - t = info->fix.smem_len / (var->xres * bpp/8); - maxvyres = t < s ? t : s; - if (maxvyres < var->yres_virtual) - var->yres_virtual=maxvyres; - if (maxvyres < var->yres) + var->xres &= ~7; + + if (((var->xres + var->left_margin + var->right_margin + + var->hsync_len) > (bpp == 32 ? 2040 : 4088)) || + ((var->yres + var->upper_margin + var->lower_margin + + var->vsync_len) > 2047)) return -EINVAL; - switch (bpp) { - case 8: - var->red.offset = 0; - var->green.offset = 0; - var->blue.offset = 0; - var->red.length = 6; - var->green.length = 6; - var->blue.length = 6; - break; - case 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; - break; - case 32: - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - break; - default: + if ((var->xres > 1600) || (var->yres > 1200)) + output("Mode %dx%d exceeds documented limits.\n", + var->xres, var->yres); + // + // try to be smart about (x|y)res_virtual problems. + // + if (var->xres > var->xres_virtual) + var->xres_virtual = var->xres; + if (var->yres > var->yres_virtual) + var->yres_virtual = var->yres; + + if (bpp == 8 || bpp == 16) { + if (var->xres_virtual > 4088) + var->xres_virtual = 4088; + } else { + if (var->xres_virtual > 2040) + var->xres_virtual = 2040; + } + var->xres_virtual &= ~7; + while (var->xres_virtual * var->yres_virtual * bpp / 8 > + info->fix.smem_len) { + if (var->yres_virtual > var->yres) + var->yres_virtual--; + else if (var->xres_virtual > var->xres) + var->xres_virtual -= 8; + else return -EINVAL; } - return 0; + switch (bpp) { + case 8: + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->red.length = 6; + var->green.length = 6; + var->blue.length = 6; + break; + case 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; + break; + case 32: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + break; + default: + return -EINVAL; + } + return 0; } //===================================================================== @@ -543,23 +653,25 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, // it, so it is also safe to be used here. BTW: datasheet CR0E on page // 90 really is CR1E, the real CRE is documented on page 72. // +// BUT: +// +// As of internal version 0.60 we do not use vga panning any longer. +// Vga panning did not allow us the use of all available video memory +// and thus prevented ywrap scrolling. We do use the "right view" +// register now. +// +// //===================================================================== static int cyblafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - unsigned int offset; + KD_GRAPHICS_RETURN(0); - offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32; info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; - - write3X4(CR0D,offset & 0xFF); - write3X4(CR0C,(offset & 0xFF00) >> 8); - write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11)); - write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17)); - write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15)); - + out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset * + var->xres_virtual)) * var->bits_per_pixel / 32)); return 0; } @@ -578,56 +690,96 @@ static void regdump(struct cyblafb_par *par) return; printk("\n"); - for(i=0; i<=0xff; i++) { - outb(i,0x3d4); - printk("CR%02x=%02x ",i,inb(0x3d5)); - if (i%16==15) + for (i = 0; i <= 0xff; i++) { + outb(i, 0x3d4); + printk("CR%02x=%02x ", i, inb(0x3d5)); + if (i % 16 == 15) printk("\n"); } - outb(0x30,0x3ce); - outb(inb(0x3cf) | 0x40,0x3cf); - for(i=0; i<=0x1f; i++) { - if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) { - outb(i,0x3d4); - printk("CR%02x=%02x ",i,inb(0x3d5)); + outb(0x30, 0x3ce); + outb(inb(0x3cf) | 0x40, 0x3cf); + for (i = 0; i <= 0x1f; i++) { + if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11 + || i == 0x16) { + outb(i, 0x3d4); + printk("CR%02x=%02x ", i, inb(0x3d5)); } else printk("------- "); - if (i%16==15) + if (i % 16 == 15) printk("\n"); } - outb(0x30,0x3ce); - outb(inb(0x3cf) & 0xbf,0x3cf); + outb(0x30, 0x3ce); + outb(inb(0x3cf) & 0xbf, 0x3cf); printk("\n"); - for(i=0; i<=0x7f; i++) { - outb(i,0x3ce); - printk("GR%02x=%02x ",i,inb(0x3cf)); - if (i%16==15) + for (i = 0; i <= 0x7f; i++) { + outb(i, 0x3ce); + printk("GR%02x=%02x ", i, inb(0x3cf)); + if (i % 16 == 15) printk("\n"); } printk("\n"); - for(i=0; i<=0xff; i++) { - outb(i,0x3c4); - printk("SR%02x=%02x ",i,inb(0x3c5)); - if (i%16==15) + for (i = 0; i <= 0xff; i++) { + outb(i, 0x3c4); + printk("SR%02x=%02x ", i, inb(0x3c5)); + if (i % 16 == 15) printk("\n"); } printk("\n"); - for(i=0; i <= 0x1F; i++) { - inb(0x3da); // next access is index! - outb(i,0x3c0); - printk("AR%02x=%02x ",i,inb(0x3c1)); - if (i%16==15) + for (i = 0; i <= 0x1F; i++) { + inb(0x3da); // next access is index! + outb(i, 0x3c0); + printk("AR%02x=%02x ", i, inb(0x3c1)); + if (i % 16 == 15) printk("\n"); } printk("\n"); - inb(0x3DA); // reset internal flag to 3c0 index - outb(0x20,0x3C0); // enable attr + inb(0x3DA); // reset internal flag to 3c0 index + outb(0x20, 0x3C0); // enable attr + + return; +} + +//======================================================================= +// +// Save State +// +// This function is called while a switch to KD_TEXT is in progress, +// before any of the other functions are called. +// +//======================================================================= +static void cyblafb_save_state(struct fb_info *info) +{ + struct cyblafb_par *par = info->par; + if (verbosity > 0) + output("Switching to KD_TEXT\n"); + disabled = 0; + regdump(par); + enable_mmio(); + return; +} + +//======================================================================= +// +// Restore State +// +// This function is called while a switch to KD_GRAPHICS is in progress, +// We have to turn on vga style panning registers again because the +// trident driver of X does not know about GE10. +// +//======================================================================= + +static void cyblafb_restore_state(struct fb_info *info) +{ + if (verbosity > 0) + output("Switching to KD_GRAPHICS\n"); + out32(GE10, 0); + disabled = 1; return; } @@ -640,32 +792,34 @@ static void regdump(struct cyblafb_par *par) static int cyblafb_set_par(struct fb_info *info) { struct cyblafb_par *par = info->par; - u32 - htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch, - vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend; + u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, + hblankend, preendfetch, vtotal, vdispend, vsyncstart, + vsyncend, vblankstart, vblankend; struct fb_var_screeninfo *var = &info->var; int bpp = var->bits_per_pixel; int i; + KD_GRAPHICS_RETURN(0); + if (verbosity > 0) output("Switching to new mode: " "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n", - var->xres,var->yres,var->xres_virtual, - var->yres_virtual,var->bits_per_pixel,var->pixclock, - var->left_margin,var->right_margin,var->upper_margin, - var->lower_margin,var->hsync_len,var->vsync_len); + var->xres, var->yres, var->xres_virtual, + var->yres_virtual, var->bits_per_pixel, var->pixclock, + var->left_margin, var->right_margin, var->upper_margin, + var->lower_margin, var->hsync_len, var->vsync_len); htotal = (var->xres + var->left_margin + var->right_margin + - var->hsync_len) / 8 - 5; - hdispend = var->xres/8 - 1; - hsyncstart = (var->xres + var->right_margin)/8; - hsyncend = var->hsync_len/8; + var->hsync_len) / 8 - 5; + hdispend = var->xres / 8 - 1; + hsyncstart = (var->xres + var->right_margin) / 8; + hsyncend = var->hsync_len / 8; hblankstart = hdispend + 1; hblankend = htotal + 3; // should be htotal + 5, bios does it this way - preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3); + preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3); vtotal = var->yres + var->upper_margin + var->lower_margin + - var->vsync_len - 2; + var->vsync_len - 2; vdispend = var->yres - 1; vsyncstart = var->yres + var->lower_margin; vblankstart = var->yres; @@ -674,101 +828,99 @@ static int cyblafb_set_par(struct fb_info *info) enable_mmio(); // necessary! ... check X ... - write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07 + write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07 - write3CE(GR30,8); + write3CE(GR30, 8); if ((displaytype == DISPLAY_FP) && var->xres < nativex) { // stretch or center ? - out8(0x3C2,0xEB); + out8(0x3C2, 0xEB); - write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on + write3CE(GR30, read3CE(GR30) | 0x81); // shadow mode on if (center) { - write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80); - write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80); - } - else if (stretch) { - write3CE(GR5D,0); - write3CE(GR52,(read3CE(GR52) & 0x7C) | 1); - write3CE(GR53,(read3CE(GR53) & 0x7C) | 1); + write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80); + write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80); + } else if (stretch) { + write3CE(GR5D, 0); + write3CE(GR52, (read3CE(GR52) & 0x7C) | 1); + write3CE(GR53, (read3CE(GR53) & 0x7C) | 1); } } else { - out8(0x3C2,0x2B); - write3CE(GR30,8); + out8(0x3C2, 0x2B); + write3CE(GR30, 8); } // // Setup CRxx regs // - write3X4(CR00,htotal & 0xFF); - write3X4(CR01,hdispend & 0xFF); - write3X4(CR02,hblankstart & 0xFF); - write3X4(CR03,hblankend & 0x1F); - write3X4(CR04,hsyncstart & 0xFF); - write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2)); - write3X4(CR06,vtotal & 0xFF); - write3X4(CR07,(vtotal & 0x100) >> 8 | - (vdispend & 0x100) >> 7 | - (vsyncstart & 0x100) >> 6 | - (vblankstart & 0x100) >> 5 | - 0x10 | - (vtotal & 0x200) >> 4 | - (vdispend & 0x200) >> 3 | - (vsyncstart & 0x200) >> 2); - write3X4(CR08,0); - write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 | // FIX !!! - ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0)); - write3X4(CR0A,0); // Init to some reasonable default - write3X4(CR0B,0); // Init to some reasonable default - write3X4(CR0C,0); // Offset 0 - write3X4(CR0D,0); // Offset 0 - write3X4(CR0E,0); // Init to some reasonable default - write3X4(CR0F,0); // Init to some reasonable default - write3X4(CR10,vsyncstart & 0xFF); - write3X4(CR11,(vsyncend & 0x0F)); - write3X4(CR12,vdispend & 0xFF); - write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF); - write3X4(CR14,0x40); // double word mode - write3X4(CR15,vblankstart & 0xFF); - write3X4(CR16,vblankend & 0xFF); - write3X4(CR17,0xC3); - write3X4(CR18,0xFF); + write3X4(CR00, htotal & 0xFF); + write3X4(CR01, hdispend & 0xFF); + write3X4(CR02, hblankstart & 0xFF); + write3X4(CR03, hblankend & 0x1F); + write3X4(CR04, hsyncstart & 0xFF); + write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2)); + write3X4(CR06, vtotal & 0xFF); + write3X4(CR07, (vtotal & 0x100) >> 8 | + (vdispend & 0x100) >> 7 | + (vsyncstart & 0x100) >> 6 | + (vblankstart & 0x100) >> 5 | + 0x10 | + (vtotal & 0x200) >> 4 | + (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2); + write3X4(CR08, 0); + write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 | // FIX !!! + ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0)); + write3X4(CR0A, 0); // Init to some reasonable default + write3X4(CR0B, 0); // Init to some reasonable default + write3X4(CR0C, 0); // Offset 0 + write3X4(CR0D, 0); // Offset 0 + write3X4(CR0E, 0); // Init to some reasonable default + write3X4(CR0F, 0); // Init to some reasonable default + write3X4(CR10, vsyncstart & 0xFF); + write3X4(CR11, (vsyncend & 0x0F)); + write3X4(CR12, vdispend & 0xFF); + write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF); + write3X4(CR14, 0x40); // double word mode + write3X4(CR15, vblankstart & 0xFF); + write3X4(CR16, vblankend & 0xFF); + write3X4(CR17, 0xE3); + write3X4(CR18, 0xFF); // CR19: needed for interlaced modes ... ignore it for now - write3X4(CR1A,0x07); // Arbitration Control Counter 1 - write3X4(CR1B,0x07); // Arbitration Control Counter 2 - write3X4(CR1C,0x07); // Arbitration Control Counter 3 - write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-) - write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80); + write3X4(CR1A, 0x07); // Arbitration Control Counter 1 + write3X4(CR1B, 0x07); // Arbitration Control Counter 2 + write3X4(CR1C, 0x07); // Arbitration Control Counter 3 + write3X4(CR1D, 0x00); // Don't know, doesn't hurt ; -) + write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80); // CR1F: do not set, contains BIOS info about memsize - write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode - write3X4(CR21,0x20); // enable linear memory access + write3X4(CR20, 0x20); // enabe wr buf, disable 16bit planar mode + write3X4(CR21, 0x20); // enable linear memory access // CR22: RO cpu latch readback // CR23: ??? // CR24: RO AR flag state // CR25: RAMDAC rw timing, pclk buffer tristate control ???? // CR26: ??? - write3X4(CR27,(vdispend & 0x400) >> 6 | - (vsyncstart & 0x400) >> 5 | - (vblankstart & 0x400) >> 4 | - (vtotal & 0x400) >> 3 | - 0x8); + write3X4(CR27, (vdispend & 0x400) >> 6 | + (vsyncstart & 0x400) >> 5 | + (vblankstart & 0x400) >> 4 | + (vtotal & 0x400) >> 3 | + 0x8); // CR28: ??? - write3X4(CR29,(read3X4(CR29) & 0xCF) | - ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4)); - write3X4(CR2A,read3X4(CR2A) | 0x40); - write3X4(CR2B,(htotal & 0x100) >> 8 | - (hdispend & 0x100) >> 7 | - // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ??? - (hsyncstart & 0x100) >> 5 | - (hblankstart & 0x100) >> 4); + write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual * + bpp) / (4 * 16)) & 0x300) >> 4)); + write3X4(CR2A, read3X4(CR2A) | 0x40); + write3X4(CR2B, (htotal & 0x100) >> 8 | + (hdispend & 0x100) >> 7 | + // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ??? + (hsyncstart & 0x100) >> 5 | + (hblankstart & 0x100) >> 4); // CR2C: ??? // CR2D: initialized in cyblafb_setup_GE() - write3X4(CR2F,0x92); // conservative, better signal quality + write3X4(CR2F, 0x92); // conservative, better signal quality // CR30: reserved // CR31: reserved // CR32: reserved @@ -777,96 +929,116 @@ static int cyblafb_set_par(struct fb_info *info) // CR35: disabled in CR36 // CR36: initialized in cyblafb_setup_GE // CR37: i2c, ignore for now - write3X4(CR38,(bpp == 8) ? 0x00 : // - (bpp == 16) ? 0x05 : // highcolor - (bpp == 24) ? 0x29 : // packed 24bit truecolor - (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus - write3X4(CR39,0x01 | // MMIO enable - (pcirb ? 0x02 : 0) | // pci read burst enable - (pciwb ? 0x04 : 0)); // pci write burst enable - write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase - (pcirr ? 0x40 : 0) | // pci read retry enable - (pciwr ? 0x80 : 0)); // pci write retry enable - write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0); - write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0); - write3X4(CR58,0x82); // Bios does this .... don't know more + write3X4(CR38, (bpp == 8) ? 0x00 : // + (bpp == 16) ? 0x05 : // highcolor + (bpp == 24) ? 0x29 : // packed 24bit truecolor + (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus + write3X4(CR39, 0x01 | // MMIO enable + (pcirb ? 0x02 : 0) | // pci read burst enable + (pciwb ? 0x04 : 0)); // pci write burst enable + write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase + (pcirr ? 0x40 : 0) | // pci read retry enable + (pciwr ? 0x80 : 0)); // pci write retry enable + write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2 + : 0); + write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0); + write3X4(CR58, 0x82); // Bios does this .... don't know more // // Setup SRxx regs // - write3C4(SR00,3); - write3C4(SR01,1); //set char clock 8 dots wide - write3C4(SR02,0x0F); //enable 4 maps needed in chain4 mode - write3C4(SR03,0); //no character map select - write3C4(SR04,0x0E); //memory mode: ext mem, even, chain4 + write3C4(SR00, 3); + write3C4(SR01, 1); //set char clock 8 dots wide + write3C4(SR02, 0x0F); //enable 4 maps needed in chain4 mode + write3C4(SR03, 0); //no character map select + write3C4(SR04, 0x0E); //memory mode: ext mem, even, chain4 - out8(0x3C4,0x0b); + out8(0x3C4, 0x0b); in8(0x3C5); // Set NEW mode - write3C4(SR0D,0x00); // test ... check + write3C4(SR0D, 0x00); // test ... check - set_vclk(par,(bpp==32 ? 200000000 : 100000000)/ - info->var.pixclock); //SR18,SR19 + set_vclk(par, (bpp == 32 ? 200000000 : 100000000) + / info->var.pixclock); //SR18, SR19 // // Setup GRxx regs // - write3CE(GR00,0x00); // test ... check - write3CE(GR01,0x00); // test ... check - write3CE(GR02,0x00); // test ... check - write3CE(GR03,0x00); // test ... check - write3CE(GR04,0x00); // test ... check - write3CE(GR05,0x40); // no CGA compat,allow 256 col - write3CE(GR06,0x05); // graphics mode - write3CE(GR07,0x0F); // planes? - write3CE(GR08,0xFF); // test ... check - write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4 - write3CE(GR20,0xC0); // test ... check - write3CE(GR2F,0xA0); // PCLK = VCLK, no skew, + write3CE(GR00, 0x00); // test ... check + write3CE(GR01, 0x00); // test ... check + write3CE(GR02, 0x00); // test ... check + write3CE(GR03, 0x00); // test ... check + write3CE(GR04, 0x00); // test ... check + write3CE(GR05, 0x40); // no CGA compat, allow 256 col + write3CE(GR06, 0x05); // graphics mode + write3CE(GR07, 0x0F); // planes? + write3CE(GR08, 0xFF); // test ... check + write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4 + write3CE(GR20, 0xC0); // test ... check + write3CE(GR2F, 0xA0); // PCLK = VCLK, no skew, // // Setup ARxx regs // - for(i = 0;i < 0x10;i++) // set AR00 .. AR0f - write3C0(i,i); - write3C0(AR10,0x41); // graphics mode and support 256 color modes - write3C0(AR12,0x0F); // planes - write3C0(AR13,0); // horizontal pel panning + for (i = 0; i < 0x10; i++) // set AR00 .. AR0f + write3C0(i, i); + write3C0(AR10, 0x41); // graphics mode and support 256 color modes + write3C0(AR12, 0x0F); // planes + write3C0(AR13, 0); // horizontal pel panning in8(0x3DA); // reset internal flag to 3c0 index - out8(0x3C0,0x20); // enable attr + out8(0x3C0, 0x20); // enable attr // // Setup hidden RAMDAC command register // - in8(0x3C8); // these reads are - in8(0x3C6); // necessary to - in8(0x3C6); // unmask the RAMDAC - in8(0x3C6); // command reg, otherwise - in8(0x3C6); // we would write the pixelmask reg! - out8(0x3C6,(bpp == 8) ? 0x00 : // 256 colors - (bpp == 15) ? 0x10 : // - (bpp == 16) ? 0x30 : // hicolor - (bpp == 24) ? 0xD0 : // truecolor - (bpp == 32) ? 0xD0 : 0); // truecolor + in8(0x3C8); // these reads are + in8(0x3C6); // necessary to + in8(0x3C6); // unmask the RAMDAC + in8(0x3C6); // command reg, otherwise + in8(0x3C6); // we would write the pixelmask reg! + out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors + (bpp == 15) ? 0x10 : // + (bpp == 16) ? 0x30 : // hicolor + (bpp == 24) ? 0xD0 : // truecolor + (bpp == 32) ? 0xD0 : 0); // truecolor in8(0x3C8); // // GR31 is not mentioned in the datasheet // if (displaytype == DISPLAY_FP) - write3CE(GR31,(read3CE(GR31) & 0x8F) | + write3CE(GR31, (read3CE(GR31) & 0x8F) | ((info->var.yres > 1024) ? 0x50 : - (info->var.yres > 768) ? 0x30 : - (info->var.yres > 600) ? 0x20 : - (info->var.yres > 480) ? 0x10 : 0)); + (info->var.yres > 768) ? 0x30 : + (info->var.yres > 600) ? 0x20 : + (info->var.yres > 480) ? 0x10 : 0)); info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - info->fix.line_length = info->var.xres * (bpp >> 3); - info->cmap.len = (bpp == 8) ? 256: 16; + info->fix.line_length = info->var.xres_virtual * (bpp >> 3); + info->cmap.len = (bpp == 8) ? 256 : 16; // // init acceleration engine // - cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel); + cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel); + + // + // Set/clear flags to allow proper scroll mode selection. + // + if (var->xres == var->xres_virtual) + info->flags &= ~FBINFO_HWACCEL_XPAN; + else + info->flags |= FBINFO_HWACCEL_XPAN; + + if (var->yres == var->yres_virtual) + info->flags &= ~FBINFO_HWACCEL_YPAN; + else + info->flags |= FBINFO_HWACCEL_YPAN; + + if (info->fix.smem_len != + var->xres_virtual * var->yres_virtual * bpp / 8) + info->flags &= ~FBINFO_HWACCEL_YWRAP; + else + info->flags |= FBINFO_HWACCEL_YWRAP; regdump(par); @@ -885,27 +1057,27 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green, { int bpp = info->var.bits_per_pixel; + KD_GRAPHICS_RETURN(0); + if (regno >= info->cmap.len) return 1; if (bpp == 8) { - out8(0x3C6,0xFF); - out8(0x3C8,regno); - out8(0x3C9,red>>10); - out8(0x3C9,green>>10); - out8(0x3C9,blue>>10); - - } else if (bpp == 16) // RGB 565 - ((u32*)info->pseudo_palette)[regno] = - (red & 0xF800) | - ((green & 0xFC00) >> 5) | - ((blue & 0xF800) >> 11); - else if (bpp == 32) // ARGB 8888 - ((u32*)info->pseudo_palette)[regno] = - ((transp & 0xFF00) <<16) | - ((red & 0xFF00) << 8) | - ((green & 0xFF00)) | - ((blue & 0xFF00)>>8); + out8(0x3C6, 0xFF); + out8(0x3C8, regno); + out8(0x3C9, red >> 10); + out8(0x3C9, green >> 10); + out8(0x3C9, blue >> 10); + + } else if (bpp == 16) // RGB 565 + ((u32 *) info->pseudo_palette)[regno] = + (red & 0xF800) | + ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); + else if (bpp == 32) // ARGB 8888 + ((u32 *) info->pseudo_palette)[regno] = + ((transp & 0xFF00) << 16) | + ((red & 0xFF00) << 8) | + ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); return 0; } @@ -918,40 +1090,41 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green, static int cyblafb_blank(int blank_mode, struct fb_info *info) { - unsigned char PMCont,DPMSCont; + unsigned char PMCont, DPMSCont; + + KD_GRAPHICS_RETURN(0); if (displaytype == DISPLAY_FP) return 0; - out8(0x83C8,0x04); // DPMS Control + out8(0x83C8, 0x04); // DPMS Control PMCont = in8(0x83C6) & 0xFC; DPMSCont = read3CE(GR23) & 0xFC; - switch (blank_mode) - { - case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On - case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On + switch (blank_mode) { + case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On + case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On PMCont |= 0x03; DPMSCont |= 0x00; break; - case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On + case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On PMCont |= 0x02; DPMSCont |= 0x01; break; - case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off + case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off PMCont |= 0x02; DPMSCont |= 0x02; break; - case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off + case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off PMCont |= 0x00; DPMSCont |= 0x03; break; } - write3CE(GR23,DPMSCont); - out8(0x83C8,4); - out8(0x83C6,PMCont); + write3CE(GR23, DPMSCont); + out8(0x83C8, 4); + out8(0x83C6, PMCont); // // let fbcon do a softblank for us // @@ -959,15 +1132,18 @@ static int cyblafb_blank(int blank_mode, struct fb_info *info) } static struct fb_ops cyblafb_ops __devinitdata = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .fb_setcolreg = cyblafb_setcolreg, .fb_pan_display = cyblafb_pan_display, .fb_blank = cyblafb_blank, .fb_check_var = cyblafb_check_var, .fb_set_par = cyblafb_set_par, .fb_fillrect = cyblafb_fillrect, - .fb_copyarea= cyblafb_copyarea, + .fb_copyarea = cyblafb_copyarea, .fb_imageblit = cyblafb_imageblit, + .fb_sync = cyblafb_sync, + .fb_restore_state = cyblafb_restore_state, + .fb_save_state = cyblafb_save_state, }; //========================================================================== @@ -986,74 +1162,89 @@ static struct fb_ops cyblafb_ops __devinitdata = { static int __devinit getstartupmode(struct fb_info *info) { - u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend, - vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend, - cr00,cr01,cr02,cr03,cr04,cr05,cr2b, - cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27, - cr38, - sr0d,sr18,sr19, - gr0f, - fi,pxclkdiv,vclkdiv,tmp,i; + u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend, + vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend, + cr00, cr01, cr02, cr03, cr04, cr05, cr2b, + cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27, + cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i; struct modus { - int xres; int yres; int vyres; int bpp; int pxclk; - int left_margin; int right_margin; int upper_margin; - int lower_margin; int hsync_len; int vsync_len; - } modedb[5] = { - { 0, 0, 8000, 0, 0, 0, 0, 0, 0, 0, 0}, - { 640, 480, 3756, 0, 0, -40, 24, 17, 0, 216, 3}, - { 800, 600, 3221, 0, 0, 96, 24, 14, 0, 136, 11}, - {1024, 768, 2815, 0, 0, 144, 24, 29, 0, 120, 3}, - {1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160, 3} + int xres; int vxres; int yres; int vyres; + int bpp; int pxclk; + int left_margin; int right_margin; + int upper_margin; int lower_margin; + int hsync_len; int vsync_len; + } modedb[5] = { + { + 0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, { + 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, { + 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, { + 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, { + 1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3} }; - outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5); - outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5); - outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5); - outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5); - outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5); - outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5); - outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5); - outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5); - outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5); - outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5); - outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf); - - htotal = cr00 | (cr2b & 0x01) << 8; - hdispend = cr01 | (cr2b & 0x02) << 7; + outb(0x00, 0x3d4); cr00 = inb(0x3d5); + outb(0x01, 0x3d4); cr01 = inb(0x3d5); + outb(0x02, 0x3d4); cr02 = inb(0x3d5); + outb(0x03, 0x3d4); cr03 = inb(0x3d5); + outb(0x04, 0x3d4); cr04 = inb(0x3d5); + outb(0x05, 0x3d4); cr05 = inb(0x3d5); + outb(0x06, 0x3d4); cr06 = inb(0x3d5); + outb(0x07, 0x3d4); cr07 = inb(0x3d5); + outb(0x09, 0x3d4); cr09 = inb(0x3d5); + outb(0x10, 0x3d4); cr10 = inb(0x3d5); + outb(0x11, 0x3d4); cr11 = inb(0x3d5); + outb(0x12, 0x3d4); cr12 = inb(0x3d5); + outb(0x15, 0x3d4); cr15 = inb(0x3d5); + outb(0x16, 0x3d4); cr16 = inb(0x3d5); + outb(0x27, 0x3d4); cr27 = inb(0x3d5); + outb(0x2b, 0x3d4); cr2b = inb(0x3d5); + outb(0x38, 0x3d4); cr38 = inb(0x3d5); + + outb(0x0b, 0x3c4); + inb(0x3c5); + + outb(0x0d, 0x3c4); sr0d = inb(0x3c5); + outb(0x18, 0x3c4); sr18 = inb(0x3c5); + outb(0x19, 0x3c4); sr19 = inb(0x3c5); + outb(0x0f, 0x3ce); gr0f = inb(0x3cf); + + htotal = cr00 | (cr2b & 0x01) << 8; + hdispend = cr01 | (cr2b & 0x02) << 7; hblankstart = cr02 | (cr2b & 0x10) << 4; - hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2; - hsyncstart = cr04 | (cr2b & 0x08) << 5; - hsyncend = cr05 & 0x1f; + hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2; + hsyncstart = cr04 | (cr2b & 0x08) << 5; + hsyncend = cr05 & 0x1f; modedb[0].xres = hblankstart * 8; modedb[0].hsync_len = hsyncend * 8; modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres; modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres - - modedb[0].right_margin - modedb[0].hsync_len; - - vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4 - | (cr27 & 0x80) << 3; - vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3 - | (cr27 & 0x10) << 6; - vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2 - | (cr27 & 0x20) << 5; - vsyncend = cr11 & 0x0f; + modedb[0].right_margin - modedb[0].hsync_len; + + vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4 + | (cr27 & 0x80) << 3; + vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3 + | (cr27 & 0x10) << 6; + vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2 + | (cr27 & 0x20) << 5; + vsyncend = cr11 & 0x0f; vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4 - | (cr27 & 0x40) << 4; - vblankend = cr16; + | (cr27 & 0x40) << 4; + vblankend = cr16; - modedb[0].yres = vdispend + 1; - modedb[0].vsync_len = vsyncend; + modedb[0].yres = vdispend + 1; + modedb[0].vsync_len = vsyncend; modedb[0].lower_margin = vsyncstart - modedb[0].yres; modedb[0].upper_margin = vtotal - modedb[0].yres - - modedb[0].lower_margin - modedb[0].vsync_len + 2; + modedb[0].lower_margin - modedb[0].vsync_len + 2; tmp = cr38 & 0x3c; modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 : - tmp == 8 ? 32 : 8; + tmp == 8 ? 32 : 8; - fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12; + fi = ((5864727 * (sr18 + 8)) / + (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12; pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1; tmp = sr0d & 0x06; vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 ! @@ -1062,10 +1253,10 @@ static int __devinit getstartupmode(struct fb_info *info) if (verbosity > 0) output("detected startup mode: " "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n", - modedb[0].xres,modedb[0].yres,modedb[0].xres, - modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin, - modedb[0].right_margin,modedb[0].upper_margin, - modedb[0].lower_margin,modedb[0].hsync_len, + modedb[0].xres, modedb[0].yres, modedb[0].xres, + modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin, + modedb[0].right_margin, modedb[0].upper_margin, + modedb[0].lower_margin, modedb[0].hsync_len, modedb[0].vsync_len); // @@ -1073,36 +1264,39 @@ static int __devinit getstartupmode(struct fb_info *info) // do not want to do it in another way! // - tryagain: + tryagain: i = (mode == NULL) ? 0 : - !strncmp(mode,"640x480",7) ? 1 : - !strncmp(mode,"800x600",7) ? 2 : - !strncmp(mode,"1024x768",8) ? 3 : - !strncmp(mode,"1280x1024",9) ? 4 : 0; + !strncmp(mode, "640x480", 7) ? 1 : + !strncmp(mode, "800x600", 7) ? 2 : + !strncmp(mode, "1024x768", 8) ? 3 : + !strncmp(mode, "1280x1024", 9) ? 4 : 0; ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref; - if(i==0) { + if (i == 0) { info->var.pixclock = modedb[i].pxclk; info->var.bits_per_pixel = modedb[i].bpp; } else { info->var.pixclock = (100000000 / - ((modedb[i].left_margin + modedb[i].xres + - modedb[i].right_margin + modedb[i].hsync_len - ) * ( - modedb[i].upper_margin + modedb[i].yres + - modedb[i].lower_margin + modedb[i].vsync_len - ) * - ref / 10000 - )); + ((modedb[i].left_margin + + modedb[i].xres + + modedb[i].right_margin + + modedb[i].hsync_len) * + (modedb[i].upper_margin + + modedb[i].yres + + modedb[i].lower_margin + + modedb[i].vsync_len) * ref / 10000)); info->var.bits_per_pixel = bpp; } info->var.left_margin = modedb[i].left_margin; info->var.right_margin = modedb[i].right_margin; info->var.xres = modedb[i].xres; - info->var.xres_virtual = modedb[i].xres; + if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32)) + info->var.xres_virtual = modedb[i].vxres; + else + info->var.xres_virtual = modedb[i].xres; info->var.xoffset = 0; info->var.hsync_len = modedb[i].hsync_len; info->var.upper_margin = modedb[i].upper_margin; @@ -1114,33 +1308,32 @@ static int __devinit getstartupmode(struct fb_info *info) info->var.sync = 0; info->var.vmode = FB_VMODE_NONINTERLACED; - if(cyblafb_check_var(&info->var,info)) { - // 640x480-8@75 should really never fail. One case would + if (cyblafb_check_var(&info->var, info)) { + // 640x480 - 8@75 should really never fail. One case would // be fp == 1 and nativex < 640 ... give up then - if(i==1 && bpp == 8 && ref == 75){ + if (i == 1 && bpp == 8 && ref == 75) { output("Can't find a valid mode :-(\n"); return -EINVAL; } // Our detected mode is unlikely to fail. If it does, - // try 640x480-8@75 ... - if(i==0) { - mode="640x480"; - bpp=8; - ref=75; + // try 640x480 - 8@75 ... + if (i == 0) { + mode = "640x480"; + bpp = 8; + ref = 75; output("Detected mode failed check_var! " - "Trying 640x480-8@75\n"); + "Trying 640x480 - 8@75\n"); goto tryagain; } // A specified video mode failed for some reason. // Try the startup mode first output("Specified mode '%s' failed check! " - "Falling back to startup mode.\n",mode); - mode=NULL; + "Falling back to startup mode.\n", mode); + mode = NULL; goto tryagain; } return 0; - } //======================================================== @@ -1160,21 +1353,28 @@ static unsigned int __devinit get_memsize(void) else { tmp = read3X4(CR1F) & 0x0F; switch (tmp) { - case 0x03: k = 1 * Mb; break; - case 0x07: k = 2 * Mb; break; - case 0x0F: k = 4 * Mb; break; - case 0x04: k = 8 * Mb; break; - default: - k = 1 * Mb; - output("Unknown memory size code %x in CR1F." - " We default to 1 Mb for now, please" - " do provide a memsize parameter!\n", - tmp); + case 0x03: + k = 1 * 1024 * 1024; + break; + case 0x07: + k = 2 * 1024 * 1024; + break; + case 0x0F: + k = 4 * 1024 * 1024; + break; + case 0x04: + k = 8 * 1024 * 1024; + break; + default: + k = 1 * 1024 * 1024; + output("Unknown memory size code %x in CR1F." + " We default to 1 Mb for now, please" + " do provide a memsize parameter!\n", tmp); } } if (verbosity > 0) - output("framebuffer size = %d Kb\n",k/Kb); + output("framebuffer size = %d Kb\n", k / Kb); return k; } @@ -1192,7 +1392,7 @@ static unsigned int __devinit get_displaytype(void) return DISPLAY_FP; if (crt) return DISPLAY_CRT; - return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT; + return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT; } //===================================== @@ -1203,7 +1403,7 @@ static unsigned int __devinit get_displaytype(void) static int __devinit get_nativex(void) { - int x,y,tmp; + int x, y, tmp; if (nativex) return nativex; @@ -1211,29 +1411,45 @@ static int __devinit get_nativex(void) tmp = (read3CE(GR52) >> 4) & 3; switch (tmp) { - case 0: x = 1280; y = 1024; break; - case 2: x = 1024; y = 768; break; - case 3: x = 800; y = 600; break; - case 4: x = 1400; y = 1050; break; - case 1: - default: x = 640; y = 480; break; + case 0: x = 1280; y = 1024; + break; + case 2: x = 1024; y = 768; + break; + case 3: x = 800; y = 600; + break; + case 4: x = 1400; y = 1050; + break; + case 1: + default: + x = 640; y = 480; + break; } if (verbosity > 0) - output("%dx%d flat panel found\n",x,y); + output("%dx%d flat panel found\n", x, y); return x; } -static int __devinit cybla_pci_probe(struct pci_dev * dev, - const struct pci_device_id * id) +static int __devinit cybla_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) { struct fb_info *info; struct cyblafb_par *par; - info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev); - + info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev); if (!info) - goto errout_alloc; + goto errout_alloc_info; + + info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL); + if (!info->pixmap.addr) { + output("allocation of pixmap buffer failed!\n"); + goto errout_alloc_pixmap; + } + info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4; + info->pixmap.buf_align = 4; + info->pixmap.access_align = 32; + info->pixmap.flags = FB_PIXMAP_SYSTEM; + info->pixmap.scan_align = 4; par = info->par; par->ops = cyblafb_ops; @@ -1246,26 +1462,31 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev, output("could not enable device!\n"); goto errout_enable; } - // might already be requested by vga console or vesafb, // so we do care about success - request_region(0x3c0,32,"cyblafb"); + if (!request_region(0x3c0, 0x20, "cyblafb")) { + output("region 0x3c0/0x20 already reserved\n"); + vesafb |= 1; + } // // Graphics Engine Registers // - request_region(GEBase,0x100,"cyblafb"); + if (!request_region(GEBase, 0x100, "cyblafb")) { + output("region %#x/0x100 already reserved\n", GEBase); + vesafb |= 2; + } regdump(par); enable_mmio(); // setup MMIO region - info->fix.mmio_start = pci_resource_start(dev,1); + info->fix.mmio_start = pci_resource_start(dev, 1); info->fix.mmio_len = 0x20000; if (!request_mem_region(info->fix.mmio_start, - info->fix.mmio_len,"cyblafb")) { + info->fix.mmio_len, "cyblafb")) { output("request_mem_region failed for mmio region!\n"); goto errout_mmio_reqmem; } @@ -1276,18 +1497,17 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev, output("ioremap failed for mmio region\n"); goto errout_mmio_remap; } - // setup framebuffer memory ... might already be requested // by vesafb. Not to fail in case of an unsuccessful request - // is useful for the development cycle - info->fix.smem_start = pci_resource_start(dev,0); + // is useful if both are loaded. + info->fix.smem_start = pci_resource_start(dev, 0); info->fix.smem_len = get_memsize(); if (!request_mem_region(info->fix.smem_start, - info->fix.smem_len,"cyblafb")) { - output("request_mem_region failed for smem region!\n"); - if (!vesafb) - goto errout_smem_req; + info->fix.smem_len, "cyblafb")) { + output("region %#lx/%#x already reserved\n", + info->fix.smem_start, info->fix.smem_len); + vesafb |= 4; } info->screen_base = ioremap_nocache(info->fix.smem_start, @@ -1300,31 +1520,30 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev, displaytype = get_displaytype(); - if(displaytype == DISPLAY_FP) + if (displaytype == DISPLAY_FP) nativex = get_nativex(); - // - // FBINFO_HWACCEL_YWRAP .... does not work (could be made to work?) - // FBINFO_PARTIAL_PAN_OK .... is not ok - // FBINFO_READS_FAST .... is necessary for optimal scrolling - // - info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN - | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT - | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST; + info->flags = FBINFO_DEFAULT + | FBINFO_HWACCEL_COPYAREA + | FBINFO_HWACCEL_FILLRECT + | FBINFO_HWACCEL_IMAGEBLIT + | FBINFO_READS_FAST +// | FBINFO_PARTIAL_PAN_OK + | FBINFO_MISC_ALWAYS_SETPAR; info->pseudo_palette = par->pseudo_pal; - if(getstartupmode(info)) + if (getstartupmode(info)) goto errout_findmode; - fb_alloc_cmap(&info->cmap,256,0); + fb_alloc_cmap(&info->cmap, 256, 0); if (register_framebuffer(info)) { output("Could not register CyBla framebuffer\n"); goto errout_register; } - pci_set_drvdata(dev,info); + pci_set_drvdata(dev, info); // // normal exit and error paths @@ -1332,23 +1551,24 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev, return 0; - errout_register: - errout_findmode: + errout_register: + errout_findmode: iounmap(info->screen_base); - errout_smem_remap: - release_mem_region(info->fix.smem_start, - info->fix.smem_len); - errout_smem_req: + errout_smem_remap: + if (!(vesafb & 4)) + release_mem_region(info->fix.smem_start, info->fix.smem_len); iounmap(io_virt); - errout_mmio_remap: - release_mem_region(info->fix.mmio_start, - info->fix.mmio_len); - errout_mmio_reqmem: -// release_region(0x3c0,32); - errout_enable: + errout_mmio_remap: + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); + errout_mmio_reqmem: + if (!(vesafb & 1)) + release_region(0x3c0, 32); + errout_enable: + kfree(info->pixmap.addr); + errout_alloc_pixmap: framebuffer_release(info); - errout_alloc: - output("CyblaFB version %s aborting init.\n",VERSION); + errout_alloc_info: + output("CyblaFB version %s aborting init.\n", VERSION); return -ENODEV; } @@ -1359,35 +1579,41 @@ static void __devexit cybla_pci_remove(struct pci_dev *dev) unregister_framebuffer(info); iounmap(io_virt); iounmap(info->screen_base); - release_mem_region(info->fix.smem_start,info->fix.smem_len); - release_mem_region(info->fix.mmio_start,info->fix.mmio_len); + if (!(vesafb & 4)) + release_mem_region(info->fix.smem_start, info->fix.smem_len); + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); fb_dealloc_cmap(&info->cmap); + if (!(vesafb & 2)) + release_region(GEBase, 0x100); + if (!(vesafb & 1)) + release_region(0x3c0, 32); + kfree(info->pixmap.addr); framebuffer_release(info); - output("CyblaFB version %s normal exit.\n",VERSION); + output("CyblaFB version %s normal exit.\n", VERSION); } // // List of boards that we are trying to support // static struct pci_device_id cybla_devices[] = { - {PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, + {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,} }; -MODULE_DEVICE_TABLE(pci,cybla_devices); +MODULE_DEVICE_TABLE(pci, cybla_devices); static struct pci_driver cyblafb_pci_driver = { - .name = "cyblafb", - .id_table = cybla_devices, - .probe = cybla_pci_probe, - .remove = __devexit_p(cybla_pci_remove) + .name = "cyblafb", + .id_table = cybla_devices, + .probe = cybla_pci_probe, + .remove = __devexit_p(cybla_pci_remove) }; //============================================================= // // kernel command line example: // -// video=cyblafb:1280x1024,bpp=16,ref=50 ... +// video=cyblafb:1280x1024, bpp=16, ref=50 ... // // modprobe command line example: // @@ -1401,46 +1627,46 @@ static int __devinit cyblafb_init(void) char *options = NULL; char *opt; - if (fb_get_options("cyblafb",&options)) + if (fb_get_options("cyblafb", &options)) return -ENODEV; if (options && *options) - while((opt = strsep(&options,",")) != NULL ) { - if (!*opt) continue; - else if (!strncmp(opt,"bpp=",4)) - bpp = simple_strtoul(opt+4,NULL,0); - else if (!strncmp(opt,"ref=",4)) - ref = simple_strtoul(opt+4,NULL,0); - else if (!strncmp(opt,"fp",2)) + while ((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + else if (!strncmp(opt, "bpp=", 4)) + bpp = simple_strtoul(opt + 4, NULL, 0); + else if (!strncmp(opt, "ref=", 4)) + ref = simple_strtoul(opt + 4, NULL, 0); + else if (!strncmp(opt, "fp", 2)) displaytype = DISPLAY_FP; - else if (!strncmp(opt,"crt",3)) + else if (!strncmp(opt, "crt", 3)) displaytype = DISPLAY_CRT; - else if (!strncmp(opt,"nativex=",8)) - nativex = simple_strtoul(opt+8,NULL,0); - else if (!strncmp(opt,"center",6)) + else if (!strncmp(opt, "nativex=", 8)) + nativex = simple_strtoul(opt + 8, NULL, 0); + else if (!strncmp(opt, "center", 6)) center = 1; - else if (!strncmp(opt,"stretch",7)) + else if (!strncmp(opt, "stretch", 7)) stretch = 1; - else if (!strncmp(opt,"pciwb=",6)) - pciwb = simple_strtoul(opt+6,NULL,0); - else if (!strncmp(opt,"pcirb=",6)) - pcirb = simple_strtoul(opt+6,NULL,0); - else if (!strncmp(opt,"pciwr=",6)) - pciwr = simple_strtoul(opt+6,NULL,0); - else if (!strncmp(opt,"pcirr=",6)) - pcirr = simple_strtoul(opt+6,NULL,0); - else if (!strncmp(opt,"memsize=",8)) - memsize = simple_strtoul(opt+8,NULL,0); - else if (!strncmp(opt,"verbosity=",10)) - verbosity = simple_strtoul(opt+10,NULL,0); - else if (!strncmp(opt,"vesafb",6)) - vesafb = 1; + else if (!strncmp(opt, "pciwb=", 6)) + pciwb = simple_strtoul(opt + 6, NULL, 0); + else if (!strncmp(opt, "pcirb=", 6)) + pcirb = simple_strtoul(opt + 6, NULL, 0); + else if (!strncmp(opt, "pciwr=", 6)) + pciwr = simple_strtoul(opt + 6, NULL, 0); + else if (!strncmp(opt, "pcirr=", 6)) + pcirr = simple_strtoul(opt + 6, NULL, 0); + else if (!strncmp(opt, "memsize=", 8)) + memsize = simple_strtoul(opt + 8, NULL, 0); + else if (!strncmp(opt, "verbosity=", 10)) + verbosity = simple_strtoul(opt + 10, NULL, 0); else mode = opt; } #endif - output("CyblaFB version %s initializing\n",VERSION); + output("CyblaFB version %s initializing\n", VERSION); return pci_module_init(&cyblafb_pci_driver); + return pci_register_driver(&cyblafb_pci_driver); } static void __exit cyblafb_exit(void) diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c index 0b6af00d197..ac90883dc3a 100644 --- a/drivers/video/fbcvt.c +++ b/drivers/video/fbcvt.c @@ -214,12 +214,11 @@ static void fb_cvt_print_name(struct fb_cvt_data *cvt) { u32 pixcount, pixcount_mod; int cnt = 255, offset = 0, read = 0; - u8 *buf = kmalloc(256, GFP_KERNEL); + u8 *buf = kzalloc(256, GFP_KERNEL); if (!buf) return; - memset(buf, 0, 256); pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000; pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000; pixcount_mod /= 1000; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 10dfdf03526..32a9b69becc 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -589,17 +589,19 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) return info->fbops->fb_read(file, buf, count, ppos); total_size = info->screen_size; + if (total_size == 0) total_size = info->fix.smem_len; if (p >= total_size) - return 0; + return 0; + if (count >= total_size) - count = total_size; + count = total_size; + if (count + p > total_size) count = total_size - p; - cnt = 0; buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); if (!buffer) @@ -636,6 +638,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) } kfree(buffer); + return (err) ? err : cnt; } @@ -648,7 +651,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *src; u32 __iomem *dst; - int c, i, cnt = 0, err; + int c, i, cnt = 0, err = 0; unsigned long total_size; if (!info || !info->screen_base) @@ -661,19 +664,19 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) return info->fbops->fb_write(file, buf, count, ppos); total_size = info->screen_size; + if (total_size == 0) total_size = info->fix.smem_len; if (p > total_size) - return -ENOSPC; + return 0; + if (count >= total_size) - count = total_size; - err = 0; - if (count + p > total_size) { - count = total_size - p; - err = -ENOSPC; - } - cnt = 0; + count = total_size; + + if (count + p > total_size) + count = total_size - p; + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); if (!buffer) @@ -687,12 +690,15 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) while (count) { c = (count > PAGE_SIZE) ? PAGE_SIZE : count; src = buffer; + if (copy_from_user(src, buf, c)) { err = -EFAULT; break; } + for (i = c >> 2; i--; ) fb_writel(*src++, dst++); + if (c & 3) { u8 *src8 = (u8 *) src; u8 __iomem *dst8 = (u8 __iomem *) dst; @@ -702,11 +708,13 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) dst = (u32 __iomem *) dst8; } + *ppos += c; buf += c; cnt += c; count -= c; } + kfree(buffer); return (err) ? err : cnt; @@ -1226,6 +1234,7 @@ fb_open(struct inode *inode, struct file *file) return -ENODEV; if (!try_module_get(info->fbops->owner)) return -ENODEV; + file->private_data = info; if (info->fbops->fb_open) { res = info->fbops->fb_open(info,1); if (res) @@ -1237,11 +1246,9 @@ fb_open(struct inode *inode, struct file *file) static int fb_release(struct inode *inode, struct file *file) { - int fbidx = iminor(inode); - struct fb_info *info; + struct fb_info * const info = file->private_data; lock_kernel(); - info = registered_fb[fbidx]; if (info->fbops->fb_release) info->fbops->fb_release(info,1); module_put(info->fbops->owner); diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index fc7965b6677..7c74e7325d9 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -317,26 +317,29 @@ static int edid_is_monitor_block(unsigned char *block) static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode) { - struct fb_var_screeninfo var; - struct fb_info info; + struct fb_var_screeninfo *var; - memset(&var, 0, sizeof(struct fb_var_screeninfo)); - var.xres = xres; - var.yres = yres; - fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, - refresh, &var, &info); - mode->xres = xres; - mode->yres = yres; - mode->pixclock = var.pixclock; - mode->refresh = refresh; - mode->left_margin = var.left_margin; - mode->right_margin = var.right_margin; - mode->upper_margin = var.upper_margin; - mode->lower_margin = var.lower_margin; - mode->hsync_len = var.hsync_len; - mode->vsync_len = var.vsync_len; - mode->vmode = 0; - mode->sync = 0; + var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); + + if (var) { + var->xres = xres; + var->yres = yres; + fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, + refresh, var, NULL); + mode->xres = xres; + mode->yres = yres; + mode->pixclock = var->pixclock; + mode->refresh = refresh; + mode->left_margin = var->left_margin; + mode->right_margin = var->right_margin; + mode->upper_margin = var->upper_margin; + mode->lower_margin = var->lower_margin; + mode->hsync_len = var->hsync_len; + mode->vsync_len = var->vsync_len; + mode->vmode = 0; + mode->sync = 0; + kfree(var); + } } static int get_est_timing(unsigned char *block, struct fb_videomode *mode) @@ -525,10 +528,9 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) unsigned char *block; int num = 0, i; - mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); + mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); if (mode == NULL) return NULL; - memset(mode, 0, 50 * sizeof(struct fb_videomode)); if (edid == NULL || !edid_checksum(edid) || !edid_check_header(edid)) { @@ -1105,15 +1107,21 @@ static void fb_timings_dclk(struct __fb_timings *timings) */ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) { - struct __fb_timings timings; + struct __fb_timings *timings; u32 interlace = 1, dscan = 1; - u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; + u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0; + + + timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL); + + if (!timings) + return -ENOMEM; /* * If monspecs are invalid, use values that are enough * for 640x480@60 */ - if (!info->monspecs.hfmax || !info->monspecs.vfmax || + if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax || !info->monspecs.dclkmax || info->monspecs.hfmax < info->monspecs.hfmin || info->monspecs.vfmax < info->monspecs.vfmin || @@ -1130,65 +1138,66 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf dclkmax = info->monspecs.dclkmax; } - memset(&timings, 0, sizeof(struct __fb_timings)); - timings.hactive = var->xres; - timings.vactive = var->yres; + timings->hactive = var->xres; + timings->vactive = var->yres; if (var->vmode & FB_VMODE_INTERLACED) { - timings.vactive /= 2; + timings->vactive /= 2; interlace = 2; } if (var->vmode & FB_VMODE_DOUBLE) { - timings.vactive *= 2; + timings->vactive *= 2; dscan = 2; } switch (flags & ~FB_IGNOREMON) { case FB_MAXTIMINGS: /* maximize refresh rate */ - timings.hfreq = hfmax; - fb_timings_hfreq(&timings); - if (timings.vfreq > vfmax) { - timings.vfreq = vfmax; - fb_timings_vfreq(&timings); + timings->hfreq = hfmax; + fb_timings_hfreq(timings); + if (timings->vfreq > vfmax) { + timings->vfreq = vfmax; + fb_timings_vfreq(timings); } - if (timings.dclk > dclkmax) { - timings.dclk = dclkmax; - fb_timings_dclk(&timings); + if (timings->dclk > dclkmax) { + timings->dclk = dclkmax; + fb_timings_dclk(timings); } break; case FB_VSYNCTIMINGS: /* vrefresh driven */ - timings.vfreq = val; - fb_timings_vfreq(&timings); + timings->vfreq = val; + fb_timings_vfreq(timings); break; case FB_HSYNCTIMINGS: /* hsync driven */ - timings.hfreq = val; - fb_timings_hfreq(&timings); + timings->hfreq = val; + fb_timings_hfreq(timings); break; case FB_DCLKTIMINGS: /* pixelclock driven */ - timings.dclk = PICOS2KHZ(val) * 1000; - fb_timings_dclk(&timings); + timings->dclk = PICOS2KHZ(val) * 1000; + fb_timings_dclk(timings); break; default: - return -EINVAL; + err = -EINVAL; } - if (!(flags & FB_IGNOREMON) && - (timings.vfreq < vfmin || timings.vfreq > vfmax || - timings.hfreq < hfmin || timings.hfreq > hfmax || - timings.dclk < dclkmin || timings.dclk > dclkmax)) - return -EINVAL; - - var->pixclock = KHZ2PICOS(timings.dclk/1000); - var->hsync_len = (timings.htotal * 8)/100; - var->right_margin = (timings.hblank/2) - var->hsync_len; - var->left_margin = timings.hblank - var->right_margin - var->hsync_len; - - var->vsync_len = (3 * interlace)/dscan; - var->lower_margin = (1 * interlace)/dscan; - var->upper_margin = (timings.vblank * interlace)/dscan - - (var->vsync_len + var->lower_margin); + if (err || (!(flags & FB_IGNOREMON) && + (timings->vfreq < vfmin || timings->vfreq > vfmax || + timings->hfreq < hfmin || timings->hfreq > hfmax || + timings->dclk < dclkmin || timings->dclk > dclkmax))) { + err = -EINVAL; + } else { + var->pixclock = KHZ2PICOS(timings->dclk/1000); + var->hsync_len = (timings->htotal * 8)/100; + var->right_margin = (timings->hblank/2) - var->hsync_len; + var->left_margin = timings->hblank - var->right_margin - + var->hsync_len; + var->vsync_len = (3 * interlace)/dscan; + var->lower_margin = (1 * interlace)/dscan; + var->upper_margin = (timings->vblank * interlace)/dscan - + (var->vsync_len + var->lower_margin); + } - return 0; + kfree(timings); + return err; } #else int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 08dac9580d1..6d26057337e 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -43,10 +43,11 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) if (size) fb_info_size += PADDING; - p = kmalloc(fb_info_size + size, GFP_KERNEL); + p = kzalloc(fb_info_size + size, GFP_KERNEL); + if (!p) return NULL; - memset(p, 0, fb_info_size + size); + info = (struct fb_info *) p; if (size) @@ -106,8 +107,7 @@ static int mode_string(char *buf, unsigned int offset, static ssize_t store_mode(struct class_device *class_device, const char * buf, size_t count) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); char mstr[100]; struct fb_var_screeninfo var; struct fb_modelist *modelist; @@ -137,8 +137,7 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf, static ssize_t show_mode(struct class_device *class_device, char *buf) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); if (!fb_info->mode) return 0; @@ -149,8 +148,7 @@ static ssize_t show_mode(struct class_device *class_device, char *buf) static ssize_t store_modes(struct class_device *class_device, const char * buf, size_t count) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); LIST_HEAD(old_list); int i = count / sizeof(struct fb_videomode); @@ -174,8 +172,7 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf, static ssize_t show_modes(struct class_device *class_device, char *buf) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); unsigned int i; struct list_head *pos; struct fb_modelist *modelist; @@ -193,8 +190,7 @@ static ssize_t show_modes(struct class_device *class_device, char *buf) static ssize_t store_bpp(struct class_device *class_device, const char * buf, size_t count) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); struct fb_var_screeninfo var; char ** last = NULL; int err; @@ -208,8 +204,7 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf, static ssize_t show_bpp(struct class_device *class_device, char *buf) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } @@ -280,8 +275,7 @@ static ssize_t show_con_rotate(struct class_device *class_device, char *buf) static ssize_t store_virtual(struct class_device *class_device, const char * buf, size_t count) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); struct fb_var_screeninfo var; char *last = NULL; int err; @@ -300,16 +294,14 @@ static ssize_t store_virtual(struct class_device *class_device, static ssize_t show_virtual(struct class_device *class_device, char *buf) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_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) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length); } @@ -320,7 +312,7 @@ static ssize_t show_stride(struct class_device *class_device, char *buf) static ssize_t store_cmap(struct class_device *class_device, const char *buf, size_t count) { - struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); int rc, i, start, length, transp = 0; if ((count > PAGE_SIZE) || ((count % 16) != 0)) @@ -380,8 +372,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf, static ssize_t show_cmap(struct class_device *class_device, char *buf) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); unsigned int i; if (!fb_info->cmap.red || !fb_info->cmap.blue || @@ -405,8 +396,7 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf) static ssize_t store_blank(struct class_device *class_device, const char * buf, size_t count) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); char *last = NULL; int err; @@ -422,41 +412,40 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf, static ssize_t show_blank(struct class_device *class_device, char *buf) { -// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); +// struct fb_info *fb_info = class_get_devdata(class_device); return 0; } static ssize_t store_console(struct class_device *class_device, const char * buf, size_t count) { -// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); +// struct fb_info *fb_info = class_get_devdata(class_device); return 0; } static ssize_t show_console(struct class_device *class_device, char *buf) { -// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); +// struct fb_info *fb_info = class_get_devdata(class_device); return 0; } static ssize_t store_cursor(struct class_device *class_device, const char * buf, size_t count) { -// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); +// struct fb_info *fb_info = class_get_devdata(class_device); return 0; } static ssize_t show_cursor(struct class_device *class_device, char *buf) { -// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); +// struct fb_info *fb_info = class_get_devdata(class_device); return 0; } static ssize_t store_pan(struct class_device *class_device, const char * buf, size_t count) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_device); struct fb_var_screeninfo var; char *last = NULL; int err; @@ -479,19 +468,40 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf, static ssize_t show_pan(struct class_device *class_device, char *buf) { - struct fb_info *fb_info = - (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_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) { - struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); + struct fb_info *fb_info = class_get_devdata(class_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) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + u32 state; + char *last = NULL; + + state = simple_strtoul(buf, &last, 0); + + acquire_console_sem(); + fb_set_suspend(fb_info, (int)state); + release_console_sem(); + + return count; +} + +static ssize_t show_fbstate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); +} + static struct class_device_attribute class_device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), @@ -507,6 +517,7 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), + __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index b37cea7d109..4e39035cf33 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -42,6 +42,7 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/vga.h> @@ -107,7 +108,7 @@ static DEFINE_SPINLOCK(hga_reg_lock); /* Framebuffer driver structures */ -static struct fb_var_screeninfo hga_default_var = { +static struct fb_var_screeninfo __initdata hga_default_var = { .xres = 720, .yres = 348, .xres_virtual = 720, @@ -121,7 +122,7 @@ static struct fb_var_screeninfo hga_default_var = { .width = -1, }; -static struct fb_fix_screeninfo hga_fix = { +static struct fb_fix_screeninfo __initdata hga_fix = { .id = "HGA", .type = FB_TYPE_PACKED_PIXELS, /* (not sure) */ .visual = FB_VISUAL_MONO10, @@ -131,8 +132,6 @@ static struct fb_fix_screeninfo hga_fix = { .accel = FB_ACCEL_NONE }; -static struct fb_info fb_info; - /* Don't assume that tty1 will be the initial current console. */ static int release_io_port = 0; static int release_io_ports = 0; @@ -549,10 +548,9 @@ static struct fb_ops hgafb_ops = { * Initialization */ -static int __init hgafb_init(void) +static int __init hgafb_probe(struct device *device) { - if (fb_get_options("hgafb", NULL)) - return -ENODEV; + struct fb_info *info; if (! hga_card_detect()) { printk(KERN_INFO "hgafb: HGA card not detected.\n"); @@ -564,41 +562,95 @@ static int __init hgafb_init(void) printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n", hga_type_name, hga_vram_len/1024); + info = framebuffer_alloc(0, NULL); + if (!info) { + iounmap(hga_vram); + return -ENOMEM; + } + hga_fix.smem_start = (unsigned long)hga_vram; hga_fix.smem_len = hga_vram_len; - fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; - fb_info.var = hga_default_var; - fb_info.fix = hga_fix; - fb_info.monspecs.hfmin = 0; - fb_info.monspecs.hfmax = 0; - fb_info.monspecs.vfmin = 10000; - fb_info.monspecs.vfmax = 10000; - fb_info.monspecs.dpms = 0; - fb_info.fbops = &hgafb_ops; - fb_info.screen_base = hga_vram; - - if (register_framebuffer(&fb_info) < 0) { + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + info->var = hga_default_var; + info->fix = hga_fix; + info->monspecs.hfmin = 0; + info->monspecs.hfmax = 0; + info->monspecs.vfmin = 10000; + info->monspecs.vfmax = 10000; + info->monspecs.dpms = 0; + info->fbops = &hgafb_ops; + info->screen_base = hga_vram; + + if (register_framebuffer(info) < 0) { + framebuffer_release(info); iounmap(hga_vram); return -EINVAL; } printk(KERN_INFO "fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + info->node, info->fix.id); + dev_set_drvdata(device, info); return 0; } -#ifdef MODULE -static void __exit hgafb_exit(void) +static int hgafb_remove(struct device *device) { + struct fb_info *info = dev_get_drvdata(device); + hga_txt_mode(); hga_clear_screen(); - unregister_framebuffer(&fb_info); + + if (info) { + unregister_framebuffer(info); + framebuffer_release(info); + } + iounmap(hga_vram); - if (release_io_ports) release_region(0x3b0, 12); - if (release_io_port) release_region(0x3bf, 1); + + if (release_io_ports) + release_region(0x3b0, 12); + + if (release_io_port) + release_region(0x3bf, 1); + + return 0; +} + +static struct device_driver hgafb_driver = { + .name = "hgafb", + .bus = &platform_bus_type, + .probe = hgafb_probe, + .remove = hgafb_remove, +}; + +static struct platform_device hgafb_device = { + .name = "hgafb", +}; + +static int __init hgafb_init(void) +{ + int ret; + + if (fb_get_options("hgafb", NULL)) + return -ENODEV; + + ret = driver_register(&hgafb_driver); + + if (!ret) { + ret = platform_device_register(&hgafb_device); + if (ret) + driver_unregister(&hgafb_driver); + } + + return ret; +} + +static void __exit hgafb_exit(void) +{ + platform_device_unregister(&hgafb_device); + driver_unregister(&hgafb_driver); } -#endif /* ------------------------------------------------------------------------- * @@ -613,7 +665,4 @@ MODULE_LICENSE("GPL"); module_param(nologo, bool, 0); MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)"); module_init(hgafb_init); - -#ifdef MODULE module_exit(hgafb_exit); -#endif diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index c61bad0da20..bd410e06db7 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -17,6 +17,7 @@ #include <linux/fb.h> #include "i810.h" #include "i810_regs.h" +#include "i810_main.h" #include "../edid.h" #define I810_DDC 0x50 @@ -42,7 +43,7 @@ static void i810i2c_setscl(void *data, int state) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; u8 __iomem *mmio = par->mmio_start_virtual; diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c index 64cd1c827cf..76764ea3486 100644 --- a/drivers/video/i810/i810_accel.c +++ b/drivers/video/i810/i810_accel.c @@ -14,6 +14,7 @@ #include "i810_regs.h" #include "i810.h" +#include "i810_main.h" static u32 i810fb_rop[] = { COLOR_COPY_ROP, /* ROP_COPY */ @@ -57,7 +58,7 @@ static inline void i810_report_error(u8 __iomem *mmio) */ static inline int wait_for_space(struct fb_info *info, u32 space) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 head, count = WAIT_COUNT, tail; u8 __iomem *mmio = par->mmio_start_virtual; @@ -88,7 +89,7 @@ static inline int wait_for_space(struct fb_info *info, u32 space) */ static inline int wait_for_engine_idle(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; int count = WAIT_COUNT; @@ -116,7 +117,7 @@ static inline int wait_for_engine_idle(struct fb_info *info) */ static inline u32 begin_iring(struct fb_info *info, u32 space) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; if (par->dev_flags & ALWAYS_SYNC) wait_for_engine_idle(info); @@ -161,7 +162,7 @@ static inline void source_copy_blit(int dwidth, int dheight, int dpitch, int xdir, int src, int dest, int rop, int blit_bpp, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; if (begin_iring(info, 24 + IRING_PAD)) return; @@ -195,7 +196,7 @@ static inline void color_blit(int width, int height, int pitch, int dest, int rop, int what, int blit_bpp, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; if (begin_iring(info, 24 + IRING_PAD)) return; @@ -236,7 +237,7 @@ static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch, int dest, const u32 *src, int bg, int fg, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return; @@ -254,7 +255,7 @@ static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch, static inline void load_front(int offset, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; if (begin_iring(info, 8 + IRING_PAD)) return; @@ -296,7 +297,7 @@ static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode) void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 dx, dy, width, height, dest, rop = 0, color = 0; if (!info->var.accel_flags || par->dev_flags & LOCKUP || @@ -322,7 +323,7 @@ void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir; if (!info->var.accel_flags || par->dev_flags & LOCKUP || @@ -361,7 +362,7 @@ void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) void i810fb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 fg = 0, bg = 0, size, dst; if (!info->var.accel_flags || par->dev_flags & LOCKUP || @@ -397,7 +398,7 @@ void i810fb_imageblit(struct fb_info *info, const struct fb_image *image) int i810fb_sync(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; if (!info->var.accel_flags || par->dev_flags & LOCKUP) return 0; @@ -407,7 +408,7 @@ int i810fb_sync(struct fb_info *info) void i810fb_load_front(u32 offset, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; if (!info->var.accel_flags || par->dev_flags & LOCKUP) @@ -427,7 +428,7 @@ void i810fb_load_front(u32 offset, struct fb_info *info) */ void i810fb_init_ringbuffer(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 tmp1, tmp2; u8 __iomem *mmio = par->mmio_start_virtual; diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c index 64f087a4466..9743d51e7f8 100644 --- a/drivers/video/i810/i810_gtf.c +++ b/drivers/video/i810/i810_gtf.c @@ -14,6 +14,7 @@ #include "i810_regs.h" #include "i810.h" +#include "i810_main.h" /* * FIFO and Watermark tables - based almost wholly on i810_wmark.c in diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index c0c974b1afa..266d0ab9266 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -42,20 +42,62 @@ #include <linux/pci_ids.h> #include <linux/resource.h> #include <linux/unistd.h> +#include <linux/console.h> #include <asm/io.h> #include <asm/div64.h> - -#ifdef CONFIG_MTRR -#include <asm/mtrr.h> -#endif - #include <asm/page.h> #include "i810_regs.h" #include "i810.h" #include "i810_main.h" +/* + * voffset - framebuffer offset in MiB from aperture start address. In order for + * the driver to work with X, we must try to use memory holes left untouched by X. The + * following table lists where X's different surfaces start at. + * + * --------------------------------------------- + * : : 64 MiB : 32 MiB : + * ---------------------------------------------- + * : FrontBuffer : 0 : 0 : + * : DepthBuffer : 48 : 16 : + * : BackBuffer : 56 : 24 : + * ---------------------------------------------- + * + * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to + * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should + * work, allowing 7 + 1 MiB of Framebuffer memory. + * Note, the size of the hole may change depending on how much memory you allocate to X, + * and how the memory is split up between these surfaces. + * + * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with + * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load. + * + * Experiment with v_offset to find out which works best for you. + */ +static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */ +static u32 voffset __initdata = 0; + +static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); +static int __devinit i810fb_init_pci (struct pci_dev *dev, + const struct pci_device_id *entry); +static void __exit i810fb_remove_pci(struct pci_dev *dev); +static int i810fb_resume(struct pci_dev *dev); +static int i810fb_suspend(struct pci_dev *dev, pm_message_t state); + +/* Chipset Specific Functions */ +static int i810fb_set_par (struct fb_info *info); +static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue, + u8 *transp, struct fb_info *info); +static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info); +static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); +static int i810fb_blank (int blank_mode, struct fb_info *info); + +/* Initialization */ +static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); + /* PCI */ static const char *i810_pci_list[] __devinitdata = { "Intel(R) 810 Framebuffer Device" , @@ -776,7 +818,7 @@ static void i810_load_cursor_image(int width, int height, u8 *data, static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; u8 red, green, blue, trans, temp; @@ -949,7 +991,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var) static int i810_check_params(struct fb_var_screeninfo *var, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; int line_length, vidmem, mode_valid = 0, retval = 0; u32 vyres = var->yres_virtual, vxres = var->xres_virtual; /* @@ -1043,7 +1085,7 @@ static int i810_check_params(struct fb_var_screeninfo *var, */ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); @@ -1154,7 +1196,7 @@ static void decode_var(const struct fb_var_screeninfo *var, static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, u8 *transp, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; u8 temp; @@ -1193,7 +1235,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, static int i810fb_open(struct fb_info *info, int user) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 count = atomic_read(&par->use_count); if (count == 0) { @@ -1212,7 +1254,7 @@ static int i810fb_open(struct fb_info *info, int user) static int i810fb_release(struct fb_info *info, int user) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 count; count = atomic_read(&par->use_count); @@ -1234,7 +1276,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; u8 temp; int i; @@ -1328,7 +1370,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 total; total = var->xoffset * par->depth + @@ -1340,7 +1382,7 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var, static int i810fb_blank (int blank_mode, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; int mode = 0, pwr, scr_off = 0; @@ -1385,7 +1427,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info) static int i810fb_set_par(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; decode_var(&info->var, par); i810_load_regs(par); @@ -1429,7 +1471,7 @@ static int i810fb_check_var(struct fb_var_screeninfo *var, static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct i810fb_par *par = (struct i810fb_par *)info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; if (!par->dev_flags & LOCKUP) @@ -1516,36 +1558,29 @@ static struct fb_ops i810fb_ops __devinitdata = { static int i810fb_suspend(struct pci_dev *dev, pm_message_t state) { struct fb_info *info = pci_get_drvdata(dev); - struct i810fb_par *par = (struct i810fb_par *) info->par; - int blank = 0, prev_state = par->cur_state; - - if (state.event == prev_state) - return 0; + struct i810fb_par *par = info->par; par->cur_state = state.event; - switch (state.event) { - case 1: - blank = VESA_VSYNC_SUSPEND; - break; - case 2: - blank = VESA_HSYNC_SUSPEND; - break; - case 3: - blank = VESA_POWERDOWN; - break; - default: - return -EINVAL; + if (state.event == PM_EVENT_FREEZE) { + dev->dev.power.power_state = state; + return 0; } - info->fbops->fb_blank(blank, info); - if (!prev_state) { - agp_unbind_memory(par->i810_gtt.i810_fb_memory); - agp_unbind_memory(par->i810_gtt.i810_cursor_memory); - pci_disable_device(dev); - } + acquire_console_sem(); + fb_set_suspend(info, 1); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + i810fb_blank(FB_BLANK_POWERDOWN, info); + agp_unbind_memory(par->i810_gtt.i810_fb_memory); + agp_unbind_memory(par->i810_gtt.i810_cursor_memory); + pci_save_state(dev); + pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); + release_console_sem(); return 0; } @@ -1553,23 +1588,29 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state) static int i810fb_resume(struct pci_dev *dev) { struct fb_info *info = pci_get_drvdata(dev); - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; + int cur_state = par->cur_state; + + par->cur_state = PM_EVENT_ON; - if (par->cur_state == 0) + if (cur_state == PM_EVENT_FREEZE) { + pci_set_power_state(dev, PCI_D0); return 0; + } - pci_restore_state(dev); + acquire_console_sem(); pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); pci_enable_device(dev); + pci_set_master(dev); agp_bind_memory(par->i810_gtt.i810_fb_memory, par->fb.offset); agp_bind_memory(par->i810_gtt.i810_cursor_memory, par->cursor_heap.offset); - + i810fb_set_par(info); + fb_set_suspend (info, 0); info->fbops->fb_blank(VESA_NO_BLANKING, info); - - par->cur_state = 0; - + release_console_sem(); return 0; } /*********************************************************************** @@ -1610,7 +1651,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par) static int __devinit i810_alloc_agp_mem(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; int size; struct agp_bridge_data *bridge; @@ -2074,7 +2115,7 @@ static void i810fb_release_resource(struct fb_info *info, static void __exit i810fb_remove_pci(struct pci_dev *dev) { struct fb_info *info = pci_get_drvdata(dev); - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; unregister_framebuffer(info); i810fb_release_resource(info, par); diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h index 06072a6466f..51d4f3d4116 100644 --- a/drivers/video/i810/i810_main.h +++ b/drivers/video/i810/i810_main.h @@ -14,55 +14,6 @@ #ifndef __I810_MAIN_H__ #define __I810_MAIN_H__ -static int __devinit i810fb_init_pci (struct pci_dev *dev, - const struct pci_device_id *entry); -static void __exit i810fb_remove_pci(struct pci_dev *dev); -static int i810fb_resume(struct pci_dev *dev); -static int i810fb_suspend(struct pci_dev *dev, pm_message_t state); - -/* - * voffset - framebuffer offset in MiB from aperture start address. In order for - * the driver to work with X, we must try to use memory holes left untouched by X. The - * following table lists where X's different surfaces start at. - * - * --------------------------------------------- - * : : 64 MiB : 32 MiB : - * ---------------------------------------------- - * : FrontBuffer : 0 : 0 : - * : DepthBuffer : 48 : 16 : - * : BackBuffer : 56 : 24 : - * ---------------------------------------------- - * - * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to - * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should - * work, allowing 7 + 1 MiB of Framebuffer memory. - * Note, the size of the hole may change depending on how much memory you allocate to X, - * and how the memory is split up between these surfaces. - * - * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with - * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load. - * - * Experiment with v_offset to find out which works best for you. - */ -static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */ -static u32 voffset __initdata = 0; - -static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); - -/* Chipset Specific Functions */ -static int i810fb_set_par (struct fb_info *info); -static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue, - u8 *transp, struct fb_info *info); -static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, - unsigned transp, struct fb_info *info); -static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); -static int i810fb_blank (int blank_mode, struct fb_info *info); - -/* Initialization */ -static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); -extern int __init agp_intel_init(void); - - /* Video Timings */ extern void round_off_xres (u32 *xres); extern void round_off_yres (u32 *xres, u32 *yres); @@ -101,7 +52,7 @@ static inline void i810_delete_i2c_busses(struct i810fb_par *par) { } /* Conditionals */ #ifdef CONFIG_X86 -inline void flush_cache(void) +static inline void flush_cache(void) { asm volatile ("wbinvd":::"memory"); } @@ -110,7 +61,9 @@ inline void flush_cache(void) #endif #ifdef CONFIG_MTRR -#define KERNEL_HAS_MTRR 1 + +#include <asm/mtrr.h> + static inline void __devinit set_mtrr(struct i810fb_par *par) { par->mtrr_reg = mtrr_add((u32) par->aperture.physical, @@ -128,7 +81,6 @@ static inline void unset_mtrr(struct i810fb_par *par) par->aperture.size); } #else -#define KERNEL_HAS_MTRR 0 #define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n") #define unset_mtrr(x) do { } while (0) diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7fbe24206b1..a5d813050db 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -323,6 +323,7 @@ struct imstt_par { unsigned long cmap_regs_phys; __u8 *cmap_regs; __u32 ramdac; + __u32 palette[16]; }; enum { @@ -657,7 +658,7 @@ set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp) static void set_imstt_regvals (struct fb_info *info, u_int bpp) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; struct imstt_regvals *init = &par->init; __u32 ctl, pitch, byteswap, scr; @@ -749,7 +750,7 @@ set_imstt_regvals (struct fb_info *info, u_int bpp) static inline void set_offset (struct fb_var_screeninfo *var, struct fb_info *info) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; __u32 off = var->yoffset * (info->fix.line_length >> 3) + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3); write_reg_le32(par->dc_regs, SSR, off); @@ -863,7 +864,7 @@ imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int imsttfb_set_par(struct fb_info *info) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; if (!compute_imstt_regvals(par, info->var.xres, info->var.yres)) return -EINVAL; @@ -881,7 +882,7 @@ static int imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; u_int bpp = info->var.bits_per_pixel; if (regno > 255) @@ -905,14 +906,17 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue, if (regno < 16) switch (bpp) { case 16: - ((u16 *)info->pseudo_palette)[regno] = (regno << (info->var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno; + par->palette[regno] = + (regno << (info->var.green.length == + 5 ? 10 : 11)) | (regno << 5) | regno; break; case 24: - ((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno; + par->palette[regno] = + (regno << 16) | (regno << 8) | regno; break; case 32: { int i = (regno << 8) | regno; - ((u32 *)info->pseudo_palette)[regno] = (i << 16) | i; + par->palette[regno] = (i << 16) |i; break; } } @@ -935,7 +939,7 @@ imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) static int imsttfb_blank(int blank, struct fb_info *info) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; __u32 ctrl; ctrl = read_reg_le32(par->dc_regs, STGCTL); @@ -989,7 +993,7 @@ imsttfb_blank(int blank, struct fb_info *info) static void imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; __u32 Bpp, line_pitch, bgc, dx, dy, width, height; bgc = rect->color; @@ -1033,7 +1037,7 @@ imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) static void imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; __u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl; __u32 cnt, bltctl, sx, sy, dx, dy, height, width; @@ -1195,7 +1199,7 @@ imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on) static int imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; u32 flags = cursor->set, fg, bg, xx, yy; if (cursor->dest == NULL && cursor->rop == ROP_XOR) @@ -1266,7 +1270,7 @@ static int imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, struct fb_info *info) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; void __user *argp = (void __user *)arg; __u32 reg[2]; __u8 idx[2]; @@ -1350,7 +1354,7 @@ static struct fb_ops imsttfb_ops = { static void __devinit init_imstt(struct fb_info *info) { - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; __u32 i, tmp, *ip, *end; tmp = read_reg_le32(par->dc_regs, PRC); @@ -1413,7 +1417,7 @@ init_imstt(struct fb_info *info) if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) { printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); - kfree(info); + framebuffer_release(info); return; } @@ -1449,7 +1453,7 @@ init_imstt(struct fb_info *info) fb_alloc_cmap(&info->cmap, 0, 0); if (register_framebuffer(info) < 0) { - kfree(info); + framebuffer_release(info); return; } @@ -1474,26 +1478,21 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) printk(KERN_ERR "imsttfb: no OF node for pci device\n"); #endif /* CONFIG_PPC_OF */ - size = sizeof(struct fb_info) + sizeof(struct imstt_par) + - sizeof(u32) * 16; - - info = kmalloc(size, GFP_KERNEL); + info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev); if (!info) { printk(KERN_ERR "imsttfb: Can't allocate memory\n"); return -ENOMEM; } - memset(info, 0, size); - - par = (struct imstt_par *) (info + 1); + par = info->par; addr = pci_resource_start (pdev, 0); size = pci_resource_len (pdev, 0); if (!request_mem_region(addr, size, "imsttfb")) { printk(KERN_ERR "imsttfb: Can't reserve memory region\n"); - kfree(info); + framebuffer_release(info); return -ENODEV; } @@ -1516,14 +1515,13 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } info->fix.smem_start = addr; - info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000); + info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? + 0x400000 : 0x800000); info->fix.mmio_start = addr + 0x800000; par->dc_regs = ioremap(addr + 0x800000, 0x1000); par->cmap_regs_phys = addr + 0x840000; par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000); - info->par = par; - info->pseudo_palette = (void *) (par + 1); - info->device = &pdev->dev; + info->pseudo_palette = par->palette; init_imstt(info); pci_set_drvdata(pdev, info); @@ -1534,7 +1532,7 @@ static void __devexit imsttfb_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); - struct imstt_par *par = (struct imstt_par *) info->par; + struct imstt_par *par = info->par; int size = pci_resource_len(pdev, 0); unregister_framebuffer(info); @@ -1542,7 +1540,7 @@ imsttfb_remove(struct pci_dev *pdev) iounmap(par->dc_regs); iounmap(info->screen_base); release_mem_region(info->fix.smem_start, size); - kfree(info); + framebuffer_release(info); } #ifndef MODULE diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 5924cc225c9..1718baaeed2 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -554,7 +554,7 @@ static int __init imxfb_probe(struct platform_device *pdev) inf = pdev->dev.platform_data; if(!inf) { - dev_err(dev,"No platform_data available\n"); + dev_err(&pdev->dev,"No platform_data available\n"); return -ENOMEM; } @@ -579,7 +579,7 @@ static int __init imxfb_probe(struct platform_device *pdev) if (!inf->fixed_screen_cpu) { ret = imxfb_map_video_memory(info); if (ret) { - dev_err(dev, "Failed to allocate video RAM: %d\n", ret); + dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret); ret = -ENOMEM; goto failed_map; } @@ -608,7 +608,7 @@ static int __init imxfb_probe(struct platform_device *pdev) imxfb_set_par(info); ret = register_framebuffer(info); if (ret < 0) { - dev_err(dev, "failed to register framebuffer\n"); + dev_err(&pdev->dev, "failed to register framebuffer\n"); goto failed_register; } diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c index 7e33cd307d4..ab5285a7f1d 100644 --- a/drivers/video/kyro/STG4000InitDevice.c +++ b/drivers/video/kyro/STG4000InitDevice.c @@ -15,6 +15,7 @@ #include <linux/pci.h> #include "STG4000Reg.h" +#include "STG4000Interface.h" /* SDRAM fixed settings */ #define SDRAM_CFG_0 0x49A1 diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/kyro/STG4000Interface.h index e75b3b4a4aa..b7c83d5dfb1 100644 --- a/drivers/video/kyro/STG4000Interface.h +++ b/drivers/video/kyro/STG4000Interface.h @@ -11,7 +11,8 @@ #ifndef _STG4000INTERFACE_H #define _STG4000INTERFACE_H -struct pci_dev; +#include <linux/pci.h> +#include <video/kyro.h> /* * Ramdac Setup diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c index 2ae9bafacdd..a8c9713413e 100644 --- a/drivers/video/kyro/STG4000OverlayDevice.c +++ b/drivers/video/kyro/STG4000OverlayDevice.c @@ -14,6 +14,7 @@ #include <linux/types.h> #include "STG4000Reg.h" +#include "STG4000Interface.h" /* HW Defines */ diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index 5eb4d5c177b..bcd359b6d4f 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -73,8 +73,6 @@ static struct fb_var_screeninfo kyro_var __devinitdata = { .vmode = FB_VMODE_NONINTERLACED, }; -static struct kyrofb_info *currentpar; - typedef struct { STG4000REG __iomem *pSTGReg; /* Virtual address of PCI register region */ u32 ulNextFreeVidMem; /* Offset from start of vid mem to next free region */ @@ -309,7 +307,7 @@ enum { /* Accessors */ static int kyro_dev_video_mode_set(struct fb_info *info) { - struct kyrofb_info *par = (struct kyrofb_info *)info->par; + struct kyrofb_info *par = info->par; /* Turn off display */ StopVTG(deviceInfo.pSTGReg); @@ -402,7 +400,7 @@ static inline unsigned long get_line_length(int x, int bpp) static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - struct kyrofb_info *par = (struct kyrofb_info *)info->par; + struct kyrofb_info *par = info->par; if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) { printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel); @@ -478,7 +476,7 @@ static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int kyrofb_set_par(struct fb_info *info) { - struct kyrofb_info *par = (struct kyrofb_info *)info->par; + struct kyrofb_info *par = info->par; unsigned long lineclock; unsigned long frameclock; @@ -536,20 +534,22 @@ static int kyrofb_set_par(struct fb_info *info) static int kyrofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { + struct kyrofb_info *par = info->par; + if (regno > 255) return 1; /* Invalid register */ if (regno < 16) { switch (info->var.bits_per_pixel) { case 16: - ((u16*)(info->pseudo_palette))[regno] = + par->palette[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 32: red >>= 8; green >>= 8; blue >>= 8; transp >>= 8; - ((u32*)(info->pseudo_palette))[regno] = + par->palette[regno] = (transp << 24) | (red << 16) | (green << 8) | blue; break; } @@ -675,6 +675,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct fb_info *info; + struct kyrofb_info *currentpar; unsigned long size; int err; @@ -683,14 +684,11 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev, return err; } - size = sizeof(struct fb_info) + sizeof(struct kyrofb_info) + 16 * sizeof(u32); - info = kmalloc(size, GFP_KERNEL); + info = framebuffer_alloc(sizeof(struct kyrofb_info), &pdev->dev); if (!info) return -ENOMEM; - memset(info, 0, size); - - currentpar = (struct kyrofb_info *)(info + 1); + currentpar = info->par; kyro_fix.smem_start = pci_resource_start(pdev, 0); kyro_fix.smem_len = pci_resource_len(pdev, 0); @@ -716,8 +714,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev, info->fbops = &kyrofb_ops; info->fix = kyro_fix; - info->par = currentpar; - info->pseudo_palette = (void *)(currentpar + 1); + info->pseudo_palette = currentpar->palette; info->flags = FBINFO_DEFAULT; SetCoreClockPLL(deviceInfo.pSTGReg, pdev); @@ -741,7 +738,6 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev, fb_memset(info->screen_base, 0, size); - info->device = &pdev->dev; if (register_framebuffer(info) < 0) goto out_unmap; @@ -757,7 +753,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev, out_unmap: iounmap(currentpar->regbase); iounmap(info->screen_base); - kfree(info); + framebuffer_release(info); return -EINVAL; } @@ -765,7 +761,7 @@ out_unmap: static void __devexit kyrofb_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); - struct kyrofb_info *par = (struct kyrofb_info *)info->par; + struct kyrofb_info *par = info->par; /* Reset the board */ StopVTG(deviceInfo.pSTGReg); @@ -789,7 +785,7 @@ static void __devexit kyrofb_remove(struct pci_dev *pdev) unregister_framebuffer(info); pci_set_drvdata(pdev, NULL); - kfree(info); + framebuffer_release(info); } static int __init kyrofb_init(void) diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile index d0244c04af5..4ef5cd19609 100644 --- a/drivers/video/logo/Makefile +++ b/drivers/video/logo/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o # How to generate logo's -# Use logo-cfiles to retreive list of .c files to be built +# Use logo-cfiles to retrieve list of .c files to be built logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \ $(wildcard $(srctree)/$(src)/*$(1).$(2)))) diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index a8c47ad2cdb..3a3e1804c56 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -50,8 +50,6 @@ #include <asm/mtrr.h> #endif -#include "../console/fbcon.h" - #if defined(CONFIG_PPC_PMAC) #include <asm/prom.h> #include <asm/pci-bridge.h> @@ -351,8 +349,6 @@ struct matrox_bios { } output; }; -extern struct display fb_display[]; - struct matrox_switch; struct matroxfb_driver; struct matroxfb_dh_fb_info; diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 35008af7db7..c122d8743dd 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -20,6 +20,8 @@ #include <asm/uaccess.h> #include <asm/div64.h> +#include "matroxfb_g450.h" + /* Definition of the various controls */ struct mctl { struct v4l2_queryctrl desc; diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index ad60bbb16cd..a1f2c5e8fc8 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -1288,18 +1288,13 @@ static int maven_detach_client(struct i2c_client* client) { return 0; } -static int maven_command(struct i2c_client* client, unsigned int cmd, void* arg) { - return -ENOIOCTLCMD; /* or -EINVAL, depends on who will call this */ -} - static struct i2c_driver maven_driver={ - .owner = THIS_MODULE, - .name = "maven", + .driver = { + .name = "maven", + }, .id = I2C_DRIVERID_MGATVO, - .flags = I2C_DF_NOTIFY, .attach_adapter = maven_attach_adapter, .detach_client = maven_detach_client, - .command = maven_command, }; /* ************************** */ diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index d9d3e9f6c08..455a46ce840 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -192,11 +192,8 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { unsigned int wd; unsigned int divider; int i; - int fwidth; struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); - fwidth = 8; - DBG(__FUNCTION__) hw->SEQ[0] = 0x00; @@ -235,10 +232,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { hw->ATTR[16] = 0x41; hw->ATTR[17] = 0xFF; hw->ATTR[18] = 0x0F; - if (fwidth == 9) - hw->ATTR[19] = 0x08; - else - hw->ATTR[19] = 0x00; + hw->ATTR[19] = 0x00; hw->ATTR[20] = 0x00; hd = m->HDisplay >> 3; diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 8486e77872d..e18c9f98a40 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -485,7 +485,7 @@ static void vgaHWRestore(const struct fb_info *info, */ static inline int neo2200_sync(struct fb_info *info) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; int waitcycles; while (readl(&par->neo2200->bltStat) & 1) @@ -525,7 +525,7 @@ static inline void neo2200_wait_fifo(struct fb_info *info, static inline void neo2200_accel_init(struct fb_info *info, struct fb_var_screeninfo *var) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; Neo2200 __iomem *neo2200 = par->neo2200; u32 bltMod, pitch; @@ -560,7 +560,7 @@ static inline void neo2200_accel_init(struct fb_info *info, static int neofb_open(struct fb_info *info, int user) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; int cnt = atomic_read(&par->ref_count); if (!cnt) { @@ -575,7 +575,7 @@ neofb_open(struct fb_info *info, int user) static int neofb_release(struct fb_info *info, int user) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; int cnt = atomic_read(&par->ref_count); if (!cnt) @@ -590,7 +590,7 @@ neofb_release(struct fb_info *info, int user) static int neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; unsigned int pixclock = var->pixclock; struct xtimings timings; int memlen, vramlen; @@ -757,7 +757,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int neofb_set_par(struct fb_info *info) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; struct xtimings timings; unsigned char temp; int i, clock_hi = 0; @@ -1216,7 +1216,7 @@ static int neofb_set_par(struct fb_info *info) static void neofb_update_start(struct fb_info *info, struct fb_var_screeninfo *var) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; struct vgastate *state = &par->state; int oldExtCRTDispAddr; int Base; @@ -1331,7 +1331,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info) * wms...Enable VESA DPMS compatible powerdown mode * run "setterm -powersave powerdown" to take advantage */ - struct neofb_par *par = (struct neofb_par *)info->par; + struct neofb_par *par = info->par; int seqflags, lcdflags, dpmsflags, reg; switch (blank_mode) { @@ -1404,7 +1404,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info) static void neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; u_long dst, rop; dst = rect->dx + rect->dy * info->var.xres_virtual; @@ -1440,7 +1440,7 @@ static void neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area) { u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy; - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; u_long src, dst, bltCntl; bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000; @@ -1472,7 +1472,7 @@ neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area) static void neo2200_imageblit(struct fb_info *info, const struct fb_image *image) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; int s_pitch = (image->width * image->depth + 7) >> 3; int scan_align = info->pixmap.scan_align - 1; int buf_align = info->pixmap.buf_align - 1; @@ -1686,7 +1686,7 @@ static struct fb_videomode __devinitdata mode800x480 = { static int __devinit neo_map_mmio(struct fb_info *info, struct pci_dev *dev) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; DBG("neo_map_mmio"); @@ -1733,7 +1733,7 @@ static int __devinit neo_map_mmio(struct fb_info *info, static void neo_unmap_mmio(struct fb_info *info) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; DBG("neo_unmap_mmio"); @@ -1796,7 +1796,7 @@ static void neo_unmap_video(struct fb_info *info) #ifdef CONFIG_MTRR { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; mtrr_del(par->mtrr, info->fix.smem_start, info->fix.smem_len); @@ -1811,7 +1811,7 @@ static void neo_unmap_video(struct fb_info *info) static int __devinit neo_scan_monitor(struct fb_info *info) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; unsigned char type, display; int w; @@ -1890,7 +1890,7 @@ static int __devinit neo_scan_monitor(struct fb_info *info) static int __devinit neo_init_hw(struct fb_info *info) { - struct neofb_par *par = (struct neofb_par *) info->par; + struct neofb_par *par = info->par; int videoRam = 896; int maxClock = 65000; int CursorMem = 1024; @@ -2014,7 +2014,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st struct fb_info *info; struct neofb_par *par; - info = framebuffer_alloc(sizeof(struct neofb_par) + sizeof(u32) * 256, &dev->dev); + info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev); if (!info) return NULL; @@ -2081,7 +2081,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st info->fix.accel = id->driver_data; info->fbops = &neofb_ops; - info->pseudo_palette = (void *) (par + 1); + info->pseudo_palette = par->palette; return info; } diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index b989358437b..99c3a8e6a23 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -52,6 +52,7 @@ #include <linux/pci.h> #include "nv_type.h" #include "nv_local.h" +#include "nv_proto.h" void NVLockUnlock(struct nvidia_par *par, int Lock) { @@ -848,7 +849,7 @@ void NVCalcStateExt(struct nvidia_par *par, int width, int hDisplaySize, int height, int dotClock, int flags) { - int pixelDepth, VClk; + int pixelDepth, VClk = 0; /* * Save mode parameters. */ @@ -938,15 +939,24 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) if (par->Architecture == NV_ARCH_04) { NV_WR32(par->PFB, 0x0200, state->config); - } else if ((par->Chipset & 0xfff0) == 0x0090) { - for (i = 0; i < 15; i++) { - NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0); - NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1); - } - } else { + } else if ((par->Architecture < NV_ARCH_40) || + (par->Chipset & 0xfff0) == 0x0040) { for (i = 0; i < 8; i++) { NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0); - NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1); + NV_WR32(par->PFB, 0x0244 + (i * 0x10), + par->FbMapSize - 1); + } + } else { + int regions = 12; + + if (((par->Chipset & 0xfff0) == 0x0090) || + ((par->Chipset & 0xfff0) == 0x01D0) || + ((par->Chipset & 0xfff0) == 0x0290)) + regions = 15; + for(i = 0; i < regions; i++) { + NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0); + NV_WR32(par->PFB, 0x0604 + (i * 0x10), + par->FbMapSize - 1); } } @@ -1182,11 +1192,17 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF); } else { if (par->Architecture >= NV_ARCH_40) { + u32 tmp; + NV_WR32(par->PGRAPH, 0x0084, 0x401287c0); NV_WR32(par->PGRAPH, 0x008C, 0x60de8051); NV_WR32(par->PGRAPH, 0x0090, 0x00008000); NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f); + tmp = NV_RD32(par->REGS, 0x1540) & 0xff; + for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++); + NV_WR32(par->PGRAPH, 0x5000, i); + if ((par->Chipset & 0xfff0) == 0x0040) { NV_WR32(par->PGRAPH, 0x09b0, 0x83280fff); @@ -1211,6 +1227,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) 0xffff7fff); break; case 0x00C0: + case 0x0120: NV_WR32(par->PGRAPH, 0x0828, 0x007596ff); NV_WR32(par->PGRAPH, 0x082C, @@ -1245,6 +1262,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) 0x00100000); break; case 0x0090: + case 0x0290: NV_WR32(par->PRAMDAC, 0x0608, NV_RD32(par->PRAMDAC, 0x0608) | 0x00100000); @@ -1310,14 +1328,44 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) } } - if ((par->Chipset & 0xfff0) == 0x0090) { - for (i = 0; i < 60; i++) - NV_WR32(par->PGRAPH, 0x0D00 + i, - NV_RD32(par->PFB, 0x0600 + i)); + if ((par->Architecture < NV_ARCH_40) || + ((par->Chipset & 0xfff0) == 0x0040)) { + for (i = 0; i < 32; i++) { + NV_WR32(par->PGRAPH, 0x0900 + i*4, + NV_RD32(par->PFB, 0x0240 +i*4)); + NV_WR32(par->PGRAPH, 0x6900 + i*4, + NV_RD32(par->PFB, 0x0240 +i*4)); + } } else { - for (i = 0; i < 32; i++) - NV_WR32(par->PGRAPH, 0x0900 + i, - NV_RD32(par->PFB, 0x0240 + i)); + if (((par->Chipset & 0xfff0) == 0x0090) || + ((par->Chipset & 0xfff0) == 0x01D0) || + ((par->Chipset & 0xfff0) == 0x0290)) { + for (i = 0; i < 60; i++) { + NV_WR32(par->PGRAPH, + 0x0D00 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + NV_WR32(par->PGRAPH, + 0x6900 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + } + } else { + for (i = 0; i < 48; i++) { + NV_WR32(par->PGRAPH, + 0x0900 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + if(((par->Chipset & 0xfff0) + != 0x0160) && + ((par->Chipset & 0xfff0) + != 0x0220)) + NV_WR32(par->PGRAPH, + 0x6900 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + } + } } if (par->Architecture >= NV_ARCH_40) { @@ -1338,7 +1386,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) NV_WR32(par->PGRAPH, 0x0868, par->FbMapSize - 1); } else { - if((par->Chipset & 0xfff0) == 0x0090) { + if ((par->Chipset & 0xfff0) == 0x0090 || + (par->Chipset & 0xfff0) == 0x01D0 || + (par->Chipset & 0xfff0) == 0x0290) { NV_WR32(par->PGRAPH, 0x0DF0, NV_RD32(par->PFB, 0x0200)); NV_WR32(par->PGRAPH, 0x0DF4, diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index 12f2884d3f0..bd9eca05e14 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c @@ -46,7 +46,7 @@ static void nvidia_gpio_setscl(void *data, int state) static void nvidia_gpio_setsda(void *data, int state) { - struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data; + struct nvidia_i2c_chan *chan = data; struct nvidia_par *par = chan->par; u32 val; @@ -64,7 +64,7 @@ static void nvidia_gpio_setsda(void *data, int state) static int nvidia_gpio_getscl(void *data) { - struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data; + struct nvidia_i2c_chan *chan = data; struct nvidia_par *par = chan->par; u32 val = 0; @@ -79,7 +79,7 @@ static int nvidia_gpio_getscl(void *data) static int nvidia_gpio_getsda(void *data) { - struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data; + struct nvidia_i2c_chan *chan = data; struct nvidia_par *par = chan->par; u32 val = 0; @@ -136,13 +136,13 @@ void nvidia_create_i2c_busses(struct nvidia_par *par) par->chan[2].par = par; par->chan[0].ddc_base = 0x3e; - nvidia_setup_i2c_bus(&par->chan[0], "BUS1"); + nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0"); par->chan[1].ddc_base = 0x36; - nvidia_setup_i2c_bus(&par->chan[1], "BUS2"); + nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1"); par->chan[2].ddc_base = 0x50; - nvidia_setup_i2c_bus(&par->chan[2], "BUS3"); + nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2"); } void nvidia_delete_i2c_busses(struct nvidia_par *par) diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index 3353103e8b0..b149a690ee0 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -4,7 +4,7 @@ #define __NV_PROTO_H__ /* in nv_setup.c */ -void NVCommonSetup(struct fb_info *info); +int NVCommonSetup(struct fb_info *info); void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value); u8 NVReadCrtc(struct nvidia_par *par, u8 index); void NVWriteGr(struct nvidia_par *par, u8 index, u8 value); diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 1f06a9f1bd0..a18a9aebf05 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -285,28 +285,34 @@ static void nv10GetConfig(struct nvidia_par *par) par->CrystalFreqKHz = 27000; } - par->CursorStart = (par->RamAmountKBytes - 96) * 1024; par->CURSOR = NULL; /* can't set this here */ par->MinVClockFreqKHz = 12000; par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000; } -void NVCommonSetup(struct fb_info *info) +int NVCommonSetup(struct fb_info *info) { struct nvidia_par *par = info->par; - struct fb_var_screeninfo var; + struct fb_var_screeninfo *var; u16 implementation = par->Chipset & 0x0ff0; u8 *edidA = NULL, *edidB = NULL; - struct fb_monspecs monitorA, monitorB; + struct fb_monspecs *monitorA, *monitorB; struct fb_monspecs *monA = NULL, *monB = NULL; int mobile = 0; int tvA = 0; int tvB = 0; int FlatPanel = -1; /* really means the CRTC is slaved */ int Television = 0; + int err = 0; - memset(&monitorA, 0, sizeof(struct fb_monspecs)); - memset(&monitorB, 0, sizeof(struct fb_monspecs)); + var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); + monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); + monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); + + if (!var || !monitorA || !monitorB) { + err = -ENOMEM; + goto done; + } par->PRAMIN = par->REGS + (0x00710000 / 4); par->PCRTC0 = par->REGS + (0x00600000 / 4); @@ -382,6 +388,8 @@ void NVCommonSetup(struct fb_info *info) case 0x0146: case 0x0147: case 0x0148: + case 0x0098: + case 0x0099: mobile = 1; break; default: @@ -406,9 +414,9 @@ void NVCommonSetup(struct fb_info *info) par->CRTCnumber = 0; if (nvidia_probe_i2c_connector(info, 1, &edidA)) nvidia_probe_of_connector(info, 1, &edidA); - if (edidA && !fb_parse_edid(edidA, &var)) { + if (edidA && !fb_parse_edid(edidA, var)) { printk("nvidiafb: EDID found from BUS1\n"); - monA = &monitorA; + monA = monitorA; fb_edid_to_monspecs(edidA, monA); FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0; @@ -494,17 +502,17 @@ void NVCommonSetup(struct fb_info *info) if (nvidia_probe_i2c_connector(info, 1, &edidA)) nvidia_probe_of_connector(info, 1, &edidA); - if (edidA && !fb_parse_edid(edidA, &var)) { + if (edidA && !fb_parse_edid(edidA, var)) { printk("nvidiafb: EDID found from BUS1\n"); - monA = &monitorA; + monA = monitorA; fb_edid_to_monspecs(edidA, monA); } if (nvidia_probe_i2c_connector(info, 2, &edidB)) nvidia_probe_of_connector(info, 2, &edidB); - if (edidB && !fb_parse_edid(edidB, &var)) { + if (edidB && !fb_parse_edid(edidB, var)) { printk("nvidiafb: EDID found from BUS2\n"); - monB = &monitorB; + monB = monitorB; fb_edid_to_monspecs(edidB, monB); } @@ -639,4 +647,9 @@ void NVCommonSetup(struct fb_info *info) kfree(edidA); kfree(edidB); +done: + kfree(var); + kfree(monitorA); + kfree(monitorB); + return err; } diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index bee09c6e48f..dbcb8962e57 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -284,6 +284,16 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x0252, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x0313, @@ -418,6 +428,7 @@ static int noaccel __devinitdata = 0; static int noscale __devinitdata = 0; static int paneltweak __devinitdata = 0; static int vram __devinitdata = 0; +static int bpp __devinitdata = 8; #ifdef CONFIG_MTRR static int nomtrr __devinitdata = 0; #endif @@ -485,7 +496,7 @@ static int nvidia_backlight_levels[] = { static int nvidia_set_backlight_enable(int on, int level, void *data) { - struct nvidia_par *par = (struct nvidia_par *)data; + struct nvidia_par *par = data; u32 tmp_pcrt, tmp_pmc, fpcontrol; tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; @@ -1382,24 +1393,36 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->monspecs.modedb_len, &info->modelist); fb_var_to_videomode(&modedb, &nvidiafb_default_var); + switch (bpp) { + case 0 ... 8: + bpp = 8; + break; + case 9 ... 16: + bpp = 16; + break; + default: + bpp = 32; + break; + } + if (specs->modedb != NULL) { struct fb_videomode *modedb; modedb = fb_find_best_display(specs, &info->modelist); fb_videomode_to_var(&nvidiafb_default_var, modedb); - nvidiafb_default_var.bits_per_pixel = 8; + nvidiafb_default_var.bits_per_pixel = bpp; } else if (par->fpWidth && par->fpHeight) { char buf[16]; memset(buf, 0, 16); snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight); fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb, - specs->modedb_len, &modedb, 8); + specs->modedb_len, &modedb, bpp); } if (mode_option) fb_find_mode(&nvidiafb_default_var, info, mode_option, - specs->modedb, specs->modedb_len, &modedb, 8); + specs->modedb, specs->modedb_len, &modedb, bpp); info->var = nvidiafb_default_var; info->fix.visual = (info->var.bits_per_pixel == 8) ? @@ -1448,11 +1471,34 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) return nvidiafb_check_var(&info->var, info); } -static u32 __devinit nvidia_get_arch(struct pci_dev *pd) +static u32 __devinit nvidia_get_chipset(struct fb_info *info) { + struct nvidia_par *par = info->par; + u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device; + + printk("nvidiafb: PCI id - %x\n", id); + if ((id & 0xfff0) == 0x00f0) { + /* pci-e */ + printk("nvidiafb: PCI-E card\n"); + id = NV_RD32(par->REGS, 0x1800); + + if ((id & 0x0000ffff) == 0x000010DE) + id = 0x10DE0000 | (id >> 16); + else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */ + id = 0x10DE0000 | ((id << 8) & 0x0000ff00) | + ((id >> 8) & 0x000000ff); + } + + printk("nvidiafb: Actual id - %x\n", id); + return id; +} + +static u32 __devinit nvidia_get_arch(struct fb_info *info) +{ + struct nvidia_par *par = info->par; u32 arch = 0; - switch (pd->device & 0x0ff0) { + switch (par->Chipset & 0x0ff0) { case 0x0100: /* GeForce 256 */ case 0x0110: /* GeForce2 MX */ case 0x0150: /* GeForce2 */ @@ -1485,6 +1531,8 @@ static u32 __devinit nvidia_get_arch(struct pci_dev *pd) case 0x0210: case 0x0220: case 0x0230: + case 0x0290: + case 0x0390: arch = NV_ARCH_40; break; case 0x0020: /* TNT, TNT2 */ @@ -1513,7 +1561,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, if (!info) goto err_out; - par = (struct nvidia_par *)info->par; + par = info->par; par->pci_dev = pd; info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL); @@ -1533,18 +1581,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, goto err_out_request; } - par->Architecture = nvidia_get_arch(pd); - - par->Chipset = (pd->vendor << 16) | pd->device; - printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset); - - if (par->Architecture == 0) { - printk(KERN_ERR PFX "unknown NV_ARCH\n"); - goto err_out_free_base0; - } - - sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4); - par->FlatPanel = flatpanel; if (flatpanel == 1) printk(KERN_INFO PFX "flatpanel support enabled\n"); @@ -1570,7 +1606,19 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, goto err_out_free_base0; } - NVCommonSetup(info); + par->Chipset = nvidia_get_chipset(info); + printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset); + par->Architecture = nvidia_get_arch(info); + + if (par->Architecture == 0) { + printk(KERN_ERR PFX "unknown NV_ARCH\n"); + goto err_out_arch; + } + + sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4); + + if (NVCommonSetup(info)) + goto err_out_arch; par->FbAddress = nvidiafb_fix.smem_start; par->FbMapSize = par->RamAmountKBytes * 1024; @@ -1581,10 +1629,15 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, if (par->FbMapSize > 64 * 1024 * 1024) par->FbMapSize = 64 * 1024 * 1024; - par->FbUsableSize = par->FbMapSize - (128 * 1024); + if(par->Architecture >= NV_ARCH_40) + par->FbUsableSize = par->FbMapSize - (560 * 1024); + else + par->FbUsableSize = par->FbMapSize - (128 * 1024); par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 : 16 * 1024; par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize; + par->CursorStart = par->FbUsableSize + (32 * 1024); + info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize); info->screen_size = par->FbUsableSize; nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024; @@ -1640,21 +1693,22 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, NVTRACE_LEAVE(); return 0; - err_out_iounmap_fb: +err_out_iounmap_fb: iounmap(info->screen_base); - err_out_free_base1: +err_out_free_base1: fb_destroy_modedb(info->monspecs.modedb); nvidia_delete_i2c_busses(par); +err_out_arch: iounmap(par->REGS); - err_out_free_base0: +err_out_free_base0: pci_release_regions(pd); - err_out_request: +err_out_request: pci_disable_device(pd); - err_out_enable: +err_out_enable: kfree(info->pixmap.addr); - err_out_kfree: +err_out_kfree: framebuffer_release(info); - err_out: +err_out: return -ENODEV; } @@ -1729,6 +1783,8 @@ static int __devinit nvidiafb_setup(char *options) #endif } else if (!strncmp(this_opt, "fpdither:", 9)) { fpdither = simple_strtol(this_opt+9, NULL, 0); + } else if (!strncmp(this_opt, "bpp:", 4)) { + bpp = simple_strtoul(this_opt+4, NULL, 0); } else mode_option = this_opt; } @@ -1804,6 +1860,11 @@ module_param(vram, int, 0); MODULE_PARM_DESC(vram, "amount of framebuffer memory to remap in MiB" "(default=0 - remap entire memory)"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "Specify initial video mode"); +module_param(bpp, int, 0); +MODULE_PARM_DESC(bpp, "pixel width in bits" + "(default=8)"); #ifdef CONFIG_MTRR module_param(nomtrr, bool, 0); MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) " diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 00d87f5bb7b..ad1434e3f22 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -223,6 +223,7 @@ static int offb_blank(int blank, struct fb_info *info) int __init offb_init(void) { struct device_node *dp = NULL, *boot_disp = NULL; + #if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) struct device_node *macos_display = NULL; #endif @@ -234,60 +235,54 @@ int __init offb_init(void) if (boot_infos != 0) { unsigned long addr = (unsigned long) boot_infos->dispDeviceBase; + u32 *addrp; + u64 daddr, dsize; + unsigned int flags; + /* find the device node corresponding to the macos display */ while ((dp = of_find_node_by_type(dp, "display"))) { int i; - /* - * Grrr... It looks like the MacOS ATI driver - * munges the assigned-addresses property (but - * the AAPL,address value is OK). - */ - if (strncmp(dp->name, "ATY,", 4) == 0 - && dp->n_addrs == 1) { - unsigned int *ap = - (unsigned int *) get_property(dp, - "AAPL,address", - NULL); - if (ap != NULL) { - dp->addrs[0].address = *ap; - dp->addrs[0].size = 0x01000000; - } - } /* - * The LTPro on the Lombard powerbook has no addresses - * on the display nodes, they are on their parent. + * Look for an AAPL,address property first. */ - if (dp->n_addrs == 0 - && device_is_compatible(dp, "ATY,264LTPro")) { - int na; - unsigned int *ap = (unsigned int *) - get_property(dp, "AAPL,address", &na); - if (ap != 0) - for (na /= sizeof(unsigned int); - na > 0; --na, ++ap) - if (*ap <= addr - && addr < - *ap + 0x1000000) - goto foundit; + unsigned int na; + unsigned int *ap = + (unsigned int *)get_property(dp, "AAPL,address", + &na); + if (ap != 0) { + for (na /= sizeof(unsigned int); na > 0; + --na, ++ap) + if (*ap <= addr && + addr < *ap + 0x1000000) { + macos_display = dp; + goto foundit; + } } /* * See if the display address is in one of the address * ranges for this display. */ - for (i = 0; i < dp->n_addrs; ++i) { - if (dp->addrs[i].address <= addr - && addr < - dp->addrs[i].address + - dp->addrs[i].size) + i = 0; + for (;;) { + addrp = of_get_address(dp, i++, &dsize, &flags); + if (addrp == NULL) break; + if (!(flags & IORESOURCE_MEM)) + continue; + daddr = of_translate_address(dp, addrp); + if (daddr == OF_BAD_ADDR) + continue; + if (daddr <= addr && addr < (daddr + dsize)) { + macos_display = dp; + goto foundit; + } } - if (i < dp->n_addrs) { - foundit: + foundit: + if (macos_display) { printk(KERN_INFO "MacOS display is %s\n", dp->full_name); - macos_display = dp; break; } } @@ -326,8 +321,10 @@ static void __init offb_init_nodriver(struct device_node *dp) int *pp, i; unsigned int len; int width = 640, height = 480, depth = 8, pitch; - unsigned int rsize, *up; - unsigned long address = 0; + unsigned int flags, rsize, *up; + u64 address = OF_BAD_ADDR; + u32 *addrp; + u64 asize; if ((pp = (int *) get_property(dp, "depth", &len)) != NULL && len == sizeof(int)) @@ -363,7 +360,7 @@ static void __init offb_init_nodriver(struct device_node *dp) break; } if (pdev) { - for (i = 0; i < 6 && address == 0; i++) { + for (i = 0; i < 6 && address == OF_BAD_ADDR; i++) { if ((pci_resource_flags(pdev, i) & IORESOURCE_MEM) && (pci_resource_len(pdev, i) >= rsize)) @@ -374,27 +371,33 @@ static void __init offb_init_nodriver(struct device_node *dp) } #endif /* CONFIG_PCI */ - if (address == 0 && - (up = (unsigned *) get_property(dp, "address", &len)) != NULL && - len == sizeof(unsigned)) - address = (u_long) * up; - if (address == 0) { - for (i = 0; i < dp->n_addrs; ++i) - if (dp->addrs[i].size >= - pitch * height * depth / 8) - break; - if (i >= dp->n_addrs) { + /* This one is dodgy, we may drop it ... */ + if (address == OF_BAD_ADDR && + (up = (unsigned *) get_property(dp, "address", &len)) != NULL && + len == sizeof(unsigned int)) + address = (u64) * up; + + if (address == OF_BAD_ADDR) { + for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) + != NULL; i++) { + if (!(flags & IORESOURCE_MEM)) + continue; + if (asize >= pitch * height * depth / 8) + break; + } + if (addrp == NULL) { printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name); return; } - - address = (u_long) dp->addrs[i].address; - -#ifdef CONFIG_PPC64 - address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset; -#endif + address = of_translate_address(dp, addrp); + if (address == OF_BAD_ADDR) { + printk(KERN_ERR + "can't translate framebuffer address for %s\n", + dp->full_name); + return; + } /* kludge for valkyrie */ if (strcmp(dp->name, "valkyrie") == 0) @@ -459,7 +462,9 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_type = cmap_unknown; if (depth == 8) { - /* XXX kludge for ati */ + + /* Palette hacks disabled for now */ +#if 0 if (dp && !strncmp(name, "ATY,Rage128", 11)) { unsigned long regbase = dp->addrs[2].address; par->cmap_adr = ioremap(regbase, 0x1FFF); @@ -490,6 +495,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); par->cmap_type = cmap_gxt2000; } +#endif fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; } else diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index ca4082ae5a1..335e3746555 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -69,6 +69,8 @@ struct fb_info_platinum { unsigned long total_vram; int clktype; int dactype; + + struct resource rsrc_fb, rsrc_reg; }; /* @@ -97,9 +99,6 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, * Interface used by the world */ -int platinumfb_init(void); -int platinumfb_setup(char*); - static struct fb_ops platinumfb_ops = { .owner = THIS_MODULE, .fb_check_var = platinumfb_check_var, @@ -138,13 +137,15 @@ static int platinumfb_set_par (struct fb_info *info) init = platinum_reg_init[pinfo->vmode-1]; - if (pinfo->vmode == 13 && pinfo->cmode > 0) - offset = 0x10; + if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8)) + offset = 0x10; + info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; info->fix.visual = (pinfo->cmode == CMODE_8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; - info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) + offset; + info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) + + offset; printk("line_length: %x\n", info->fix.line_length); return 0; } @@ -221,7 +222,9 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static inline int platinum_vram_reqd(int video_mode, int color_mode) { return vmode_attrs[video_mode-1].vres * - (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 0x20) +0x1000; + (vmode_attrs[video_mode-1].hres * (1<<color_mode) + + ((video_mode == VMODE_832_624_75) && + (color_mode > CMODE_8)) ? 0x10 : 0x20) + 0x1000; } #define STORE_D2(a, d) { \ @@ -481,7 +484,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, /* * Parse user speficied options (`video=platinumfb:') */ -int __init platinumfb_setup(char *options) +static int __init platinumfb_setup(char *options) { char *this_opt; @@ -522,19 +525,15 @@ int __init platinumfb_setup(char *options) #define invalidate_cache(addr) #endif -static int __devinit platinumfb_probe(struct of_device* odev, const struct of_device_id *match) +static int __devinit platinumfb_probe(struct of_device* odev, + const struct of_device_id *match) { struct device_node *dp = odev->node; struct fb_info *info; struct fb_info_platinum *pinfo; - unsigned long addr, size; volatile __u8 *fbuffer; - int i, bank0, bank1, bank2, bank3, rc; + int bank0, bank1, bank2, bank3, rc; - if (dp->n_addrs != 2) { - printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs); - return -ENXIO; - } printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n"); info = framebuffer_alloc(sizeof(*pinfo), &odev->dev); @@ -542,26 +541,39 @@ static int __devinit platinumfb_probe(struct of_device* odev, const struct of_de return -ENOMEM; pinfo = info->par; - /* Map in frame buffer and registers */ - for (i = 0; i < dp->n_addrs; ++i) { - addr = dp->addrs[i].address; - size = dp->addrs[i].size; - /* Let's assume we can request either all or nothing */ - if (!request_mem_region(addr, size, "platinumfb")) { - framebuffer_release(info); - return -ENXIO; - } - if (size >= 0x400000) { - /* frame buffer - map only 4MB */ - pinfo->frame_buffer_phys = addr; - pinfo->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU); - pinfo->base_frame_buffer = pinfo->frame_buffer; - } else { - /* registers */ - pinfo->platinum_regs_phys = addr; - pinfo->platinum_regs = ioremap(addr, size); - } + if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) || + of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) { + printk(KERN_ERR "platinumfb: Can't get resources\n"); + framebuffer_release(info); + return -ENXIO; } + if (!request_mem_region(pinfo->rsrc_reg.start, + pinfo->rsrc_reg.start - + pinfo->rsrc_reg.end + 1, + "platinumfb registers")) { + framebuffer_release(info); + return -ENXIO; + } + if (!request_mem_region(pinfo->rsrc_fb.start, + pinfo->rsrc_fb.start + - pinfo->rsrc_fb.end + 1, + "platinumfb framebuffer")) { + release_mem_region(pinfo->rsrc_reg.start, + pinfo->rsrc_reg.end - + pinfo->rsrc_reg.start + 1); + framebuffer_release(info); + return -ENXIO; + } + + /* frame buffer - map only 4MB */ + pinfo->frame_buffer_phys = pinfo->rsrc_fb.start; + pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000, + _PAGE_WRITETHRU); + pinfo->base_frame_buffer = pinfo->frame_buffer; + + /* registers */ + pinfo->platinum_regs_phys = pinfo->rsrc_reg.start; + pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000); pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap"); @@ -624,18 +636,16 @@ static int __devexit platinumfb_remove(struct of_device* odev) { struct fb_info *info = dev_get_drvdata(&odev->dev); struct fb_info_platinum *pinfo = info->par; - struct device_node *dp = odev->node; - unsigned long addr, size; - int i; unregister_framebuffer (info); /* Unmap frame buffer and registers */ - for (i = 0; i < dp->n_addrs; ++i) { - addr = dp->addrs[i].address; - size = dp->addrs[i].size; - release_mem_region(addr, size); - } + release_mem_region(pinfo->rsrc_fb.start, + pinfo->rsrc_fb.end - + pinfo->rsrc_fb.start + 1); + release_mem_region(pinfo->rsrc_reg.start, + pinfo->rsrc_reg.end - + pinfo->rsrc_reg.start + 1); iounmap(pinfo->frame_buffer); iounmap(pinfo->platinum_regs); release_mem_region(pinfo->cmap_regs_phys, 0x1000); @@ -662,7 +672,7 @@ static struct of_platform_driver platinum_driver = .remove = platinumfb_remove, }; -int __init platinumfb_init(void) +static int __init platinumfb_init(void) { #ifndef MODULE char *option = NULL; @@ -676,7 +686,7 @@ int __init platinumfb_init(void) return 0; } -void __exit platinumfb_exit(void) +static void __exit platinumfb_exit(void) { of_unregister_driver(&platinum_driver); } diff --git a/drivers/video/platinumfb.h b/drivers/video/platinumfb.h index 2834fc1c344..f6bd77cafd1 100644 --- a/drivers/video/platinumfb.h +++ b/drivers/video/platinumfb.h @@ -158,7 +158,9 @@ static struct platinum_regvals platinum_reg_init_14 = { /* 832x624, 75Hz (13) */ static struct platinum_regvals platinum_reg_init_13 = { 0x70, - { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */ + { 864, 1680, 3344 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB, + * and we use 3344 instead of 3360 to fit in 2Mb + */ { 0xff0, 4, 0, 0, 0, 0, 0x299, 0, 0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37, 0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52, diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 0277ce031e5..5fe197943de 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -91,6 +91,7 @@ struct pm2fb_par u32 mem_config; /* MemConfig reg at probe */ u32 mem_control; /* MemControl reg at probe */ u32 boot_address; /* BootAddress reg at probe */ + u32 palette[16]; }; /* @@ -674,7 +675,7 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) */ static int pm2fb_set_par(struct fb_info *info) { - struct pm2fb_par *par = (struct pm2fb_par *) info->par; + struct pm2fb_par *par = info->par; u32 pixclock; u32 width, height, depth; u32 hsstart, hsend, hbend, htotal; @@ -854,7 +855,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct pm2fb_par *par = (struct pm2fb_par *) info->par; + struct pm2fb_par *par = info->par; if (regno >= info->cmap.len) /* no. of hw registers */ return 1; @@ -929,7 +930,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, case 16: case 24: case 32: - ((u32*)(info->pseudo_palette))[regno] = v; + par->palette[regno] = v; break; } return 0; @@ -955,7 +956,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, static int pm2fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - struct pm2fb_par *p = (struct pm2fb_par *) info->par; + struct pm2fb_par *p = info->par; u32 base; u32 depth; u32 xres; @@ -987,7 +988,7 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var, */ static int pm2fb_blank(int blank_mode, struct fb_info *info) { - struct pm2fb_par *par = (struct pm2fb_par *) info->par; + struct pm2fb_par *par = info->par; u32 video = par->video; DPRINTK("blank_mode %d\n", blank_mode); @@ -1054,8 +1055,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, { struct pm2fb_par *default_par; struct fb_info *info; - int size, err; - int err_retval = -ENXIO; + int err, err_retval = -ENXIO; err = pci_enable_device(pdev); if ( err ) { @@ -1063,11 +1063,10 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, return err; } - size = sizeof(struct pm2fb_par) + 256 * sizeof(u32); - info = framebuffer_alloc(size, &pdev->dev); + info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev); if ( !info ) return -ENOMEM; - default_par = (struct pm2fb_par *) info->par; + default_par = info->par; switch (pdev->device) { case PCI_DEVICE_ID_TI_TVP4020: @@ -1171,7 +1170,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, info->fbops = &pm2fb_ops; info->fix = pm2fb_fix; - info->pseudo_palette = (void *)(default_par + 1); + info->pseudo_palette = default_par->palette; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 3e9f96e9237..6c19ab6afb0 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -630,7 +630,7 @@ static void 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; - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; struct riva_regs newmode; NVTRACE_ENTER(); @@ -925,7 +925,7 @@ riva_set_rop_solid(struct riva_par *par, int rop) static void riva_setup_accel(struct fb_info *info) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; RIVA_FIFO_FREE(par->riva, Clip, 2); NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0); @@ -979,7 +979,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) #ifdef CONFIG_PMAC_BACKLIGHT static int riva_set_backlight_enable(int on, int level, void *data) { - struct riva_par *par = (struct riva_par *)data; + struct riva_par *par = data; U032 tmp_pcrt, tmp_pmc; tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; @@ -1008,7 +1008,7 @@ static int riva_set_backlight_level(int level, void *data) static int rivafb_open(struct fb_info *info, int user) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; int cnt = atomic_read(&par->ref_count); NVTRACE_ENTER(); @@ -1034,7 +1034,7 @@ static int rivafb_open(struct fb_info *info, int user) static int rivafb_release(struct fb_info *info, int user) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; int cnt = atomic_read(&par->ref_count); NVTRACE_ENTER(); @@ -1057,7 +1057,7 @@ static int rivafb_release(struct fb_info *info, int user) static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct fb_videomode *mode; - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; int nom, den; /* translating from pixels->bytes */ int mode_valid = 0; @@ -1166,7 +1166,7 @@ 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 = (struct riva_par *) info->par; + struct riva_par *par = info->par; NVTRACE_ENTER(); /* vgaHWunlock() + riva unlock (0x7F) */ @@ -1205,43 +1205,19 @@ static int rivafb_set_par(struct fb_info *info) static int rivafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - struct riva_par *par = (struct riva_par *)info->par; + struct riva_par *par = info->par; unsigned int base; NVTRACE_ENTER(); - if (var->xoffset > (var->xres_virtual - var->xres)) - return -EINVAL; - if (var->yoffset > (var->yres_virtual - var->yres)) - return -EINVAL; - - if (var->vmode & FB_VMODE_YWRAP) { - if (var->yoffset < 0 - || var->yoffset >= info->var.yres_virtual - || var->xoffset) return -EINVAL; - } else { - if (var->xoffset + info->var.xres > info->var.xres_virtual || - var->yoffset + info->var.yres > info->var.yres_virtual) - return -EINVAL; - } - base = var->yoffset * info->fix.line_length + var->xoffset; - par->riva.SetStartAddress(&par->riva, base); - - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - - if (var->vmode & FB_VMODE_YWRAP) - info->var.vmode |= FB_VMODE_YWRAP; - else - info->var.vmode &= ~FB_VMODE_YWRAP; NVTRACE_LEAVE(); return 0; } static int rivafb_blank(int blank, struct fb_info *info) { - struct riva_par *par= (struct riva_par *)info->par; + struct riva_par *par= info->par; unsigned char tmp, vesa; tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */ @@ -1304,7 +1280,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct riva_par *par = (struct riva_par *)info->par; + struct riva_par *par = info->par; RIVA_HW_INST *chip = &par->riva; int i; @@ -1393,7 +1369,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, */ static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; u_int color, rop = 0; if ((info->flags & FBINFO_HWACCEL_DISABLED)) { @@ -1449,7 +1425,7 @@ static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect */ static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; if ((info->flags & FBINFO_HWACCEL_DISABLED)) { cfb_copyarea(info, region); @@ -1495,7 +1471,7 @@ static inline void convert_bgcolor_16(u32 *col) static void rivafb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; u32 fgx = 0, bgx = 0, width, tmp; u8 *cdat = (u8 *) image->data; volatile u32 __iomem *d; @@ -1580,7 +1556,7 @@ static void rivafb_imageblit(struct fb_info *info, */ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; u8 data[MAX_CURS * MAX_CURS/8]; int i, set = cursor->set; u16 fg, bg; @@ -1664,7 +1640,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) static int rivafb_sync(struct fb_info *info) { - struct riva_par *par = (struct riva_par *)info->par; + struct riva_par *par = info->par; wait_for_idle(par); return 0; @@ -1696,7 +1672,7 @@ static struct fb_ops riva_fb_ops = { static int __devinit riva_set_fbinfo(struct fb_info *info) { unsigned int cmap_len; - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; NVTRACE_ENTER(); info->flags = FBINFO_DEFAULT @@ -1733,7 +1709,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info) #ifdef CONFIG_PPC_OF static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; struct device_node *dp; unsigned char *pedid = NULL; unsigned char *disptype = NULL; @@ -1767,7 +1743,7 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) #if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF) static int __devinit riva_get_EDID_i2c(struct fb_info *info) { - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; struct fb_var_screeninfo var; int i; @@ -1837,7 +1813,7 @@ static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev) static void __devinit riva_get_edidinfo(struct fb_info *info) { struct fb_var_screeninfo *var = &rivafb_default_var; - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; fb_edid_to_monspecs(par->EDID, &info->monspecs); fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len, @@ -1909,7 +1885,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd, ret = -ENOMEM; goto err_ret; } - default_par = (struct riva_par *) info->par; + default_par = info->par; default_par->pdev = pd; info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL); @@ -2070,7 +2046,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd, err_iounmap_screen_base: #ifdef CONFIG_FB_RIVA_I2C - riva_delete_i2c_busses((struct riva_par *) info->par); + riva_delete_i2c_busses(info->par); #endif iounmap(info->screen_base); err_iounmap_pramin: @@ -2093,7 +2069,7 @@ err_ret: static void __exit rivafb_remove(struct pci_dev *pd) { struct fb_info *info = pci_get_drvdata(pd); - struct riva_par *par = (struct riva_par *) info->par; + struct riva_par *par = info->par; NVTRACE_ENTER(); if (!info) diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c index 77151d8e076..8b1967fc116 100644 --- a/drivers/video/riva/rivafb-i2c.c +++ b/drivers/video/riva/rivafb-i2c.c @@ -30,7 +30,7 @@ static void riva_gpio_setscl(void* data, int state) { - struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_i2c_chan *chan = data; struct riva_par *par = chan->par; u32 val; @@ -48,7 +48,7 @@ static void riva_gpio_setscl(void* data, int state) static void riva_gpio_setsda(void* data, int state) { - struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_i2c_chan *chan = data; struct riva_par *par = chan->par; u32 val; @@ -66,7 +66,7 @@ static void riva_gpio_setsda(void* data, int state) static int riva_gpio_getscl(void* data) { - struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_i2c_chan *chan = data; struct riva_par *par = chan->par; u32 val = 0; @@ -81,7 +81,7 @@ static int riva_gpio_getscl(void* data) static int riva_gpio_getsda(void* data) { - struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_i2c_chan *chan = data; struct riva_par *par = chan->par; u32 val = 0; diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index ce6e749db3a..d574dd3c9c8 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -87,6 +87,7 @@ #include <linux/workqueue.h> #include <linux/wait.h> #include <linux/platform_device.h> +#include <linux/clk.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -96,7 +97,6 @@ #include <asm/arch/regs-lcd.h> #include <asm/arch/regs-gpio.h> #include <asm/arch/fb.h> -#include <asm/hardware/clock.h> #ifdef CONFIG_PM #include <linux/pm.h> @@ -552,7 +552,7 @@ static inline void modify_gpio(void __iomem *reg, * s3c2410fb_init_registers - Initialise all LCD-related registers */ -int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) +static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) { unsigned long flags; @@ -634,7 +634,7 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r) static char driver_name[]="s3c2410fb"; -int __init s3c2410fb_probe(struct platform_device *pdev) +static int __init s3c2410fb_probe(struct platform_device *pdev) { struct s3c2410fb_info *info; struct fb_info *fbinfo; @@ -667,8 +667,6 @@ int __init s3c2410fb_probe(struct platform_device *pdev) info->fb = fbinfo; platform_set_drvdata(pdev, fbinfo); - s3c2410fb_init_registers(info); - dprintk("devinit\n"); strcpy(fbinfo->fix.id, driver_name); @@ -701,8 +699,8 @@ int __init s3c2410fb_probe(struct platform_device *pdev) fbinfo->var.yres_virtual = mach_info->yres.defval; fbinfo->var.bits_per_pixel = mach_info->bpp.defval; - fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) +1; - fbinfo->var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) +1; + fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1; + fbinfo->var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) + 1; fbinfo->var.vsync_len = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1; fbinfo->var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1; @@ -746,7 +744,6 @@ int __init s3c2410fb_probe(struct platform_device *pdev) goto release_irq; } - clk_use(info->clk); clk_enable(info->clk); dprintk("got and enabled clock\n"); @@ -783,7 +780,6 @@ free_video_memory: s3c2410fb_unmap_video_memory(info); release_clock: clk_disable(info->clk); - clk_unuse(info->clk); clk_put(info->clk); release_irq: free_irq(irq,info); @@ -828,7 +824,6 @@ static int s3c2410fb_remove(struct platform_device *pdev) if (info->clk) { clk_disable(info->clk); - clk_unuse(info->clk); clk_put(info->clk); info->clk = NULL; } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 2ea1354e439..087e58689e4 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -178,7 +178,6 @@ #include <asm/hardware.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/mach-types.h> #include <asm/uaccess.h> #include <asm/arch/assabet.h> @@ -1455,7 +1454,11 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) static int __init sa1100fb_probe(struct platform_device *pdev) { struct sa1100fb_info *fbi; - int ret; + int ret, irq; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + return -EINVAL; if (!request_mem_region(0xb0100000, 0x10000, "LCD")) return -EBUSY; @@ -1470,7 +1473,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev) if (ret) goto failed; - ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT, + ret = request_irq(irq, sa1100fb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); @@ -1492,7 +1495,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev) ret = register_framebuffer(&fbi->fb); if (ret < 0) - goto failed; + goto err_free_irq; #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = sa1100fb_freq_transition; @@ -1504,7 +1507,9 @@ static int __init sa1100fb_probe(struct platform_device *pdev) /* This driver cannot be unloaded at the moment */ return 0; -failed: + err_free_irq: + free_irq(irq, fbi); + failed: platform_set_drvdata(pdev, NULL); kfree(fbi); release_mem_region(0xb0100000, 0x10000); diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 3c98457783c..00719a91479 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -49,7 +49,7 @@ static void savage4_gpio_setscl(void *data, int val) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; unsigned int r; r = readl(chan->ioaddr + chan->reg); @@ -63,7 +63,7 @@ static void savage4_gpio_setscl(void *data, int val) static void savage4_gpio_setsda(void *data, int val) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; unsigned int r; r = readl(chan->ioaddr + chan->reg); @@ -77,21 +77,21 @@ static void savage4_gpio_setsda(void *data, int val) static int savage4_gpio_getscl(void *data) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN)); } static int savage4_gpio_getsda(void *data) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN)); } static void prosavage_gpio_setscl(void* data, int val) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; u32 r; SET_CR_IX(chan->ioaddr, chan->reg); @@ -107,7 +107,7 @@ static void prosavage_gpio_setscl(void* data, int val) static void prosavage_gpio_setsda(void* data, int val) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; unsigned int r; SET_CR_IX(chan->ioaddr, chan->reg); @@ -123,7 +123,7 @@ static void prosavage_gpio_setsda(void* data, int val) static int prosavage_gpio_getscl(void* data) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; SET_CR_IX(chan->ioaddr, chan->reg); return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN)); @@ -131,7 +131,7 @@ static int prosavage_gpio_getscl(void* data) static int prosavage_gpio_getsda(void* data) { - struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data; + struct savagefb_i2c_chan *chan = data; SET_CR_IX(chan->ioaddr, chan->reg); return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN)); @@ -140,10 +140,9 @@ static int prosavage_gpio_getsda(void* data) static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, const char *name) { - int (*add_bus)(struct i2c_adapter *) = symbol_get(i2c_bit_add_bus); int rc = 0; - if (add_bus && chan->par) { + if (chan->par) { strcpy(chan->adapter.name, name); chan->adapter.owner = THIS_MODULE; chan->adapter.id = I2C_HW_B_SAVAGE; @@ -161,7 +160,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, chan->algo.setscl(chan, 1); udelay(20); - rc = add_bus(&chan->adapter); + rc = i2c_bit_add_bus(&chan->adapter); if (rc == 0) dev_dbg(&chan->par->pcidev->dev, @@ -169,8 +168,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, else dev_warn(&chan->par->pcidev->dev, "Failed to register I2C bus %s.\n", name); - - symbol_put(i2c_bit_add_bus); } else chan->par = NULL; @@ -179,7 +176,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, void savagefb_create_i2c_busses(struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; par->chan.par = par; switch(info->fix.accel) { @@ -193,6 +190,7 @@ void savagefb_create_i2c_busses(struct fb_info *info) par->chan.algo.getscl = prosavage_gpio_getscl; break; case FB_ACCEL_SAVAGE4: + case FB_ACCEL_SAVAGE2000: par->chan.reg = 0xff20; par->chan.ioaddr = par->mmio.vbase; par->chan.algo.setsda = savage4_gpio_setsda; @@ -209,14 +207,10 @@ void savagefb_create_i2c_busses(struct fb_info *info) void savagefb_delete_i2c_busses(struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; - int (*del_bus)(struct i2c_adapter *) = - symbol_get(i2c_bit_del_bus); + struct savagefb_par *par = info->par; - if (del_bus && par->chan.par) { - del_bus(&par->chan.adapter); - symbol_put(i2c_bit_del_bus); - } + if (par->chan.par) + i2c_bit_del_bus(&par->chan.adapter); par->chan.par = NULL; } @@ -224,8 +218,6 @@ void savagefb_delete_i2c_busses(struct fb_info *info) static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan) { u8 start = 0x0; - int (*transfer)(struct i2c_adapter *, struct i2c_msg *, int) = - symbol_get(i2c_transfer); struct i2c_msg msgs[] = { { .addr = SAVAGE_DDC, @@ -239,21 +231,19 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan) }; u8 *buf = NULL; - if (transfer && chan->par) { + if (chan->par) { buf = kmalloc(EDID_LENGTH, GFP_KERNEL); if (buf) { msgs[1].buf = buf; - if (transfer(&chan->adapter, msgs, 2) != 2) { + if (i2c_transfer(&chan->adapter, msgs, 2) != 2) { dev_dbg(&chan->par->pcidev->dev, "Unable to read EDID block.\n"); kfree(buf); buf = NULL; } } - - symbol_put(i2c_transfer); } return buf; diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c index bac8ea3a010..bbcc055d3bb 100644 --- a/drivers/video/savage/savagefb_accel.c +++ b/drivers/video/savage/savagefb_accel.c @@ -21,7 +21,7 @@ static u32 savagefb_rop[] = { int savagefb_sync(struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; par->SavageWaitIdle(par); return 0; @@ -29,7 +29,7 @@ int savagefb_sync(struct fb_info *info) void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int sx = region->sx, dx = region->dx; int sy = region->sy, dy = region->dy; int cmd; @@ -63,7 +63,7 @@ void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region) void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int cmd, color; if (!rect->width || !rect->height) @@ -90,7 +90,7 @@ void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) void savagefb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int fg, bg, size, i, width; int cmd; u32 *src = (u32 *) image->data; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 09e2f284190..ab727eaa7f4 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -686,7 +686,7 @@ static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode static int savagefb_check_var (struct fb_var_screeninfo *var, struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int memlen, vramlen, mode_valid = 0; DBG("savagefb_check_var"); @@ -1025,7 +1025,7 @@ static int savagefb_setcolreg(unsigned regno, unsigned transp, struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; if (regno >= NR_PALETTE) return -EINVAL; @@ -1328,7 +1328,7 @@ static void savagefb_set_fix(struct fb_info *info) #if defined(CONFIG_FB_SAVAGE_ACCEL) static void savagefb_set_clip(struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int cmd; cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW; @@ -1342,7 +1342,7 @@ static void savagefb_set_clip(struct fb_info *info) static int savagefb_set_par (struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; struct fb_var_screeninfo *var = &info->var; int err; @@ -1381,29 +1381,9 @@ static int savagefb_set_par (struct fb_info *info) static int savagefb_pan_display (struct fb_var_screeninfo *var, struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; - u_int y_bottom; - - y_bottom = var->yoffset; - - if (!(var->vmode & FB_VMODE_YWRAP)) - y_bottom += var->yres; - - if (var->xoffset > (var->xres_virtual - var->xres)) - return -EINVAL; - if (y_bottom > info->var.yres_virtual) - return -EINVAL; + struct savagefb_par *par = info->par; savagefb_update_start (par, var); - - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - - if (var->vmode & FB_VMODE_YWRAP) - info->var.vmode |= FB_VMODE_YWRAP; - else - info->var.vmode &= ~FB_VMODE_YWRAP; - return 0; } @@ -1534,7 +1514,7 @@ static void savage_disable_mmio (struct savagefb_par *par) static int __devinit savage_map_mmio (struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; DBG ("savage_map_mmio"); if (S3_SAVAGE3D_SERIES (par->chip)) @@ -1567,7 +1547,7 @@ static int __devinit savage_map_mmio (struct fb_info *info) static void __devinit savage_unmap_mmio (struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; DBG ("savage_unmap_mmio"); savage_disable_mmio(par); @@ -1581,7 +1561,7 @@ static void __devinit savage_unmap_mmio (struct fb_info *info) static int __devinit savage_map_video (struct fb_info *info, int video_len) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int resource; DBG("savage_map_video"); @@ -1619,7 +1599,7 @@ static int __devinit savage_map_video (struct fb_info *info, static void __devinit savage_unmap_video (struct fb_info *info) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; DBG("savage_unmap_video"); @@ -1869,7 +1849,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info, struct pci_dev *dev, const struct pci_device_id *id) { - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct savagefb_par *par = info->par; int err = 0; par->pcidev = dev; @@ -2139,8 +2119,7 @@ static int __devinit savagefb_probe (struct pci_dev* dev, static void __devexit savagefb_remove (struct pci_dev *dev) { - struct fb_info *info = - (struct fb_info *)pci_get_drvdata(dev); + struct fb_info *info = pci_get_drvdata(dev); DBG("savagefb_remove"); @@ -2174,9 +2153,8 @@ static void __devexit savagefb_remove (struct pci_dev *dev) static int savagefb_suspend (struct pci_dev* dev, pm_message_t state) { - struct fb_info *info = - (struct fb_info *)pci_get_drvdata(dev); - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct fb_info *info = pci_get_drvdata(dev); + struct savagefb_par *par = info->par; DBG("savagefb_suspend"); @@ -2210,9 +2188,8 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state) static int savagefb_resume (struct pci_dev* dev) { - struct fb_info *info = - (struct fb_info *)pci_get_drvdata(dev); - struct savagefb_par *par = (struct savagefb_par *)info->par; + struct fb_info *info = pci_get_drvdata(dev); + struct savagefb_par *par = info->par; int cur_state = par->pm_state; DBG("savage_resume"); diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index a01e7ecc15e..9b707771d75 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -115,7 +115,8 @@ static struct fb_fix_screeninfo xxxfb_fix __initdata = { /* * If your driver supports multiple boards or it supports multiple * framebuffers, you should make these arrays, or allocate them - * dynamically (using kmalloc()). + * dynamically using framebuffer_alloc() and free them with + * framebuffer_release(). */ static struct fb_info info; @@ -179,18 +180,31 @@ static int xxxfb_release(const struct fb_info *info, int user) * intent to only test a mode and not actually set it. The stuff in * modedb.c is a example of this. If the var passed in is slightly * off by what the hardware can support then we alter the var PASSED in - * to what we can do. If the hardware doesn't support mode change - * a -EINVAL will be returned by the upper layers. You don't need to - * implement this function then. If you hardware doesn't support - * changing the resolution then this function is not needed. In this - * case the driver woudl just provide a var that represents the static - * state the screen is in. + * to what we can do. + * + * For values that are off, this function must round them _up_ to the + * next value that is supported by the hardware. If the value is + * greater than the highest value supported by the hardware, then this + * function must return -EINVAL. + * + * Exception to the above rule: Some drivers have a fixed mode, ie, + * the hardware is already set at boot up, and cannot be changed. In + * this case, it is more acceptable that this function just return + * a copy of the currently working var (info->var). Better is to not + * implement this function, as the upper layer will do the copying + * of the current var for you. + * + * Note: This is the only function where the contents of var can be + * freely adjusted after the driver has been registered. If you find + * that you have code outside of this function that alters the content + * of var, then you are doing something wrong. Note also that the + * contents of info->var must be left untouched at all times after + * driver registration. * * Returns negative errno on error, or zero on success. */ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - const struct xxx_par *par = (const struct xxx_par *) info->par; /* ... */ return 0; } @@ -204,14 +218,39 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in * fb_info since we are using that data. This means we depend on the * data in var inside fb_info to be supported by the hardware. - * xxxfb_check_var is always called before xxxfb_set_par to ensure this. + * + * This function is also used to recover/restore the hardware to a + * known working state. + * + * xxxfb_check_var is always called before xxxfb_set_par to ensure that + * the contents of var is always valid. + * * Again if you can't change the resolution you don't need this function. * + * However, even if your hardware does not support mode changing, + * a set_par might be needed to at least initialize the hardware to + * a known working state, especially if it came back from another + * process that also modifies the same hardware, such as X. + * + * If this is the case, a combination such as the following should work: + * + * static int xxxfb_check_var(struct fb_var_screeninfo *var, + * struct fb_info *info) + * { + * *var = info->var; + * return 0; + * } + * + * static int xxxfb_set_par(struct fb_info *info) + * { + * init your hardware here + * } + * * Returns negative errno on error, or zero on success. */ static int xxxfb_set_par(struct fb_info *info) { - struct xxx_par *par = (struct xxx_par *) info->par; + struct xxx_par *par = info->par; /* ... */ return 0; } @@ -258,70 +297,110 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, * var->{color}.offset contains start of bitfield * var->{color}.length contains length of bitfield * {hardwarespecific} contains width of DAC - * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset) + * pseudo_palette[X] is programmed to (X << red.offset) | + * (X << green.offset) | + * (X << blue.offset) * RAMDAC[X] is programmed to (red, green, blue) + * color depth = SUM(var->{color}.length) * * Pseudocolor: - * uses offset = 0 && length = DAC register width. * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC - * cmap is not used - * DAC[X] is programmed to (red, green, blue) + * var->{color}.length contains width of DAC or the number of unique + * colors available (color depth) + * pseudo_palette is not used + * RAMDAC[X] is programmed to (red, green, blue) + * color depth = var->{color}.length + * + * Static pseudocolor: + * same as Pseudocolor, but the RAMDAC is not programmed (read-only) + * + * Mono01/Mono10: + * Has only 2 values, black on white or white on black (fg on bg), + * var->{color}.offset is 0 + * white = (1 << var->{color}.length) - 1, black = 0 + * pseudo_palette is not used + * RAMDAC does not exist + * color depth is always 2 + * * Truecolor: * does not use RAMDAC (usually has 3 of them). * var->{color}.offset contains start of bitfield * var->{color}.length contains length of bitfield - * cmap is programmed to (red << red.offset) | (green << green.offset) | - * (blue << blue.offset) | (transp << transp.offset) + * pseudo_palette is programmed to (red << red.offset) | + * (green << green.offset) | + * (blue << blue.offset) | + * (transp << transp.offset) * RAMDAC does not exist + * color depth = SUM(var->{color}.length}) + * + * The color depth is used by fbcon for choosing the logo and also + * for color palette transformation if color depth < 4 + * + * As can be seen from the above, the field bits_per_pixel is _NOT_ + * a criteria for describing the color visual. + * + * A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor, + * and higher than that, true/directcolor. This is incorrect, one needs + * to look at the fix->visual. + * + * Another common mistake is using bits_per_pixel to calculate the color + * depth. The bits_per_pixel field does not directly translate to color + * depth. You have to compute for the color depth (using the color + * bitfields) and fix->visual as seen above. + */ + + /* + * This is the point where the color is converted to something that + * is acceptable by the hardware. */ #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - case FB_VISUAL_PSEUDOCOLOR: - red = CNVT_TOHW(red, info->var.red.length); - green = CNVT_TOHW(green, info->var.green.length); - blue = CNVT_TOHW(blue, info->var.blue.length); - transp = CNVT_TOHW(transp, info->var.transp.length); - break; - case FB_VISUAL_DIRECTCOLOR: - /* example here assumes 8 bit DAC. Might be different - * for your hardware */ - red = CNVT_TOHW(red, 8); - green = CNVT_TOHW(green, 8); - blue = CNVT_TOHW(blue, 8); - /* hey, there is bug in transp handling... */ - transp = CNVT_TOHW(transp, 8); - break; - } + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); #undef CNVT_TOHW - /* Truecolor has hardware independent palette */ - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 v; - - if (regno >= 16) - return -EINVAL; - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset) | - (transp << info->var.transp.offset); - - switch (info->var.bits_per_pixel) { - case 8: - /* Yes some hand held devices have this. */ - ((u8*)(info->pseudo_palette))[regno] = v; - break; - case 16: - ((u16*)(info->pseudo_palette))[regno] = v; - break; - case 24: - case 32: - ((u32*)(info->pseudo_palette))[regno] = v; - break; - } - return 0; + /* + * This is the point where the function feeds the color to the hardware + * palette after converting the colors to something acceptable by + * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and + * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette. + * If you have code that writes to the hardware CLUT, and it's not + * any of the above visuals, then you are doing something wrong. + */ + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR || + info->fix.visual == FB_VISUAL_TRUECOLOR) + write_{red|green|blue|transp}_to_clut(); + + /* This is the point were you need to fill up the contents of + * info->pseudo_palette. This structure is used _only_ by fbcon, thus + * it only contains 16 entries to match the number of colors supported + * by the console. The pseudo_palette is used only if the visual is + * in directcolor or truecolor mode. With other visuals, the + * pseudo_palette is not used. (This might change in the future.) + * + * The contents of the pseudo_palette is in raw pixel format. Ie, each + * entry can be written directly to the framebuffer without any conversion. + * The pseudo_palette is (void *). However, if using the generic + * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette + * must be casted to (u32 *) _regardless_ of the bits per pixel. If the + * driver is using its own drawing functions, then it can use whatever + * size it wants. + */ + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + u32 v; + + if (regno >= 16) + return -EINVAL; + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + + ((u32*)(info->pseudo_palette))[regno] = v; } + /* ... */ return 0; } @@ -340,6 +419,17 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, static int xxxfb_pan_display(struct fb_var_screeninfo *var, const struct fb_info *info) { + /* + * If your hardware does not support panning, _do_ _not_ implement this + * function. Creating a dummy function will just confuse user apps. + */ + + /* + * Note that even if this function is fully functional, a setting of + * 0 in both xpanstep and ypanstep means that this function will never + * get called. + */ + /* ... */ return 0; } @@ -349,15 +439,20 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var, * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer * - * Blank the screen if blank_mode != 0, else unblank. Return 0 if - * blanking succeeded, != 0 if un-/blanking failed due to e.g. a - * video mode which doesn't support it. Implements VESA suspend - * and powerdown modes on hardware that supports disabling hsync/vsync: - * blank_mode == 2: suspend vsync - * blank_mode == 3: suspend hsync - * blank_mode == 4: powerdown + * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank. + * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to + * e.g. a video mode which doesn't support it. * - * Returns negative errno on error, or zero on success. + * Implements VESA suspend and powerdown modes on hardware that supports + * disabling hsync/vsync: + * + * FB_BLANK_NORMAL = display is blanked, syncs are on. + * FB_BLANK_HSYNC_SUSPEND = hsync off + * FB_BLANK_VSYNC_SUSPEND = vsync off + * FB_BLANK_POWERDOWN = hsync and vsync off + * + * If implementing this function, at least support FB_BLANK_UNBLANK. + * Return !0 for any modes that are unimplemented. * */ static int xxxfb_blank(int blank_mode, const struct fb_info *info) @@ -454,6 +549,14 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) * @data: The actual data used to construct the image on the display. * @cmap: The colormap used for color images. */ + +/* + * The generic function, cfb_imageblit, expects that the bitmap scanlines are + * padded to the next byte. Most hardware accelerators may require padding to + * the next u16 or the next u32. If that is the case, the driver can specify + * this by setting info->pixmap.scan_align = 2 or 4. See a more + * comprehensive description of the pixmap below. + */ } /** @@ -517,6 +620,7 @@ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) */ void xxxfb_rotate(struct fb_info *info, int angle) { +/* Will be deprecated */ } /** @@ -540,6 +644,9 @@ void xxxfb_poll(struct fb_info *info, poll_table *wait) * so we can have consistent display output. * * @info: frame buffer structure that represents a single frame buffer + * + * If the driver has implemented its own hardware-based drawing function, + * implementing this function is highly recommended. */ void xxxfb_sync(struct fb_info *info) { @@ -549,20 +656,25 @@ void xxxfb_sync(struct fb_info *info) * Initialization */ -int __init xxxfb_init(void) +/* static int __init xxfb_probe (struct device *device) -- for platform devs */ +static int __init xxxfb_probe(struct pci_dev *dev, + const_struct pci_device_id *ent) { + struct fb_info *info; + struct xxx_par *par; + struct device = &dev->dev; /* for pci drivers */ int cmap_len, retval; /* - * For kernel boot options (in 'video=xxxfb:<options>' format) + * Dynamically allocate info and par */ -#ifndef MODULE - char *option = NULL; + info = framebuffer_alloc(sizeof(struct xxx_par), device); - if (fb_get_options("xxxfb", &option)) - return -ENODEV; - xxxfb_setup(option); -#endif + if (!info) { + /* goto error path */ + } + + par = info->par; /* * Here we set the screen_base to the virtual memory address @@ -570,18 +682,87 @@ int __init xxxfb_init(void) * from the bus layer and then translate it to virtual memory * space via ioremap. Consult ioport.h. */ - info.screen_base = framebuffer_virtual_memory; - info.fbops = &xxxfb_ops; - info.fix = xxxfb_fix; - info.pseudo_palette = pseudo_palette; - + info->screen_base = framebuffer_virtual_memory; + info->fbops = &xxxfb_ops; + info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be + * used, so mark it as __initdata + */ + info->pseudo_palette = pseudo_palette; /* The pseudopalette is an + * 16-member array + */ /* * Set up flags to indicate what sort of acceleration your * driver can provide (pan/wrap/copyarea/etc.) and whether it * is a module -- see FBINFO_* in include/linux/fb.h + * + * If your hardware can support any of the hardware accelerated functions + * fbcon performance will improve if info->flags is set properly. + * + * FBINFO_HWACCEL_COPYAREA - hardware moves + * FBINFO_HWACCEL_FILLRECT - hardware fills + * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion + * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis + * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis + * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled + * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion + * FBINFO_MISC_TILEBLITTING - hardware can do tile blits + * + * NOTE: These are for fbcon use only. + */ + info->flags = FBINFO_DEFAULT; + +/********************* This stage is optional ******************************/ + /* + * The struct pixmap is a scratch pad for the drawing functions. This + * is where the monochrome bitmap is constructed by the higher layers + * and then passed to the accelerator. For drivers that uses + * cfb_imageblit, you can skip this part. For those that have a more + * rigorous requirement, this stage is needed + */ + + /* PIXMAP_SIZE should be small enough to optimize drawing, but not + * large enough that memory is wasted. A safe size is + * (max_xres * max_font_height/8). max_xres is driver dependent, + * max_font_height is 32. + */ + info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); + if (!info->pixmap.addr) { + /* goto error */ + } + + info->pixmap.size = PIXMAP_SIZE; + + /* + * FB_PIXMAP_SYSTEM - memory is in system ram + * FB_PIXMAP_IO - memory is iomapped + * FB_PIXMAP_SYNC - if set, will call fb_sync() per access to pixmap, + * usually if FB_PIXMAP_IO is set. + * + * Currently, FB_PIXMAP_IO is unimplemented. + */ + info->pixmap.flags = FB_PIXMAP_SYSTEM; + + /* + * scan_align is the number of padding for each scanline. It is in bytes. + * Thus for accelerators that need padding to the next u32, put 4 here. + */ + info->pixmap.scan_align = 4; + + /* + * buf_align is the amount to be padded for the buffer. For example, + * the i810fb needs a scan_align of 2 but expects it to be fed with + * dwords, so a buf_align = 4 is required. */ - info.flags = FBINFO_DEFAULT; - info.par = current_par; + info->pixmap.buf_align = 4; + + /* access_align is how many bits can be accessed from the framebuffer + * ie. some epson cards allow 16-bit access only. Most drivers will + * be safe with u32 here. + * + * NOTE: This field is currently unused. + */ + info->pixmap.scan_align = 32 +/***************************** End optional stage ***************************/ /* * This should give a reasonable default video mode. The following is @@ -590,42 +771,145 @@ int __init xxxfb_init(void) if (!mode_option) mode_option = "640x480@60"; - retval = fb_find_mode(&info.var, &info, mode_option, NULL, 0, NULL, 8); + retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8); if (!retval || retval == 4) return -EINVAL; /* This has to been done !!! */ - fb_alloc_cmap(&info.cmap, cmap_len, 0); + fb_alloc_cmap(info->cmap, cmap_len, 0); /* * The following is done in the case of having hardware with a static * mode. If we are setting the mode ourselves we don't call this. */ - info.var = xxxfb_var; - - if (register_framebuffer(&info) < 0) + info->var = xxxfb_var; + + /* + * For drivers that can... + */ + xxxfb_check_var(&info->var, info); + + /* + * Does a call to fb_set_par() before register_framebuffer needed? This + * will depend on you and the hardware. If you are sure that your driver + * is the only device in the system, a call to fb_set_par() is safe. + * + * Hardware in x86 systems has a VGA core. Calling set_par() at this + * point will corrupt the VGA console, so it might be safer to skip a + * call to set_par here and just allow fbcon to do it for you. + */ + /* xxxfb_set_par(info); */ + + if (register_framebuffer(info) < 0) return -EINVAL; - printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node, - info.fix.id); + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + info->fix.id); + pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */ return 0; } /* * Cleanup */ +/* static void __exit xxxfb_remove(struct device *device) */ +static void __exit xxxfb_remove(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drv_data(dev); + /* or dev_get_drv_data(device); */ + + if (info) { + unregister_framebuffer(info); + fb_dealloc_cmap(&info.cmap); + /* ... */ + framebuffer_release(info); + } + + return 0; +} -static void __exit xxxfb_cleanup(void) +#if CONFIG_PCI +/* For PCI drivers */ +static struct pci_driver xxxfb_driver = { + .name = "xxxfb", + .id_table = xxxfb_devices, + .probe = xxxfb_probe, + .remove = __devexit_p(xxxfb_remove), + .suspend = xxxfb_suspend, /* optional */ + .resume = xxxfb_resume, /* optional */ +}; + +static int __init xxxfb_init(void) { - /* - * If your driver supports multiple boards, you should unregister and - * clean up all instances. - */ + /* + * For kernel boot options (in 'video=xxxfb:<options>' format) + */ +#ifndef MODULE + char *option = NULL; - unregister_framebuffer(info); - fb_dealloc_cmap(&info.cmap); - /* ... */ + if (fb_get_options("xxxfb", &option)) + return -ENODEV; + xxxfb_setup(option); +#endif + + return pci_register_driver(&xxxfb_driver); +} + +static void __exit xxxfb_exit(void) +{ + pci_unregister_driver(&xxxfb_driver); } +#else +#include <linux/platform_device.h> +/* for platform devices */ +static struct device_driver xxxfb_driver = { + .name = "xxxfb", + .bus = &platform_bus_type, + .probe = xxxfb_probe, + .remove = xxxfb_remove, + .suspend = xxxfb_suspend, /* optional */ + .resume = xxxfb_resume, /* optional */ +}; + +static struct platform_device xxxfb_device = { + .name = "xxxfb", +}; + +static int __init xxxfb_init(void) +{ + int ret; + /* + * For kernel boot options (in 'video=xxxfb:<options>' format) + */ +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("xxxfb", &option)) + return -ENODEV; + xxxfb_setup(option); +#endif + ret = driver_register(&xxxfb_driver); + + if (!ret) { + ret = platform_device_register(&xxxfb_device); + if (ret) + driver_unregister(&xxxfb_driver); + } + + return ret; +} + +static void __exit xxxfb_exit(void) +{ + platform_device_unregister(&xxxfb_device); + driver_unregister(&xxxfb_driver); +} +#endif + +MODULE_LICENSE("GPL"); +module_init(xxxfb_init); +module_exit(xxxfb_exit); + /* * Setup diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index e0f14df840d..8a5ce210bb2 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -382,7 +382,7 @@ static void sstfb_clear_screen(struct fb_info *info) static int sstfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; int hSyncOff = var->xres + var->right_margin + var->left_margin; int vSyncOff = var->yres + var->lower_margin + var->upper_margin; int vBackPorch = var->left_margin, yDim = var->yres; @@ -542,7 +542,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var, */ static int sstfb_set_par(struct fb_info *info) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0; struct pci_dev *sst_dev = par->dev; unsigned int freq; @@ -748,13 +748,14 @@ static int sstfb_set_par(struct fb_info *info) static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { + struct sstfb_par *par = info->par; u32 col; f_dddprintk("sstfb_setcolreg\n"); f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n", regno, red, green, blue, transp); - if (regno >= 16) - return -EINVAL; + if (regno > 15) + return 0; red >>= (16 - info->var.red.length); green >>= (16 - info->var.green.length); @@ -765,7 +766,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | (blue << info->var.blue.offset) | (transp << info->var.transp.offset); - ((u32 *)info->pseudo_palette)[regno] = col; + par->palette[regno] = col; return 0; } @@ -773,7 +774,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int sstfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, struct fb_info *info ) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; struct pci_dev *sst_dev = par->dev; u32 fbiinit0, tmp, val; u_long p; @@ -830,7 +831,7 @@ static int sstfb_ioctl(struct inode *inode, struct file *file, #if 0 static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; u32 stride = info->fix.line_length; if (!IS_VOODOO2(par)) @@ -855,7 +856,7 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) */ static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; u32 stride = info->fix.line_length; if (!IS_VOODOO2(par)) @@ -925,7 +926,7 @@ static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize) static int __devinit sst_detect_att(struct fb_info *info) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; int i, mir, dir; for (i=0; i<3; i++) { @@ -950,7 +951,7 @@ static int __devinit sst_detect_att(struct fb_info *info) static int __devinit sst_detect_ti(struct fb_info *info) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; int i, mir, dir; for (i = 0; i<3; i++) { @@ -986,7 +987,7 @@ static int __devinit sst_detect_ti(struct fb_info *info) */ static int __devinit sst_detect_ics(struct fb_info *info) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; int m_clk0_1, m_clk0_7, m_clk1_b; int n_clk0_1, n_clk0_7, n_clk1_b; int i; @@ -1023,7 +1024,7 @@ static int __devinit sst_detect_ics(struct fb_info *info) static int sst_set_pll_att_ti(struct fb_info *info, const struct pll_timing *t, const int clock) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; u8 cr0, cc; /* enable indexed mode */ @@ -1077,7 +1078,7 @@ static int sst_set_pll_att_ti(struct fb_info *info, static int sst_set_pll_ics(struct fb_info *info, const struct pll_timing *t, const int clock) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; u8 pll_ctrl; sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL); @@ -1114,7 +1115,7 @@ static int sst_set_pll_ics(struct fb_info *info, static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; u8 cr0; sst_dac_write(DACREG_WMA, 0); /* backdoor */ @@ -1149,7 +1150,7 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp) static void sst_set_vidmod_ics(struct fb_info *info, const int bpp) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; switch(bpp) { case 16: @@ -1308,7 +1309,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par) static void __devexit sst_shutdown(struct fb_info *info) { - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; struct pci_dev *dev = par->dev; struct pll_timing gfx_timings; int Fout; @@ -1394,12 +1395,6 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, struct sst_spec *spec; int err; - struct all_info { - struct fb_info info; - struct sstfb_par par; - u32 pseudo_palette[16]; - } *all; - /* Enable device in PCI config. */ if ((err=pci_enable_device(pdev))) { eprintk("cannot enable device\n"); @@ -1407,14 +1402,13 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, } /* Allocate the fb and par structures. */ - all = kmalloc(sizeof(*all), GFP_KERNEL); - if (!all) + info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev); + if (!info) return -ENOMEM; - memset(all, 0, sizeof(*all)); - pci_set_drvdata(pdev, all); + + pci_set_drvdata(pdev, info); - info = &all->info; - par = info->par = &all->par; + par = info->par; fix = &info->fix; par->type = id->driver_data; @@ -1471,7 +1465,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, info->flags = FBINFO_DEFAULT; info->fbops = &sstfb_ops; - info->pseudo_palette = &all->pseudo_palette; + info->pseudo_palette = par->palette; fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_TRUECOLOR; @@ -1527,7 +1521,7 @@ fail_mmio_remap: fail_fb_mem: release_mem_region(fix->mmio_start, info->fix.mmio_len); fail_mmio_mem: - kfree(info); + framebuffer_release(info); return -ENXIO; /* no voodoo detected */ } @@ -1537,7 +1531,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev) struct fb_info *info; info = pci_get_drvdata(pdev); - par = (struct sstfb_par *) info->par; + par = info->par; sst_shutdown(info); unregister_framebuffer(info); @@ -1545,7 +1539,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev) iounmap(par->mmio_vbase); release_mem_region(info->fix.smem_start, 0x400000); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); - kfree(info); + framebuffer_release(info); } @@ -1613,7 +1607,7 @@ static int sstfb_dump_regs(struct fb_info *info) const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]); const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]); - struct sstfb_par *par = (struct sstfb_par *) info->par; + struct sstfb_par *par = info->par; struct pci_dev *dev = par->dev; u32 pci_res[pci_s]; u32 sst_res[sst_s]; diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 9d53387e6a6..3e7baf4c9fa 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -291,7 +291,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size) static int banshee_wait_idle(struct fb_info *info) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; int i = 0; banshee_make_room(par, 1); @@ -364,7 +364,7 @@ static u32 do_calc_pll(int freq, int* freq_out) static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; int i; banshee_wait_idle(info); @@ -469,7 +469,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 lpitch; if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && @@ -558,7 +558,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info) static int tdfxfb_set_par(struct fb_info *info) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 hdispend, hsyncsta, hsyncend, htotal; u32 hd, hs, he, ht, hbs, hbe; u32 vd, vs, ve, vt, vbs, vbe; @@ -780,7 +780,7 @@ static int tdfxfb_set_par(struct fb_info *info) static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,unsigned transp,struct fb_info *info) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 rgbcol; if (regno >= info->cmap.len || regno > 255) return 1; @@ -794,11 +794,15 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, break; /* Truecolor has no hardware color palettes. */ case FB_VISUAL_TRUECOLOR: - rgbcol = (CNVT_TOHW( red, info->var.red.length) << info->var.red.offset) | - (CNVT_TOHW( green, info->var.green.length) << info->var.green.offset) | - (CNVT_TOHW( blue, info->var.blue.length) << info->var.blue.offset) | - (CNVT_TOHW( transp, info->var.transp.length) << info->var.transp.offset); - ((u32*)(info->pseudo_palette))[regno] = rgbcol; + rgbcol = (CNVT_TOHW( red, info->var.red.length) << + info->var.red.offset) | + (CNVT_TOHW( green, info->var.green.length) << + info->var.green.offset) | + (CNVT_TOHW( blue, info->var.blue.length) << + info->var.blue.offset) | + (CNVT_TOHW( transp, info->var.transp.length) << + info->var.transp.offset); + par->palette[regno] = rgbcol; break; default: DPRINTK("bad depth %u\n", info->var.bits_per_pixel); @@ -810,7 +814,7 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ static int tdfxfb_blank(int blank, struct fb_info *info) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 dacmode, state = 0, vgablank = 0; dacmode = tdfx_inl(par, DACMODE); @@ -855,7 +859,7 @@ static int tdfxfb_blank(int blank, struct fb_info *info) static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 addr; if (nopan || var->xoffset || (var->yoffset > var->yres_virtual)) @@ -878,7 +882,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, */ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 bpp = info->var.bits_per_pixel; u32 stride = info->fix.line_length; u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); @@ -894,7 +898,7 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { tdfx_outl(par, COLORFORE, rect->color); } else { /* FB_VISUAL_TRUECOLOR */ - tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]); + tdfx_outl(par, COLORFORE, par->palette[rect->color]); } tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16)); @@ -906,7 +910,7 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect */ static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy; u32 bpp = info->var.bits_per_pixel; u32 stride = info->fix.line_length; @@ -938,7 +942,7 @@ static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; int size = image->height * ((image->width * image->depth + 7)>>3); int fifo_free; int i, stride = info->fix.line_length; @@ -961,8 +965,10 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) break; case FB_VISUAL_TRUECOLOR: default: - tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[image->fg_color]); - tdfx_outl(par, COLORBACK, ((u32*)(info->pseudo_palette))[image->bg_color]); + tdfx_outl(par, COLORFORE, + par->palette[image->fg_color]); + tdfx_outl(par, COLORBACK, + par->palette[image->bg_color]); } #ifdef __BIG_ENDIAN srcfmt = 0x400000 | BIT(20); @@ -1007,7 +1013,7 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) #ifdef TDFX_HARDWARE_CURSOR static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; unsigned long flags; /* @@ -1157,18 +1163,17 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, { struct tdfx_par *default_par; struct fb_info *info; - int size, err, lpitch; + int err, lpitch; if ((err = pci_enable_device(pdev))) { printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err); return err; } - size = sizeof(struct tdfx_par)+256*sizeof(u32); + info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev); - info = framebuffer_alloc(size, &pdev->dev); - - if (!info) return -ENOMEM; + if (!info) + return -ENOMEM; default_par = info->par; @@ -1248,7 +1253,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, info->fbops = &tdfxfb_ops; info->fix = tdfx_fix; - info->pseudo_palette = (void *)(default_par + 1); + info->pseudo_palette = default_par->palette; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; #ifdef CONFIG_FB_3DFX_ACCEL info->flags |= FBINFO_HWACCEL_FILLRECT | @@ -1307,7 +1312,7 @@ out_err: } #ifndef MODULE -void tdfxfb_setup(char *options) +static void tdfxfb_setup(char *options) { char* this_opt; @@ -1340,7 +1345,7 @@ void tdfxfb_setup(char *options) static void __devexit tdfxfb_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); - struct tdfx_par *par = (struct tdfx_par *) info->par; + struct tdfx_par *par = info->par; unregister_framebuffer(info); iounmap(par->regbase_virt); diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index ce97ec8eae9..2bdeb4baa95 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -342,19 +342,19 @@ int __init valkyriefb_init(void) #else /* ppc (!CONFIG_MAC) */ { struct device_node *dp; + struct resource r; - dp = find_devices("valkyrie"); + dp = of_find_node_by_name(NULL, "valkyrie"); if (dp == 0) return 0; - if (dp->n_addrs != 1) { - printk(KERN_ERR "expecting 1 address for valkyrie (got %d)\n", - dp->n_addrs); + if (of_address_to_resource(dp, 0, &r)) { + printk(KERN_ERR "can't find address for valkyrie\n"); return 0; } - frame_buffer_phys = dp->addrs[0].address; - cmap_regs_phys = dp->addrs[0].address+0x304000; + frame_buffer_phys = r.start; + cmap_regs_phys = r.start + 0x304000; flags = _PAGE_WRITETHRU; } #endif /* ppc (!CONFIG_MAC) */ diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 3e58ddc2bc3..8982e540214 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -57,7 +57,6 @@ static unsigned short *pmi_base = NULL; static void (*pmi_start)(void); static void (*pmi_pal)(void); static int depth; -static int vga_compat; /* --------------------------------------------------------------------- */ @@ -67,15 +66,6 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, #ifdef __i386__ int offset; - if (!ypan) - return -EINVAL; - if (var->xoffset) - return -EINVAL; - if (var->yoffset > var->yres_virtual) - return -EINVAL; - if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual) - return -EINVAL; - offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4; __asm__ __volatile__( @@ -90,37 +80,6 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, return 0; } -static int vesafb_blank(int blank, struct fb_info *info) -{ - int err = 1; - - if (vga_compat) { - int loop = 10000; - u8 seq = 0, crtc17 = 0; - - if (blank == FB_BLANK_POWERDOWN) { - seq = 0x20; - crtc17 = 0x00; - err = 0; - } else { - seq = 0x00; - crtc17 = 0x80; - err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL; - } - - vga_wseq(NULL, 0x00, 0x01); - seq |= vga_rseq(NULL, 0x01) & ~0x20; - vga_wseq(NULL, 0x00, seq); - - crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80; - while (loop--); - vga_wcrt(NULL, 0x17, crtc17); - vga_wseq(NULL, 0x00, 0x03); - } - - return err; -} - static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue) { @@ -205,7 +164,6 @@ static struct fb_ops vesafb_ops = { .owner = THIS_MODULE, .fb_setcolreg = vesafb_setcolreg, .fb_pan_display = vesafb_pan_display, - .fb_blank = vesafb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, @@ -459,9 +417,8 @@ static int __init vesafb_probe(struct platform_device *dev) info->flags = FBINFO_FLAG_DEFAULT | (ypan) ? FBINFO_HWACCEL_YPAN : 0; - vga_compat = (screen_info.capabilities & 2) ? 0 : 1; - printk("vesafb: Mode is %sVGA compatible\n", - (vga_compat) ? "" : "not "); + if (!ypan) + info->fbops->fb_pan_display = NULL; if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { err = -ENOMEM; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 226ae8a8848..f3f16fd9f23 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -705,15 +705,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, static int vga16fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - if (var->xoffset + info->var.xres > info->var.xres_virtual || - var->yoffset + info->var.yres > info->var.yres_virtual) - return -EINVAL; - vga16fb_pan_var(info, var); - - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - info->var.vmode &= ~FB_VMODE_YWRAP; return 0; } diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c index d9e01daee63..15179ec6233 100644 --- a/drivers/video/vgastate.c +++ b/drivers/video/vgastate.c @@ -356,10 +356,11 @@ int save_vga(struct vgastate *state) { struct regstate *saved; - saved = kmalloc(sizeof(struct regstate), GFP_KERNEL); + saved = kzalloc(sizeof(struct regstate), GFP_KERNEL); + if (saved == NULL) return 1; - memset (saved, 0, sizeof(struct regstate)); + state->vidstate = (void *)saved; if (state->flags & VGA_SAVE_CMAP) { |