blob: bd879b7ec1193442edb2623d56909c8a16ceb843 [file] [log] [blame]
Pavel Machek987132b2005-09-06 15:16:45 -07001/*
2 * Backlight control code for Sharp Zaurus SL-5500
3 *
4 * Copyright 2005 John Lenz <lenz@cs.wisc.edu>
5 * Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-)
6 * GPL v2
7 *
8 * This driver assumes single CPU. That's okay, because collie is
9 * slightly old hardware, and noone is going to retrofit second CPU to
10 * old PDA.
11 */
12
13/* LCD power functions */
14#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/interrupt.h>
Richard Purdiee4423782006-06-26 00:26:27 -070020#include <linux/fb.h>
21#include <linux/backlight.h>
Pavel Machek987132b2005-09-06 15:16:45 -070022
23#include <asm/hardware/locomo.h>
24#include <asm/irq.h>
Pavel Machek36a95bf2006-03-25 03:07:33 -080025#include <asm/mach/sharpsl_param.h>
26#include <asm/mach-types.h>
Pavel Machek987132b2005-09-06 15:16:45 -070027
Pavel Machek36a95bf2006-03-25 03:07:33 -080028#include "../../../arch/arm/mach-sa1100/generic.h"
Pavel Machek987132b2005-09-06 15:16:45 -070029
Richard Purdiee4423782006-06-26 00:26:27 -070030static struct backlight_device *locomolcd_bl_device;
Pavel Machek987132b2005-09-06 15:16:45 -070031static struct locomo_dev *locomolcd_dev;
Richard Purdiee4423782006-06-26 00:26:27 -070032static unsigned long locomolcd_flags;
33#define LOCOMOLCD_SUSPENDED 0x01
Pavel Machek987132b2005-09-06 15:16:45 -070034
35static void locomolcd_on(int comadj)
36{
37 locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
38 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1);
39 mdelay(2);
40
41 locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
42 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1);
43 mdelay(2);
44
45 locomo_m62332_senddata(locomolcd_dev, comadj, 0);
46 mdelay(5);
47
48 locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
49 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1);
50 mdelay(10);
51
52 /* TFTCRST | CPSOUT=0 | CPSEN */
53 locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
54
55 /* Set CPSD */
56 locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
57
58 /* TFTCRST | CPSOUT=0 | CPSEN */
59 locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
60 mdelay(10);
61
62 locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
63 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1);
64}
65
66static void locomolcd_off(int comadj)
67{
68 /* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
69 locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
70 mdelay(1);
71
72 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
73 mdelay(110);
74
75 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
76 mdelay(700);
77
78 /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
79 locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
80 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
81 locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
82}
83
84void locomolcd_power(int on)
85{
Pavel Machek36a95bf2006-03-25 03:07:33 -080086 int comadj = sharpsl_param.comadj;
Pavel Machek987132b2005-09-06 15:16:45 -070087 unsigned long flags;
88
89 local_irq_save(flags);
90
91 if (!locomolcd_dev) {
92 local_irq_restore(flags);
93 return;
94 }
95
96 /* read comadj */
Richard Purdiee4423782006-06-26 00:26:27 -070097 if (comadj == -1 && machine_is_collie())
98 comadj = 128;
99 if (comadj == -1 && machine_is_poodle())
100 comadj = 118;
Pavel Machek987132b2005-09-06 15:16:45 -0700101
102 if (on)
103 locomolcd_on(comadj);
104 else
105 locomolcd_off(comadj);
106
107 local_irq_restore(flags);
108}
109EXPORT_SYMBOL(locomolcd_power);
110
Richard Purdiee4423782006-06-26 00:26:27 -0700111
112static int current_intensity;
113
114static int locomolcd_set_intensity(struct backlight_device *bd)
115{
116 int intensity = bd->props->brightness;
117
118 if (bd->props->power != FB_BLANK_UNBLANK)
119 intensity = 0;
120 if (bd->props->fb_blank != FB_BLANK_UNBLANK)
121 intensity = 0;
122 if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
123 intensity = 0;
124
125 switch (intensity) {
126 /* AC and non-AC are handled differently, but produce same results in sharp code? */
127 case 0: locomo_frontlight_set(locomolcd_dev, 0, 0, 161); break;
128 case 1: locomo_frontlight_set(locomolcd_dev, 117, 0, 161); break;
129 case 2: locomo_frontlight_set(locomolcd_dev, 163, 0, 148); break;
130 case 3: locomo_frontlight_set(locomolcd_dev, 194, 0, 161); break;
131 case 4: locomo_frontlight_set(locomolcd_dev, 194, 1, 161); break;
132
133 default:
134 return -ENODEV;
135 }
136 current_intensity = intensity;
137 return 0;
138}
139
140static int locomolcd_get_intensity(struct backlight_device *bd)
141{
142 return current_intensity;
143}
144
145static struct backlight_properties locomobl_data = {
146 .owner = THIS_MODULE,
147 .get_brightness = locomolcd_get_intensity,
148 .update_status = locomolcd_set_intensity,
149 .max_brightness = 4,
150};
151
152#ifdef CONFIG_PM
153static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state)
154{
155 locomolcd_flags |= LOCOMOLCD_SUSPENDED;
156 locomolcd_set_intensity(locomolcd_bl_device);
157 return 0;
158}
159
160static int locomolcd_resume(struct locomo_dev *dev)
161{
162 locomolcd_flags &= ~LOCOMOLCD_SUSPENDED;
163 locomolcd_set_intensity(locomolcd_bl_device);
164 return 0;
165}
166#else
167#define locomolcd_suspend NULL
168#define locomolcd_resume NULL
169#endif
170
171static int locomolcd_probe(struct locomo_dev *dev)
Pavel Machek987132b2005-09-06 15:16:45 -0700172{
173 unsigned long flags;
174
175 local_irq_save(flags);
176 locomolcd_dev = dev;
177
Richard Purdiee4423782006-06-26 00:26:27 -0700178 locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0);
179
Pavel Machek987132b2005-09-06 15:16:45 -0700180 /* the poodle_lcd_power function is called for the first time
181 * from fs_initcall, which is before locomo is activated.
182 * We need to recall poodle_lcd_power here*/
Richard Purdiee4423782006-06-26 00:26:27 -0700183 if (machine_is_poodle())
184 locomolcd_power(1);
185
Pavel Machek987132b2005-09-06 15:16:45 -0700186 local_irq_restore(flags);
Richard Purdiee4423782006-06-26 00:26:27 -0700187
188 locomolcd_bl_device = backlight_device_register("locomo-bl", NULL, &locomobl_data);
189
190 if (IS_ERR (locomolcd_bl_device))
191 return PTR_ERR (locomolcd_bl_device);
192
193 /* Set up frontlight so that screen is readable */
194 locomobl_data.brightness = 2;
195 locomolcd_set_intensity(locomolcd_bl_device);
196
Pavel Machek987132b2005-09-06 15:16:45 -0700197 return 0;
198}
199
Richard Purdiee4423782006-06-26 00:26:27 -0700200static int locomolcd_remove(struct locomo_dev *dev)
Pavel Machek987132b2005-09-06 15:16:45 -0700201{
202 unsigned long flags;
Richard Purdiee4423782006-06-26 00:26:27 -0700203
204 backlight_device_unregister(locomolcd_bl_device);
Pavel Machek987132b2005-09-06 15:16:45 -0700205 local_irq_save(flags);
206 locomolcd_dev = NULL;
207 local_irq_restore(flags);
208 return 0;
209}
210
211static struct locomo_driver poodle_lcd_driver = {
212 .drv = {
213 .name = "locomo-backlight",
214 },
215 .devid = LOCOMO_DEVID_BACKLIGHT,
Richard Purdiee4423782006-06-26 00:26:27 -0700216 .probe = locomolcd_probe,
217 .remove = locomolcd_remove,
218 .suspend = locomolcd_suspend,
219 .resume = locomolcd_resume,
Pavel Machek987132b2005-09-06 15:16:45 -0700220};
221
Richard Purdiee4423782006-06-26 00:26:27 -0700222
223static int __init locomolcd_init(void)
Pavel Machek987132b2005-09-06 15:16:45 -0700224{
225 int ret = locomo_driver_register(&poodle_lcd_driver);
Richard Purdiee4423782006-06-26 00:26:27 -0700226 if (ret)
227 return ret;
Pavel Machek987132b2005-09-06 15:16:45 -0700228
229#ifdef CONFIG_SA1100_COLLIE
230 sa1100fb_lcd_power = locomolcd_power;
231#endif
232 return 0;
233}
Pavel Machek987132b2005-09-06 15:16:45 -0700234
Richard Purdiee4423782006-06-26 00:26:27 -0700235static void __exit locomolcd_exit(void)
236{
237 locomo_driver_unregister(&poodle_lcd_driver);
238}
239
240module_init(locomolcd_init);
241module_exit(locomolcd_exit);
242
243MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@suse.cz>");
244MODULE_DESCRIPTION("Collie LCD driver");
245MODULE_LICENSE("GPL");