1 From 8741ead92bc93e66740237e51b88b8690ebcbba3 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 6/7] Add ili8960 lcd driver
6 Includes the following changes from the jz-3.5 branch:
7 - Use module_spi_driver
11 Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
13 drivers/video/backlight/Kconfig | 7 +
14 drivers/video/backlight/Makefile | 1 +
15 drivers/video/backlight/ili8960.c | 262 +++++++++++++++++++++++++++++++++++++
16 3 files changed, 270 insertions(+)
17 create mode 100644 drivers/video/backlight/ili8960.c
19 --- a/drivers/video/backlight/Kconfig
20 +++ b/drivers/video/backlight/Kconfig
21 @@ -59,6 +59,13 @@ config LCD_LTV350QV
23 The LTV350QV panel is present on all ATSTK1000 boards.
26 + tristate "Ilitek ili8960 LCD driver"
27 + depends on LCD_CLASS_DEVICE && SPI
30 + Driver for the Ilitek ili8960 LCD controller chip.
33 tristate "ILI Technology ILI9221/ILI9222 support"
35 --- a/drivers/video/backlight/Makefile
36 +++ b/drivers/video/backlight/Makefile
37 @@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
38 obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
39 obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
40 obj-$(CONFIG_LCD_HX8357) += hx8357.o
41 +obj-$(CONFIG_LCD_ILI8960) += ili8960.o
42 obj-$(CONFIG_LCD_ILI922X) += ili922x.o
43 obj-$(CONFIG_LCD_ILI9320) += ili9320.o
44 obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
46 +++ b/drivers/video/backlight/ili8960.c
49 + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
50 + * Driver for Ilitek ili8960 LCD
52 + * This program is free software; you can redistribute it and/or modify it
53 + * under the terms of the GNU General Public License as published by the
54 + * Free Software Foundation; either version 2 of the License, or (at your
55 + * option) any later version.
57 + * You should have received a copy of the GNU General Public License along
58 + * with this program; if not, write to the Free Software Foundation, Inc.,
59 + * 675 Mass Ave, Cambridge, MA 02139, USA.
63 +#include <linux/module.h>
64 +#include <linux/spi/spi.h>
65 +#include <linux/lcd.h>
66 +#include <linux/delay.h>
69 + struct spi_device *spi;
70 + struct lcd_device *lcd;
72 + unsigned int brightness;
75 +#define ILI8960_REG_BRIGHTNESS 0x03
76 +#define ILI8960_REG_POWER 0x05
77 +#define ILI8960_REG_CONTRAST 0x0d
79 +static int ili8960_write_reg(struct spi_device *spi, uint8_t reg,
83 + buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f);
86 + return spi_write(spi, buf, sizeof(buf));
89 +static int ili8960_programm_power(struct spi_device *spi, bool enabled)
96 + ret = ili8960_write_reg(spi, ILI8960_REG_POWER, enabled ? 0xc7 : 0xc6);
104 +static int ili8960_set_power(struct lcd_device *lcd, int power)
106 + struct ili8960 *ili8960 = lcd_get_data(lcd);
109 + case FB_BLANK_UNBLANK:
110 + ili8960->enabled = true;
116 + return ili8960_programm_power(ili8960->spi, ili8960->enabled);
119 +static int ili8960_early_set_power(struct lcd_device *lcd, int power)
121 + struct ili8960 *ili8960 = lcd_get_data(lcd);
124 + case FB_BLANK_UNBLANK:
127 + ili8960->enabled = false;
131 + return ili8960_programm_power(ili8960->spi, ili8960->enabled);
134 +static int ili8960_get_power(struct lcd_device *lcd)
136 + struct ili8960 *ili8960 = lcd_get_data(lcd);
137 + return ili8960->enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
140 +static int ili8960_set_contrast(struct lcd_device *lcd, int contrast)
142 + struct ili8960 *ili8960 = lcd_get_data(lcd);
144 + return ili8960_write_reg(ili8960->spi, ILI8960_REG_CONTRAST, contrast);
147 +static int ili8960_set_mode(struct lcd_device *lcd, struct fb_videomode *mode)
149 + if (mode->xres != 320 && mode->yres != 240)
155 +static int ili8960_set_brightness(struct ili8960 *ili8960, int brightness)
159 + ret = ili8960_write_reg(ili8960->spi, ILI8960_REG_BRIGHTNESS, brightness);
162 + ili8960->brightness = brightness;
167 +static ssize_t ili8960_show_brightness(struct device *dev,
168 + struct device_attribute *attr, char *buf)
170 + struct lcd_device *ld = to_lcd_device(dev);
171 + struct ili8960 *ili8960 = lcd_get_data(ld);
173 + return sprintf(buf, "%u\n", ili8960->brightness);
176 +static ssize_t ili8960_store_brightness(struct device *dev,
177 + struct device_attribute *attr, const char *buf, size_t count)
179 + struct lcd_device *ld = to_lcd_device(dev);
180 + struct ili8960 *ili8960 = lcd_get_data(ld);
181 + unsigned long brightness;
184 + ret = kstrtoul(buf, 0, &brightness);
188 + if (brightness > 255)
191 + ili8960_set_brightness(ili8960, brightness);
197 +static DEVICE_ATTR(brightness, 0644, ili8960_show_brightness,
198 + ili8960_store_brightness);
200 +static struct lcd_ops ili8960_lcd_ops = {
201 + .set_power = ili8960_set_power,
202 + .early_set_power = ili8960_early_set_power,
203 + .get_power = ili8960_get_power,
204 + .set_contrast = ili8960_set_contrast,
205 + .set_mode = ili8960_set_mode,
208 +static int ili8960_probe(struct spi_device *spi)
211 + struct ili8960 *ili8960;
213 + ili8960 = devm_kzalloc(&spi->dev, sizeof(*ili8960), GFP_KERNEL);
217 + spi->bits_per_word = 8;
218 + spi->mode = SPI_MODE_3;
220 + ret = spi_setup(spi);
222 + dev_err(&spi->dev, "Failed to setup spi\n");
226 + ili8960->spi = spi;
228 + ili8960->lcd = lcd_device_register("ili8960-lcd", &spi->dev, ili8960,
231 + if (IS_ERR(ili8960->lcd)) {
232 + ret = PTR_ERR(ili8960->lcd);
233 + dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret);
237 + ili8960->lcd->props.max_contrast = 255;
239 + ret = device_create_file(&ili8960->lcd->dev, &dev_attr_brightness);
241 + goto err_unregister_lcd;
243 + ili8960_programm_power(ili8960->spi, true);
244 + ili8960->enabled = true;
246 + spi_set_drvdata(spi, ili8960);
248 + ili8960_write_reg(spi, 0x13, 0x01);
252 + lcd_device_unregister(ili8960->lcd);
256 +static int ili8960_remove(struct spi_device *spi)
258 + struct ili8960 *ili8960 = spi_get_drvdata(spi);
260 + device_remove_file(&ili8960->lcd->dev, &dev_attr_brightness);
261 + lcd_device_unregister(ili8960->lcd);
263 + spi_set_drvdata(spi, NULL);
269 +static int ili8960_suspend(struct spi_device *spi, pm_message_t state)
271 + struct ili8960 *ili8960 = spi_get_drvdata(spi);
273 + if (ili8960->enabled)
274 + ili8960_programm_power(ili8960->spi, false);
279 +static int ili8960_resume(struct spi_device *spi)
281 + struct ili8960 *ili8960 = spi_get_drvdata(spi);
283 + if (ili8960->enabled)
284 + ili8960_programm_power(ili8960->spi, true);
290 +#define ili8960_suspend NULL
291 +#define ili8960_resume NULL
294 +static struct spi_driver ili8960_driver = {
297 + .owner = THIS_MODULE,
299 + .probe = ili8960_probe,
300 + .remove = ili8960_remove,
301 + .suspend = ili8960_suspend,
302 + .resume = ili8960_resume,
304 +module_spi_driver(ili8960_driver);
306 +MODULE_AUTHOR("Lars-Peter Clausen");
307 +MODULE_LICENSE("GPL");
308 +MODULE_DESCRIPTION("LCD driver for Ilitek ili8960");
309 +MODULE_ALIAS("spi:ili8960");