[target/xburst] level up target xburst to linux kernel version 3.2.1
[openwrt.git] / target / linux / xburst / patches-3.2 / 0007-Add-ili8960-lcd-driver.patch
1 From 2248fb9c47fe7e72c735d6c16aba27bf92e1673a Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Sun, 1 Aug 2010 21:19:40 +0200
4 Subject: [PATCH 07/21] Add ili8960 lcd driver
5
6 ---
7 drivers/video/backlight/Kconfig | 7 +
8 drivers/video/backlight/Makefile | 1 +
9 drivers/video/backlight/ili8960.c | 263 +++++++++++++++++++++++++++++++++++++
10 3 files changed, 271 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/video/backlight/ili8960.c
12
13 diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
14 index 278aeaa..f617883 100644
15 --- a/drivers/video/backlight/Kconfig
16 +++ b/drivers/video/backlight/Kconfig
17 @@ -59,6 +59,13 @@ config LCD_LTV350QV
18
19 The LTV350QV panel is present on all ATSTK1000 boards.
20
21 +config LCD_ILI8960
22 + tristate "Ilitek ili8960 LCD driver"
23 + depends on LCD_CLASS_DEVICE && SPI
24 + default n
25 + help
26 + Driver for the Ilitek ili8960 LCD controller chip.
27 +
28 config LCD_ILI9320
29 tristate
30 help
31 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
32 index fdd1fc4..01ec378 100644
33 --- a/drivers/video/backlight/Makefile
34 +++ b/drivers/video/backlight/Makefile
35 @@ -6,6 +6,7 @@ obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
36 obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
37 obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
38 obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
39 +obj-$(CONFIG_LCD_ILI8960) += ili8960.o
40 obj-$(CONFIG_LCD_ILI9320) += ili9320.o
41 obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
42 obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
43 diff --git a/drivers/video/backlight/ili8960.c b/drivers/video/backlight/ili8960.c
44 new file mode 100644
45 index 0000000..1438e92
46 --- /dev/null
47 +++ b/drivers/video/backlight/ili8960.c
48 @@ -0,0 +1,263 @@
49 +/*
50 + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
51 + * Driver for Ilitek ili8960 LCD
52 + *
53 + * This program is free software; you can redistribute it and/or modify it
54 + * under the terms of the GNU General Public License as published by the
55 + * Free Software Foundation; either version 2 of the License, or (at your
56 + * option) any later version.
57 + *
58 + * You should have received a copy of the GNU General Public License along
59 + * with this program; if not, write to the Free Software Foundation, Inc.,
60 + * 675 Mass Ave, Cambridge, MA 02139, USA.
61 + *
62 + */
63 +
64 +#include <linux/module.h>
65 +#include <linux/spi/spi.h>
66 +#include <linux/lcd.h>
67 +#include <linux/backlight.h>
68 +#include <linux/delay.h>
69 +
70 +struct ili8960 {
71 + struct spi_device *spi;
72 + struct lcd_device *lcd;
73 + struct backlight_device *bl;
74 + bool enabled;
75 + unsigned int brightness;
76 +};
77 +
78 +#define ILI8960_REG_BRIGHTNESS 0x03
79 +#define ILI8960_REG_POWER 0x05
80 +#define ILI8960_REG_CONTRAST 0x0d
81 +
82 +static int ili8960_write_reg(struct spi_device *spi, uint8_t reg,
83 + uint8_t data)
84 +{
85 + uint8_t buf[2];
86 + buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f);
87 + buf[1] = data;
88 +
89 + return spi_write(spi, buf, sizeof(buf));
90 +}
91 +
92 +static int ili8960_programm_power(struct spi_device *spi, bool enabled)
93 +{
94 + int ret;
95 +
96 + if (enabled)
97 + mdelay(20);
98 +
99 + ret = ili8960_write_reg(spi, ILI8960_REG_POWER, enabled ? 0xc7 : 0xc6);
100 +
101 + if (!enabled)
102 + mdelay(20);
103 +
104 + return ret;
105 +}
106 +
107 +static int ili8960_set_power(struct lcd_device *lcd, int power)
108 +{
109 + struct ili8960 *ili8960 = lcd_get_data(lcd);
110 +
111 + switch (power) {
112 + case FB_BLANK_UNBLANK:
113 + ili8960->enabled = true;
114 + break;
115 + default:
116 + ili8960->enabled = false;
117 + break;
118 + }
119 +
120 + return ili8960_programm_power(ili8960->spi, ili8960->enabled);
121 +}
122 +
123 +static int ili8960_get_power(struct lcd_device *lcd)
124 +{
125 + struct ili8960 *ili8960 = lcd_get_data(lcd);
126 + return ili8960->enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
127 +}
128 +
129 +static int ili8960_set_contrast(struct lcd_device *lcd, int contrast)
130 +{
131 + struct ili8960 *ili8960 = lcd_get_data(lcd);
132 +
133 + return ili8960_write_reg(ili8960->spi, ILI8960_REG_CONTRAST, contrast);
134 +}
135 +
136 +static int ili8960_set_mode(struct lcd_device *lcd, struct fb_videomode *mode)
137 +{
138 + if (mode->xres != 320 && mode->yres != 240)
139 + return -EINVAL;
140 +
141 + return 0;
142 +}
143 +
144 +static int ili8960_set_brightness(struct ili8960 *ili8960, int brightness)
145 +{
146 + int ret;
147 +
148 + ret = ili8960_write_reg(ili8960->spi, ILI8960_REG_BRIGHTNESS, brightness);
149 +
150 + if (ret == 0)
151 + ili8960->brightness = brightness;
152 +
153 + return ret;
154 +}
155 +
156 +static ssize_t ili8960_show_brightness(struct device *dev,
157 + struct device_attribute *attr, char *buf)
158 +{
159 + struct lcd_device *ld = to_lcd_device(dev);
160 + struct ili8960 *ili8960 = lcd_get_data(ld);
161 +
162 + return sprintf(buf, "%u\n", ili8960->brightness);
163 +}
164 +
165 +static ssize_t ili8960_store_brightness(struct device *dev,
166 + struct device_attribute *attr, const char *buf, size_t count)
167 +{
168 + struct lcd_device *ld = to_lcd_device(dev);
169 + struct ili8960 *ili8960 = lcd_get_data(ld);
170 + unsigned long brightness;
171 + int ret;
172 +
173 + ret = strict_strtoul(buf, 0, &brightness);
174 + if (ret)
175 + return ret;
176 +
177 + if (brightness > 255)
178 + return -EINVAL;
179 +
180 + ili8960_set_brightness(ili8960, brightness);
181 +
182 + return count;
183 +}
184 +
185 +
186 +static DEVICE_ATTR(brightness, 0644, ili8960_show_brightness,
187 + ili8960_store_brightness);
188 +
189 +static struct lcd_ops ili8960_lcd_ops = {
190 + .set_power = ili8960_set_power,
191 + .get_power = ili8960_get_power,
192 + .set_contrast = ili8960_set_contrast,
193 + .set_mode = ili8960_set_mode,
194 +};
195 +
196 +static int __devinit ili8960_probe(struct spi_device *spi)
197 +{
198 + int ret;
199 + struct ili8960 *ili8960;
200 +
201 + ili8960 = kmalloc(sizeof(*ili8960), GFP_KERNEL);
202 + if (!ili8960)
203 + return -ENOMEM;
204 +
205 + spi->bits_per_word = 8;
206 + spi->mode = SPI_MODE_3;
207 +
208 + ret = spi_setup(spi);
209 + if (ret) {
210 + dev_err(&spi->dev, "Failed to setup spi\n");
211 + goto err_free_ili8960;
212 + }
213 +
214 + ili8960->spi = spi;
215 +
216 + ili8960->lcd = lcd_device_register("ili8960-lcd", &spi->dev, ili8960,
217 + &ili8960_lcd_ops);
218 +
219 + if (IS_ERR(ili8960->lcd)) {
220 + ret = PTR_ERR(ili8960->lcd);
221 + dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret);
222 + goto err_free_ili8960;
223 + }
224 +
225 + ili8960->lcd->props.max_contrast = 255;
226 +
227 + ret = device_create_file(&ili8960->lcd->dev, &dev_attr_brightness);
228 + if (ret)
229 + goto err_unregister_lcd;
230 +
231 + ili8960_programm_power(ili8960->spi, true);
232 + ili8960->enabled = true;
233 +
234 + spi_set_drvdata(spi, ili8960);
235 +
236 + ili8960_write_reg(spi, 0x13, 0x01);
237 +
238 + return 0;
239 +err_unregister_lcd:
240 + lcd_device_unregister(ili8960->lcd);
241 +err_free_ili8960:
242 + kfree(ili8960);
243 + return ret;
244 +}
245 +
246 +static int __devexit ili8960_remove(struct spi_device *spi)
247 +{
248 + struct ili8960 *ili8960 = spi_get_drvdata(spi);
249 +
250 + device_remove_file(&ili8960->lcd->dev, &dev_attr_brightness);
251 + lcd_device_unregister(ili8960->lcd);
252 +
253 + spi_set_drvdata(spi, NULL);
254 + kfree(ili8960);
255 + return 0;
256 +}
257 +
258 +#ifdef CONFIG_PM
259 +
260 +static int ili8960_suspend(struct spi_device *spi, pm_message_t state)
261 +{
262 + struct ili8960 *ili8960 = spi_get_drvdata(spi);
263 +
264 + if (ili8960->enabled)
265 + ili8960_programm_power(ili8960->spi, false);
266 +
267 + return 0;
268 +}
269 +
270 +static int ili8960_resume(struct spi_device *spi)
271 +{
272 + struct ili8960 *ili8960 = spi_get_drvdata(spi);
273 +
274 + if (ili8960->enabled)
275 + ili8960_programm_power(ili8960->spi, true);
276 +
277 + return 0;
278 +}
279 +
280 +#else
281 +#define ili8960_suspend NULL
282 +#define ili8960_resume NULL
283 +#endif
284 +
285 +static struct spi_driver ili8960_driver = {
286 + .driver = {
287 + .name = "ili8960",
288 + .owner = THIS_MODULE,
289 + },
290 + .probe = ili8960_probe,
291 + .remove = __devexit_p(ili8960_remove),
292 + .suspend = ili8960_suspend,
293 + .resume = ili8960_resume,
294 +};
295 +
296 +static int __init ili8960_init(void)
297 +{
298 + return spi_register_driver(&ili8960_driver);
299 +}
300 +module_init(ili8960_init);
301 +
302 +static void __exit ili8960_exit(void)
303 +{
304 + spi_unregister_driver(&ili8960_driver);
305 +}
306 +module_exit(ili8960_exit)
307 +
308 +MODULE_AUTHOR("Lars-Peter Clausen");
309 +MODULE_LICENSE("GPL");
310 +MODULE_DESCRIPTION("LCD driver for Ilitek ili8960");
311 +MODULE_ALIAS("spi:ili8960");
312 --
313 1.7.5.4
314
This page took 0.062483 seconds and 5 git commands to generate.