diff options
Diffstat (limited to 'drivers/video/backlight')
-rw-r--r-- | drivers/video/backlight/Kconfig | 18 | ||||
-rw-r--r-- | drivers/video/backlight/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/backlight/backlight.c | 3 | ||||
-rw-r--r-- | drivers/video/backlight/jornada720_bl.c | 161 | ||||
-rw-r--r-- | drivers/video/backlight/jornada720_lcd.c | 153 | ||||
-rw-r--r-- | drivers/video/backlight/lcd.c | 3 | ||||
-rw-r--r-- | drivers/video/backlight/mbp_nvidia_bl.c | 191 | ||||
-rw-r--r-- | drivers/video/backlight/pwm_bl.c | 4 |
8 files changed, 497 insertions, 38 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 72facb9eb7db..f9d19be05540 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 63d759498165..4eb178c1d684 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 157057c79ca3..dd37cbcaf8ce 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -35,6 +35,8 @@ 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 || @@ -47,6 +49,7 @@ 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 000000000000..c3ebb6b41ce1 --- /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 000000000000..cbbb167fd268 --- /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 b6449470106c..0bb13df0fa89 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -40,6 +40,8 @@ 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) { @@ -51,6 +53,7 @@ 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 65864c500455..3bb4c0a50c62 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 ea07258565f0..e641584e212e 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"); |