aboutsummaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/backlight/Kconfig18
-rw-r--r--drivers/video/backlight/Makefile2
-rw-r--r--drivers/video/backlight/backlight.c3
-rw-r--r--drivers/video/backlight/jornada720_bl.c161
-rw-r--r--drivers/video/backlight/jornada720_lcd.c153
-rw-r--r--drivers/video/backlight/lcd.c3
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c191
-rw-r--r--drivers/video/backlight/pwm_bl.c4
-rw-r--r--drivers/video/cirrusfb.c4
-rw-r--r--drivers/video/console/fbcon.c55
-rw-r--r--drivers/video/efifb.c7
-rw-r--r--drivers/video/fbmem.c19
-rw-r--r--drivers/video/intelfb/intelfb.h2
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c1
-rw-r--r--drivers/video/intelfb/intelfbhw.c5
-rw-r--r--drivers/video/mx3fb.c56
-rw-r--r--drivers/video/s3fb.c6
-rw-r--r--drivers/video/sa1100fb.c15
-rw-r--r--drivers/video/sa1100fb.h7
-rw-r--r--drivers/video/sis/sis_main.c2
-rw-r--r--drivers/video/skeletonfb.c8
-rw-r--r--drivers/video/tdfxfb.c267
-rw-r--r--drivers/video/uvesafb.c35
-rw-r--r--drivers/video/vfb.c11
27 files changed, 872 insertions, 177 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index ffe2f2796e2..7826bdce4bb 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1550,6 +1550,7 @@ config FB_3DFX
select FB_CFB_IMAGEBLIT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
+ select FB_MODE_HELPERS
help
This driver supports graphics boards with the 3Dfx Banshee,
Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
@@ -1565,6 +1566,14 @@ config FB_3DFX_ACCEL
This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
device driver with acceleration functions.
+config FB_3DFX_I2C
+ bool "Enable DDC/I2C support"
+ depends on FB_3DFX && EXPERIMENTAL
+ select FB_DDC
+ default y
+ help
+ Say Y here if you want DDC/I2C support for your 3dfx Voodoo3.
+
config FB_VOODOO1
tristate "3Dfx Voodoo Graphics (sst1) support"
depends on FB && PCI
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 16bb7e3c031..6c37e8ee5ef 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -698,8 +698,8 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
found:
/*
* Some methods fail to retrieve SCLK and MCLK values, we apply default
- * settings in this case (200Mhz). If that really happne often, we could
- * fetch from registers instead...
+ * settings in this case (200Mhz). If that really happens often, we
+ * could fetch from registers instead...
*/
if (rinfo->pll.mclk == 0)
rinfo->pll.mclk = 20000;
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 72facb9eb7d..f9d19be0554 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -84,6 +84,15 @@ config LCD_TOSA
If you have an Sharp SL-6000 Zaurus say Y to enable a driver
for its LCD.
+config LCD_HP700
+ tristate "HP Jornada 700 series LCD Driver"
+ depends on LCD_CLASS_DEVICE
+ depends on SA1100_JORNADA720_SSP && !PREEMPT
+ default y
+ help
+ If you have an HP Jornada 700 series handheld (710/720/728)
+ say Y to enable LCD control driver.
+
#
# Backlight
#
@@ -157,6 +166,15 @@ config BACKLIGHT_HP680
If you have a HP Jornada 680, say y to enable the
backlight driver.
+config BACKLIGHT_HP700
+ tristate "HP Jornada 700 series Backlight Driver"
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on SA1100_JORNADA720_SSP && !PREEMPT
+ default y
+ help
+ If you have an HP Jornada 700 series,
+ say Y to include backlight control driver.
+
config BACKLIGHT_PROGEAR
tristate "Frontpath ProGear Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE && PCI && X86
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 63d75949816..4eb178c1d68 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -2,6 +2,7 @@
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
+obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
obj-$(CONFIG_LCD_ILI9320) += ili9320.o
obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
+obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index dd37cbcaf8c..157057c79ca 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -35,8 +35,6 @@ static int fb_notifier_callback(struct notifier_block *self,
return 0;
bd = container_of(self, struct backlight_device, fb_notif);
- if (!lock_fb_info(evdata->info))
- return -ENODEV;
mutex_lock(&bd->ops_lock);
if (bd->ops)
if (!bd->ops->check_fb ||
@@ -49,7 +47,6 @@ static int fb_notifier_callback(struct notifier_block *self,
backlight_update_status(bd);
}
mutex_unlock(&bd->ops_lock);
- unlock_fb_info(evdata->info);
return 0;
}
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
new file mode 100644
index 00000000000..c3ebb6b41ce
--- /dev/null
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -0,0 +1,161 @@
+/*
+ *
+ * Backlight driver for HP Jornada 700 series (710/720/728)
+ * Copyright (C) 2006-2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 or any later version as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <mach/jornada720.h>
+#include <mach/hardware.h>
+
+#include <video/s1d13xxxfb.h>
+
+#define BL_MAX_BRIGHT 255
+#define BL_DEF_BRIGHT 25
+
+static int jornada_bl_get_brightness(struct backlight_device *bd)
+{
+ int ret;
+
+ /* check if backlight is on */
+ if (!(PPSR & PPC_LDD1))
+ return 0;
+
+ jornada_ssp_start();
+
+ /* cmd should return txdummy */
+ ret = jornada_ssp_byte(GETBRIGHTNESS);
+
+ if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
+ printk(KERN_ERR "bl : get brightness timeout\n");
+ jornada_ssp_end();
+ return -ETIMEDOUT;
+ } else /* exchange txdummy for value */
+ ret = jornada_ssp_byte(TXDUMMY);
+
+ jornada_ssp_end();
+
+ return (BL_MAX_BRIGHT - ret);
+}
+
+static int jornada_bl_update_status(struct backlight_device *bd)
+{
+ int ret = 0;
+
+ jornada_ssp_start();
+
+ /* If backlight is off then really turn it off */
+ if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
+ ret = jornada_ssp_byte(BRIGHTNESSOFF);
+ if (ret != TXDUMMY) {
+ printk(KERN_INFO "bl : brightness off timeout\n");
+ /* turn off backlight */
+ PPSR &= ~PPC_LDD1;
+ PPDR |= PPC_LDD1;
+ ret = -ETIMEDOUT;
+ }
+ } else /* turn on backlight */
+ PPSR |= PPC_LDD1;
+
+ /* send command to our mcu */
+ if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
+ printk(KERN_INFO "bl : failed to set brightness\n");
+ ret = -ETIMEDOUT;
+ goto out
+ }
+
+ /* at this point we expect that the mcu has accepted
+ our command and is waiting for our new value
+ please note that maximum brightness is 255,
+ but due to physical layout it is equal to 0, so we simply
+ invert the value (MAX VALUE - NEW VALUE). */
+ if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
+ printk(KERN_ERR "bl : set brightness failed\n");
+ ret = -ETIMEDOUT;
+ }
+
+ /* If infact we get an TXDUMMY as output we are happy and dont
+ make any further comments about it */
+out:
+ jornada_ssp_end();
+
+ return ret;
+}
+
+static struct backlight_ops jornada_bl_ops = {
+ .get_brightness = jornada_bl_get_brightness,
+ .update_status = jornada_bl_update_status,
+ .options = BL_CORE_SUSPENDRESUME,
+};
+
+static int jornada_bl_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct backlight_device *bd;
+
+ bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_bl_ops);
+
+ if (IS_ERR(bd)) {
+ ret = PTR_ERR(bd);
+ printk(KERN_ERR "bl : failed to register device, err=%x\n", ret);
+ return ret;
+ }
+
+ bd->props.power = FB_BLANK_UNBLANK;
+ bd->props.brightness = BL_DEF_BRIGHT;
+ /* note. make sure max brightness is set otherwise
+ you will get seemingly non-related errors when
+ trying to change brightness */
+ bd->props.max_brightness = BL_MAX_BRIGHT;
+ jornada_bl_update_status(bd);
+
+ platform_set_drvdata(pdev, bd);
+ printk(KERN_INFO "HP Jornada 700 series backlight driver\n");
+
+ return 0;
+}
+
+static int jornada_bl_remove(struct platform_device *pdev)
+{
+ struct backlight_device *bd = platform_get_drvdata(pdev);
+
+ backlight_device_unregister(bd);
+
+ return 0;
+}
+
+static struct platform_driver jornada_bl_driver = {
+ .probe = jornada_bl_probe,
+ .remove = jornada_bl_remove,
+ .driver = {
+ .name = "jornada_bl",
+ },
+};
+
+int __init jornada_bl_init(void)
+{
+ return platform_driver_register(&jornada_bl_driver);
+}
+
+void __exit jornada_bl_exit(void)
+{
+ platform_driver_unregister(&jornada_bl_driver);
+}
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
+MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
+MODULE_LICENSE("GPL");
+
+module_init(jornada_bl_init);
+module_exit(jornada_bl_exit);
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
new file mode 100644
index 00000000000..cbbb167fd26
--- /dev/null
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -0,0 +1,153 @@
+/*
+ *
+ * LCD driver for HP Jornada 700 series (710/720/728)
+ * Copyright (C) 2006-2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 or any later version as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/jornada720.h>
+#include <mach/hardware.h>
+
+#include <video/s1d13xxxfb.h>
+
+#define LCD_MAX_CONTRAST 0xff
+#define LCD_DEF_CONTRAST 0x80
+
+static int jornada_lcd_get_power(struct lcd_device *dev)
+{
+ /* LDD2 in PPC = LCD POWER */
+ if (PPSR & PPC_LDD2)
+ return FB_BLANK_UNBLANK; /* PW ON */
+ else
+ return FB_BLANK_POWERDOWN; /* PW OFF */
+}
+
+static int jornada_lcd_get_contrast(struct lcd_device *dev)
+{
+ int ret;
+
+ if (jornada_lcd_get_power(dev) != FB_BLANK_UNBLANK)
+ return 0;
+
+ jornada_ssp_start();
+
+ if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
+ printk(KERN_ERR "lcd: get contrast failed\n");
+ jornada_ssp_end();
+ return -ETIMEDOUT;
+ } else {
+ ret = jornada_ssp_byte(TXDUMMY);
+ jornada_ssp_end();
+ return ret;
+ }
+}
+
+static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
+{
+ int ret;
+
+ jornada_ssp_start();
+
+ /* start by sending our set contrast cmd to mcu */
+ ret = jornada_ssp_byte(SETCONTRAST);
+
+ /* push the new value */
+ if (jornada_ssp_byte(value) != TXDUMMY) {
+ printk(KERN_ERR "lcd : set contrast failed\n");
+ jornada_ssp_end();
+ return -ETIMEDOUT;
+ }
+
+ /* if we get here we can assume everything went well */
+ jornada_ssp_end();
+
+ return 0;
+}
+
+static int jornada_lcd_set_power(struct lcd_device *dev, int power)
+{
+ if (power != FB_BLANK_UNBLANK) {
+ PPSR &= ~PPC_LDD2;
+ PPDR |= PPC_LDD2;
+ } else
+ PPSR |= PPC_LDD2;
+
+ return 0;
+}
+
+static struct lcd_ops jornada_lcd_props = {
+ .get_contrast = jornada_lcd_get_contrast,
+ .set_contrast = jornada_lcd_set_contrast,
+ .get_power = jornada_lcd_get_power,
+ .set_power = jornada_lcd_set_power,
+};
+
+static int jornada_lcd_probe(struct platform_device *pdev)
+{
+ struct lcd_device *lcd_device;
+ int ret;
+
+ lcd_device = lcd_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_lcd_props);
+
+ if (IS_ERR(lcd_device)) {
+ ret = PTR_ERR(lcd_device);
+ printk(KERN_ERR "lcd : failed to register device\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, lcd_device);
+
+ /* lets set our default values */
+ jornada_lcd_set_contrast(lcd_device, LCD_DEF_CONTRAST);
+ jornada_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
+ /* give it some time to startup */
+ msleep(100);
+
+ return 0;
+}
+
+static int jornada_lcd_remove(struct platform_device *pdev)
+{
+ struct lcd_device *lcd_device = platform_get_drvdata(pdev);
+
+ lcd_device_unregister(lcd_device);
+
+ return 0;
+}
+
+static struct platform_driver jornada_lcd_driver = {
+ .probe = jornada_lcd_probe,
+ .remove = jornada_lcd_remove,
+ .driver = {
+ .name = "jornada_lcd",
+ },
+};
+
+int __init jornada_lcd_init(void)
+{
+ return platform_driver_register(&jornada_lcd_driver);
+}
+
+void __exit jornada_lcd_exit(void)
+{
+ platform_driver_unregister(&jornada_lcd_driver);
+}
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver");
+MODULE_LICENSE("GPL");
+
+module_init(jornada_lcd_init);
+module_exit(jornada_lcd_exit);
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 0bb13df0fa8..b6449470106 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -40,8 +40,6 @@ static int fb_notifier_callback(struct notifier_block *self,
if (!ld->ops)
return 0;
- if (!lock_fb_info(evdata->info))
- return -ENODEV;
mutex_lock(&ld->ops_lock);
if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
if (event == FB_EVENT_BLANK) {
@@ -53,7 +51,6 @@ static int fb_notifier_callback(struct notifier_block *self,
}
}
mutex_unlock(&ld->ops_lock);
- unlock_fb_info(evdata->info);
return 0;
}
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 65864c50045..3bb4c0a50c6 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -27,73 +27,192 @@
static struct backlight_device *mbp_backlight_device;
-static struct dmi_system_id __initdata mbp_device_table[] = {
+/* Structure to be passed to the DMI_MATCH function. */
+struct dmi_match_data {
+ /* I/O resource to allocate. */
+ unsigned long iostart;
+ unsigned long iolen;
+ /* Backlight operations structure. */
+ struct backlight_ops backlight_ops;
+};
+
+/* Module parameters. */
+static int debug;
+module_param_named(debug, debug, int, 0644);
+MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
+
+/*
+ * Implementation for MacBooks with Intel chipset.
+ */
+static int intel_chipset_send_intensity(struct backlight_device *bd)
+{
+ int intensity = bd->props.brightness;
+
+ if (debug)
+ printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n",
+ intensity);
+
+ outb(0x04 | (intensity << 4), 0xb3);
+ outb(0xbf, 0xb2);
+ return 0;
+}
+
+static int intel_chipset_get_intensity(struct backlight_device *bd)
+{
+ int intensity;
+
+ outb(0x03, 0xb3);
+ outb(0xbf, 0xb2);
+ intensity = inb(0xb3) >> 4;
+
+ if (debug)
+ printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n",
+ intensity);
+
+ return intensity;
+}
+
+static const struct dmi_match_data intel_chipset_data = {
+ .iostart = 0xb2,
+ .iolen = 2,
+ .backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .get_brightness = intel_chipset_get_intensity,
+ .update_status = intel_chipset_send_intensity,
+ }
+};
+
+/*
+ * Implementation for MacBooks with Nvidia chipset.
+ */
+static int nvidia_chipset_send_intensity(struct backlight_device *bd)
+{
+ int intensity = bd->props.brightness;
+
+ if (debug)
+ printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n",
+ intensity);
+
+ outb(0x04 | (intensity << 4), 0x52f);
+ outb(0xbf, 0x52e);
+ return 0;
+}
+
+static int nvidia_chipset_get_intensity(struct backlight_device *bd)
+{
+ int intensity;
+
+ outb(0x03, 0x52f);
+ outb(0xbf, 0x52e);
+ intensity = inb(0x52f) >> 4;
+
+ if (debug)
+ printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n",
+ intensity);
+
+ return intensity;
+}
+
+static const struct dmi_match_data nvidia_chipset_data = {
+ .iostart = 0x52e,
+ .iolen = 2,
+ .backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .get_brightness = nvidia_chipset_get_intensity,
+ .update_status = nvidia_chipset_send_intensity
+ }
+};
+
+/*
+ * DMI matching.
+ */
+static /* const */ struct dmi_match_data *driver_data;
+
+static int mbp_dmi_match(const struct dmi_system_id *id)
+{
+ driver_data = id->driver_data;
+
+ printk(KERN_INFO "mbp_nvidia_bl: %s detected\n", id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id __initdata mbp_device_table[] = {
{
- .ident = "3,1",
- .matches = {
+ .callback = mbp_dmi_match,
+ .ident = "MacBookPro 3,1",
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
},
+ .driver_data = (void *)&intel_chipset_data,
},
{
- .ident = "3,2",
- .matches = {
+ .callback = mbp_dmi_match,
+ .ident = "MacBookPro 3,2",
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
},
+ .driver_data = (void *)&intel_chipset_data,
},
{
- .ident = "4,1",
- .matches = {
+ .callback = mbp_dmi_match,
+ .ident = "MacBookPro 4,1",
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
},
+ .driver_data = (void *)&intel_chipset_data,
+ },
+ {
+ .callback = mbp_dmi_match,
+ .ident = "MacBook 5,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"),
+ },
+ .driver_data = (void *)&nvidia_chipset_data,
+ },
+ {
+ .callback = mbp_dmi_match,
+ .ident = "MacBookAir 2,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"),
+ },
+ .driver_data = (void *)&nvidia_chipset_data,
+ },
+ {
+ .callback = mbp_dmi_match,
+ .ident = "MacBookPro 5,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
+ },
+ .driver_data = (void *)&nvidia_chipset_data,
},
{ }
};
-static int mbp_send_intensity(struct backlight_device *bd)
-{
- int intensity = bd->props.brightness;
-
- outb(0x04 | (intensity << 4), 0xb3);
- outb(0xbf, 0xb2);
-
- return 0;
-}
-
-static int mbp_get_intensity(struct backlight_device *bd)
-{
- outb(0x03, 0xb3);
- outb(0xbf, 0xb2);
- return inb(0xb3) >> 4;
-}
-
-static struct backlight_ops mbp_ops = {
- .options = BL_CORE_SUSPENDRESUME,
- .get_brightness = mbp_get_intensity,
- .update_status = mbp_send_intensity,
-};
-
static int __init mbp_init(void)
{
if (!dmi_check_system(mbp_device_table))
return -ENODEV;
- if (!request_region(0xb2, 2, "Macbook Pro backlight"))
+ if (!request_region(driver_data->iostart, driver_data->iolen,
+ "Macbook Pro backlight"))
return -ENXIO;
mbp_backlight_device = backlight_device_register("mbp_backlight",
- NULL, NULL,
- &mbp_ops);
+ NULL, NULL, &driver_data->backlight_ops);
if (IS_ERR(mbp_backlight_device)) {
- release_region(0xb2, 2);
+ release_region(driver_data->iostart, driver_data->iolen);
return PTR_ERR(mbp_backlight_device);
}
mbp_backlight_device->props.max_brightness = 15;
mbp_backlight_device->props.brightness =
- mbp_get_intensity(mbp_backlight_device);
+ driver_data->backlight_ops.get_brightness(mbp_backlight_device);
backlight_update_status(mbp_backlight_device);
return 0;
@@ -103,7 +222,7 @@ static void __exit mbp_exit(void)
{
backlight_device_unregister(mbp_backlight_device);
- release_region(0xb2, 2);
+ release_region(driver_data->iostart, driver_data->iolen);
}
module_init(mbp_init);
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index ea07258565f..e641584e212 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -3,7 +3,7 @@
*
* simple PWM based backlight control, board code has to setup
* 1) pin configuration so PWM waveforms can output
- * 2) platform_data casts to the PWM id (0/1/2/3 on PXA)
+ * 2) platform_data being correctly configured
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -97,7 +97,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
} else
dev_dbg(&pdev->dev, "got pwm for backlight\n");
- bl = backlight_device_register(pdev->name, &pdev->dev,
+ bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
pb, &pwm_backlight_ops);
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index d42e385f091..4c2bf923418 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -567,9 +567,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
default:
dev_dbg(info->device,
"Unsupported bpp size: %d\n", var->bits_per_pixel);
- assert(false);
- /* should never occur */
- break;
+ return -EINVAL;
}
if (var->xres_virtual < var->xres)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2cd500a304f..471a9a60376 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2263,9 +2263,12 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
}
+ if (!lock_fb_info(info))
+ return;
event.info = info;
event.data = &blank;
fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
+ unlock_fb_info(info);
}
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
@@ -2956,8 +2959,6 @@ static int fbcon_fb_unregistered(struct fb_info *info)
{
int i, idx;
- if (!lock_fb_info(info))
- return -ENODEV;
idx = info->node;
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map[i] == idx)
@@ -2985,8 +2986,6 @@ static int fbcon_fb_unregistered(struct fb_info *info)
if (primary_device == idx)
primary_device = -1;
- unlock_fb_info(info);
-
if (!num_registered_fb)
unregister_con_driver(&fb_con);
@@ -3027,11 +3026,8 @@ static int fbcon_fb_registered(struct fb_info *info)
{
int ret = 0, i, idx;
- if (!lock_fb_info(info))
- return -ENODEV;
idx = info->node;
fbcon_select_primary(info);
- unlock_fb_info(info);
if (info_idx == -1) {
for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -3152,53 +3148,23 @@ static int fbcon_event_notify(struct notifier_block *self,
switch(action) {
case FB_EVENT_SUSPEND:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_suspended(info);
- unlock_fb_info(info);
break;
case FB_EVENT_RESUME:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_resumed(info);
- unlock_fb_info(info);
break;
case FB_EVENT_MODE_CHANGE:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_modechanged(info);
- unlock_fb_info(info);
break;
case FB_EVENT_MODE_CHANGE_ALL:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_set_all_vcs(info);
- unlock_fb_info(info);
break;
case FB_EVENT_MODE_DELETE:
mode = event->data;
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
ret = fbcon_mode_deleted(info, mode);
- unlock_fb_info(info);
break;
case FB_EVENT_FB_UNBIND:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
idx = info->node;
- unlock_fb_info(info);
ret = fbcon_fb_unbind(idx);
break;
case FB_EVENT_FB_REGISTERED:
@@ -3217,29 +3183,14 @@ static int fbcon_event_notify(struct notifier_block *self,
con2fb->framebuffer = con2fb_map[con2fb->console - 1];
break;
case FB_EVENT_BLANK:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_fb_blanked(info, *(int *)event->data);
- unlock_fb_info(info);
break;
case FB_EVENT_NEW_MODELIST:
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_new_modelist(info);
- unlock_fb_info(info);
break;
case FB_EVENT_GET_REQ:
caps = event->data;
- if (!lock_fb_info(info)) {
- ret = -ENODEV;
- goto done;
- }
fbcon_get_requirement(info, caps);
- unlock_fb_info(info);
break;
}
done:
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 0c5b9a9fd56..8dea2bc9270 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -210,12 +210,15 @@ static int __init efifb_probe(struct platform_device *dev)
unsigned int size_total;
int request_succeeded = 0;
- printk(KERN_INFO "efifb: probing for efifb\n");
-
if (!screen_info.lfb_depth)
screen_info.lfb_depth = 32;
if (!screen_info.pages)
screen_info.pages = 1;
+ if (!screen_info.lfb_base) {
+ printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "efifb: probing for efifb\n");
/* just assume they're all unset if any are */
if (!screen_info.blue_size) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 2ac32e6b595..d412a1ddc12 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1097,8 +1097,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
return -EINVAL;
con2fb.framebuffer = -1;
event.data = &con2fb;
+ if (!lock_fb_info(info))
+ return -ENODEV;
event.info = info;
fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
+ unlock_fb_info(info);
ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
break;
case FBIOPUT_CON2FBMAP:
@@ -1115,8 +1118,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
break;
}
event.data = &con2fb;
+ if (!lock_fb_info(info))
+ return -ENODEV;
event.info = info;
ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
+ unlock_fb_info(info);
break;
case FBIOBLANK:
if (!lock_fb_info(info))
@@ -1521,7 +1527,10 @@ register_framebuffer(struct fb_info *fb_info)
registered_fb[i] = fb_info;
event.info = fb_info;
+ if (!lock_fb_info(fb_info))
+ return -ENODEV;
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+ unlock_fb_info(fb_info);
return 0;
}
@@ -1555,8 +1564,12 @@ unregister_framebuffer(struct fb_info *fb_info)
goto done;
}
+
+ if (!lock_fb_info(fb_info))
+ return -ENODEV;
event.info = fb_info;
ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+ unlock_fb_info(fb_info);
if (ret) {
ret = -EINVAL;
@@ -1590,6 +1603,8 @@ void fb_set_suspend(struct fb_info *info, int state)
{
struct fb_event event;
+ if (!lock_fb_info(info))
+ return;
event.info = info;
if (state) {
fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
@@ -1598,6 +1613,7 @@ void fb_set_suspend(struct fb_info *info, int state)
info->state = FBINFO_STATE_RUNNING;
fb_notifier_call_chain(FB_EVENT_RESUME, &event);
}
+ unlock_fb_info(info);
}
/**
@@ -1667,8 +1683,11 @@ int fb_new_modelist(struct fb_info *info)
err = 1;
if (!list_empty(&info->modelist)) {
+ if (!lock_fb_info(info))
+ return -ENODEV;
event.info = info;
err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
+ unlock_fb_info(info);
}
return err;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index a50bea61480..40984551c92 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -53,6 +53,7 @@
#define PCI_DEVICE_ID_INTEL_830M 0x3577
#define PCI_DEVICE_ID_INTEL_845G 0x2562
#define PCI_DEVICE_ID_INTEL_85XGM 0x3582
+#define PCI_DEVICE_ID_INTEL_854 0x358E
#define PCI_DEVICE_ID_INTEL_865G 0x2572
#define PCI_DEVICE_ID_INTEL_915G 0x2582
#define PCI_DEVICE_ID_INTEL_915GM 0x2592
@@ -154,6 +155,7 @@ enum intel_chips {
INTEL_85XGM,
INTEL_852GM,
INTEL_852GME,
+ INTEL_854,
INTEL_855GM,
INTEL_855GME,
INTEL_865G,
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index b3065492bb2..487f2be4746 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -156,6 +156,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
switch(dinfo->chipset) {
case INTEL_830M:
case INTEL_845G:
+ case INTEL_854:
case INTEL_855GM:
case INTEL_865G:
dinfo->output[i].type = INTELFB_OUTPUT_DVO;
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 6d8e5415c80..ace14fe02fc 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -182,6 +182,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 8b26b27c2db..0689f97c523 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -84,6 +84,11 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
dinfo->mobile = 0;
dinfo->pll_index = PLLS_I8xx;
return 0;
+ case PCI_DEVICE_ID_INTEL_854:
+ dinfo->mobile = 1;
+ dinfo->name = "Intel(R) 854";
+ dinfo->chipset = INTEL_854;
+ return 0;
case PCI_DEVICE_ID_INTEL_85XGM:
tmp = 0;
dinfo->mobile = 1;
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index fa1a512ce03..21b3692092f 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -400,12 +400,12 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel,
int16_t x_pos, int16_t y_pos)
{
- x_pos += mx3fb->h_start_width;
- y_pos += mx3fb->v_start_width;
-
if (channel != IDMAC_SDC_0)
return -EINVAL;
+ x_pos += mx3fb->h_start_width;
+ y_pos += mx3fb->v_start_width;
+
mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS);
return 0;
}
@@ -491,11 +491,13 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
* 2^4 to get fractional part, as long as we stay under ~250MHz and on
* i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
*/
- dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk);
-
ipu_clk = clk_get(mx3fb->dev, NULL);
- div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
- clk_put(ipu_clk);
+ if (!IS_ERR(ipu_clk)) {
+ div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
+ clk_put(ipu_clk);
+ } else {
+ div = 0;
+ }
if (div < 0x40) { /* Divider less than 4 */
dev_dbg(mx3fb->dev,
@@ -503,6 +505,9 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
div = 0x40;
}
+ dev_dbg(mx3fb->dev, "pixel clk = %u, divider %u.%u\n",
+ pixel_clk, div >> 4, (div & 7) * 125);
+
spin_lock_irqsave(&mx3fb->lock, lock_flags);
/*
@@ -515,16 +520,16 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
/* DI settings */
old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF;
old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT |
- sig.clksel_en << DI_D3_CLK_SEL_SHIFT |
- sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT;
+ sig.clksel_en << DI_D3_CLK_SEL_SHIFT |
+ sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT;
mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF);
old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF;
old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT |
- sig.clk_pol << DI_D3_CLK_POL_SHIFT |
- sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT |
- sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT |
- sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
+ sig.clk_pol << DI_D3_CLK_POL_SHIFT |
+ sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT |
+ sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT |
+ sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
switch (pixel_fmt) {
@@ -721,7 +726,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
struct idmac_channel *ichan = mx3_fbi->idmac_channel;
struct idmac_video_param *video = &ichan->params.video;
struct scatterlist *sg = mx3_fbi->sg;
- size_t screen_size;
dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
@@ -745,12 +749,10 @@ static int mx3fb_set_par(struct fb_info *fbi)
}
}
- screen_size = fbi->fix.line_length * fbi->var.yres;
-
sg_init_table(&sg[0], 1);
sg_init_table(&sg[1], 1);
- sg_dma_address(&sg[0]) = fbi->fix.smem_start;
+ sg_dma_address(&sg[0]) = fbi->fix.smem_start;
sg_set_page(&sg[0], virt_to_page(fbi->screen_base),
fbi->fix.smem_len,
offset_in_page(fbi->screen_base));
@@ -927,7 +929,7 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
u32 val;
int ret = 1;
- dev_dbg(fbi->device, "%s\n", __func__);
+ dev_dbg(fbi->device, "%s, regno = %u\n", __func__, regno);
mutex_lock(&mx3_fbi->mutex);
/*
@@ -973,9 +975,8 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
struct mx3fb_info *mx3_fbi = fbi->par;
struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
- dev_dbg(fbi->device, "%s\n", __func__);
-
- dev_dbg(fbi->device, "blank = %d\n", blank);
+ dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
+ blank, fbi->screen_base, fbi->fix.smem_len);
if (mx3_fbi->blank == blank)
return 0;
@@ -988,8 +989,11 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_NORMAL:
- sdc_disable_channel(mx3_fbi);
sdc_set_brightness(mx3fb, 0);
+ memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+ /* Give LCD time to update - enough for 50 and 60 Hz */
+ msleep(25);
+ sdc_disable_channel(mx3_fbi);
break;
case FB_BLANK_UNBLANK:
sdc_enable_channel(mx3_fbi);
@@ -1063,6 +1067,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
mutex_unlock(&mx3_fbi->mutex);
dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ?
"user interrupt" : "timeout");
+ disable_irq(mx3_fbi->idmac_channel->eof_irq);
return ret ? : -ETIMEDOUT;
}
@@ -1073,6 +1078,9 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len,
offset_in_page(fbi->screen_base + offset));
+ if (mx3_fbi->txd)
+ async_tx_ack(mx3_fbi->txd);
+
txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
if (!txd) {
@@ -1099,8 +1107,6 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
return -EIO;
}
- if (mx3_fbi->txd)
- async_tx_ack(mx3_fbi->txd);
mx3_fbi->txd = txd;
fbi->var.xoffset = var->xoffset;
@@ -1506,7 +1512,7 @@ static struct platform_driver mx3fb_driver = {
* example:
* video=mx3fb:bpp=16
*/
-static int mx3fb_setup(void)
+static int __init mx3fb_setup(void)
{
#ifndef MODULE
char *opt, *options = NULL;
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 4dcec48a1d7..c3fad34309e 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -45,11 +45,11 @@ struct s3fb_info {
static const struct svga_fb_format s3fb_formats[] = {
{ 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4, FB_VISUAL_PSEUDOCOLOR, 8, 16},
- { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
+ { 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16},
- { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1,
+ { 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 1,
FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 8, 16},
- { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
+ { 8, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 4, 8},
{16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0,
FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 4},
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index fad58cf9ef7..10ddad8e17d 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -199,16 +199,20 @@
extern void (*sa1100fb_backlight_power)(int on);
extern void (*sa1100fb_lcd_power)(int on);
-/*
- * IMHO this looks wrong. In 8BPP, length should be 8.
- */
-static struct sa1100fb_rgb rgb_8 = {
+static struct sa1100fb_rgb rgb_4 = {
.red = { .offset = 0, .length = 4, },
.green = { .offset = 0, .length = 4, },
.blue = { .offset = 0, .length = 4, },
.transp = { .offset = 0, .length = 0, },
};
+static struct sa1100fb_rgb rgb_8 = {
+ .red = { .offset = 0, .length = 8, },
+ .green = { .offset = 0, .length = 8, },
+ .blue = { .offset = 0, .length = 8, },
+ .transp = { .offset = 0, .length = 0, },
+};
+
static struct sa1100fb_rgb def_rgb_16 = {
.red = { .offset = 11, .length = 5, },
.green = { .offset = 5, .length = 6, },
@@ -613,7 +617,7 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
switch (var->bits_per_pixel) {
case 4:
- rgbidx = RGB_8;
+ rgbidx = RGB_4;
break;
case 8:
rgbidx = RGB_8;
@@ -1382,6 +1386,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
fbi->fb.monspecs = monspecs;
fbi->fb.pseudo_palette = (fbi + 1);
+ fbi->rgb[RGB_4] = &rgb_4;
fbi->rgb[RGB_8] = &rgb_8;
fbi->rgb[RGB_16] = &def_rgb_16;
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index 86831db9a04..1c3b459865d 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -57,9 +57,10 @@ struct sa1100fb_lcd_reg {
unsigned long lccr3;
};
-#define RGB_8 (0)
-#define RGB_16 (1)
-#define NR_RGB 2
+#define RGB_4 (0)
+#define RGB_8 (1)
+#define RGB_16 (2)
+#define NR_RGB 3
struct sa1100fb_info {
struct fb_info fb;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 346d6458cf7..7e17ee95a97 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1129,7 +1129,7 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
switch(var->bits_per_pixel) {
case 8:
var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 6;
+ var->red.length = var->green.length = var->blue.length = 8;
break;
case 16:
var->red.offset = 11;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a439159204a..89158bc71da 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -308,9 +308,11 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
* color depth = SUM(var->{color}.length)
*
* Pseudocolor:
- * var->{color}.offset is 0
- * var->{color}.length contains width of DAC or the number of unique
- * colors available (color depth)
+ * var->{color}.offset is 0 unless the palette index takes less than
+ * bits_per_pixel bits and is stored in the upper
+ * bits of the pixel value
+ * var->{color}.length is set so that 1 << length is the number of
+ * available palette entries
* pseudo_palette is not used
* RAMDAC[X] is programmed to (red, green, blue)
* color depth = var->{color}.length
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ee64771fbe3..89f231dc443 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -10,6 +10,12 @@
* Created : Thu Sep 23 18:17:43 1999, hmallat
* Last modified: Tue Nov 2 21:19:47 1999, hmallat
*
+ * I2C part copied from the i2c-voodoo3.c driver by:
+ * Frodo Looijaard <frodol@dds.nl>,
+ * Philip Edelbrock <phil@netroedge.com>,
+ * Ralph Metzler <rjkm@thp.uni-koeln.de>, and
+ * Mark D. Studebaker <mdsxyz123@yahoo.com>
+ *
* Lots of the information here comes from the Daryll Strauss' Banshee
* patches to the XF86 server, and the rest comes from the 3dfx
* Banshee specification. I'm very much indebted to Daryll for his
@@ -481,6 +487,12 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return -EINVAL;
}
+ if (info->monspecs.hfmax && info->monspecs.vfmax &&
+ info->monspecs.dclkmax && fb_validate_mode(var, info) < 0) {
+ DPRINTK("mode outside monitor's specs\n");
+ return -EINVAL;
+ }
+
var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
@@ -1167,6 +1179,207 @@ static struct fb_ops tdfxfb_ops = {
#endif
};
+#ifdef CONFIG_FB_3DFX_I2C
+/* The voo GPIO registers don't have individual masks for each bit
+ so we always have to read before writing. */
+
+static void tdfxfb_i2c_setscl(void *data, int val)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+ unsigned int r;
+
+ r = tdfx_inl(par, VIDSERPARPORT);
+ if (val)
+ r |= I2C_SCL_OUT;
+ else
+ r &= ~I2C_SCL_OUT;
+ tdfx_outl(par, VIDSERPARPORT, r);
+ tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
+}
+
+static void tdfxfb_i2c_setsda(void *data, int val)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+ unsigned int r;
+
+ r = tdfx_inl(par, VIDSERPARPORT);
+ if (val)
+ r |= I2C_SDA_OUT;
+ else
+ r &= ~I2C_SDA_OUT;
+ tdfx_outl(par, VIDSERPARPORT, r);
+ tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
+}
+
+/* The GPIO pins are open drain, so the pins always remain outputs.
+ We rely on the i2c-algo-bit routines to set the pins high before
+ reading the input from other chips. */
+
+static int tdfxfb_i2c_getscl(void *data)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+
+ return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SCL_IN));
+}
+
+static int tdfxfb_i2c_getsda(void *data)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+
+ return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SDA_IN));
+}
+
+static void tdfxfb_ddc_setscl(void *data, int val)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+ unsigned int r;
+
+ r = tdfx_inl(par, VIDSERPARPORT);
+ if (val)
+ r |= DDC_SCL_OUT;
+ else
+ r &= ~DDC_SCL_OUT;
+ tdfx_outl(par, VIDSERPARPORT, r);
+ tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
+}
+
+static void tdfxfb_ddc_setsda(void *data, int val)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+ unsigned int r;
+
+ r = tdfx_inl(par, VIDSERPARPORT);
+ if (val)
+ r |= DDC_SDA_OUT;
+ else
+ r &= ~DDC_SDA_OUT;
+ tdfx_outl(par, VIDSERPARPORT, r);
+ tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
+}
+
+static int tdfxfb_ddc_getscl(void *data)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+
+ return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SCL_IN));
+}
+
+static int tdfxfb_ddc_getsda(void *data)
+{
+ struct tdfxfb_i2c_chan *chan = data;
+ struct tdfx_par *par = chan->par;
+
+ return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
+}
+
+static int __devinit tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan,
+ const char *name, struct device *dev)
+{
+ int rc;
+
+ strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.class = I2C_CLASS_DDC;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = dev;
+ chan->algo.setsda = tdfxfb_ddc_setsda;
+ chan->algo.setscl = tdfxfb_ddc_setscl;
+ chan->algo.getsda = tdfxfb_ddc_getsda;
+ chan->algo.getscl = tdfxfb_ddc_getscl;
+ chan->algo.udelay = 10;
+ chan->algo.timeout = msecs_to_jiffies(500);
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->adapter, chan);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ DPRINTK("I2C bus %s registered.\n", name);
+ else
+ chan->par = NULL;
+
+ return rc;
+}
+
+static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
+ const char *name, struct device *dev)
+{
+ int rc;
+
+ strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.class = I2C_CLASS_TV_ANALOG;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = dev;
+ chan->algo.setsda = tdfxfb_i2c_setsda;
+ chan->algo.setscl = tdfxfb_i2c_setscl;
+ chan->algo.getsda = tdfxfb_i2c_getsda;
+ chan->algo.getscl = tdfxfb_i2c_getscl;
+ chan->algo.udelay = 10;
+ chan->algo.timeout = msecs_to_jiffies(500);
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->adapter, chan);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ DPRINTK("I2C bus %s registered.\n", name);
+ else
+ chan->par = NULL;
+
+ return rc;
+}
+
+static void __devinit tdfxfb_create_i2c_busses(struct fb_info *info)
+{
+ struct tdfx_par *par = info->par;
+
+ tdfx_outl(par, VIDINFORMAT, 0x8160);
+ tdfx_outl(par, VIDSERPARPORT, 0xcffc0020);
+
+ par->chan[0].par = par;
+ par->chan[1].par = par;
+
+ tdfxfb_setup_ddc_bus(&par->chan[0], "Voodoo3-DDC", info->dev);
+ tdfxfb_setup_i2c_bus(&par->chan[1], "Voodoo3-I2C", info->dev);
+}
+
+static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
+{
+ if (par->chan[0].par)
+ i2c_del_adapter(&par->chan[0].adapter);
+ par->chan[0].par = NULL;
+
+ if (par->chan[1].par)
+ i2c_del_adapter(&par->chan[1].adapter);
+ par->chan[1].par = NULL;
+}
+
+static int tdfxfb_probe_i2c_connector(struct tdfx_par *par,
+ struct fb_monspecs *specs)
+{
+ u8 *edid = NULL;
+
+ DPRINTK("Probe DDC Bus\n");
+ if (par->chan[0].par)
+ edid = fb_ddc_read(&par->chan[0].adapter);
+
+ if (edid) {
+ fb_edid_to_monspecs(edid, specs);
+ kfree(edid);
+ return 0;
+ }
+ return 1;
+}
+#endif /* CONFIG_FB_3DFX_I2C */
+
/**
* tdfxfb_probe - Device Initializiation
*
@@ -1182,6 +1395,8 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
struct tdfx_par *default_par;
struct fb_info *info;
int err, lpitch;
+ struct fb_monspecs *specs;
+ bool found;
err = pci_enable_device(pdev);
if (err) {
@@ -1284,13 +1499,49 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
if (hwcursor)
info->fix.smem_len = (info->fix.smem_len - 1024) &
(PAGE_MASK << 1);
-
- if (!mode_option)
+ specs = &info->monspecs;
+ found = false;
+ info->var.bits_per_pixel = 8;
+#ifdef CONFIG_FB_3DFX_I2C
+ tdfxfb_create_i2c_busses(info);
+ err = tdfxfb_probe_i2c_connector(default_par, specs);
+
+ if (!err) {
+ if (specs->modedb == NULL)
+ DPRINTK("Unable to get Mode Database\n");
+ else {
+ const struct fb_videomode *m;
+
+ fb_videomode_to_modelist(specs->modedb,
+ specs->modedb_len,
+ &info->modelist);
+ m = fb_find_best_display(specs, &info->modelist);
+ if (m) {
+ fb_videomode_to_var(&info->var, m);
+ /* fill all other info->var's fields */
+ if (tdfxfb_check_var(&info->var, info) < 0)
+ info->var = tdfx_var;
+ else
+ found = true;
+ }
+ }
+ }
+#endif
+ if (!mode_option && !found)
mode_option = "640x480@60";
- err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
- if (!err || err == 4)
- info->var = tdfx_var;
+ if (mode_option) {
+ err = fb_find_mode(&info->var, info, mode_option,
+ specs->modedb, specs->modedb_len,
+ NULL, info->var.bits_per_pixel);
+ if (!err || err == 4)
+ info->var = tdfx_var;
+ }
+
+ if (found) {
+ fb_destroy_modedb(specs->modedb);
+ specs->modedb = NULL;
+ }
/* maximize virtual vertical length */
lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
@@ -1315,6 +1566,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
return 0;
out_err_iobase:
+#ifdef CONFIG_FB_3DFX_I2C
+ tdfxfb_delete_i2c_busses(default_par);
+#endif
if (default_par->mtrr_handle >= 0)
mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
info->fix.smem_len);
@@ -1379,6 +1633,9 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev)
struct tdfx_par *par = info->par;
unregister_framebuffer(info);
+#ifdef CONFIG_FB_3DFX_I2C
+ tdfxfb_delete_i2c_busses(par);
+#endif
if (par->mtrr_handle >= 0)
mtrr_del(par->mtrr_handle, info->fix.smem_start,
info->fix.smem_len);
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 0b370aebdbf..421770b5e6a 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -55,6 +55,7 @@ static u16 maxvf __devinitdata; /* maximum vertical frequency */
static u16 maxhf __devinitdata; /* maximum horizontal frequency */
static u16 vbemode __devinitdata; /* force use of a specific VBE mode */
static char *mode_option __devinitdata;
+static u8 dac_width = 6;
static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
static DEFINE_MUTEX(uvfb_lock);
@@ -303,22 +304,10 @@ static void uvesafb_setup_var(struct fb_var_screeninfo *var,
var->blue.offset = 0;
var->transp.offset = 0;
- /*
- * We're assuming that we can switch the DAC to 8 bits. If
- * this proves to be incorrect, we'll update the fields
- * later in set_par().
- */
- if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) {
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 0;
- } else {
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- var->transp.length = 0;
- }
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 0;
}
}
@@ -1006,7 +995,7 @@ static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info)
{
struct uvesafb_pal_entry entry;
- int shift = 16 - info->var.green.length;
+ int shift = 16 - dac_width;
int err = 0;
if (regno >= info->cmap.len)
@@ -1055,7 +1044,7 @@ static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
{
struct uvesafb_pal_entry *entries;
- int shift = 16 - info->var.green.length;
+ int shift = 16 - dac_width;
int i, err = 0;
if (info->var.bits_per_pixel == 8) {
@@ -1317,13 +1306,9 @@ setmode:
err = uvesafb_exec(task);
if (err || (task->t.regs.eax & 0xffff) != 0x004f ||
((task->t.regs.ebx & 0xff00) >> 8) != 8) {
- /*
- * We've failed to set the DAC palette format -
- * time to correct var.
- */
- info->var.red.length = 6;
- info->var.green.length = 6;
- info->var.blue.length = 6;
+ dac_width = 6;
+ } else {
+ dac_width = 8;
}
}
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index cc919ae4657..050d432c7d9 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -318,13 +318,16 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* {hardwarespecific} contains width of RAMDAC
* cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
- *
+ *
* Pseudocolor:
- * uses offset = 0 && length = RAMDAC register width.
- * var->{color}.offset is 0
- * var->{color}.length contains widht of DAC
+ * var->{color}.offset is 0 unless the palette index takes less than
+ * bits_per_pixel bits and is stored in the upper
+ * bits of the pixel value
+ * var->{color}.length is set so that 1 << length is the number of available
+ * palette entries
* cmap is not used
* RAMDAC[X] is programmed to (red, green, blue)
+ *
* Truecolor:
* does not use DAC. Usually 3 are present.
* var->{color}.offset contains start of bitfield