Commit e4423781 authored by Richard Purdie's avatar Richard Purdie Committed by Linus Torvalds

[PATCH] backlight: LOCOMO Backlight Driver updates

Add backlight intensity control to the LOCOMO lcd/backlight driver using the
backlight class and add basic power management support.

This is a reimplementation and improvement of patches by John Lenz and Pavel
Machek
Signed-off-by: default avatarRichard Purdie <rpurdie@rpsys.net>
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Cc: Pavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f8020dc5
...@@ -629,21 +629,6 @@ static int locomo_resume(struct platform_device *dev) ...@@ -629,21 +629,6 @@ static int locomo_resume(struct platform_device *dev)
#endif #endif
#define LCM_ALC_EN 0x8000
void frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf)
{
unsigned long flags;
spin_lock_irqsave(&lchip->lock, flags);
locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
udelay(100);
locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
spin_unlock_irqrestore(&lchip->lock, flags);
}
/** /**
* locomo_probe - probe for a single LoCoMo chip. * locomo_probe - probe for a single LoCoMo chip.
* @phys_addr: physical address of device. * @phys_addr: physical address of device.
...@@ -698,14 +683,10 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) ...@@ -698,14 +683,10 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
, lchip->base + LOCOMO_GPD); , lchip->base + LOCOMO_GPD);
locomo_writel(0, lchip->base + LOCOMO_GIE); locomo_writel(0, lchip->base + LOCOMO_GIE);
/* FrontLight */ /* Frontlight */
locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
/* Same constants can be used for collie and poodle
(depending on CONFIG options in original sharp code)? */
frontlight_set(lchip, 163, 0, 148);
/* Longtime timer */ /* Longtime timer */
locomo_writel(0, lchip->base + LOCOMO_LTINT); locomo_writel(0, lchip->base + LOCOMO_LTINT);
/* SPI */ /* SPI */
...@@ -1062,6 +1043,30 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int ...@@ -1062,6 +1043,30 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
spin_unlock_irqrestore(&lchip->lock, flags); spin_unlock_irqrestore(&lchip->lock, flags);
} }
/*
* Frontlight control
*/
static struct locomo *locomo_chip_driver(struct locomo_dev *ldev);
void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
{
unsigned long flags;
struct locomo *lchip = locomo_chip_driver(dev);
if (vr)
locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 1);
else
locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 0);
spin_lock_irqsave(&lchip->lock, flags);
locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
udelay(100);
locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
spin_unlock_irqrestore(&lchip->lock, flags);
}
/* /*
* LoCoMo "Register Access Bus." * LoCoMo "Register Access Bus."
* *
......
...@@ -50,6 +50,14 @@ config BACKLIGHT_CORGI ...@@ -50,6 +50,14 @@ config BACKLIGHT_CORGI
If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x 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. backlight driver.
config BACKLIGHT_LOCOMO
tristate "Sharp LOCOMO LCD/Backlight Driver"
depends on BACKLIGHT_DEVICE && SHARP_LOCOMO
default y
help
If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
enable the LCD/backlight driver.
config BACKLIGHT_HP680 config BACKLIGHT_HP680
tristate "HP Jornada 680 Backlight Driver" tristate "HP Jornada 680 Backlight Driver"
depends on BACKLIGHT_DEVICE && SH_HP6XX depends on BACKLIGHT_DEVICE && SH_HP6XX
......
...@@ -4,4 +4,4 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o ...@@ -4,4 +4,4 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <asm/hardware/locomo.h> #include <asm/hardware/locomo.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -25,7 +27,10 @@ ...@@ -25,7 +27,10 @@
#include "../../../arch/arm/mach-sa1100/generic.h" #include "../../../arch/arm/mach-sa1100/generic.h"
static struct backlight_device *locomolcd_bl_device;
static struct locomo_dev *locomolcd_dev; static struct locomo_dev *locomolcd_dev;
static unsigned long locomolcd_flags;
#define LOCOMOLCD_SUSPENDED 0x01
static void locomolcd_on(int comadj) static void locomolcd_on(int comadj)
{ {
...@@ -89,12 +94,10 @@ void locomolcd_power(int on) ...@@ -89,12 +94,10 @@ void locomolcd_power(int on)
} }
/* read comadj */ /* read comadj */
if (comadj == -1) { if (comadj == -1 && machine_is_collie())
if (machine_is_poodle()) comadj = 128;
comadj = 118; if (comadj == -1 && machine_is_poodle())
if (machine_is_collie()) comadj = 118;
comadj = 128;
}
if (on) if (on)
locomolcd_on(comadj); locomolcd_on(comadj);
...@@ -105,26 +108,100 @@ void locomolcd_power(int on) ...@@ -105,26 +108,100 @@ void locomolcd_power(int on)
} }
EXPORT_SYMBOL(locomolcd_power); EXPORT_SYMBOL(locomolcd_power);
static int poodle_lcd_probe(struct locomo_dev *dev)
static int current_intensity;
static int locomolcd_set_intensity(struct backlight_device *bd)
{
int intensity = bd->props->brightness;
if (bd->props->power != FB_BLANK_UNBLANK)
intensity = 0;
if (bd->props->fb_blank != FB_BLANK_UNBLANK)
intensity = 0;
if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
intensity = 0;
switch (intensity) {
/* AC and non-AC are handled differently, but produce same results in sharp code? */
case 0: locomo_frontlight_set(locomolcd_dev, 0, 0, 161); break;
case 1: locomo_frontlight_set(locomolcd_dev, 117, 0, 161); break;
case 2: locomo_frontlight_set(locomolcd_dev, 163, 0, 148); break;
case 3: locomo_frontlight_set(locomolcd_dev, 194, 0, 161); break;
case 4: locomo_frontlight_set(locomolcd_dev, 194, 1, 161); break;
default:
return -ENODEV;
}
current_intensity = intensity;
return 0;
}
static int locomolcd_get_intensity(struct backlight_device *bd)
{
return current_intensity;
}
static struct backlight_properties locomobl_data = {
.owner = THIS_MODULE,
.get_brightness = locomolcd_get_intensity,
.update_status = locomolcd_set_intensity,
.max_brightness = 4,
};
#ifdef CONFIG_PM
static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state)
{
locomolcd_flags |= LOCOMOLCD_SUSPENDED;
locomolcd_set_intensity(locomolcd_bl_device);
return 0;
}
static int locomolcd_resume(struct locomo_dev *dev)
{
locomolcd_flags &= ~LOCOMOLCD_SUSPENDED;
locomolcd_set_intensity(locomolcd_bl_device);
return 0;
}
#else
#define locomolcd_suspend NULL
#define locomolcd_resume NULL
#endif
static int locomolcd_probe(struct locomo_dev *dev)
{ {
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
locomolcd_dev = dev; locomolcd_dev = dev;
locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0);
/* the poodle_lcd_power function is called for the first time /* the poodle_lcd_power function is called for the first time
* from fs_initcall, which is before locomo is activated. * from fs_initcall, which is before locomo is activated.
* We need to recall poodle_lcd_power here*/ * We need to recall poodle_lcd_power here*/
#ifdef CONFIG_MACH_POODLE if (machine_is_poodle())
locomolcd_power(1); locomolcd_power(1);
#endif
local_irq_restore(flags); local_irq_restore(flags);
locomolcd_bl_device = backlight_device_register("locomo-bl", NULL, &locomobl_data);
if (IS_ERR (locomolcd_bl_device))
return PTR_ERR (locomolcd_bl_device);
/* Set up frontlight so that screen is readable */
locomobl_data.brightness = 2;
locomolcd_set_intensity(locomolcd_bl_device);
return 0; return 0;
} }
static int poodle_lcd_remove(struct locomo_dev *dev) static int locomolcd_remove(struct locomo_dev *dev)
{ {
unsigned long flags; unsigned long flags;
backlight_device_unregister(locomolcd_bl_device);
local_irq_save(flags); local_irq_save(flags);
locomolcd_dev = NULL; locomolcd_dev = NULL;
local_irq_restore(flags); local_irq_restore(flags);
...@@ -136,19 +213,33 @@ static struct locomo_driver poodle_lcd_driver = { ...@@ -136,19 +213,33 @@ static struct locomo_driver poodle_lcd_driver = {
.name = "locomo-backlight", .name = "locomo-backlight",
}, },
.devid = LOCOMO_DEVID_BACKLIGHT, .devid = LOCOMO_DEVID_BACKLIGHT,
.probe = poodle_lcd_probe, .probe = locomolcd_probe,
.remove = poodle_lcd_remove, .remove = locomolcd_remove,
.suspend = locomolcd_suspend,
.resume = locomolcd_resume,
}; };
static int __init poodle_lcd_init(void)
static int __init locomolcd_init(void)
{ {
int ret = locomo_driver_register(&poodle_lcd_driver); int ret = locomo_driver_register(&poodle_lcd_driver);
if (ret) return ret; if (ret)
return ret;
#ifdef CONFIG_SA1100_COLLIE #ifdef CONFIG_SA1100_COLLIE
sa1100fb_lcd_power = locomolcd_power; sa1100fb_lcd_power = locomolcd_power;
#endif #endif
return 0; return 0;
} }
device_initcall(poodle_lcd_init);
static void __exit locomolcd_exit(void)
{
locomo_driver_unregister(&poodle_lcd_driver);
}
module_init(locomolcd_init);
module_exit(locomolcd_exit);
MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@suse.cz>");
MODULE_DESCRIPTION("Collie LCD driver");
MODULE_LICENSE("GPL");
...@@ -111,6 +111,8 @@ ...@@ -111,6 +111,8 @@
#define LOCOMO_ALS 0x00 /* Adjust light cycle */ #define LOCOMO_ALS 0x00 /* Adjust light cycle */
#define LOCOMO_ALD 0x04 /* Adjust light duty */ #define LOCOMO_ALD 0x04 /* Adjust light duty */
#define LOCOMO_ALC_EN 0x8000
/* Backlight controller: TFT signal */ /* Backlight controller: TFT signal */
#define LOCOMO_BACKLIGHT 0x38 #define LOCOMO_BACKLIGHT 0x38
#define LOCOMO_TC 0x00 /* TFT control signal */ #define LOCOMO_TC 0x00 /* TFT control signal */
...@@ -203,4 +205,7 @@ void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int ...@@ -203,4 +205,7 @@ void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int
/* M62332 control function */ /* M62332 control function */
void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel); void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel);
/* Frontlight control */
void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment