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
6 Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
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
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.
22 +config BACKLIGHT_TOSA
23 + tristate "Sharp Tosa LCD/Backlight Driver (SL-6000)"
24 + depends on BACKLIGHT_CLASS_DEVICE && MACH_TOSA
30 + If you have a Sharp Zaurus SL-6000y enable this driver.
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
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
49 index 0000000..11a89c6
51 +++ b/drivers/video/backlight/tosa_bl.c
54 + * LCD / Backlight control code for Sharp SL-6000x (tosa)
56 + * Copyright (c) 2005 Dirk Opfer
57 + * Copyright (c) 2007 Dmitry Baryshkov
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.
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>
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>
81 +#define DAC_BASE 0x4e
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
91 +static unsigned short normal_i2c[] = { DAC_BASE, I2C_CLIENT_END };
94 +struct tosa_bl_data {
95 + struct i2c_client client;
98 + spinlock_t nssp_lock;
99 + struct ssp_dev nssp_dev;
100 + struct ssp_state nssp_state;
102 + struct backlight_device *bl_dev;
105 +static struct i2c_driver tosa_bl_driver;
107 +static void pxa_nssp_output(struct tosa_bl_data *data, unsigned char reg, unsigned char value)
109 + unsigned long flag;
111 + u32 dat = ( ((reg << 5) & 0xe0) | (value & 0x1f) );
112 + spin_lock_irqsave(&data->nssp_lock, flag);
114 + ssp_config(&data->nssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(128));
115 + ssp_enable(&data->nssp_dev);
117 + ssp_write_word(&data->nssp_dev,dat);
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);
126 +static void tosa_set_backlight(struct tosa_bl_data *data, int brightness)
128 + /* SetBacklightDuty */
129 + i2c_smbus_write_byte_data(&data->client, DAC_CH2, (unsigned char)brightness);
131 + /* SetBacklightVR */
133 + gpio_set_value(TOSA_TC6393XB_BL_C20MA, 1);
135 + gpio_set_value(TOSA_TC6393XB_BL_C20MA, 0);
137 + /* bl_enable GP04=1 otherwise GP04=0*/
138 + pxa_nssp_output(data, TG_GPODR2, brightness ? 0x01 : 0x00);
141 +static void tosa_lcd_tg_init(struct tosa_bl_data *data)
143 + dev_dbg(&data->bl_dev->dev, "tosa_lcd_init\n");
146 + set_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393XB_L3V_ON);
150 + gpio_set_value(TOSA_TC6393XB_TG_ON, 0);
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 */
157 +static void tosa_lcd_tg_on(struct tosa_bl_data *data/*, const struct fb_videomode *mode*/)
159 + const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
161 + tosa_lcd_tg_init(data);
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));
166 + /* TG LCD pannel power up */
167 + pxa_nssp_output(data, TG_PINICTL,0x4);
171 + pxa_nssp_output(data, TG_PINICTL,0x0);
174 + /* set common voltage */
175 + i2c_smbus_write_byte_data(&data->client, DAC_CH1, data->comadj);
178 +static void tosa_lcd_tg_off(struct tosa_bl_data *data)
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);
186 + /* TG LCD signal off */
187 + pxa_nssp_output(data, TG_PINICTL,0x6);
191 + gpio_set_value(TOSA_TC6393XB_TG_ON, 1);
195 + reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393XB_L3V_ON);
199 +static int tosa_bl_update_status(struct backlight_device *dev)
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);
205 + tosa_set_backlight(data, props->brightness);
208 + tosa_lcd_tg_off(data);
210 + tosa_lcd_tg_on(data);
215 +static int tosa_bl_get_brightness(struct backlight_device *dev)
217 + struct backlight_properties *props = &dev->props;
219 + return props->brightness;
222 +static struct backlight_ops tosa_bl_ops = {
223 + .get_brightness = tosa_bl_get_brightness,
224 + .update_status = tosa_bl_update_status,
227 +static int tosa_bl_detect_client(struct i2c_adapter *adapter, int address,
231 + struct i2c_client *client;
232 + struct tosa_bl_data *data;
234 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA ))
237 + if (!(data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL))) {
242 + client = &data->client;
243 + i2c_set_clientdata(client, data);
245 + client->addr = address;
246 + client->adapter = adapter;
247 + client->driver = &tosa_bl_driver;
249 + strlcpy(client->name, "tosa_bl", I2C_NAME_SIZE);
251 + spin_lock_init(&data->nssp_lock);
252 + data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
254 + err = gpio_request(TOSA_TC6393XB_BL_C20MA, "backlight");
256 + dev_dbg(&data->bl_dev->dev, "Unable to request gpio!\n");
260 + err = gpio_request(TOSA_TC6393XB_TG_ON, "tg");
262 + dev_dbg(&data->bl_dev->dev, "Unable to request gpio!\n");
266 + err = ssp_init(&data->nssp_dev,2,0);
268 + dev_err(&data->bl_dev->dev, "Unable to register NSSP handler!\n");
272 + /* Tell the i2c layer a new client has arrived */
273 + err = i2c_attach_client(client);
275 + goto err_i2c_attach;
277 + gpio_direction_output(TOSA_TC6393XB_BL_C20MA, 0);
278 + gpio_direction_output(TOSA_TC6393XB_TG_ON, 1);
280 + tosa_lcd_tg_init(data);
282 + data->bl_dev = backlight_device_register("tosa_bl",
283 + &client->dev, data, &tosa_bl_ops);
285 + goto err_bl_register;
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);
296 + tosa_set_backlight(data, 0);
297 + tosa_lcd_tg_off(data);
299 + err = i2c_detach_client(client);
303 + ssp_exit(&data->nssp_dev);
305 + gpio_free(TOSA_TC6393XB_TG_ON);
307 + gpio_free(TOSA_TC6393XB_BL_C20MA);
314 +static int tosa_bl_detach_client(struct i2c_client *client)
317 + struct tosa_bl_data *data = i2c_get_clientdata(client);
319 + backlight_device_unregister(data->bl_dev);
321 + tosa_set_backlight(data, 0);
322 + tosa_lcd_tg_off(data);
324 + /* Try to detach the client from i2c space */
325 + if ((err = i2c_detach_client(client)))
328 + ssp_exit(&data->nssp_dev);
330 + gpio_free(TOSA_TC6393XB_TG_ON);
331 + gpio_free(TOSA_TC6393XB_BL_C20MA);
339 +static int tosa_bl_suspend(struct i2c_client *client, pm_message_t mesg)
341 + struct tosa_bl_data *data = i2c_get_clientdata(client);
343 + tosa_lcd_tg_off(data);
344 + ssp_flush(&data->nssp_dev);
345 + ssp_save_state(&data->nssp_dev,&data->nssp_state);
350 +static int tosa_bl_resume(struct i2c_client *client)
352 + struct tosa_bl_data *data = i2c_get_clientdata(client);
354 + ssp_restore_state(&data->nssp_dev,&data->nssp_state);
355 + ssp_enable(&data->nssp_dev);
356 + tosa_bl_update_status(data->bl_dev);
361 +#define tosa_bl_suspend NULL
362 +#define tosa_bl_resume NULL
365 +static int tosa_bl_attach_adapter(struct i2c_adapter *adapter)
367 + return i2c_probe(adapter, &addr_data, &tosa_bl_detect_client);
370 +static struct i2c_driver tosa_bl_driver = {
375 + .attach_adapter = tosa_bl_attach_adapter,
376 + .detach_client = tosa_bl_detach_client,
378 + .suspend = tosa_bl_suspend,
379 + .resume = tosa_bl_resume,
382 +static int __init tosa_bl_init(void)
384 + return i2c_add_driver(&tosa_bl_driver);
387 +static void __exit tosa_bl_cleanup (void)
389 + i2c_del_driver(&tosa_bl_driver);
392 +module_init(tosa_bl_init);
393 +module_exit(tosa_bl_cleanup);
395 +MODULE_DESCRIPTION("Tosa LCD device");
396 +MODULE_AUTHOR("Dirk Opfer, Dmitry Baryshkov");
397 +MODULE_LICENSE("GPL v2");