diff options
Diffstat (limited to 'drivers/video/backlight')
-rw-r--r-- | drivers/video/backlight/Kconfig | 4 | ||||
-rw-r--r-- | drivers/video/backlight/backlight.c | 84 | ||||
-rw-r--r-- | drivers/video/backlight/corgi_bl.c | 124 | ||||
-rw-r--r-- | drivers/video/backlight/hp680_bl.c | 139 |
4 files changed, 163 insertions, 188 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 9d996f2c10d5..b895eaaa73fd 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -43,11 +43,11 @@ config LCD_DEVICE default y config BACKLIGHT_CORGI - tristate "Sharp Corgi Backlight Driver (SL-C7xx Series)" + tristate "Sharp Corgi Backlight Driver (SL Series)" depends on BACKLIGHT_DEVICE && PXA_SHARPSL default y help - If you have a Sharp Zaurus SL-C7xx, say y to enable the + If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the backlight driver. config BACKLIGHT_HP680 diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 151fda8dded0..334b1db1bd7c 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -16,14 +16,12 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); - if (likely(bd->props && bd->props->get_power)) - rc = sprintf(buf, "%d\n", bd->props->get_power(bd)); - else - rc = -ENXIO; + if (likely(bd->props)) + rc = sprintf(buf, "%d\n", bd->props->power); up(&bd->sem); return rc; @@ -31,7 +29,7 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count) { - int rc, power; + int rc = -ENXIO, power; char *endp; struct backlight_device *bd = to_backlight_device(cdev); @@ -40,12 +38,13 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, return -EINVAL; down(&bd->sem); - if (likely(bd->props && bd->props->set_power)) { + if (likely(bd->props)) { pr_debug("backlight: set power to %d\n", power); - bd->props->set_power(bd, power); + bd->props->power = power; + if (likely(bd->props->update_status)) + bd->props->update_status(bd); rc = count; - } else - rc = -ENXIO; + } up(&bd->sem); return rc; @@ -53,14 +52,12 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); - if (likely(bd->props && bd->props->get_brightness)) - rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); - else - rc = -ENXIO; + if (likely(bd->props)) + rc = sprintf(buf, "%d\n", bd->props->brightness); up(&bd->sem); return rc; @@ -68,7 +65,7 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count) { - int rc, brightness; + int rc = -ENXIO, brightness; char *endp; struct backlight_device *bd = to_backlight_device(cdev); @@ -77,12 +74,18 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char return -EINVAL; down(&bd->sem); - if (likely(bd->props && bd->props->set_brightness)) { - pr_debug("backlight: set brightness to %d\n", brightness); - bd->props->set_brightness(bd, brightness); - rc = count; - } else - rc = -ENXIO; + if (likely(bd->props)) { + if (brightness > bd->props->max_brightness) + rc = -EINVAL; + else { + pr_debug("backlight: set brightness to %d\n", + brightness); + bd->props->brightness = brightness; + if (likely(bd->props->update_status)) + bd->props->update_status(bd); + rc = count; + } + } up(&bd->sem); return rc; @@ -90,14 +93,26 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); if (likely(bd->props)) rc = sprintf(buf, "%d\n", bd->props->max_brightness); - else - rc = -ENXIO; + up(&bd->sem); + + return rc; +} + +static ssize_t backlight_show_actual_brightness(struct class_device *cdev, + char *buf) +{ + int rc = -ENXIO; + struct backlight_device *bd = to_backlight_device(cdev); + + down(&bd->sem); + if (likely(bd->props && bd->props->get_brightness)) + rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); up(&bd->sem); return rc; @@ -123,7 +138,10 @@ static struct class backlight_class = { static struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), - DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), + DECLARE_ATTR(brightness, 0644, backlight_show_brightness, + backlight_store_brightness), + DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness, + NULL), DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), }; @@ -144,8 +162,12 @@ static int fb_notifier_callback(struct notifier_block *self, bd = container_of(self, struct backlight_device, fb_notif); down(&bd->sem); if (bd->props) - if (!bd->props->check_fb || bd->props->check_fb(evdata->info)) - bd->props->set_power(bd, *(int *)evdata->data); + if (!bd->props->check_fb || + bd->props->check_fb(evdata->info)) { + bd->props->fb_blank = *(int *)evdata->data; + if (likely(bd->props && bd->props->update_status)) + bd->props->update_status(bd); + } up(&bd->sem); return 0; } @@ -231,6 +253,12 @@ void backlight_device_unregister(struct backlight_device *bd) &bl_class_device_attributes[i]); down(&bd->sem); + if (likely(bd->props && bd->props->update_status)) { + bd->props->brightness = 0; + bd->props->power = 0; + bd->props->update_status(bd); + } + bd->props = NULL; up(&bd->sem); diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index d0aaf450e8c7..2ebbfd95145f 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -1,7 +1,7 @@ /* - * Backlight Driver for Sharp Corgi + * Backlight Driver for Sharp Zaurus Handhelds (various models) * - * Copyright (c) 2004-2005 Richard Purdie + * Copyright (c) 2004-2006 Richard Purdie * * Based on Sharp's 2.4 Backlight Driver * @@ -15,80 +15,63 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/fb.h> #include <linux/backlight.h> - #include <asm/arch/sharpsl.h> #include <asm/hardware/sharpsl_pm.h> -#define CORGI_DEFAULT_INTENSITY 0x1f -#define CORGI_LIMIT_MASK 0x0b - -static int corgibl_powermode = FB_BLANK_UNBLANK; -static int current_intensity = 0; -static int corgibl_limit = 0; -static void (*corgibl_mach_set_intensity)(int intensity); -static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static int corgibl_intensity; +static DEFINE_MUTEX(bl_mutex); static struct backlight_properties corgibl_data; +static struct backlight_device *corgi_backlight_device; +static struct corgibl_machinfo *bl_machinfo; -static void corgibl_send_intensity(int intensity) +static unsigned long corgibl_flags; +#define CORGIBL_SUSPENDED 0x01 +#define CORGIBL_BATTLOW 0x02 + +static int corgibl_send_intensity(struct backlight_device *bd) { - unsigned long flags; void (*corgi_kick_batt)(void); + int intensity = bd->props->brightness; - if (corgibl_powermode != FB_BLANK_UNBLANK) { + if (bd->props->power != FB_BLANK_UNBLANK) intensity = 0; - } else { - if (corgibl_limit) - intensity &= CORGI_LIMIT_MASK; - } - - spin_lock_irqsave(&bl_lock, flags); + if (bd->props->fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + if (corgibl_flags & CORGIBL_SUSPENDED) + intensity = 0; + if (corgibl_flags & CORGIBL_BATTLOW) + intensity &= bl_machinfo->limit_mask; - corgibl_mach_set_intensity(intensity); + mutex_lock(&bl_mutex); + bl_machinfo->set_bl_intensity(intensity); + mutex_unlock(&bl_mutex); - spin_unlock_irqrestore(&bl_lock, flags); + corgibl_intensity = intensity; corgi_kick_batt = symbol_get(sharpsl_battery_kick); if (corgi_kick_batt) { corgi_kick_batt(); symbol_put(sharpsl_battery_kick); } -} -static void corgibl_blank(int blank) -{ - switch(blank) { - - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (corgibl_powermode == FB_BLANK_UNBLANK) { - corgibl_send_intensity(0); - corgibl_powermode = blank; - } - break; - case FB_BLANK_UNBLANK: - if (corgibl_powermode != FB_BLANK_UNBLANK) { - corgibl_powermode = blank; - corgibl_send_intensity(current_intensity); - } - break; - } + return 0; } #ifdef CONFIG_PM static int corgibl_suspend(struct platform_device *dev, pm_message_t state) { - corgibl_blank(FB_BLANK_POWERDOWN); + corgibl_flags |= CORGIBL_SUSPENDED; + corgibl_send_intensity(corgi_backlight_device); return 0; } static int corgibl_resume(struct platform_device *dev) { - corgibl_blank(FB_BLANK_UNBLANK); + corgibl_flags &= ~CORGIBL_SUSPENDED; + corgibl_send_intensity(corgi_backlight_device); return 0; } #else @@ -96,68 +79,55 @@ static int corgibl_resume(struct platform_device *dev) #define corgibl_resume NULL #endif - -static int corgibl_set_power(struct backlight_device *bd, int state) -{ - corgibl_blank(state); - return 0; -} - -static int corgibl_get_power(struct backlight_device *bd) +static int corgibl_get_intensity(struct backlight_device *bd) { - return corgibl_powermode; + return corgibl_intensity; } -static int corgibl_set_intensity(struct backlight_device *bd, int intensity) +static int corgibl_set_intensity(struct backlight_device *bd) { - if (intensity > corgibl_data.max_brightness) - intensity = corgibl_data.max_brightness; - corgibl_send_intensity(intensity); - current_intensity=intensity; + corgibl_send_intensity(corgi_backlight_device); return 0; } -static int corgibl_get_intensity(struct backlight_device *bd) -{ - return current_intensity; -} - /* * Called when the battery is low to limit the backlight intensity. * If limit==0 clear any limit, otherwise limit the intensity */ void corgibl_limit_intensity(int limit) { - corgibl_limit = (limit ? 1 : 0); - corgibl_send_intensity(current_intensity); + if (limit) + corgibl_flags |= CORGIBL_BATTLOW; + else + corgibl_flags &= ~CORGIBL_BATTLOW; + corgibl_send_intensity(corgi_backlight_device); } EXPORT_SYMBOL(corgibl_limit_intensity); static struct backlight_properties corgibl_data = { - .owner = THIS_MODULE, - .get_power = corgibl_get_power, - .set_power = corgibl_set_power, + .owner = THIS_MODULE, .get_brightness = corgibl_get_intensity, - .set_brightness = corgibl_set_intensity, + .update_status = corgibl_set_intensity, }; -static struct backlight_device *corgi_backlight_device; - static int __init corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; + bl_machinfo = machinfo; corgibl_data.max_brightness = machinfo->max_intensity; - corgibl_mach_set_intensity = machinfo->set_bl_intensity; + if (!machinfo->limit_mask) + machinfo->limit_mask = -1; corgi_backlight_device = backlight_device_register ("corgi-bl", NULL, &corgibl_data); if (IS_ERR (corgi_backlight_device)) return PTR_ERR (corgi_backlight_device); - corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); - corgibl_limit_intensity(0); + corgibl_data.power = FB_BLANK_UNBLANK; + corgibl_data.brightness = machinfo->default_intensity; + corgibl_send_intensity(corgi_backlight_device); printk("Corgi Backlight Driver Initialized.\n"); return 0; @@ -167,8 +137,6 @@ static int corgibl_remove(struct platform_device *dev) { backlight_device_unregister(corgi_backlight_device); - corgibl_set_intensity(NULL, 0); - printk("Corgi Backlight Driver Unloaded\n"); return 0; } diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index 95da4c9ed1f1..a71e984c93d4 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -13,7 +13,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/fb.h> #include <linux/backlight.h> @@ -25,66 +25,58 @@ #define HP680_MAX_INTENSITY 255 #define HP680_DEFAULT_INTENSITY 10 -static int hp680bl_powermode = FB_BLANK_UNBLANK; +static int hp680bl_suspended; static int current_intensity = 0; static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static struct backlight_device *hp680_backlight_device; -static void hp680bl_send_intensity(int intensity) +static void hp680bl_send_intensity(struct backlight_device *bd) { unsigned long flags; + u16 v; + int intensity = bd->props->brightness; - if (hp680bl_powermode != FB_BLANK_UNBLANK) + if (bd->props->power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props->fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + if (hp680bl_suspended) intensity = 0; spin_lock_irqsave(&bl_lock, flags); - sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + if (intensity && current_intensity == 0) { + sh_dac_enable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v &= ~HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } else if (intensity == 0 && current_intensity != 0) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + sh_dac_disable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v |= HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + } else if (intensity) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } spin_unlock_irqrestore(&bl_lock, flags); -} -static void hp680bl_blank(int blank) -{ - u16 v; - - switch(blank) { - - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (hp680bl_powermode == FB_BLANK_UNBLANK) { - hp680bl_send_intensity(0); - hp680bl_powermode = blank; - sh_dac_disable(DAC_LCD_BRIGHTNESS); - v = inw(HD64461_GPBDR); - v |= HD64461_GPBDR_LCDOFF; - outw(v, HD64461_GPBDR); - } - break; - case FB_BLANK_UNBLANK: - if (hp680bl_powermode != FB_BLANK_UNBLANK) { - sh_dac_enable(DAC_LCD_BRIGHTNESS); - v = inw(HD64461_GPBDR); - v &= ~HD64461_GPBDR_LCDOFF; - outw(v, HD64461_GPBDR); - hp680bl_powermode = blank; - hp680bl_send_intensity(current_intensity); - } - break; - } + current_intensity = intensity; } + #ifdef CONFIG_PM -static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level) +static int hp680bl_suspend(struct platform_device *dev, pm_message_t state) { - if (level == SUSPEND_POWER_DOWN) - hp680bl_blank(FB_BLANK_POWERDOWN); + hp680bl_suspended = 1; + hp680bl_send_intensity(hp680_backlight_device); return 0; } -static int hp680bl_resume(struct device *dev, u32 level) +static int hp680bl_resume(struct platform_device *dev) { - if (level == RESUME_POWER_ON) - hp680bl_blank(FB_BLANK_UNBLANK); + hp680bl_suspended = 0; + hp680bl_send_intensity(hp680_backlight_device); return 0; } #else @@ -92,24 +84,9 @@ static int hp680bl_resume(struct device *dev, u32 level) #define hp680bl_resume NULL #endif - -static int hp680bl_set_power(struct backlight_device *bd, int state) +static int hp680bl_set_intensity(struct backlight_device *bd) { - hp680bl_blank(state); - return 0; -} - -static int hp680bl_get_power(struct backlight_device *bd) -{ - return hp680bl_powermode; -} - -static int hp680bl_set_intensity(struct backlight_device *bd, int intensity) -{ - if (intensity > HP680_MAX_INTENSITY) - intensity = HP680_MAX_INTENSITY; - hp680bl_send_intensity(intensity); - current_intensity = intensity; + hp680bl_send_intensity(bd); return 0; } @@ -120,65 +97,67 @@ static int hp680bl_get_intensity(struct backlight_device *bd) static struct backlight_properties hp680bl_data = { .owner = THIS_MODULE, - .get_power = hp680bl_get_power, - .set_power = hp680bl_set_power, .max_brightness = HP680_MAX_INTENSITY, .get_brightness = hp680bl_get_intensity, - .set_brightness = hp680bl_set_intensity, + .update_status = hp680bl_set_intensity, }; -static struct backlight_device *hp680_backlight_device; - -static int __init hp680bl_probe(struct device *dev) +static int __init hp680bl_probe(struct platform_device *dev) { hp680_backlight_device = backlight_device_register ("hp680-bl", NULL, &hp680bl_data); if (IS_ERR (hp680_backlight_device)) return PTR_ERR (hp680_backlight_device); - hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY); + hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY; + hp680bl_send_intensity(hp680_backlight_device); return 0; } -static int hp680bl_remove(struct device *dev) +static int hp680bl_remove(struct platform_device *dev) { backlight_device_unregister(hp680_backlight_device); return 0; } -static struct device_driver hp680bl_driver = { - .name = "hp680-bl", - .bus = &platform_bus_type, +static struct platform_driver hp680bl_driver = { .probe = hp680bl_probe, .remove = hp680bl_remove, .suspend = hp680bl_suspend, .resume = hp680bl_resume, + .driver = { + .name = "hp680-bl", + }, }; -static struct platform_device hp680bl_device = { - .name = "hp680-bl", - .id = -1, -}; +static struct platform_device *hp680bl_device; static int __init hp680bl_init(void) { int ret; - ret=driver_register(&hp680bl_driver); + ret = platform_driver_register(&hp680bl_driver); if (!ret) { - ret = platform_device_register(&hp680bl_device); - if (ret) - driver_unregister(&hp680bl_driver); + hp680bl_device = platform_device_alloc("hp680-bl", -1); + if (!hp680bl_device) + return -ENOMEM; + + ret = platform_device_add(hp680bl_device); + + if (ret) { + platform_device_put(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); + } } return ret; } static void __exit hp680bl_exit(void) { - platform_device_unregister(&hp680bl_device); - driver_unregister(&hp680bl_driver); + platform_device_unregister(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); } module_init(hp680bl_init); |