aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorAlberto Panizzo <maramaopercheseimorto@gmail.com>2009-12-18 10:42:11 -0500
committerRichard Purdie <rpurdie@linux.intel.com>2010-03-16 15:47:53 -0400
commite7fb9c4ad351a8da7c09e182bd2e7ccd043daf08 (patch)
treedc3dc3f491e01d987d7edd82f37fac994cd8ac7c /drivers/video
parenta3d3203e4bb40f253b1541e310dc0f9305be7c84 (diff)
backlight: Add Epson L4F00242T03 LCD driver
The Epson LCD L4F00242T03 is mounted on the Freescale i.MX31 PDK board. Based upon Marek Vasut work in l4f00242t03.c, this driver provides basic init and power on/off functionality for this device through the sysfs lcd interface. Unfortunately Datasheet for this device are not available and all the control sequences sent to the display were copied from the freescale driver that in the i.MX31 Linux BSP. As in the i.MX31PDK board the core and io suppliers are voltage regulators, that functionality is embedded here, but not strict. Signed-off-by: Alberto Panizzo <maramaopercheseimorto@gmail.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/backlight/Kconfig7
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/l4f00242t03.c256
3 files changed, 264 insertions, 0 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 0c77fc610212..c025c84601b0 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -31,6 +31,13 @@ config LCD_CORGI
31 Say y here to support the LCD panels usually found on SHARP 31 Say y here to support the LCD panels usually found on SHARP
32 corgi (C7x0) and spitz (Cxx00) models. 32 corgi (C7x0) and spitz (Cxx00) models.
33 33
34config LCD_L4F00242T03
35 tristate "Epson L4F00242T03 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO
37 help
38 SPI driver for Epson L4F00242T03. This provides basic support
39 for init and powering the LCD up/down through a sysfs interface.
40
34config LCD_LMS283GF05 41config LCD_LMS283GF05
35 tristate "Samsung LMS283GF05 LCD" 42 tristate "Samsung LMS283GF05 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 43 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 6c704d41462d..09d1f14d6257 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,6 +3,7 @@
3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o 3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o 4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
5obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o 5obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
6obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
6obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o 7obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
7obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o 8obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
8obj-$(CONFIG_LCD_ILI9320) += ili9320.o 9obj-$(CONFIG_LCD_ILI9320) += ili9320.o
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
new file mode 100644
index 000000000000..42d061e1403b
--- /dev/null
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -0,0 +1,256 @@
1/*
2 * l4f00242t03.c -- support for Epson L4F00242T03 LCD
3 *
4 * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
5 *
6 * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
7 * Inspired by Marek Vasut work in l4f00242t03.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/delay.h>
17#include <linux/gpio.h>
18#include <linux/lcd.h>
19#include <linux/regulator/consumer.h>
20
21#include <linux/spi/spi.h>
22#include <linux/spi/l4f00242t03.h>
23
24struct l4f00242t03_priv {
25 struct spi_device *spi;
26 struct lcd_device *ld;
27 int lcd_on:1;
28 struct regulator *io_reg;
29 struct regulator *core_reg;
30};
31
32
33static void l4f00242t03_reset(unsigned int gpio)
34{
35 pr_debug("l4f00242t03_reset.\n");
36 gpio_set_value(gpio, 1);
37 mdelay(100);
38 gpio_set_value(gpio, 0);
39 mdelay(10); /* tRES >= 100us */
40 gpio_set_value(gpio, 1);
41 mdelay(20);
42}
43
44#define param(x) ((x) | 0x100)
45
46static void l4f00242t03_lcd_init(struct spi_device *spi)
47{
48 struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
49 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
50 const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
51
52 dev_dbg(&spi->dev, "initializing LCD\n");
53
54 if (priv->io_reg) {
55 regulator_set_voltage(priv->io_reg, 1800000, 1800000);
56 regulator_enable(priv->io_reg);
57 }
58
59 if (priv->core_reg) {
60 regulator_set_voltage(priv->core_reg, 2800000, 2800000);
61 regulator_enable(priv->core_reg);
62 }
63
64 gpio_set_value(pdata->data_enable_gpio, 1);
65 msleep(60);
66 spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16));
67}
68
69static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power)
70{
71 struct l4f00242t03_priv *priv = lcd_get_data(ld);
72 struct spi_device *spi = priv->spi;
73
74 const u16 slpout = 0x11;
75 const u16 dison = 0x29;
76
77 const u16 slpin = 0x10;
78 const u16 disoff = 0x28;
79
80 if (power) {
81 if (priv->lcd_on)
82 return 0;
83
84 dev_dbg(&spi->dev, "turning on LCD\n");
85
86 spi_write(spi, (const u8 *)&slpout, sizeof(u16));
87 msleep(60);
88 spi_write(spi, (const u8 *)&dison, sizeof(u16));
89
90 priv->lcd_on = 1;
91 } else {
92 if (!priv->lcd_on)
93 return 0;
94
95 dev_dbg(&spi->dev, "turning off LCD\n");
96
97 spi_write(spi, (const u8 *)&disoff, sizeof(u16));
98 msleep(60);
99 spi_write(spi, (const u8 *)&slpin, sizeof(u16));
100
101 priv->lcd_on = 0;
102 }
103
104 return 0;
105}
106
107static struct lcd_ops l4f_ops = {
108 .set_power = l4f00242t03_lcd_power_set,
109 .get_power = NULL,
110};
111
112static int __devinit l4f00242t03_probe(struct spi_device *spi)
113{
114 struct l4f00242t03_priv *priv;
115 struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
116 int ret;
117
118 if (pdata == NULL) {
119 dev_err(&spi->dev, "Uninitialized platform data.\n");
120 return -EINVAL;
121 }
122
123 priv = kzalloc(sizeof(struct l4f00242t03_priv), GFP_KERNEL);
124
125 if (priv == NULL) {
126 dev_err(&spi->dev, "No memory for this device.\n");
127 ret = -ENOMEM;
128 goto err;
129 }
130
131 dev_set_drvdata(&spi->dev, priv);
132 spi->bits_per_word = 9;
133 spi_setup(spi);
134
135 priv->spi = spi;
136
137 ret = gpio_request(pdata->reset_gpio, "lcd l4f00242t03 reset");
138 if (ret) {
139 dev_err(&spi->dev,
140 "Unable to get the lcd l4f00242t03 reset gpio.\n");
141 return ret;
142 }
143
144 ret = gpio_direction_output(pdata->reset_gpio, 1);
145 if (ret)
146 goto err2;
147
148 ret = gpio_request(pdata->data_enable_gpio,
149 "lcd l4f00242t03 data enable");
150 if (ret) {
151 dev_err(&spi->dev,
152 "Unable to get the lcd l4f00242t03 data en gpio.\n");
153 return ret;
154 }
155
156 ret = gpio_direction_output(pdata->data_enable_gpio, 0);
157 if (ret)
158 goto err3;
159
160 if (pdata->io_supply) {
161 priv->io_reg = regulator_get(NULL, pdata->io_supply);
162
163 if (IS_ERR(priv->io_reg)) {
164 pr_err("%s: Unable to get the IO regulator\n",
165 __func__);
166 goto err3;
167 }
168 }
169
170 if (pdata->core_supply) {
171 priv->core_reg = regulator_get(NULL, pdata->core_supply);
172
173 if (IS_ERR(priv->core_reg)) {
174 pr_err("%s: Unable to get the core regulator\n",
175 __func__);
176 goto err4;
177 }
178 }
179
180 priv->ld = lcd_device_register("l4f00242t03",
181 &spi->dev, priv, &l4f_ops);
182 if (IS_ERR(priv->ld)) {
183 ret = PTR_ERR(priv->ld);
184 goto err5;
185 }
186
187 /* Init the LCD */
188 l4f00242t03_reset(pdata->reset_gpio);
189 l4f00242t03_lcd_init(spi);
190 l4f00242t03_lcd_power_set(priv->ld, 1);
191
192 dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n");
193
194 return 0;
195
196err5:
197 if (priv->core_reg)
198 regulator_put(priv->core_reg);
199err4:
200 if (priv->io_reg)
201 regulator_put(priv->io_reg);
202err3:
203 gpio_free(pdata->data_enable_gpio);
204err2:
205 gpio_free(pdata->reset_gpio);
206err:
207 kfree(priv);
208
209 return ret;
210}
211
212static int __devexit l4f00242t03_remove(struct spi_device *spi)
213{
214 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
215 struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data;
216
217 l4f00242t03_lcd_power_set(priv->ld, 0);
218 lcd_device_unregister(priv->ld);
219
220 gpio_free(pdata->data_enable_gpio);
221 gpio_free(pdata->reset_gpio);
222
223 if (priv->io_reg)
224 regulator_put(priv->core_reg);
225 if (priv->core_reg)
226 regulator_put(priv->io_reg);
227
228 kfree(priv);
229
230 return 0;
231}
232
233static struct spi_driver l4f00242t03_driver = {
234 .driver = {
235 .name = "l4f00242t03",
236 .owner = THIS_MODULE,
237 },
238 .probe = l4f00242t03_probe,
239 .remove = __devexit_p(l4f00242t03_remove),
240};
241
242static __init int l4f00242t03_init(void)
243{
244 return spi_register_driver(&l4f00242t03_driver);
245}
246
247static __exit void l4f00242t03_exit(void)
248{
249 spi_unregister_driver(&l4f00242t03_driver);
250}
251
252module_init(l4f00242t03_init);
253module_exit(l4f00242t03_exit);
254
255MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
256MODULE_DESCRIPTION("EPSON L4F00242T03 LCD");