diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 40 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/aty/aty128fb.c | 31 | ||||
-rw-r--r-- | drivers/video/aty/atyfb_base.c | 22 | ||||
-rw-r--r-- | drivers/video/aty/radeon_backlight.c | 4 | ||||
-rw-r--r-- | drivers/video/aty/radeon_base.c | 18 | ||||
-rw-r--r-- | drivers/video/aty/radeon_pm.c | 146 | ||||
-rw-r--r-- | drivers/video/aty/radeonfb.h | 6 | ||||
-rw-r--r-- | drivers/video/au1100fb.c | 18 | ||||
-rw-r--r-- | drivers/video/backlight/Kconfig | 4 | ||||
-rw-r--r-- | drivers/video/console/mdacon.c | 4 | ||||
-rw-r--r-- | drivers/video/fb_notify.c | 46 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 54 | ||||
-rw-r--r-- | drivers/video/imacfb.c | 49 | ||||
-rw-r--r-- | drivers/video/matrox/g450_pll.c | 8 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_backlight.c | 18 | ||||
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 9 | ||||
-rw-r--r-- | drivers/video/offb.c | 307 | ||||
-rw-r--r-- | drivers/video/riva/fbdev.c | 25 |
19 files changed, 503 insertions, 307 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6533b0f39231..702eb933cf88 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -86,9 +86,11 @@ config FB_MACMODES default n config FB_BACKLIGHT - bool - depends on FB - default n + bool + depends on FB + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default n config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" @@ -420,7 +422,7 @@ config FB_OF config FB_CONTROL bool "Apple \"control\" display support" - depends on (FB = y) && PPC_PMAC + depends on (FB = y) && PPC_PMAC && PPC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -431,7 +433,7 @@ config FB_CONTROL config FB_PLATINUM bool "Apple \"platinum\" display support" - depends on (FB = y) && PPC_PMAC + depends on (FB = y) && PPC_PMAC && PPC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -442,7 +444,7 @@ config FB_PLATINUM config FB_VALKYRIE bool "Apple \"valkyrie\" display support" - depends on (FB = y) && (MAC || PPC_PMAC) + depends on (FB = y) && (MAC || (PPC_PMAC && PPC32)) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -453,7 +455,7 @@ config FB_VALKYRIE config FB_CT65550 bool "Chips 65550 display support" - depends on (FB = y) && PPC + depends on (FB = y) && PPC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -552,7 +554,7 @@ config FB_VESA config FB_IMAC bool "Intel-based Macintosh Framebuffer Support" - depends on (FB = y) && X86 + depends on (FB = y) && X86 && EFI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -721,10 +723,8 @@ config FB_NVIDIA_I2C config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" - depends on FB_NVIDIA && PPC_PMAC + depends on FB_NVIDIA && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -769,10 +769,8 @@ config FB_RIVA_DEBUG config FB_RIVA_BACKLIGHT bool "Support for backlight control" - depends on FB_RIVA && PPC_PMAC + depends on FB_RIVA && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1025,10 +1023,8 @@ config FB_RADEON_I2C config FB_RADEON_BACKLIGHT bool "Support for backlight control" - depends on FB_RADEON && PPC_PMAC + depends on FB_RADEON && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1059,10 +1055,8 @@ config FB_ATY128 config FB_ATY128_BACKLIGHT bool "Support for backlight control" - depends on FB_ATY128 && PPC_PMAC + depends on FB_ATY128 && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1111,10 +1105,8 @@ config FB_ATY_GX config FB_ATY_BACKLIGHT bool "Support for backlight control" - depends on FB_ATY && PPC_PMAC + depends on FB_ATY && PMAC_BACKLIGHT select FB_BACKLIGHT - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1620,7 +1612,7 @@ if FB || SGI_NEWPORT_CONSOLE source "drivers/video/logo/Kconfig" endif -if FB && SYSFS +if SYSFS source "drivers/video/backlight/Kconfig" endif diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 95563c9c6b9c..481c6c9695f8 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -4,6 +4,7 @@ # Each configuration option enables a list of files. +obj-y += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ modedb.o fbcvt.o diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index c64a717e2d4b..276a21530b95 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -455,7 +455,10 @@ static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_idle(struct aty128fb_par *par); static u32 depth_to_dst(u32 depth); + +#ifdef CONFIG_FB_ATY128_BACKLIGHT static void aty128_bl_set_power(struct fb_info *info, int power); +#endif #define BIOS_IN8(v) (readb(bios + (v))) #define BIOS_IN16(v) (readb(bios + (v)) | \ @@ -1798,10 +1801,14 @@ static struct backlight_properties aty128_bl_data = { static void aty128_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty128_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __aty128_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -1825,7 +1832,7 @@ static void aty128_bl_init(struct aty128fb_par *par) bd = backlight_device_register(name, par, &aty128_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("aty128: Backlight registration failed\n"); + printk(KERN_WARNING "aty128: Backlight registration failed\n"); goto error; } @@ -1836,11 +1843,11 @@ static void aty128_bl_init(struct aty128fb_par *par) 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = aty128_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); @@ -1910,9 +1917,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u8 chip_rev; u32 dac; - if (!par->vram_size) /* may have already been probed */ - par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; - /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; @@ -2025,9 +2029,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_init_engine(par); - if (register_framebuffer(info) < 0) - return 0; - par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; @@ -2037,6 +2038,9 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_bl_init(par); #endif + if (register_framebuffer(info) < 0) + return 0; + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); @@ -2086,7 +2090,6 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ par = info->par; info->pseudo_palette = par->pseudo_palette; - info->fix = aty128fb_fix; /* Virtualize mmio region */ info->fix.mmio_start = reg_addr; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 1507d19f481f..19a71f045784 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2200,10 +2200,14 @@ static struct backlight_properties aty_bl_data = { static void aty_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __aty_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -2223,7 +2227,7 @@ static void aty_bl_init(struct atyfb_par *par) bd = backlight_device_register(name, par, &aty_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("aty: Backlight registration failed\n"); + printk(KERN_WARNING "aty: Backlight registration failed\n"); goto error; } @@ -2234,11 +2238,11 @@ static void aty_bl_init(struct atyfb_par *par) 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = aty_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); @@ -2812,7 +2816,7 @@ static int atyfb_blank(int blank, struct fb_info *info) if (par->lock_blank || par->asleep) return 0; -#ifdef CONFIG_PMAC_BACKLIGHT +#ifdef CONFIG_FB_ATY_BACKLIGHT if (machine_is(powermac) && blank > FB_BLANK_NORMAL) aty_bl_set_power(info, FB_BLANK_POWERDOWN); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) @@ -2844,7 +2848,7 @@ static int atyfb_blank(int blank, struct fb_info *info) } aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); -#ifdef CONFIG_PMAC_BACKLIGHT +#ifdef CONFIG_FB_ATY_BACKLIGHT if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) aty_bl_set_power(info, FB_BLANK_UNBLANK); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index 1755dddf1899..585eb7b9e636 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c @@ -195,11 +195,11 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); mutex_unlock(&rinfo->info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = radeon_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 8d85fc58142e..8e3400d5dd21 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -266,6 +266,8 @@ static int force_measure_pll = 0; #ifdef CONFIG_MTRR static int nomtrr = 0; #endif +static int force_sleep; +static int ignore_devlist; /* * prototypes @@ -2327,9 +2329,9 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, /* -2 is special: means ON on mobility chips and do not * change on others */ - radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1); + radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep); } else - radeonfb_pm_init(rinfo, default_dynclk); + radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep); pci_set_drvdata(pdev, info); @@ -2477,6 +2479,12 @@ static int __init radeonfb_setup (char *options) force_measure_pll = 1; } else if (!strncmp(this_opt, "ignore_edid", 11)) { ignore_edid = 1; +#if defined(CONFIG_PM) && defined(CONFIG_X86) + } else if (!strncmp(this_opt, "force_sleep", 11)) { + force_sleep = 1; + } else if (!strncmp(this_opt, "ignore_devlist", 14)) { + ignore_devlist = 1; +#endif } else mode_option = this_opt; } @@ -2532,3 +2540,9 @@ module_param(panel_yres, int, 0); MODULE_PARM_DESC(panel_yres, "int: set panel yres"); module_param(mode_option, charp, 0); MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); +#if defined(CONFIG_PM) && defined(CONFIG_X86) +module_param(force_sleep, bool, 0); +MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware"); +module_param(ignore_devlist, bool, 0); +MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops"); +#endif diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index c7091761cef4..f31e606a2ded 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -27,6 +27,99 @@ #include "ati_ids.h" +static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); + +/* + * Workarounds for bugs in PC laptops: + * - enable D2 sleep in some IBM Thinkpads + * - special case for Samsung P35 + * + * Whitelist by subsystem vendor/device because + * its the subsystem vendor's fault! + */ + +#if defined(CONFIG_PM) && defined(CONFIG_X86) +struct radeon_device_id { + const char *ident; /* (arbitrary) Name */ + const unsigned short subsystem_vendor; /* Subsystem Vendor ID */ + const unsigned short subsystem_device; /* Subsystem Device ID */ + const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */ + const reinit_function_ptr new_reinit_func; /* changed reinit_func */ +}; + +#define BUGFIX(model, sv, sd, pm, fn) { \ + .ident = model, \ + .subsystem_vendor = sv, \ + .subsystem_device = sd, \ + .pm_mode_modifier = pm, \ + .new_reinit_func = fn \ +} + +static struct radeon_device_id radeon_workaround_list[] = { + BUGFIX("IBM Thinkpad R32", + PCI_VENDOR_ID_IBM, 0x1905, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R40", + PCI_VENDOR_ID_IBM, 0x0526, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R40", + PCI_VENDOR_ID_IBM, 0x0527, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R50/R51/T40/T41", + PCI_VENDOR_ID_IBM, 0x0531, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad R51/T40/T41/T42", + PCI_VENDOR_ID_IBM, 0x0530, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad T30", + PCI_VENDOR_ID_IBM, 0x0517, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad T40p", + PCI_VENDOR_ID_IBM, 0x054d, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad T42", + PCI_VENDOR_ID_IBM, 0x0550, + radeon_pm_d2, NULL), + BUGFIX("IBM Thinkpad X31/X32", + PCI_VENDOR_ID_IBM, 0x052f, + radeon_pm_d2, NULL), + BUGFIX("Samsung P35", + PCI_VENDOR_ID_SAMSUNG, 0xc00c, + radeon_pm_off, radeon_reinitialize_M10), + { .ident = NULL } +}; + +static int radeon_apply_workarounds(struct radeonfb_info *rinfo) +{ + struct radeon_device_id *id; + + for (id = radeon_workaround_list; id->ident != NULL; id++ ) + if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) && + (id->subsystem_device == rinfo->pdev->subsystem_device )) { + + /* we found a device that requires workaround */ + printk(KERN_DEBUG "radeonfb: %s detected" + ", enabling workaround\n", id->ident); + + rinfo->pm_mode |= id->pm_mode_modifier; + + if (id->new_reinit_func != NULL) + rinfo->reinit_func = id->new_reinit_func; + + return 1; + } + return 0; /* not found */ +} + +#else /* defined(CONFIG_PM) && defined(CONFIG_X86) */ +static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo) +{ + return 0; +} +#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */ + + + static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) { u32 tmp; @@ -852,18 +945,26 @@ static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo) /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; OUTPLL( pllMCLK_MISC, tmp); - - /* AGP PLL control */ - if (rinfo->family <= CHIP_FAMILY_RV280) { - OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); - OUTREG(BUS_CNTL1, - (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) - | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX - } else { - OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); - OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); + /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset + * and radeon chip dependent. Thus we only enable it on Mac for + * now (until we get more info on how to compute the correct + * value for various X86 bridges). + */ +#ifdef CONFIG_PPC_PMAC + if (machine_is(powermac)) { + /* AGP PLL control */ + if (rinfo->family <= CHIP_FAMILY_RV280) { + OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); + OUTREG(BUS_CNTL1, + (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) + | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX + } else { + OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); + OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); + } } +#endif OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); @@ -2713,7 +2814,7 @@ static void radeonfb_early_resume(void *data) #endif /* CONFIG_PM */ -void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) +void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep) { /* Find PM registers in config space if any*/ rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM); @@ -2729,22 +2830,13 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) } #if defined(CONFIG_PM) +#if defined(CONFIG_PPC_PMAC) /* Check if we can power manage on suspend/resume. We can do * D2 on M6, M7 and M9, and we can resume from D3 cold a few other * "Mac" cards, but that's all. We need more infos about what the * BIOS does tho. Right now, all this PM stuff is pmac-only for that * reason. --BenH */ - /* Special case for Samsung P35 laptops - */ - if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) && - (rinfo->pdev->device == PCI_CHIP_RV350_NP) && - (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) && - (rinfo->pdev->subsystem_device == 0xc00c)) { - rinfo->reinit_func = radeon_reinitialize_M10; - rinfo->pm_mode |= radeon_pm_off; - } -#if defined(CONFIG_PPC_PMAC) if (machine_is(powermac) && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) @@ -2790,6 +2882,18 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) } #endif /* defined(CONFIG_PPC_PMAC) */ #endif /* defined(CONFIG_PM) */ + + if (ignore_devlist) + printk(KERN_DEBUG + "radeonfb: skipping test for device workarounds\n"); + else + radeon_apply_workarounds(rinfo); + + if (force_sleep) { + printk(KERN_DEBUG + "radeonfb: forcefully enabling D2 sleep mode\n"); + rinfo->pm_mode |= radeon_pm_d2; + } } void radeonfb_pm_exit(struct radeonfb_info *rinfo) diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 38657b2d10eb..d5ff224a6258 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -273,6 +273,8 @@ enum radeon_pm_mode { radeon_pm_off = 0x00000002, /* Can resume from D3 cold */ }; +typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo); + struct radeonfb_info { struct fb_info *info; @@ -338,7 +340,7 @@ struct radeonfb_info { int dynclk; int no_schedule; enum radeon_pm_mode pm_mode; - void (*reinit_func)(struct radeonfb_info *rinfo); + reinit_function_ptr reinit_func; /* Lock on register access */ spinlock_t reg_lock; @@ -600,7 +602,7 @@ extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 /* PM Functions */ extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); extern int radeonfb_pci_resume(struct pci_dev *pdev); -extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk); +extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep); extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); /* Monitor probe functions */ diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index a92a91fef16f..f25d5d648333 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -156,7 +156,7 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ - } + } } else { /* mono */ info->fix.visual = FB_VISUAL_MONO10; @@ -164,20 +164,16 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) } info->screen_size = info->fix.line_length * info->var.yres_virtual; + info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \ + >> LCD_CONTROL_SM_BIT) * 90; /* Determine BPP mode and format */ - fbdev->regs->lcd_control = fbdev->panel->control_base | - ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); - - fbdev->regs->lcd_intenable = 0; - fbdev->regs->lcd_intstatus = 0; - + fbdev->regs->lcd_control = fbdev->panel->control_base; fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; - fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; - fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; - + fbdev->regs->lcd_intenable = 0; + fbdev->regs->lcd_intstatus = 0; fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); if (panel_is_dual(fbdev->panel)) { @@ -206,6 +202,8 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) /* Resume controller */ fbdev->regs->lcd_control |= LCD_CONTROL_GO; + mdelay(10); + au1100fb_fb_blank(VESA_NO_BLANKING, info); return 0; } diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 022f9d3473f5..02f15297a021 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -10,7 +10,7 @@ menuconfig BACKLIGHT_LCD_SUPPORT config BACKLIGHT_CLASS_DEVICE tristate "Lowlevel Backlight controls" - depends on BACKLIGHT_LCD_SUPPORT && FB + depends on BACKLIGHT_LCD_SUPPORT default m help This framework adds support for low-level control of the LCD @@ -26,7 +26,7 @@ config BACKLIGHT_DEVICE config LCD_CLASS_DEVICE tristate "Lowlevel LCD controls" - depends on BACKLIGHT_LCD_SUPPORT && FB + depends on BACKLIGHT_LCD_SUPPORT default m help This framework adds support for low-level control of LCD. diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 52ed12b12acc..eb4d03fa5391 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -197,7 +197,7 @@ static int __init mdacon_setup(char *str) __setup("mdacon=", mdacon_setup); #endif -static int __init mda_detect(void) +static int mda_detect(void) { int count=0; u16 *p, p_save; @@ -282,7 +282,7 @@ static int __init mda_detect(void) return 1; } -static void __init mda_initialize(void) +static void mda_initialize(void) { write_mda_b(97, 0x00); /* horizontal total */ write_mda_b(80, 0x01); /* horizontal displayed */ diff --git a/drivers/video/fb_notify.c b/drivers/video/fb_notify.c new file mode 100644 index 000000000000..8c020389e4fa --- /dev/null +++ b/drivers/video/fb_notify.c @@ -0,0 +1,46 @@ +/* + * linux/drivers/video/fb_notify.c + * + * Copyright (C) 2006 Antonino Daplas <adaplas@pol.net> + * + * 2001 - Documented with DocBook + * - Brad Douglas <brad@neruo.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ +#include <linux/fb.h> +#include <linux/notifier.h> + +static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); + +/** + * fb_register_client - register a client notifier + * @nb: notifier block to callback on events + */ +int fb_register_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&fb_notifier_list, nb); +} +EXPORT_SYMBOL(fb_register_client); + +/** + * fb_unregister_client - unregister a client notifier + * @nb: notifier block to callback on events + */ +int fb_unregister_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&fb_notifier_list, nb); +} +EXPORT_SYMBOL(fb_unregister_client); + +/** + * fb_notifier_call_chain - notify clients of fb_events + * + */ +int fb_notifier_call_chain(unsigned long val, void *v) +{ + return blocking_notifier_call_chain(&fb_notifier_list, val, v); +} +EXPORT_SYMBOL_GPL(fb_notifier_call_chain); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 4fc9df426c1a..17961e3ecaa0 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -52,7 +52,6 @@ #define FBPIXMAPSIZE (1024 * 8) -static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); struct fb_info *registered_fb[FB_MAX]; int num_registered_fb; @@ -791,8 +790,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) event.info = info; event.data = &mode1; - ret = blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_MODE_DELETE, &event); + ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event); } if (!ret) @@ -837,8 +835,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) info->flags &= ~FBINFO_MISC_USEREVENT; event.info = info; - blocking_notifier_call_chain(&fb_notifier_list, - evnt, &event); + fb_notifier_call_chain(evnt, &event); } } } @@ -861,8 +858,7 @@ fb_blank(struct fb_info *info, int blank) event.info = info; event.data = ␣ - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_BLANK, &event); + fb_notifier_call_chain(FB_EVENT_BLANK, &event); } return ret; @@ -933,8 +929,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, con2fb.framebuffer = -1; event.info = info; event.data = &con2fb; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_GET_CONSOLE_MAP, &event); + fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; case FBIOPUT_CON2FBMAP: @@ -952,9 +947,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EINVAL; event.info = info; event.data = &con2fb; - return blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_SET_CONSOLE_MAP, - &event); + return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, + &event); case FBIOBLANK: acquire_console_sem(); info->flags |= FBINFO_MISC_USEREVENT; @@ -1330,8 +1324,7 @@ register_framebuffer(struct fb_info *fb_info) registered_fb[i] = fb_info; event.info = fb_info; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_FB_REGISTERED, &event); + fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); return 0; } @@ -1365,30 +1358,11 @@ unregister_framebuffer(struct fb_info *fb_info) fb_cleanup_class_device(fb_info); class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_FB_UNREGISTERED, &event); + fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); return 0; } /** - * fb_register_client - register a client notifier - * @nb: notifier block to callback on events - */ -int fb_register_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&fb_notifier_list, nb); -} - -/** - * fb_unregister_client - unregister a client notifier - * @nb: notifier block to callback on events - */ -int fb_unregister_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&fb_notifier_list, nb); -} - -/** * fb_set_suspend - low level driver signals suspend * @info: framebuffer affected * @state: 0 = resuming, !=0 = suspending @@ -1403,13 +1377,11 @@ void fb_set_suspend(struct fb_info *info, int state) event.info = info; if (state) { - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_SUSPEND, &event); + fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); info->state = FBINFO_STATE_SUSPENDED; } else { info->state = FBINFO_STATE_RUNNING; - blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_RESUME, &event); + fb_notifier_call_chain(FB_EVENT_RESUME, &event); } } @@ -1480,9 +1452,7 @@ int fb_new_modelist(struct fb_info *info) if (!list_empty(&info->modelist)) { event.info = info; - err = blocking_notifier_call_chain(&fb_notifier_list, - FB_EVENT_NEW_MODELIST, - &event); + err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); } return err; @@ -1594,8 +1564,6 @@ EXPORT_SYMBOL(fb_blank); EXPORT_SYMBOL(fb_pan_display); EXPORT_SYMBOL(fb_get_buffer_offset); EXPORT_SYMBOL(fb_set_suspend); -EXPORT_SYMBOL(fb_register_client); -EXPORT_SYMBOL(fb_unregister_client); EXPORT_SYMBOL(fb_get_options); MODULE_LICENSE("GPL"); diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c index ff233b84dec4..18ea4a549105 100644 --- a/drivers/video/imacfb.c +++ b/drivers/video/imacfb.c @@ -18,6 +18,8 @@ #include <linux/screen_info.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/dmi.h> +#include <linux/efi.h> #include <asm/io.h> @@ -28,7 +30,7 @@ typedef enum _MAC_TYPE { M_I20, M_MINI, M_MACBOOK, - M_NEW + M_UNKNOWN } MAC_TYPE; /* --------------------------------------------------------------------- */ @@ -52,10 +54,36 @@ static struct fb_fix_screeninfo imacfb_fix __initdata = { }; static int inverse; -static int model = M_NEW; +static int model = M_UNKNOWN; static int manual_height; static int manual_width; +static int set_system(struct dmi_system_id *id) +{ + printk(KERN_INFO "imacfb: %s detected - set system to %ld\n", + id->ident, (long)id->driver_data); + + model = (long)id->driver_data; + + return 0; +} + +static struct dmi_system_id __initdata dmi_system_table[] = { + { set_system, "iMac4,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17}, + { set_system, "MacBookPro1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17}, + { set_system, "MacBook1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK}, + { set_system, "Macmini1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI}, + {}, +}; + #define DEFAULT_FB_MEM 1024*1024*16 /* --------------------------------------------------------------------- */ @@ -149,7 +177,6 @@ static int __init imacfb_probe(struct platform_device *dev) screen_info.lfb_linelength = 1472 * 4; screen_info.lfb_base = 0x80010000; break; - case M_NEW: case M_I20: screen_info.lfb_width = 1680; screen_info.lfb_height = 1050; @@ -207,6 +234,10 @@ static int __init imacfb_probe(struct platform_device *dev) size_remap = size_total; imacfb_fix.smem_len = size_remap; +#ifndef __i386__ + screen_info.imacpm_seg = 0; +#endif + if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { printk(KERN_WARNING "imacfb: cannot reserve video memory at 0x%lx\n", @@ -324,8 +355,16 @@ static int __init imacfb_init(void) int ret; char *option = NULL; - /* ignore error return of fb_get_options */ - fb_get_options("imacfb", &option); + if (!efi_enabled) + return -ENODEV; + if (!dmi_check_system(dmi_system_table)) + return -ENODEV; + if (model == M_UNKNOWN) + return -ENODEV; + + if (fb_get_options("imacfb", &option)) + return -ENODEV; + imacfb_setup(option); ret = platform_driver_register(&imacfb_driver); diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c index 440272ad10e7..7c76e079ca7d 100644 --- a/drivers/video/matrox/g450_pll.c +++ b/drivers/video/matrox/g450_pll.c @@ -331,7 +331,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, tmp |= M1064_XPIXCLKCTRL_PLL_UP; } matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); +#ifdef __powerpc__ + /* This is necessary to avoid jitter on PowerPC + * (OpenFirmware) systems, but apparently + * introduces jitter, at least on a x86-64 + * using DVI. + * A simple workaround is disable for non-PPC. + */ matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0); +#endif /* __powerpc__ */ matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl); matroxfb_DAC_unlock_irqrestore(flags); diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index b45f577094ac..5b75ae4e9457 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c @@ -113,10 +113,14 @@ static struct backlight_properties nvidia_bl_data = { void nvidia_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __nvidia_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __nvidia_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -140,7 +144,7 @@ void nvidia_bl_init(struct nvidia_par *par) bd = backlight_device_register(name, par, &nvidia_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("nvidia: Backlight registration failed\n"); + printk(KERN_WARNING "nvidia: Backlight registration failed\n"); goto error; } @@ -151,11 +155,11 @@ void nvidia_bl_init(struct nvidia_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = nvidia_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 9f2066f0745a..d4f850117874 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -34,10 +34,6 @@ #include "nv_proto.h" #include "nv_dma.h" -#ifndef CONFIG_PCI /* sanity check */ -#error This driver requires PCI support. -#endif - #undef CONFIG_FB_NVIDIA_DEBUG #ifdef CONFIG_FB_NVIDIA_DEBUG #define NVTRACE printk @@ -1303,20 +1299,19 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, nvidia_save_vga(par, &par->SavedReg); + pci_set_drvdata(pd, info); + nvidia_bl_init(par); if (register_framebuffer(info) < 0) { printk(KERN_ERR PFX "error registering nVidia framebuffer\n"); goto err_out_iounmap_fb; } - pci_set_drvdata(pd, info); printk(KERN_INFO PFX "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", info->fix.id, par->FbMapSize / (1024 * 1024), info->fix.smem_start); - nvidia_bl_init(par); - NVTRACE_LEAVE(); return 0; diff --git a/drivers/video/offb.c b/drivers/video/offb.c index ce5f3031b99b..0013311e0564 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -62,8 +62,6 @@ struct offb_par default_par; * Interface used by the world */ -int offb_init(void); - static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int offb_blank(int blank, struct fb_info *info); @@ -72,11 +70,6 @@ static int offb_blank(int blank, struct fb_info *info); extern boot_infos_t *boot_infos; #endif -static void offb_init_nodriver(struct device_node *); -static void offb_init_fb(const char *name, const char *full_name, - int width, int height, int depth, int pitch, - unsigned long address, struct device_node *dp); - static struct fb_ops offb_ops = { .owner = THIS_MODULE, .fb_setcolreg = offb_setcolreg, @@ -229,123 +222,17 @@ static int offb_blank(int blank, struct fb_info *info) return 0; } - /* - * Initialisation - */ -int __init offb_init(void) +static void __iomem *offb_map_reg(struct device_node *np, int index, + unsigned long offset, unsigned long size) { - struct device_node *dp = NULL, *boot_disp = NULL; - - if (fb_get_options("offb", NULL)) - return -ENODEV; + struct resource r; - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - get_property(dp, "linux,boot-display", NULL)) { - boot_disp = dp; - offb_init_nodriver(dp); - } - } - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - dp != boot_disp) - offb_init_nodriver(dp); - } - - return 0; -} - - -static void __init offb_init_nodriver(struct device_node *dp) -{ - unsigned int len; - int i, width = 640, height = 480, depth = 8, pitch = 640; - unsigned int flags, rsize, addr_prop = 0; - unsigned long max_size = 0; - u64 rstart, address = OF_BAD_ADDR; - u32 *pp, *addrp, *up; - u64 asize; - - pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "depth", &len); - if (pp && len == sizeof(u32)) - depth = *pp; - - pp = (u32 *)get_property(dp, "linux,bootx-width", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "width", &len); - if (pp && len == sizeof(u32)) - width = *pp; - - pp = (u32 *)get_property(dp, "linux,bootx-height", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "height", &len); - if (pp && len == sizeof(u32)) - height = *pp; - - pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); - if (pp == NULL) - pp = (u32 *)get_property(dp, "linebytes", &len); - if (pp && len == sizeof(u32)) - pitch = *pp; - else - pitch = width * ((depth + 7) / 8); - - rsize = (unsigned long)pitch * (unsigned long)height; - - /* Ok, now we try to figure out the address of the framebuffer. - * - * Unfortunately, Open Firmware doesn't provide a standard way to do - * so. All we can do is a dodgy heuristic that happens to work in - * practice. On most machines, the "address" property contains what - * we need, though not on Matrox cards found in IBM machines. What I've - * found that appears to give good results is to go through the PCI - * ranges and pick one that is both big enough and if possible encloses - * the "address" property. If none match, we pick the biggest - */ - up = (u32 *)get_property(dp, "linux,bootx-addr", &len); - if (up == NULL) - up = (u32 *)get_property(dp, "address", &len); - if (up && len == sizeof(u32)) - addr_prop = *up; - - for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) - != NULL; i++) { - int match_addrp = 0; - - if (!(flags & IORESOURCE_MEM)) - continue; - if (asize < rsize) - continue; - rstart = of_translate_address(dp, addrp); - if (rstart == OF_BAD_ADDR) - continue; - if (addr_prop && (rstart <= addr_prop) && - ((rstart + asize) >= (addr_prop + rsize))) - match_addrp = 1; - if (match_addrp) { - address = addr_prop; - break; - } - if (rsize > max_size) { - max_size = rsize; - address = OF_BAD_ADDR; - } - - if (address == OF_BAD_ADDR) - address = rstart; - } - if (address == OF_BAD_ADDR && addr_prop) - address = (u64)addr_prop; - if (address != OF_BAD_ADDR) { - /* kludge for valkyrie */ - if (strcmp(dp->name, "valkyrie") == 0) - address += 0x1000; - offb_init_fb(dp->name, dp->full_name, width, height, depth, - pitch, address, dp); - } + if (of_address_to_resource(np, index, &r)) + return 0; + if ((r.start + offset + size) > r.end) + return 0; + return ioremap(r.start + offset, size); } static void __init offb_init_fb(const char *name, const char *full_name, @@ -402,45 +289,39 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_type = cmap_unknown; if (depth == 8) { - /* Palette hacks disabled for now */ -#if 0 if (dp && !strncmp(name, "ATY,Rage128", 11)) { - unsigned long regbase = dp->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_r128; + par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_r128; } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) || !strncmp(name, "ATY,RageM3p12A", 14))) { - unsigned long regbase = - dp->parent->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_M3A; + par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_M3A; } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { - unsigned long regbase = - dp->parent->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_M3B; + par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_M3B; } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { - unsigned long regbase = dp->addrs[1].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_radeon; + par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); + if (par->cmap_adr) + par->cmap_type = cmap_radeon; } else if (!strncmp(name, "ATY,", 4)) { unsigned long base = address & 0xff000000UL; par->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0; par->cmap_data = par->cmap_adr + 1; par->cmap_type = cmap_m64; - } else if (device_is_compatible(dp, "pci1014,b7")) { - unsigned long regbase = dp->addrs[0].address; - par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); - par->cmap_type = cmap_gxt2000; + } else if (dp && device_is_compatible(dp, "pci1014,b7")) { + par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); + if (par->cmap_adr) + par->cmap_type = cmap_gxt2000; } -#endif - fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_STATIC_PSEUDOCOLOR; + fix->visual = (par->cmap_type != cmap_unknown) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; } else - fix->visual = /* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR - : */ FB_VISUAL_TRUECOLOR; + fix->visual = FB_VISUAL_TRUECOLOR; var->xoffset = var->yoffset = 0; switch (depth) { @@ -520,5 +401,139 @@ static void __init offb_init_fb(const char *name, const char *full_name, info->node, full_name); } + +static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) +{ + unsigned int len; + int i, width = 640, height = 480, depth = 8, pitch = 640; + unsigned int flags, rsize, addr_prop = 0; + unsigned long max_size = 0; + u64 rstart, address = OF_BAD_ADDR; + u32 *pp, *addrp, *up; + u64 asize; + + pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "depth", &len); + if (pp && len == sizeof(u32)) + depth = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-width", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "width", &len); + if (pp && len == sizeof(u32)) + width = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-height", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "height", &len); + if (pp && len == sizeof(u32)) + height = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "linebytes", &len); + if (pp && len == sizeof(u32)) + pitch = *pp; + else + pitch = width * ((depth + 7) / 8); + + rsize = (unsigned long)pitch * (unsigned long)height; + + /* Ok, now we try to figure out the address of the framebuffer. + * + * Unfortunately, Open Firmware doesn't provide a standard way to do + * so. All we can do is a dodgy heuristic that happens to work in + * practice. On most machines, the "address" property contains what + * we need, though not on Matrox cards found in IBM machines. What I've + * found that appears to give good results is to go through the PCI + * ranges and pick one that is both big enough and if possible encloses + * the "address" property. If none match, we pick the biggest + */ + up = (u32 *)get_property(dp, "linux,bootx-addr", &len); + if (up == NULL) + up = (u32 *)get_property(dp, "address", &len); + if (up && len == sizeof(u32)) + addr_prop = *up; + + /* Hack for when BootX is passing us */ + if (no_real_node) + goto skip_addr; + + for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) + != NULL; i++) { + int match_addrp = 0; + + if (!(flags & IORESOURCE_MEM)) + continue; + if (asize < rsize) + continue; + rstart = of_translate_address(dp, addrp); + if (rstart == OF_BAD_ADDR) + continue; + if (addr_prop && (rstart <= addr_prop) && + ((rstart + asize) >= (addr_prop + rsize))) + match_addrp = 1; + if (match_addrp) { + address = addr_prop; + break; + } + if (rsize > max_size) { + max_size = rsize; + address = OF_BAD_ADDR; + } + + if (address == OF_BAD_ADDR) + address = rstart; + } + skip_addr: + if (address == OF_BAD_ADDR && addr_prop) + address = (u64)addr_prop; + if (address != OF_BAD_ADDR) { + /* kludge for valkyrie */ + if (strcmp(dp->name, "valkyrie") == 0) + address += 0x1000; + offb_init_fb(no_real_node ? "bootx" : dp->name, + no_real_node ? "display" : dp->full_name, + width, height, depth, pitch, address, + no_real_node ? dp : NULL); + } +} + +static int __init offb_init(void) +{ + struct device_node *dp = NULL, *boot_disp = NULL; + + if (fb_get_options("offb", NULL)) + return -ENODEV; + + /* Check if we have a MacOS display without a node spec */ + if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) { + /* The old code tried to work out which node was the MacOS + * display based on the address. I'm dropping that since the + * lack of a node spec only happens with old BootX versions + * (users can update) and with this code, they'll still get + * a display (just not the palette hacks). + */ + offb_init_nodriver(of_chosen, 1); + } + + for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { + if (get_property(dp, "linux,opened", NULL) && + get_property(dp, "linux,boot-display", NULL)) { + boot_disp = dp; + offb_init_nodriver(dp, 0); + } + } + for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { + if (get_property(dp, "linux,opened", NULL) && + dp != boot_disp) + offb_init_nodriver(dp, 0); + } + + return 0; +} + + module_init(offb_init); MODULE_LICENSE("GPL"); diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 33dddbae5420..8ddb47a56b07 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -355,10 +355,14 @@ static struct backlight_properties riva_bl_data = { static void riva_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - up(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __riva_bl_update_status(info->bl_dev); - down(&info->bl_dev->sem); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __riva_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); } @@ -382,7 +386,7 @@ static void riva_bl_init(struct riva_par *par) bd = backlight_device_register(name, par, &riva_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk("riva: Backlight registration failed\n"); + printk(KERN_WARNING "riva: Backlight registration failed\n"); goto error; } @@ -393,11 +397,11 @@ static void riva_bl_init(struct riva_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - up(&bd->sem); + down(&bd->sem); bd->props->brightness = riva_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - down(&bd->sem); + up(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); @@ -2132,6 +2136,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd, fb_destroy_modedb(info->monspecs.modedb); info->monspecs.modedb = NULL; + + pci_set_drvdata(pd, info); + riva_bl_init(info->par); ret = register_framebuffer(info); if (ret < 0) { printk(KERN_ERR PFX @@ -2139,8 +2146,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd, goto err_iounmap_screen_base; } - pci_set_drvdata(pd, info); - printk(KERN_INFO PFX "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n", info->fix.id, @@ -2148,8 +2153,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd, info->fix.smem_len / (1024 * 1024), info->fix.smem_start); - riva_bl_init(info->par); - NVTRACE_LEAVE(); return 0; |