merge of '0b604857bbf871639fdb43ee8380222e8ef64bb7'
[vuplus_openembedded] / packages / linux / linux-rp-2.6.24 / tosa / 0052-tosa-platform-backlight-support.patch
1 From c7537657bc33d4ee1616accd0259e160d57c5c1b Mon Sep 17 00:00:00 2001
2 From: Ian Molton <spyro@f2s.com>
3 Date: Wed, 9 Jan 2008 02:05:40 +0300
4 Subject: [PATCH 52/64] tosa platform backlight support
5
6 Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
7 ---
8  drivers/video/backlight/Kconfig   |   10 +
9  drivers/video/backlight/Makefile  |    1 +
10  drivers/video/backlight/tosa_bl.c |  345 +++++++++++++++++++++++++++++++++++++
11  3 files changed, 356 insertions(+), 0 deletions(-)
12  create mode 100644 drivers/video/backlight/tosa_bl.c
13
14 diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
15 index 9609a6c..f47a601 100644
16 --- a/drivers/video/backlight/Kconfig
17 +++ b/drivers/video/backlight/Kconfig
18 @@ -59,6 +59,16 @@ config BACKLIGHT_CORGI
19           known as the Corgi backlight driver. If you have a Sharp Zaurus
20           SL-C7xx, SL-Cxx00 or SL-6000x say y. Most users can say n.
21  
22 +config BACKLIGHT_TOSA
23 +       tristate "Sharp Tosa LCD/Backlight Driver (SL-6000)"
24 +       depends on BACKLIGHT_CLASS_DEVICE && MACH_TOSA
25 +       default y
26 +       select I2C
27 +       select I2C_PXA
28 +       select PXA_SSP
29 +       help
30 +         If you have a Sharp Zaurus SL-6000y enable this driver.
31 +
32  config BACKLIGHT_LOCOMO
33         tristate "Sharp LOCOMO LCD/Backlight Driver"
34         depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
35 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
36 index 965a78b..e8a6a7c 100644
37 --- a/drivers/video/backlight/Makefile
38 +++ b/drivers/video/backlight/Makefile
39 @@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_LTV350QV)      += ltv350qv.o
40  
41  obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
42  obj-$(CONFIG_BACKLIGHT_CORGI)  += corgi_bl.o
43 +obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
44  obj-$(CONFIG_BACKLIGHT_HP680)  += hp680_bl.o
45  obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
46  obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
47 diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
48 new file mode 100644
49 index 0000000..11a89c6
50 --- /dev/null
51 +++ b/drivers/video/backlight/tosa_bl.c
52 @@ -0,0 +1,345 @@
53 +/*
54 + *  LCD / Backlight control code for Sharp SL-6000x (tosa)
55 + *
56 + *  Copyright (c) 2005         Dirk Opfer
57 + *  Copyright (c) 2007         Dmitry Baryshkov
58 + *
59 + *  This program is free software; you can redistribute it and/or modify
60 + *  it under the terms of the GNU General Public License version 2 as
61 + *  published by the Free Software Foundation.
62 + *
63 + */
64 +
65 +#include <linux/kernel.h>
66 +#include <linux/module.h>
67 +#include <linux/i2c.h>
68 +#include <linux/backlight.h>
69 +#include <linux/platform_device.h>
70 +#include <linux/delay.h>
71 +#include <linux/fb.h>
72 +#include <linux/mfd/tc6393xb.h>
73 +
74 +#include <asm/hardware/scoop.h>
75 +#include <asm/mach/sharpsl_param.h>
76 +#include <asm/arch/ssp.h>
77 +#include <asm/arch/pxa-regs.h>
78 +#include <asm/arch/tosa.h>
79 +#include <asm/gpio.h>
80 +
81 +#define        DAC_BASE        0x4e
82 +#define DAC_CH1                0
83 +#define DAC_CH2                1
84 +
85 +#define TG_REG0_VQV    0x0001
86 +#define TG_REG0_COLOR  0x0002
87 +#define TG_REG0_UD     0x0004
88 +#define TG_REG0_LR     0x0008
89 +#define COMADJ_DEFAULT         97
90 +
91 +static unsigned short normal_i2c[] = { DAC_BASE, I2C_CLIENT_END };
92 +I2C_CLIENT_INSMOD;
93 +
94 +struct tosa_bl_data {
95 +       struct i2c_client       client;
96 +
97 +       int                     comadj;
98 +       spinlock_t              nssp_lock;
99 +       struct ssp_dev          nssp_dev;
100 +       struct ssp_state        nssp_state;
101 +
102 +       struct backlight_device *bl_dev;
103 +};
104 +
105 +static struct i2c_driver tosa_bl_driver;
106 +
107 +static void pxa_nssp_output(struct tosa_bl_data *data, unsigned char reg, unsigned char value)
108 +{
109 +       unsigned long flag;
110 +       u32 dummy;
111 +       u32 dat = ( ((reg << 5) & 0xe0) | (value & 0x1f) );
112 +       spin_lock_irqsave(&data->nssp_lock, flag);
113 +
114 +       ssp_config(&data->nssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(128));
115 +       ssp_enable(&data->nssp_dev);
116 +
117 +       ssp_write_word(&data->nssp_dev,dat);
118 +
119 +       /* Read null data back from device to prevent SSP overflow */
120 +       ssp_read_word(&data->nssp_dev, &dummy);
121 +       ssp_disable(&data->nssp_dev);
122 +       spin_unlock_irqrestore(&data->nssp_lock, flag);
123 +
124 +}
125 +
126 +static void tosa_set_backlight(struct tosa_bl_data *data, int brightness)
127 +{
128 +       /* SetBacklightDuty */
129 +       i2c_smbus_write_byte_data(&data->client, DAC_CH2, (unsigned char)brightness);
130 +
131 +       /* SetBacklightVR */
132 +       if (brightness)
133 +               gpio_set_value(TOSA_TC6393XB_BL_C20MA, 1);
134 +       else
135 +               gpio_set_value(TOSA_TC6393XB_BL_C20MA, 0);
136 +
137 +       /* bl_enable GP04=1 otherwise GP04=0*/
138 +       pxa_nssp_output(data, TG_GPODR2, brightness ? 0x01 : 0x00);
139 +}
140 +
141 +static void tosa_lcd_tg_init(struct tosa_bl_data *data)
142 +{
143 +       dev_dbg(&data->bl_dev->dev, "tosa_lcd_init\n");
144 +
145 +       /* L3V On */
146 +       set_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393XB_L3V_ON);
147 +       mdelay(60);
148 +
149 +       /* TG On */
150 +       gpio_set_value(TOSA_TC6393XB_TG_ON, 0);
151 +       mdelay(60);
152 +
153 +       pxa_nssp_output(data, TG_TPOSCTL,0x00); /* delayed 0clk TCTL signal for VGA */
154 +       pxa_nssp_output(data, TG_GPOSR,0x02);           /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
155 +}
156 +
157 +static void tosa_lcd_tg_on(struct tosa_bl_data *data/*, const struct fb_videomode *mode*/)
158 +{
159 +       const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
160 +
161 +       tosa_lcd_tg_init(data);
162 +
163 +       dev_dbg(&data->bl_dev->dev, "tosa_lcd_on\n");
164 +       pxa_nssp_output(data, TG_PNLCTL, value | (/*mode->yres == 320 ? 0 : */ TG_REG0_VQV));
165 +
166 +       /* TG LCD pannel power up */
167 +       pxa_nssp_output(data, TG_PINICTL,0x4);
168 +       mdelay(50);
169 +
170 +       /* TG LCD GVSS */
171 +       pxa_nssp_output(data, TG_PINICTL,0x0);
172 +       mdelay(50);
173 +
174 +       /* set common voltage */
175 +       i2c_smbus_write_byte_data(&data->client, DAC_CH1, data->comadj);
176 +}
177 +
178 +static void tosa_lcd_tg_off(struct tosa_bl_data *data)
179 +{
180 +       tosa_set_backlight(data, 0);
181 +       dev_dbg(&data->bl_dev->dev, "tosa_lcd_off\n");
182 +       /* TG LCD VHSA off */
183 +       pxa_nssp_output(data, TG_PINICTL,0x4);
184 +       mdelay(50);
185 +
186 +       /* TG LCD signal off */
187 +       pxa_nssp_output(data, TG_PINICTL,0x6);
188 +       mdelay(50);
189 +
190 +       /* TG Off */
191 +       gpio_set_value(TOSA_TC6393XB_TG_ON, 1);
192 +       mdelay(100);
193 +
194 +       /* L3V Off */
195 +       reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393XB_L3V_ON);
196 +}
197 +
198 +
199 +static int tosa_bl_update_status(struct backlight_device *dev)
200 +{
201 +       struct backlight_properties *props = &dev->props;
202 +       struct tosa_bl_data *data = dev_get_drvdata(&dev->dev);
203 +       int new_power = max(props->power, props->fb_blank);
204 +
205 +       tosa_set_backlight(data, props->brightness);
206 +
207 +       if (new_power)
208 +               tosa_lcd_tg_off(data);
209 +       else
210 +               tosa_lcd_tg_on(data);
211 +
212 +       return 0;
213 +}
214 +
215 +static int tosa_bl_get_brightness(struct backlight_device *dev)
216 +{
217 +       struct backlight_properties *props = &dev->props;
218 +
219 +       return props->brightness;
220 +}
221 +
222 +static struct backlight_ops tosa_bl_ops = {
223 +       .get_brightness         = tosa_bl_get_brightness,
224 +       .update_status          = tosa_bl_update_status,
225 +};
226 +
227 +static int tosa_bl_detect_client(struct i2c_adapter *adapter, int address,
228 +                        int kind)
229 +{
230 +       int err = 0;
231 +       struct i2c_client *client;
232 +       struct tosa_bl_data *data;
233 +
234 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA ))
235 +               goto out;
236 +
237 +       if (!(data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL))) {
238 +               err = -ENOMEM;
239 +               goto out;
240 +       }
241 +
242 +       client = &data->client;
243 +       i2c_set_clientdata(client, data);
244 +
245 +       client->addr = address;
246 +       client->adapter = adapter;
247 +       client->driver = &tosa_bl_driver;
248 +
249 +       strlcpy(client->name, "tosa_bl", I2C_NAME_SIZE);
250 +
251 +       spin_lock_init(&data->nssp_lock);
252 +       data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
253 +
254 +       err = gpio_request(TOSA_TC6393XB_BL_C20MA, "backlight");
255 +       if (err) {
256 +               dev_dbg(&data->bl_dev->dev, "Unable to request gpio!\n");
257 +               goto err_gpio_bl;
258 +       }
259 +
260 +       err = gpio_request(TOSA_TC6393XB_TG_ON, "tg");
261 +       if (err) {
262 +               dev_dbg(&data->bl_dev->dev, "Unable to request gpio!\n");
263 +               goto err_gpio_tg;
264 +       }
265 +
266 +       err = ssp_init(&data->nssp_dev,2,0);
267 +       if (err) {
268 +               dev_err(&data->bl_dev->dev, "Unable to register NSSP handler!\n");
269 +               goto err_ssp_init;
270 +       }
271 +
272 +       /* Tell the i2c layer a new client has arrived */
273 +       err = i2c_attach_client(client);
274 +       if (err)
275 +               goto err_i2c_attach;
276 +
277 +       gpio_direction_output(TOSA_TC6393XB_BL_C20MA, 0);
278 +       gpio_direction_output(TOSA_TC6393XB_TG_ON, 1);
279 +
280 +       tosa_lcd_tg_init(data);
281 +
282 +       data->bl_dev = backlight_device_register("tosa_bl",
283 +                       &client->dev, data, &tosa_bl_ops);
284 +       if (err)
285 +               goto err_bl_register;
286 +
287 +       data->bl_dev->props.brightness = 69;
288 +       data->bl_dev->props.max_brightness = 255;
289 +       data->bl_dev->props.power = FB_BLANK_UNBLANK;
290 +       backlight_update_status(data->bl_dev);
291 +
292 +
293 +       return 0;
294 +
295 +err_bl_register:
296 +       tosa_set_backlight(data, 0);
297 +       tosa_lcd_tg_off(data);
298 +
299 +       err = i2c_detach_client(client);
300 +       if (err)
301 +               return err;
302 +err_i2c_attach:
303 +       ssp_exit(&data->nssp_dev);
304 +err_ssp_init:
305 +       gpio_free(TOSA_TC6393XB_TG_ON);
306 +err_gpio_tg:
307 +       gpio_free(TOSA_TC6393XB_BL_C20MA);
308 +err_gpio_bl:
309 +       kfree(data);
310 +out:
311 +       return err;
312 +}
313 +
314 +static int tosa_bl_detach_client(struct i2c_client *client)
315 +{
316 +       int err = 0;
317 +       struct tosa_bl_data *data = i2c_get_clientdata(client);
318 +
319 +       backlight_device_unregister(data->bl_dev);
320 +
321 +       tosa_set_backlight(data, 0);
322 +       tosa_lcd_tg_off(data);
323 +
324 +       /* Try to detach the client from i2c space */
325 +       if ((err = i2c_detach_client(client)))
326 +               return err;
327 +
328 +       ssp_exit(&data->nssp_dev);
329 +
330 +       gpio_free(TOSA_TC6393XB_TG_ON);
331 +       gpio_free(TOSA_TC6393XB_BL_C20MA);
332 +
333 +       kfree(data);
334 +
335 +       return err;
336 +}
337 +
338 +#ifdef CONFIG_PM
339 +static int tosa_bl_suspend(struct i2c_client *client, pm_message_t mesg)
340 +{
341 +       struct tosa_bl_data *data = i2c_get_clientdata(client);
342 +
343 +       tosa_lcd_tg_off(data);
344 +       ssp_flush(&data->nssp_dev);
345 +       ssp_save_state(&data->nssp_dev,&data->nssp_state);
346 +
347 +       return 0;
348 +}
349 +
350 +static int tosa_bl_resume(struct i2c_client *client)
351 +{
352 +       struct tosa_bl_data *data = i2c_get_clientdata(client);
353 +
354 +       ssp_restore_state(&data->nssp_dev,&data->nssp_state);
355 +       ssp_enable(&data->nssp_dev);
356 +       tosa_bl_update_status(data->bl_dev);
357 +
358 +       return 0;
359 +}
360 +#else
361 +#define tosa_bl_suspend NULL
362 +#define tosa_bl_resume NULL
363 +#endif
364 +
365 +static int tosa_bl_attach_adapter(struct i2c_adapter *adapter)
366 +{
367 +       return i2c_probe(adapter, &addr_data, &tosa_bl_detect_client);
368 +}
369 +
370 +static struct i2c_driver tosa_bl_driver = {
371 +       .driver = {
372 +               .name   = "tosa_bl",
373 +       },
374 +
375 +       .attach_adapter = tosa_bl_attach_adapter,
376 +       .detach_client  = tosa_bl_detach_client,
377 +
378 +       .suspend        = tosa_bl_suspend,
379 +       .resume         = tosa_bl_resume,
380 +};
381 +
382 +static int __init tosa_bl_init(void)
383 +{
384 +       return i2c_add_driver(&tosa_bl_driver);
385 +}
386 +
387 +static void __exit tosa_bl_cleanup (void)
388 +{
389 +       i2c_del_driver(&tosa_bl_driver);
390 +}
391 +
392 +module_init(tosa_bl_init);
393 +module_exit(tosa_bl_cleanup);
394 +
395 +MODULE_DESCRIPTION("Tosa LCD device");
396 +MODULE_AUTHOR("Dirk Opfer, Dmitry Baryshkov");
397 +MODULE_LICENSE("GPL v2");
398 -- 
399 1.5.3.8
400