aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/displays
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-10-14 20:19:52 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-10-14 20:19:52 -0400
commitef26b7943c5821aaff1efc14c098840c49fe15c0 (patch)
treea91834ef396633c5c56a0597c2fc525e0684fc30 /drivers/video/omap2/displays
parent07aaae44f5a3962c3a410a6dd7936dfa7dece2b9 (diff)
parent3e28189038bb831512cf4f8313e1aead97c3e63f (diff)
Merge branch 'for-florian' of git://gitorious.org/linux-omap-dss2/linux into fbdev-next
Diffstat (limited to 'drivers/video/omap2/displays')
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-dvi.c363
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c113
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c747
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c594
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-taal.c123
8 files changed, 2157 insertions, 102 deletions
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 609a28073178..8d8e1fe1901c 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
10 Supports LCD Panel used in TI SDP3430 and EVM boards, 10 Supports LCD Panel used in TI SDP3430 and EVM boards,
11 OMAP3517 EVM boards and CM-T35. 11 OMAP3517 EVM boards and CM-T35.
12 12
13config PANEL_DVI
14 tristate "DVI output"
15 depends on OMAP2_DSS_DPI
16 help
17 Driver for external monitors, connected via DVI. The driver uses i2c
18 to read EDID information from the monitor.
19
13config PANEL_LGPHILIPS_LB035Q02 20config PANEL_LGPHILIPS_LB035Q02
14 tristate "LG.Philips LB035Q02 LCD Panel" 21 tristate "LG.Philips LB035Q02 LCD Panel"
15 depends on OMAP2_DSS_DPI && SPI 22 depends on OMAP2_DSS_DPI && SPI
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
19config PANEL_SHARP_LS037V7DW01 26config PANEL_SHARP_LS037V7DW01
20 tristate "Sharp LS037V7DW01 LCD Panel" 27 tristate "Sharp LS037V7DW01 LCD Panel"
21 depends on OMAP2_DSS_DPI 28 depends on OMAP2_DSS_DPI
22 select BACKLIGHT_CLASS_DEVICE 29 depends on BACKLIGHT_CLASS_DEVICE
23 help 30 help
24 LCD Panel used in TI's SDP3430 and EVM boards 31 LCD Panel used in TI's SDP3430 and EVM boards
25 32
26config PANEL_NEC_NL8048HL11_01B 33config PANEL_NEC_NL8048HL11_01B
27 tristate "NEC NL8048HL11-01B Panel" 34 tristate "NEC NL8048HL11-01B Panel"
28 depends on OMAP2_DSS_DPI 35 depends on OMAP2_DSS_DPI
36 depends on SPI
37 depends on BACKLIGHT_CLASS_DEVICE
29 help 38 help
30 This NEC NL8048HL11-01B panel is TFT LCD 39 This NEC NL8048HL11-01B panel is TFT LCD
31 used in the Zoom2/3/3630 sdp boards. 40 used in the Zoom2/3/3630 sdp boards.
32 41
42config PANEL_PICODLP
43 tristate "TI PICO DLP mini-projector"
44 depends on OMAP2_DSS && I2C
45 help
46 A mini-projector used in TI's SDP4430 and EVM boards
47 For more info please visit http://www.dlp.com/projector/
48
33config PANEL_TAAL 49config PANEL_TAAL
34 tristate "Taal DSI Panel" 50 tristate "Taal DSI Panel"
35 depends on OMAP2_DSS_DSI 51 depends on OMAP2_DSS_DSI
52 depends on BACKLIGHT_CLASS_DEVICE
36 help 53 help
37 Taal DSI command mode panel from TPO. 54 Taal DSI command mode panel from TPO.
38 55
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
45config PANEL_ACX565AKM 62config PANEL_ACX565AKM
46 tristate "ACX565AKM Panel" 63 tristate "ACX565AKM Panel"
47 depends on OMAP2_DSS_SDI && SPI 64 depends on OMAP2_DSS_SDI && SPI
48 select BACKLIGHT_CLASS_DEVICE 65 depends on BACKLIGHT_CLASS_DEVICE
49 help 66 help
50 This is the LCD panel used on Nokia N900 67 This is the LCD panel used on Nokia N900
68
69config PANEL_N8X0
70 tristate "N8X0 Panel"
71 depends on OMAP2_DSS_RFBI && SPI
72 depends on BACKLIGHT_CLASS_DEVICE
73 help
74 This is the LCD panel used on Nokia N8x0
51endmenu 75endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 0f601ab3abf4..fbfafc6eebb4 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,8 +1,11 @@
1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o 1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
2obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
2obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o 3obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
3obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o 4obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
4obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o 5obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
5 6
6obj-$(CONFIG_PANEL_TAAL) += panel-taal.o 7obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
8obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 9obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o 10obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
11obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c
new file mode 100644
index 000000000000..03eb14af33e0
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-dvi.c
@@ -0,0 +1,363 @@
1/*
2 * DVI output support
3 *
4 * Copyright (C) 2011 Texas Instruments Inc
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <video/omapdss.h>
23#include <linux/i2c.h>
24#include <drm/drm_edid.h>
25
26#include <video/omap-panel-dvi.h>
27
28static const struct omap_video_timings panel_dvi_default_timings = {
29 .x_res = 640,
30 .y_res = 480,
31
32 .pixel_clock = 23500,
33
34 .hfp = 48,
35 .hsw = 32,
36 .hbp = 80,
37
38 .vfp = 3,
39 .vsw = 4,
40 .vbp = 7,
41};
42
43struct panel_drv_data {
44 struct omap_dss_device *dssdev;
45
46 struct mutex lock;
47};
48
49static inline struct panel_dvi_platform_data
50*get_pdata(const struct omap_dss_device *dssdev)
51{
52 return dssdev->data;
53}
54
55static int panel_dvi_power_on(struct omap_dss_device *dssdev)
56{
57 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
58 int r;
59
60 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
61 return 0;
62
63 r = omapdss_dpi_display_enable(dssdev);
64 if (r)
65 goto err0;
66
67 if (pdata->platform_enable) {
68 r = pdata->platform_enable(dssdev);
69 if (r)
70 goto err1;
71 }
72
73 return 0;
74err1:
75 omapdss_dpi_display_disable(dssdev);
76err0:
77 return r;
78}
79
80static void panel_dvi_power_off(struct omap_dss_device *dssdev)
81{
82 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
83
84 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
85 return;
86
87 if (pdata->platform_disable)
88 pdata->platform_disable(dssdev);
89
90 omapdss_dpi_display_disable(dssdev);
91}
92
93static int panel_dvi_probe(struct omap_dss_device *dssdev)
94{
95 struct panel_drv_data *ddata;
96
97 ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
98 if (!ddata)
99 return -ENOMEM;
100
101 dssdev->panel.timings = panel_dvi_default_timings;
102 dssdev->panel.config = OMAP_DSS_LCD_TFT;
103
104 ddata->dssdev = dssdev;
105 mutex_init(&ddata->lock);
106
107 dev_set_drvdata(&dssdev->dev, ddata);
108
109 return 0;
110}
111
112static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
113{
114 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
115
116 mutex_lock(&ddata->lock);
117
118 dev_set_drvdata(&dssdev->dev, NULL);
119
120 mutex_unlock(&ddata->lock);
121
122 kfree(ddata);
123}
124
125static int panel_dvi_enable(struct omap_dss_device *dssdev)
126{
127 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
128 int r;
129
130 mutex_lock(&ddata->lock);
131
132 r = panel_dvi_power_on(dssdev);
133 if (r == 0)
134 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
135
136 mutex_unlock(&ddata->lock);
137
138 return r;
139}
140
141static void panel_dvi_disable(struct omap_dss_device *dssdev)
142{
143 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
144
145 mutex_lock(&ddata->lock);
146
147 panel_dvi_power_off(dssdev);
148
149 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
150
151 mutex_unlock(&ddata->lock);
152}
153
154static int panel_dvi_suspend(struct omap_dss_device *dssdev)
155{
156 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
157
158 mutex_lock(&ddata->lock);
159
160 panel_dvi_power_off(dssdev);
161
162 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
163
164 mutex_unlock(&ddata->lock);
165
166 return 0;
167}
168
169static int panel_dvi_resume(struct omap_dss_device *dssdev)
170{
171 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
172 int r;
173
174 mutex_lock(&ddata->lock);
175
176 r = panel_dvi_power_on(dssdev);
177 if (r == 0)
178 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
179
180 mutex_unlock(&ddata->lock);
181
182 return r;
183}
184
185static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
186 struct omap_video_timings *timings)
187{
188 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
189
190 mutex_lock(&ddata->lock);
191 dpi_set_timings(dssdev, timings);
192 mutex_unlock(&ddata->lock);
193}
194
195static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
196 struct omap_video_timings *timings)
197{
198 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
199
200 mutex_lock(&ddata->lock);
201 *timings = dssdev->panel.timings;
202 mutex_unlock(&ddata->lock);
203}
204
205static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
206 struct omap_video_timings *timings)
207{
208 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
209 int r;
210
211 mutex_lock(&ddata->lock);
212 r = dpi_check_timings(dssdev, timings);
213 mutex_unlock(&ddata->lock);
214
215 return r;
216}
217
218
219static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
220 unsigned char *buf, u16 count, u8 offset)
221{
222 int r, retries;
223
224 for (retries = 3; retries > 0; retries--) {
225 struct i2c_msg msgs[] = {
226 {
227 .addr = DDC_ADDR,
228 .flags = 0,
229 .len = 1,
230 .buf = &offset,
231 }, {
232 .addr = DDC_ADDR,
233 .flags = I2C_M_RD,
234 .len = count,
235 .buf = buf,
236 }
237 };
238
239 r = i2c_transfer(adapter, msgs, 2);
240 if (r == 2)
241 return 0;
242
243 if (r != -EAGAIN)
244 break;
245 }
246
247 return r < 0 ? r : -EIO;
248}
249
250static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
251 u8 *edid, int len)
252{
253 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
254 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
255 struct i2c_adapter *adapter;
256 int r, l, bytes_read;
257
258 mutex_lock(&ddata->lock);
259
260 if (pdata->i2c_bus_num == 0) {
261 r = -ENODEV;
262 goto err;
263 }
264
265 adapter = i2c_get_adapter(pdata->i2c_bus_num);
266 if (!adapter) {
267 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
268 pdata->i2c_bus_num);
269 r = -EINVAL;
270 goto err;
271 }
272
273 l = min(EDID_LENGTH, len);
274 r = panel_dvi_ddc_read(adapter, edid, l, 0);
275 if (r)
276 goto err;
277
278 bytes_read = l;
279
280 /* if there are extensions, read second block */
281 if (len > EDID_LENGTH && edid[0x7e] > 0) {
282 l = min(EDID_LENGTH, len - EDID_LENGTH);
283
284 r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
285 l, EDID_LENGTH);
286 if (r)
287 goto err;
288
289 bytes_read += l;
290 }
291
292 mutex_unlock(&ddata->lock);
293
294 return bytes_read;
295
296err:
297 mutex_unlock(&ddata->lock);
298 return r;
299}
300
301static bool panel_dvi_detect(struct omap_dss_device *dssdev)
302{
303 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
304 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
305 struct i2c_adapter *adapter;
306 unsigned char out;
307 int r;
308
309 mutex_lock(&ddata->lock);
310
311 if (pdata->i2c_bus_num == 0)
312 goto out;
313
314 adapter = i2c_get_adapter(pdata->i2c_bus_num);
315 if (!adapter)
316 goto out;
317
318 r = panel_dvi_ddc_read(adapter, &out, 1, 0);
319
320 mutex_unlock(&ddata->lock);
321
322 return r == 0;
323
324out:
325 mutex_unlock(&ddata->lock);
326 return true;
327}
328
329static struct omap_dss_driver panel_dvi_driver = {
330 .probe = panel_dvi_probe,
331 .remove = __exit_p(panel_dvi_remove),
332
333 .enable = panel_dvi_enable,
334 .disable = panel_dvi_disable,
335 .suspend = panel_dvi_suspend,
336 .resume = panel_dvi_resume,
337
338 .set_timings = panel_dvi_set_timings,
339 .get_timings = panel_dvi_get_timings,
340 .check_timings = panel_dvi_check_timings,
341
342 .read_edid = panel_dvi_read_edid,
343 .detect = panel_dvi_detect,
344
345 .driver = {
346 .name = "dvi",
347 .owner = THIS_MODULE,
348 },
349};
350
351static int __init panel_dvi_init(void)
352{
353 return omap_dss_register_driver(&panel_dvi_driver);
354}
355
356static void __exit panel_dvi_exit(void)
357{
358 omap_dss_unregister_driver(&panel_dvi_driver);
359}
360
361module_init(panel_dvi_init);
362module_exit(panel_dvi_exit);
363MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75653fb..519c47d2057f 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -58,30 +58,6 @@ struct panel_config {
58 58
59/* Panel configurations */ 59/* Panel configurations */
60static struct panel_config generic_dpi_panels[] = { 60static struct panel_config generic_dpi_panels[] = {
61 /* Generic Panel */
62 {
63 {
64 .x_res = 640,
65 .y_res = 480,
66
67 .pixel_clock = 23500,
68
69 .hfp = 48,
70 .hsw = 32,
71 .hbp = 80,
72
73 .vfp = 3,
74 .vsw = 4,
75 .vbp = 7,
76 },
77 .acbi = 0x0,
78 .acb = 0x0,
79 .config = OMAP_DSS_LCD_TFT,
80 .power_on_delay = 0,
81 .power_off_delay = 0,
82 .name = "generic",
83 },
84
85 /* Sharp LQ043T1DG01 */ 61 /* Sharp LQ043T1DG01 */
86 { 62 {
87 { 63 {
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
232 .power_off_delay = 0, 208 .power_off_delay = 0,
233 .name = "powertip_ph480272t", 209 .name = "powertip_ph480272t",
234 }, 210 },
211
212 /* Innolux AT070TN83 */
213 {
214 {
215 .x_res = 800,
216 .y_res = 480,
217
218 .pixel_clock = 40000,
219
220 .hsw = 48,
221 .hfp = 1,
222 .hbp = 1,
223
224 .vsw = 3,
225 .vfp = 12,
226 .vbp = 25,
227 },
228 .acbi = 0x0,
229 .acb = 0x28,
230 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
231 OMAP_DSS_LCD_IHS,
232 .power_on_delay = 0,
233 .power_off_delay = 0,
234 .name = "innolux_at070tn83",
235 },
236
237 /* NEC NL2432DR22-11B */
238 {
239 {
240 .x_res = 240,
241 .y_res = 320,
242
243 .pixel_clock = 5400,
244
245 .hsw = 3,
246 .hfp = 3,
247 .hbp = 39,
248
249 .vsw = 1,
250 .vfp = 2,
251 .vbp = 7,
252 },
253 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
254 OMAP_DSS_LCD_IHS,
255 .name = "nec_nl2432dr22-11b",
256 },
257
258 /* Unknown panel used in OMAP H4 */
259 {
260 {
261 .x_res = 240,
262 .y_res = 320,
263
264 .pixel_clock = 6250,
265
266 .hsw = 15,
267 .hfp = 15,
268 .hbp = 60,
269
270 .vsw = 1,
271 .vfp = 1,
272 .vbp = 1,
273 },
274 .config = OMAP_DSS_LCD_TFT,
275
276 .name = "h4",
277 },
278
279 /* Unknown panel used in Samsung OMAP2 Apollon */
280 {
281 {
282 .x_res = 480,
283 .y_res = 272,
284
285 .pixel_clock = 6250,
286
287 .hsw = 41,
288 .hfp = 2,
289 .hbp = 2,
290
291 .vsw = 10,
292 .vfp = 2,
293 .vbp = 2,
294 },
295 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
296 OMAP_DSS_LCD_IHS,
297
298 .name = "apollon",
299 },
235}; 300};
236 301
237struct panel_drv_data { 302struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
new file mode 100644
index 000000000000..150e8bae35a1
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -0,0 +1,747 @@
1/* #define DEBUG */
2
3#include <linux/module.h>
4#include <linux/delay.h>
5#include <linux/slab.h>
6#include <linux/gpio.h>
7#include <linux/spi/spi.h>
8#include <linux/backlight.h>
9#include <linux/fb.h>
10
11#include <video/omapdss.h>
12#include <video/omap-panel-n8x0.h>
13
14#define BLIZZARD_REV_CODE 0x00
15#define BLIZZARD_CONFIG 0x02
16#define BLIZZARD_PLL_DIV 0x04
17#define BLIZZARD_PLL_LOCK_RANGE 0x06
18#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
19#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
20#define BLIZZARD_PLL_MODE 0x0c
21#define BLIZZARD_CLK_SRC 0x0e
22#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
23#define BLIZZARD_MEM_BANK0_STATUS 0x14
24#define BLIZZARD_PANEL_CONFIGURATION 0x28
25#define BLIZZARD_HDISP 0x2a
26#define BLIZZARD_HNDP 0x2c
27#define BLIZZARD_VDISP0 0x2e
28#define BLIZZARD_VDISP1 0x30
29#define BLIZZARD_VNDP 0x32
30#define BLIZZARD_HSW 0x34
31#define BLIZZARD_VSW 0x38
32#define BLIZZARD_DISPLAY_MODE 0x68
33#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
34#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
35#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
36#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
37#define BLIZZARD_POWER_SAVE 0xE6
38#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
39
40/* Data source select */
41/* For S1D13745 */
42#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
43#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
44#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
45#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
46/* For S1D13744 */
47#define BLIZZARD_SRC_WRITE_LCD 0x00
48#define BLIZZARD_SRC_BLT_LCD 0x06
49
50#define BLIZZARD_COLOR_RGB565 0x01
51#define BLIZZARD_COLOR_YUV420 0x09
52
53#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
54#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
55
56#define MIPID_CMD_READ_DISP_ID 0x04
57#define MIPID_CMD_READ_RED 0x06
58#define MIPID_CMD_READ_GREEN 0x07
59#define MIPID_CMD_READ_BLUE 0x08
60#define MIPID_CMD_READ_DISP_STATUS 0x09
61#define MIPID_CMD_RDDSDR 0x0F
62#define MIPID_CMD_SLEEP_IN 0x10
63#define MIPID_CMD_SLEEP_OUT 0x11
64#define MIPID_CMD_DISP_OFF 0x28
65#define MIPID_CMD_DISP_ON 0x29
66
67static struct panel_drv_data {
68 struct mutex lock;
69
70 struct omap_dss_device *dssdev;
71 struct spi_device *spidev;
72 struct backlight_device *bldev;
73
74 int blizzard_ver;
75} s_drv_data;
76
77
78static inline
79struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
80{
81 return dssdev->data;
82}
83
84static inline
85struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
86{
87 return &s_drv_data;
88}
89
90
91static inline void blizzard_cmd(u8 cmd)
92{
93 omap_rfbi_write_command(&cmd, 1);
94}
95
96static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
97{
98 omap_rfbi_write_command(&cmd, 1);
99 omap_rfbi_write_data(buf, len);
100}
101
102static inline void blizzard_read(u8 cmd, u8 *buf, int len)
103{
104 omap_rfbi_write_command(&cmd, 1);
105 omap_rfbi_read_data(buf, len);
106}
107
108static u8 blizzard_read_reg(u8 cmd)
109{
110 u8 data;
111 blizzard_read(cmd, &data, 1);
112 return data;
113}
114
115static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
116 int x, int y, int w, int h)
117{
118 struct panel_drv_data *ddata = get_drv_data(dssdev);
119 u8 tmp[18];
120 int x_end, y_end;
121
122 x_end = x + w - 1;
123 y_end = y + h - 1;
124
125 tmp[0] = x;
126 tmp[1] = x >> 8;
127 tmp[2] = y;
128 tmp[3] = y >> 8;
129 tmp[4] = x_end;
130 tmp[5] = x_end >> 8;
131 tmp[6] = y_end;
132 tmp[7] = y_end >> 8;
133
134 /* scaling? */
135 tmp[8] = x;
136 tmp[9] = x >> 8;
137 tmp[10] = y;
138 tmp[11] = y >> 8;
139 tmp[12] = x_end;
140 tmp[13] = x_end >> 8;
141 tmp[14] = y_end;
142 tmp[15] = y_end >> 8;
143
144 tmp[16] = BLIZZARD_COLOR_RGB565;
145
146 if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
147 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
148 else
149 tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
150 BLIZZARD_SRC_WRITE_LCD :
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
152
153 omap_rfbi_configure(dssdev, 16, 8);
154
155 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
156
157 omap_rfbi_configure(dssdev, 16, 16);
158}
159
160static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
161 int wlen, u8 *rbuf, int rlen)
162{
163 struct spi_message m;
164 struct spi_transfer *x, xfer[4];
165 u16 w;
166 int r;
167
168 spi_message_init(&m);
169
170 memset(xfer, 0, sizeof(xfer));
171 x = &xfer[0];
172
173 cmd &= 0xff;
174 x->tx_buf = &cmd;
175 x->bits_per_word = 9;
176 x->len = 2;
177 spi_message_add_tail(x, &m);
178
179 if (wlen) {
180 x++;
181 x->tx_buf = wbuf;
182 x->len = wlen;
183 x->bits_per_word = 9;
184 spi_message_add_tail(x, &m);
185 }
186
187 if (rlen) {
188 x++;
189 x->rx_buf = &w;
190 x->len = 1;
191 spi_message_add_tail(x, &m);
192
193 if (rlen > 1) {
194 /* Arrange for the extra clock before the first
195 * data bit.
196 */
197 x->bits_per_word = 9;
198 x->len = 2;
199
200 x++;
201 x->rx_buf = &rbuf[1];
202 x->len = rlen - 1;
203 spi_message_add_tail(x, &m);
204 }
205 }
206
207 r = spi_sync(spi, &m);
208 if (r < 0)
209 dev_dbg(&spi->dev, "spi_sync %d\n", r);
210
211 if (rlen)
212 rbuf[0] = w & 0xff;
213}
214
215static inline void mipid_cmd(struct spi_device *spi, int cmd)
216{
217 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
218}
219
220static inline void mipid_write(struct spi_device *spi,
221 int reg, const u8 *buf, int len)
222{
223 mipid_transfer(spi, reg, buf, len, NULL, 0);
224}
225
226static inline void mipid_read(struct spi_device *spi,
227 int reg, u8 *buf, int len)
228{
229 mipid_transfer(spi, reg, NULL, 0, buf, len);
230}
231
232static void set_data_lines(struct spi_device *spi, int data_lines)
233{
234 u16 par;
235
236 switch (data_lines) {
237 case 16:
238 par = 0x150;
239 break;
240 case 18:
241 par = 0x160;
242 break;
243 case 24:
244 par = 0x170;
245 break;
246 }
247
248 mipid_write(spi, 0x3a, (u8 *)&par, 2);
249}
250
251static void send_init_string(struct spi_device *spi)
252{
253 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
254 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
255}
256
257static void send_display_on(struct spi_device *spi)
258{
259 mipid_cmd(spi, MIPID_CMD_DISP_ON);
260}
261
262static void send_display_off(struct spi_device *spi)
263{
264 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
265}
266
267static void send_sleep_out(struct spi_device *spi)
268{
269 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
270 msleep(120);
271}
272
273static void send_sleep_in(struct spi_device *spi)
274{
275 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
276 msleep(50);
277}
278
279static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
280{
281 int r;
282 struct panel_n8x0_data *bdata = get_board_data(dssdev);
283 struct panel_drv_data *ddata = get_drv_data(dssdev);
284 struct spi_device *spi = ddata->spidev;
285 u8 rev, conf;
286 u8 display_id[3];
287 const char *panel_name;
288
289 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
290 return 0;
291
292 gpio_direction_output(bdata->ctrl_pwrdown, 1);
293
294 if (bdata->platform_enable) {
295 r = bdata->platform_enable(dssdev);
296 if (r)
297 goto err_plat_en;
298 }
299
300 r = omapdss_rfbi_display_enable(dssdev);
301 if (r)
302 goto err_rfbi_en;
303
304 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
305 conf = blizzard_read_reg(BLIZZARD_CONFIG);
306
307 switch (rev & 0xfc) {
308 case 0x9c:
309 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
310 dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
311 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
312 break;
313 case 0xa4:
314 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
315 dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
316 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
317 break;
318 default:
319 dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
320 r = -ENODEV;
321 goto err_inv_chip;
322 }
323
324 /* panel */
325
326 gpio_direction_output(bdata->panel_reset, 1);
327
328 mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
329 dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
330 display_id[0], display_id[1], display_id[2]);
331
332 switch (display_id[0]) {
333 case 0x45:
334 panel_name = "lph8923";
335 break;
336 case 0x83:
337 panel_name = "ls041y3";
338 break;
339 default:
340 dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
341 display_id[0]);
342 r = -ENODEV;
343 goto err_inv_panel;
344 }
345
346 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
347 panel_name, display_id[1]);
348
349 send_sleep_out(spi);
350 send_init_string(spi);
351 set_data_lines(spi, 24);
352 send_display_on(spi);
353
354 return 0;
355
356err_inv_panel:
357 /*
358 * HACK: we should turn off the panel here, but there is some problem
359 * with the initialization sequence, and we fail to init the panel if we
360 * have turned it off
361 */
362 /* gpio_direction_output(bdata->panel_reset, 0); */
363err_inv_chip:
364 omapdss_rfbi_display_disable(dssdev);
365err_rfbi_en:
366 if (bdata->platform_disable)
367 bdata->platform_disable(dssdev);
368err_plat_en:
369 gpio_direction_output(bdata->ctrl_pwrdown, 0);
370 return r;
371}
372
373static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
374{
375 struct panel_n8x0_data *bdata = get_board_data(dssdev);
376 struct panel_drv_data *ddata = get_drv_data(dssdev);
377 struct spi_device *spi = ddata->spidev;
378
379 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
380 return;
381
382 send_display_off(spi);
383 send_sleep_in(spi);
384
385 if (bdata->platform_disable)
386 bdata->platform_disable(dssdev);
387
388 /*
389 * HACK: we should turn off the panel here, but there is some problem
390 * with the initialization sequence, and we fail to init the panel if we
391 * have turned it off
392 */
393 /* gpio_direction_output(bdata->panel_reset, 0); */
394 gpio_direction_output(bdata->ctrl_pwrdown, 0);
395 omapdss_rfbi_display_disable(dssdev);
396}
397
398static const struct rfbi_timings n8x0_panel_timings = {
399 .cs_on_time = 0,
400
401 .we_on_time = 9000,
402 .we_off_time = 18000,
403 .we_cycle_time = 36000,
404
405 .re_on_time = 9000,
406 .re_off_time = 27000,
407 .re_cycle_time = 36000,
408
409 .access_time = 27000,
410 .cs_off_time = 36000,
411
412 .cs_pulse_width = 0,
413};
414
415static int n8x0_bl_update_status(struct backlight_device *dev)
416{
417 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
418 struct panel_n8x0_data *bdata = get_board_data(dssdev);
419 struct panel_drv_data *ddata = get_drv_data(dssdev);
420 int r;
421 int level;
422
423 mutex_lock(&ddata->lock);
424
425 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
426 dev->props.power == FB_BLANK_UNBLANK)
427 level = dev->props.brightness;
428 else
429 level = 0;
430
431 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
432
433 if (!bdata->set_backlight)
434 r = -EINVAL;
435 else
436 r = bdata->set_backlight(dssdev, level);
437
438 mutex_unlock(&ddata->lock);
439
440 return r;
441}
442
443static int n8x0_bl_get_intensity(struct backlight_device *dev)
444{
445 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
446 dev->props.power == FB_BLANK_UNBLANK)
447 return dev->props.brightness;
448
449 return 0;
450}
451
452static const struct backlight_ops n8x0_bl_ops = {
453 .get_brightness = n8x0_bl_get_intensity,
454 .update_status = n8x0_bl_update_status,
455};
456
457static int n8x0_panel_probe(struct omap_dss_device *dssdev)
458{
459 struct panel_n8x0_data *bdata = get_board_data(dssdev);
460 struct panel_drv_data *ddata;
461 struct backlight_device *bldev;
462 struct backlight_properties props;
463 int r;
464
465 dev_dbg(&dssdev->dev, "probe\n");
466
467 if (!bdata)
468 return -EINVAL;
469
470 s_drv_data.dssdev = dssdev;
471
472 ddata = &s_drv_data;
473
474 mutex_init(&ddata->lock);
475
476 dssdev->panel.config = OMAP_DSS_LCD_TFT;
477 dssdev->panel.timings.x_res = 800;
478 dssdev->panel.timings.y_res = 480;
479 dssdev->ctrl.pixel_size = 16;
480 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
481
482 memset(&props, 0, sizeof(props));
483 props.max_brightness = 127;
484 props.type = BACKLIGHT_PLATFORM;
485 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
486 dssdev, &n8x0_bl_ops, &props);
487 if (IS_ERR(bldev)) {
488 r = PTR_ERR(bldev);
489 dev_err(&dssdev->dev, "register backlight failed\n");
490 return r;
491 }
492
493 ddata->bldev = bldev;
494
495 bldev->props.fb_blank = FB_BLANK_UNBLANK;
496 bldev->props.power = FB_BLANK_UNBLANK;
497 bldev->props.brightness = 127;
498
499 n8x0_bl_update_status(bldev);
500
501 return 0;
502}
503
504static void n8x0_panel_remove(struct omap_dss_device *dssdev)
505{
506 struct panel_drv_data *ddata = get_drv_data(dssdev);
507 struct backlight_device *bldev;
508
509 dev_dbg(&dssdev->dev, "remove\n");
510
511 bldev = ddata->bldev;
512 bldev->props.power = FB_BLANK_POWERDOWN;
513 n8x0_bl_update_status(bldev);
514 backlight_device_unregister(bldev);
515
516 dev_set_drvdata(&dssdev->dev, NULL);
517}
518
519static int n8x0_panel_enable(struct omap_dss_device *dssdev)
520{
521 struct panel_drv_data *ddata = get_drv_data(dssdev);
522 int r;
523
524 dev_dbg(&dssdev->dev, "enable\n");
525
526 mutex_lock(&ddata->lock);
527
528 rfbi_bus_lock();
529
530 r = n8x0_panel_power_on(dssdev);
531
532 rfbi_bus_unlock();
533
534 if (r) {
535 mutex_unlock(&ddata->lock);
536 return r;
537 }
538
539 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
540
541 mutex_unlock(&ddata->lock);
542
543 return 0;
544}
545
546static void n8x0_panel_disable(struct omap_dss_device *dssdev)
547{
548 struct panel_drv_data *ddata = get_drv_data(dssdev);
549
550 dev_dbg(&dssdev->dev, "disable\n");
551
552 mutex_lock(&ddata->lock);
553
554 rfbi_bus_lock();
555
556 n8x0_panel_power_off(dssdev);
557
558 rfbi_bus_unlock();
559
560 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
561
562 mutex_unlock(&ddata->lock);
563}
564
565static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
566{
567 struct panel_drv_data *ddata = get_drv_data(dssdev);
568
569 dev_dbg(&dssdev->dev, "suspend\n");
570
571 mutex_lock(&ddata->lock);
572
573 rfbi_bus_lock();
574
575 n8x0_panel_power_off(dssdev);
576
577 rfbi_bus_unlock();
578
579 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
580
581 mutex_unlock(&ddata->lock);
582
583 return 0;
584}
585
586static int n8x0_panel_resume(struct omap_dss_device *dssdev)
587{
588 struct panel_drv_data *ddata = get_drv_data(dssdev);
589 int r;
590
591 dev_dbg(&dssdev->dev, "resume\n");
592
593 mutex_lock(&ddata->lock);
594
595 rfbi_bus_lock();
596
597 r = n8x0_panel_power_on(dssdev);
598
599 rfbi_bus_unlock();
600
601 if (r) {
602 mutex_unlock(&ddata->lock);
603 return r;
604 }
605
606 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
607
608 mutex_unlock(&ddata->lock);
609
610 return 0;
611}
612
613static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
614 struct omap_video_timings *timings)
615{
616 *timings = dssdev->panel.timings;
617}
618
619static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
620 u16 *xres, u16 *yres)
621{
622 *xres = dssdev->panel.timings.x_res;
623 *yres = dssdev->panel.timings.y_res;
624}
625
626static void update_done(void *data)
627{
628 rfbi_bus_unlock();
629}
630
631static int n8x0_panel_update(struct omap_dss_device *dssdev,
632 u16 x, u16 y, u16 w, u16 h)
633{
634 struct panel_drv_data *ddata = get_drv_data(dssdev);
635
636 dev_dbg(&dssdev->dev, "update\n");
637
638 mutex_lock(&ddata->lock);
639 rfbi_bus_lock();
640
641 omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
642
643 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
644
645 omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
646
647 mutex_unlock(&ddata->lock);
648
649 return 0;
650}
651
652static int n8x0_panel_sync(struct omap_dss_device *dssdev)
653{
654 struct panel_drv_data *ddata = get_drv_data(dssdev);
655
656 dev_dbg(&dssdev->dev, "sync\n");
657
658 mutex_lock(&ddata->lock);
659 rfbi_bus_lock();
660 rfbi_bus_unlock();
661 mutex_unlock(&ddata->lock);
662
663 return 0;
664}
665
666static struct omap_dss_driver n8x0_panel_driver = {
667 .probe = n8x0_panel_probe,
668 .remove = n8x0_panel_remove,
669
670 .enable = n8x0_panel_enable,
671 .disable = n8x0_panel_disable,
672 .suspend = n8x0_panel_suspend,
673 .resume = n8x0_panel_resume,
674
675 .update = n8x0_panel_update,
676 .sync = n8x0_panel_sync,
677
678 .get_resolution = n8x0_panel_get_resolution,
679 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
680
681 .get_timings = n8x0_panel_get_timings,
682
683 .driver = {
684 .name = "n8x0_panel",
685 .owner = THIS_MODULE,
686 },
687};
688
689/* PANEL */
690
691static int mipid_spi_probe(struct spi_device *spi)
692{
693 dev_dbg(&spi->dev, "mipid_spi_probe\n");
694
695 spi->mode = SPI_MODE_0;
696
697 s_drv_data.spidev = spi;
698
699 return 0;
700}
701
702static int mipid_spi_remove(struct spi_device *spi)
703{
704 dev_dbg(&spi->dev, "mipid_spi_remove\n");
705 return 0;
706}
707
708static struct spi_driver mipid_spi_driver = {
709 .driver = {
710 .name = "lcd_mipid",
711 .bus = &spi_bus_type,
712 .owner = THIS_MODULE,
713 },
714 .probe = mipid_spi_probe,
715 .remove = __devexit_p(mipid_spi_remove),
716};
717
718static int __init n8x0_panel_drv_init(void)
719{
720 int r;
721
722 r = spi_register_driver(&mipid_spi_driver);
723 if (r) {
724 pr_err("n8x0_panel: spi driver registration failed\n");
725 return r;
726 }
727
728 r = omap_dss_register_driver(&n8x0_panel_driver);
729 if (r) {
730 pr_err("n8x0_panel: dss driver registration failed\n");
731 spi_unregister_driver(&mipid_spi_driver);
732 return r;
733 }
734
735 return 0;
736}
737
738static void __exit n8x0_panel_drv_exit(void)
739{
740 spi_unregister_driver(&mipid_spi_driver);
741
742 omap_dss_unregister_driver(&n8x0_panel_driver);
743}
744
745module_init(n8x0_panel_drv_init);
746module_exit(n8x0_panel_drv_exit);
747MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
new file mode 100644
index 000000000000..98ebdaddab5a
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -0,0 +1,594 @@
1/*
2 * picodlp panel driver
3 * picodlp_i2c_driver: i2c_client driver
4 *
5 * Copyright (C) 2009-2011 Texas Instruments
6 * Author: Mythri P K <mythripk@ti.com>
7 * Mayuresh Janorkar <mayur@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/module.h>
23#include <linux/input.h>
24#include <linux/platform_device.h>
25#include <linux/interrupt.h>
26#include <linux/firmware.h>
27#include <linux/slab.h>
28#include <linux/mutex.h>
29#include <linux/i2c.h>
30#include <linux/delay.h>
31#include <linux/gpio.h>
32
33#include <video/omapdss.h>
34#include <video/omap-panel-picodlp.h>
35
36#include "panel-picodlp.h"
37
38struct picodlp_data {
39 struct mutex lock;
40 struct i2c_client *picodlp_i2c_client;
41};
42
43static struct i2c_board_info picodlp_i2c_board_info = {
44 I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
45};
46
47struct picodlp_i2c_data {
48 struct mutex xfer_lock;
49};
50
51static struct i2c_device_id picodlp_i2c_id[] = {
52 { "picodlp_i2c_driver", 0 },
53};
54
55struct picodlp_i2c_command {
56 u8 reg;
57 u32 value;
58};
59
60static struct omap_video_timings pico_ls_timings = {
61 .x_res = 864,
62 .y_res = 480,
63 .hsw = 7,
64 .hfp = 11,
65 .hbp = 7,
66
67 .pixel_clock = 19200,
68
69 .vsw = 2,
70 .vfp = 3,
71 .vbp = 14,
72};
73
74static inline struct picodlp_panel_data
75 *get_panel_data(const struct omap_dss_device *dssdev)
76{
77 return (struct picodlp_panel_data *) dssdev->data;
78}
79
80static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
81{
82 u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
83 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
84 struct i2c_msg msg[2];
85
86 mutex_lock(&picodlp_i2c_data->xfer_lock);
87
88 msg[0].addr = client->addr;
89 msg[0].flags = 0;
90 msg[0].len = 2;
91 msg[0].buf = read_cmd;
92
93 msg[1].addr = client->addr;
94 msg[1].flags = I2C_M_RD;
95 msg[1].len = 4;
96 msg[1].buf = data;
97
98 i2c_transfer(client->adapter, msg, 2);
99 mutex_unlock(&picodlp_i2c_data->xfer_lock);
100 return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
101}
102
103static int picodlp_i2c_write_block(struct i2c_client *client,
104 u8 *data, int len)
105{
106 struct i2c_msg msg;
107 int i, r, msg_count = 1;
108
109 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
110
111 if (len < 1 || len > 32) {
112 dev_err(&client->dev,
113 "too long syn_write_block len %d\n", len);
114 return -EIO;
115 }
116 mutex_lock(&picodlp_i2c_data->xfer_lock);
117
118 msg.addr = client->addr;
119 msg.flags = 0;
120 msg.len = len;
121 msg.buf = data;
122 r = i2c_transfer(client->adapter, &msg, msg_count);
123 mutex_unlock(&picodlp_i2c_data->xfer_lock);
124
125 /*
126 * i2c_transfer returns:
127 * number of messages sent in case of success
128 * a negative error number in case of failure
129 */
130 if (r != msg_count)
131 goto err;
132
133 /* In case of success */
134 for (i = 0; i < len; i++)
135 dev_dbg(&client->dev,
136 "addr %x bw 0x%02x[%d]: 0x%02x\n",
137 client->addr, data[0] + i, i, data[i]);
138
139 return 0;
140err:
141 dev_err(&client->dev, "picodlp_i2c_write error\n");
142 return r;
143}
144
145static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
146{
147 u8 data[5];
148 int i;
149
150 data[0] = reg;
151 for (i = 1; i < 5; i++)
152 data[i] = (value >> (32 - (i) * 8)) & 0xFF;
153
154 return picodlp_i2c_write_block(client, data, 5);
155}
156
157static int picodlp_i2c_write_array(struct i2c_client *client,
158 const struct picodlp_i2c_command commands[],
159 int count)
160{
161 int i, r = 0;
162 for (i = 0; i < count; i++) {
163 r = picodlp_i2c_write(client, commands[i].reg,
164 commands[i].value);
165 if (r)
166 return r;
167 }
168 return r;
169}
170
171static int picodlp_wait_for_dma_done(struct i2c_client *client)
172{
173 u8 trial = 100;
174
175 do {
176 msleep(1);
177 if (!trial--)
178 return -ETIMEDOUT;
179 } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
180
181 return 0;
182}
183
184/**
185 * picodlp_i2c_init: i2c_initialization routine
186 * client: i2c_client for communication
187 *
188 * return
189 * 0 : Success, no error
190 * error code : Failure
191 */
192static int picodlp_i2c_init(struct i2c_client *client)
193{
194 int r;
195 static const struct picodlp_i2c_command init_cmd_set1[] = {
196 {SOFT_RESET, 1},
197 {DMD_PARK_TRIGGER, 1},
198 {MISC_REG, 5},
199 {SEQ_CONTROL, 0},
200 {SEQ_VECTOR, 0x100},
201 {DMD_BLOCK_COUNT, 7},
202 {DMD_VCC_CONTROL, 0x109},
203 {DMD_PARK_PULSE_COUNT, 0xA},
204 {DMD_PARK_PULSE_WIDTH, 0xB},
205 {DMD_PARK_DELAY, 0x2ED},
206 {DMD_SHADOW_ENABLE, 0},
207 {FLASH_OPCODE, 0xB},
208 {FLASH_DUMMY_BYTES, 1},
209 {FLASH_ADDR_BYTES, 3},
210 {PBC_CONTROL, 0},
211 {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
212 {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
213 {CMT_SPLASH_LUT_START_ADDR, 0},
214 {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
215 {PBC_CONTROL, 1},
216 };
217
218 static const struct picodlp_i2c_command init_cmd_set2[] = {
219 {PBC_CONTROL, 0},
220 {CMT_SPLASH_LUT_DEST_SELECT, 0},
221 {PBC_CONTROL, 0},
222 {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
223 {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
224 {SEQ_RESET_LUT_START_ADDR, 0},
225 {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
226 {PBC_CONTROL, 1},
227 };
228
229 static const struct picodlp_i2c_command init_cmd_set3[] = {
230 {PBC_CONTROL, 0},
231 {SEQ_RESET_LUT_DEST_SELECT, 0},
232 {PBC_CONTROL, 0},
233 {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
234 {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
235 {SEQ_RESET_LUT_START_ADDR, 0},
236 {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
237 {PBC_CONTROL, 1},
238 };
239
240 static const struct picodlp_i2c_command init_cmd_set4[] = {
241 {PBC_CONTROL, 0},
242 {SEQ_RESET_LUT_DEST_SELECT, 0},
243 {SDC_ENABLE, 1},
244 {AGC_CTRL, 7},
245 {CCA_C1A, 0x100},
246 {CCA_C1B, 0x0},
247 {CCA_C1C, 0x0},
248 {CCA_C2A, 0x0},
249 {CCA_C2B, 0x100},
250 {CCA_C2C, 0x0},
251 {CCA_C3A, 0x0},
252 {CCA_C3B, 0x0},
253 {CCA_C3C, 0x100},
254 {CCA_C7A, 0x100},
255 {CCA_C7B, 0x100},
256 {CCA_C7C, 0x100},
257 {CCA_ENABLE, 1},
258 {CPU_IF_MODE, 1},
259 {SHORT_FLIP, 1},
260 {CURTAIN_CONTROL, 0},
261 {DMD_PARK_TRIGGER, 0},
262 {R_DRIVE_CURRENT, 0x298},
263 {G_DRIVE_CURRENT, 0x298},
264 {B_DRIVE_CURRENT, 0x298},
265 {RGB_DRIVER_ENABLE, 7},
266 {SEQ_CONTROL, 0},
267 {ACTGEN_CONTROL, 0x10},
268 {SEQUENCE_MODE, SEQ_LOCK},
269 {DATA_FORMAT, RGB888},
270 {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
271 {INPUT_SOURCE, PARALLEL_RGB},
272 {CPU_IF_SYNC_METHOD, 1},
273 {SEQ_CONTROL, 1}
274 };
275
276 r = picodlp_i2c_write_array(client, init_cmd_set1,
277 ARRAY_SIZE(init_cmd_set1));
278 if (r)
279 return r;
280
281 r = picodlp_wait_for_dma_done(client);
282 if (r)
283 return r;
284
285 r = picodlp_i2c_write_array(client, init_cmd_set2,
286 ARRAY_SIZE(init_cmd_set2));
287 if (r)
288 return r;
289
290 r = picodlp_wait_for_dma_done(client);
291 if (r)
292 return r;
293
294 r = picodlp_i2c_write_array(client, init_cmd_set3,
295 ARRAY_SIZE(init_cmd_set3));
296 if (r)
297 return r;
298
299 r = picodlp_wait_for_dma_done(client);
300 if (r)
301 return r;
302
303 r = picodlp_i2c_write_array(client, init_cmd_set4,
304 ARRAY_SIZE(init_cmd_set4));
305 if (r)
306 return r;
307
308 return 0;
309}
310
311static int picodlp_i2c_probe(struct i2c_client *client,
312 const struct i2c_device_id *id)
313{
314 struct picodlp_i2c_data *picodlp_i2c_data;
315
316 picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
317
318 if (!picodlp_i2c_data)
319 return -ENOMEM;
320
321 mutex_init(&picodlp_i2c_data->xfer_lock);
322 i2c_set_clientdata(client, picodlp_i2c_data);
323
324 return 0;
325}
326
327static int picodlp_i2c_remove(struct i2c_client *client)
328{
329 struct picodlp_i2c_data *picodlp_i2c_data =
330 i2c_get_clientdata(client);
331 kfree(picodlp_i2c_data);
332 return 0;
333}
334
335static struct i2c_driver picodlp_i2c_driver = {
336 .driver = {
337 .name = "picodlp_i2c_driver",
338 },
339 .probe = picodlp_i2c_probe,
340 .remove = picodlp_i2c_remove,
341 .id_table = picodlp_i2c_id,
342};
343
344static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
345{
346 int r, trial = 100;
347 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
348 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
349
350 if (dssdev->platform_enable) {
351 r = dssdev->platform_enable(dssdev);
352 if (r)
353 return r;
354 }
355
356 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
357 msleep(1);
358 gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
359
360 while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
361 if (!trial--) {
362 dev_err(&dssdev->dev, "emu_done signal not"
363 " going high\n");
364 return -ETIMEDOUT;
365 }
366 msleep(5);
367 }
368 /*
369 * As per dpp2600 programming guide,
370 * it is required to sleep for 1000ms after emu_done signal goes high
371 * then only i2c commands can be successfully sent to dpp2600
372 */
373 msleep(1000);
374 r = omapdss_dpi_display_enable(dssdev);
375 if (r) {
376 dev_err(&dssdev->dev, "failed to enable DPI\n");
377 goto err1;
378 }
379
380 r = picodlp_i2c_init(picod->picodlp_i2c_client);
381 if (r)
382 goto err;
383
384 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
385
386 return r;
387err:
388 omapdss_dpi_display_disable(dssdev);
389err1:
390 if (dssdev->platform_disable)
391 dssdev->platform_disable(dssdev);
392
393 return r;
394}
395
396static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
397{
398 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
399
400 omapdss_dpi_display_disable(dssdev);
401
402 gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
403 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
404
405 if (dssdev->platform_disable)
406 dssdev->platform_disable(dssdev);
407}
408
409static int picodlp_panel_probe(struct omap_dss_device *dssdev)
410{
411 struct picodlp_data *picod;
412 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
413 struct i2c_adapter *adapter;
414 struct i2c_client *picodlp_i2c_client;
415 int r = 0, picodlp_adapter_id;
416
417 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF |
418 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS;
419 dssdev->panel.acb = 0x0;
420 dssdev->panel.timings = pico_ls_timings;
421
422 picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
423 if (!picod)
424 return -ENOMEM;
425
426 mutex_init(&picod->lock);
427
428 picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
429
430 adapter = i2c_get_adapter(picodlp_adapter_id);
431 if (!adapter) {
432 dev_err(&dssdev->dev, "can't get i2c adapter\n");
433 r = -ENODEV;
434 goto err;
435 }
436
437 picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
438 if (!picodlp_i2c_client) {
439 dev_err(&dssdev->dev, "can't add i2c device::"
440 " picodlp_i2c_client is NULL\n");
441 r = -ENODEV;
442 goto err;
443 }
444
445 picod->picodlp_i2c_client = picodlp_i2c_client;
446
447 dev_set_drvdata(&dssdev->dev, picod);
448 return r;
449err:
450 kfree(picod);
451 return r;
452}
453
454static void picodlp_panel_remove(struct omap_dss_device *dssdev)
455{
456 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
457
458 i2c_unregister_device(picod->picodlp_i2c_client);
459 dev_set_drvdata(&dssdev->dev, NULL);
460 dev_dbg(&dssdev->dev, "removing picodlp panel\n");
461
462 kfree(picod);
463}
464
465static int picodlp_panel_enable(struct omap_dss_device *dssdev)
466{
467 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
468 int r;
469
470 dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
471
472 mutex_lock(&picod->lock);
473 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
474 mutex_unlock(&picod->lock);
475 return -EINVAL;
476 }
477
478 r = picodlp_panel_power_on(dssdev);
479 mutex_unlock(&picod->lock);
480
481 return r;
482}
483
484static void picodlp_panel_disable(struct omap_dss_device *dssdev)
485{
486 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
487
488 mutex_lock(&picod->lock);
489 /* Turn off DLP Power */
490 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
491 picodlp_panel_power_off(dssdev);
492
493 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
494 mutex_unlock(&picod->lock);
495
496 dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
497}
498
499static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
500{
501 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
502
503 mutex_lock(&picod->lock);
504 /* Turn off DLP Power */
505 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
506 mutex_unlock(&picod->lock);
507 dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
508 " panel is not ACTIVE\n");
509 return -EINVAL;
510 }
511
512 picodlp_panel_power_off(dssdev);
513
514 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
515 mutex_unlock(&picod->lock);
516
517 dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
518 return 0;
519}
520
521static int picodlp_panel_resume(struct omap_dss_device *dssdev)
522{
523 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
524 int r;
525
526 mutex_lock(&picod->lock);
527 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
528 mutex_unlock(&picod->lock);
529 dev_err(&dssdev->dev, "unable to resume picodlp panel,"
530 " panel is not ACTIVE\n");
531 return -EINVAL;
532 }
533
534 r = picodlp_panel_power_on(dssdev);
535 mutex_unlock(&picod->lock);
536 dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
537 return r;
538}
539
540static void picodlp_get_resolution(struct omap_dss_device *dssdev,
541 u16 *xres, u16 *yres)
542{
543 *xres = dssdev->panel.timings.x_res;
544 *yres = dssdev->panel.timings.y_res;
545}
546
547static struct omap_dss_driver picodlp_driver = {
548 .probe = picodlp_panel_probe,
549 .remove = picodlp_panel_remove,
550
551 .enable = picodlp_panel_enable,
552 .disable = picodlp_panel_disable,
553
554 .get_resolution = picodlp_get_resolution,
555
556 .suspend = picodlp_panel_suspend,
557 .resume = picodlp_panel_resume,
558
559 .driver = {
560 .name = "picodlp_panel",
561 .owner = THIS_MODULE,
562 },
563};
564
565static int __init picodlp_init(void)
566{
567 int r = 0;
568
569 r = i2c_add_driver(&picodlp_i2c_driver);
570 if (r) {
571 printk(KERN_WARNING "picodlp_i2c_driver" \
572 " registration failed\n");
573 return r;
574 }
575
576 r = omap_dss_register_driver(&picodlp_driver);
577 if (r)
578 i2c_del_driver(&picodlp_i2c_driver);
579
580 return r;
581}
582
583static void __exit picodlp_exit(void)
584{
585 i2c_del_driver(&picodlp_i2c_driver);
586 omap_dss_unregister_driver(&picodlp_driver);
587}
588
589module_init(picodlp_init);
590module_exit(picodlp_exit);
591
592MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
593MODULE_DESCRIPTION("picodlp driver");
594MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
new file mode 100644
index 000000000000..a34b431a7267
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-picodlp.h
@@ -0,0 +1,288 @@
1/*
2 * Header file required by picodlp panel driver
3 *
4 * Copyright (C) 2009-2011 Texas Instruments
5 * Author: Mythri P K <mythripk@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H
21#define __OMAP2_DISPLAY_PANEL_PICODLP_H
22
23/* Commands used for configuring picodlp panel */
24
25#define MAIN_STATUS 0x03
26#define PBC_CONTROL 0x08
27#define INPUT_SOURCE 0x0B
28#define INPUT_RESOLUTION 0x0C
29#define DATA_FORMAT 0x0D
30#define IMG_ROTATION 0x0E
31#define LONG_FLIP 0x0F
32#define SHORT_FLIP 0x10
33#define TEST_PAT_SELECT 0x11
34#define R_DRIVE_CURRENT 0x12
35#define G_DRIVE_CURRENT 0x13
36#define B_DRIVE_CURRENT 0x14
37#define READ_REG_SELECT 0x15
38#define RGB_DRIVER_ENABLE 0x16
39
40#define CPU_IF_MODE 0x18
41#define FRAME_RATE 0x19
42#define CPU_IF_SYNC_METHOD 0x1A
43#define CPU_IF_SOF 0x1B
44#define CPU_IF_EOF 0x1C
45#define CPU_IF_SLEEP 0x1D
46
47#define SEQUENCE_MODE 0x1E
48#define SOFT_RESET 0x1F
49#define FRONT_END_RESET 0x21
50#define AUTO_PWR_ENABLE 0x22
51
52#define VSYNC_LINE_DELAY 0x23
53#define CPU_PI_HORIZ_START 0x24
54#define CPU_PI_VERT_START 0x25
55#define CPU_PI_HORIZ_WIDTH 0x26
56#define CPU_PI_VERT_HEIGHT 0x27
57
58#define PIXEL_MASK_CROP 0x28
59#define CROP_FIRST_LINE 0x29
60#define CROP_LAST_LINE 0x2A
61#define CROP_FIRST_PIXEL 0x2B
62#define CROP_LAST_PIXEL 0x2C
63#define DMD_PARK_TRIGGER 0x2D
64
65#define MISC_REG 0x30
66
67/* AGC registers */
68#define AGC_CTRL 0x50
69#define AGC_CLIPPED_PIXS 0x55
70#define AGC_BRIGHT_PIXS 0x56
71#define AGC_BG_PIXS 0x57
72#define AGC_SAFETY_MARGIN 0x17
73
74/* Color Coordinate Adjustment registers */
75#define CCA_ENABLE 0x5E
76#define CCA_C1A 0x5F
77#define CCA_C1B 0x60
78#define CCA_C1C 0x61
79#define CCA_C2A 0x62
80#define CCA_C2B 0x63
81#define CCA_C2C 0x64
82#define CCA_C3A 0x65
83#define CCA_C3B 0x66
84#define CCA_C3C 0x67
85#define CCA_C7A 0x71
86#define CCA_C7B 0x72
87#define CCA_C7C 0x73
88
89/**
90 * DLP Pico Processor 2600 comes with flash
91 * We can do DMA operations from flash for accessing Look Up Tables
92 */
93#define DMA_STATUS 0x100
94#define FLASH_ADDR_BYTES 0x74
95#define FLASH_DUMMY_BYTES 0x75
96#define FLASH_WRITE_BYTES 0x76
97#define FLASH_READ_BYTES 0x77
98#define FLASH_OPCODE 0x78
99#define FLASH_START_ADDR 0x79
100#define FLASH_DUMMY2 0x7A
101#define FLASH_WRITE_DATA 0x7B
102
103#define TEMPORAL_DITH_DISABLE 0x7E
104#define SEQ_CONTROL 0x82
105#define SEQ_VECTOR 0x83
106
107/* DMD is Digital Micromirror Device */
108#define DMD_BLOCK_COUNT 0x84
109#define DMD_VCC_CONTROL 0x86
110#define DMD_PARK_PULSE_COUNT 0x87
111#define DMD_PARK_PULSE_WIDTH 0x88
112#define DMD_PARK_DELAY 0x89
113#define DMD_SHADOW_ENABLE 0x8E
114#define SEQ_STATUS 0x8F
115#define FLASH_CLOCK_CONTROL 0x98
116#define DMD_PARK 0x2D
117
118#define SDRAM_BIST_ENABLE 0x46
119#define DDR_DRIVER_STRENGTH 0x9A
120#define SDC_ENABLE 0x9D
121#define SDC_BUFF_SWAP_DISABLE 0xA3
122#define CURTAIN_CONTROL 0xA6
123#define DDR_BUS_SWAP_ENABLE 0xA7
124#define DMD_TRC_ENABLE 0xA8
125#define DMD_BUS_SWAP_ENABLE 0xA9
126
127#define ACTGEN_ENABLE 0xAE
128#define ACTGEN_CONTROL 0xAF
129#define ACTGEN_HORIZ_BP 0xB0
130#define ACTGEN_VERT_BP 0xB1
131
132/* Look Up Table access */
133#define CMT_SPLASH_LUT_START_ADDR 0xFA
134#define CMT_SPLASH_LUT_DEST_SELECT 0xFB
135#define CMT_SPLASH_LUT_DATA 0xFC
136#define SEQ_RESET_LUT_START_ADDR 0xFD
137#define SEQ_RESET_LUT_DEST_SELECT 0xFE
138#define SEQ_RESET_LUT_DATA 0xFF
139
140/* Input source definitions */
141#define PARALLEL_RGB 0
142#define INT_TEST_PATTERN 1
143#define SPLASH_SCREEN 2
144#define CPU_INTF 3
145#define BT656 4
146
147/* Standard input resolution definitions */
148#define QWVGA_LANDSCAPE 3 /* (427h*240v) */
149#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */
150#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */
151
152/* Standard data format definitions */
153#define RGB565 0
154#define RGB666 1
155#define RGB888 2
156
157/* Test Pattern definitions */
158#define TPG_CHECKERBOARD 0
159#define TPG_BLACK 1
160#define TPG_WHITE 2
161#define TPG_RED 3
162#define TPG_BLUE 4
163#define TPG_GREEN 5
164#define TPG_VLINES_BLACK 6
165#define TPG_HLINES_BLACK 7
166#define TPG_VLINES_ALT 8
167#define TPG_HLINES_ALT 9
168#define TPG_DIAG_LINES 10
169#define TPG_GREYRAMP_VERT 11
170#define TPG_GREYRAMP_HORIZ 12
171#define TPG_ANSI_CHECKERBOARD 13
172
173/* sequence mode definitions */
174#define SEQ_FREE_RUN 0
175#define SEQ_LOCK 1
176
177/* curtain color definitions */
178#define CURTAIN_BLACK 0
179#define CURTAIN_RED 1
180#define CURTAIN_GREEN 2
181#define CURTAIN_BLUE 3
182#define CURTAIN_YELLOW 4
183#define CURTAIN_MAGENTA 5
184#define CURTAIN_CYAN 6
185#define CURTAIN_WHITE 7
186
187/* LUT definitions */
188#define CMT_LUT_NONE 0
189#define CMT_LUT_GREEN 1
190#define CMT_LUT_RED 2
191#define CMT_LUT_BLUE 3
192#define CMT_LUT_ALL 4
193#define SPLASH_LUT 5
194
195#define SEQ_LUT_NONE 0
196#define SEQ_DRC_LUT_0 1
197#define SEQ_DRC_LUT_1 2
198#define SEQ_DRC_LUT_2 3
199#define SEQ_DRC_LUT_3 4
200#define SEQ_SEQ_LUT 5
201#define SEQ_DRC_LUT_ALL 6
202#define WPC_PROGRAM_LUT 7
203
204#define BITSTREAM_START_ADDR 0x00000000
205#define BITSTREAM_SIZE 0x00040000
206
207#define WPC_FW_0_START_ADDR 0x00040000
208#define WPC_FW_0_SIZE 0x00000ce8
209
210#define SEQUENCE_0_START_ADDR 0x00044000
211#define SEQUENCE_0_SIZE 0x00001000
212
213#define SEQUENCE_1_START_ADDR 0x00045000
214#define SEQUENCE_1_SIZE 0x00000d10
215
216#define SEQUENCE_2_START_ADDR 0x00046000
217#define SEQUENCE_2_SIZE 0x00000d10
218
219#define SEQUENCE_3_START_ADDR 0x00047000
220#define SEQUENCE_3_SIZE 0x00000d10
221
222#define SEQUENCE_4_START_ADDR 0x00048000
223#define SEQUENCE_4_SIZE 0x00000d10
224
225#define SEQUENCE_5_START_ADDR 0x00049000
226#define SEQUENCE_5_SIZE 0x00000d10
227
228#define SEQUENCE_6_START_ADDR 0x0004a000
229#define SEQUENCE_6_SIZE 0x00000d10
230
231#define CMT_LUT_0_START_ADDR 0x0004b200
232#define CMT_LUT_0_SIZE 0x00000600
233
234#define CMT_LUT_1_START_ADDR 0x0004b800
235#define CMT_LUT_1_SIZE 0x00000600
236
237#define CMT_LUT_2_START_ADDR 0x0004be00
238#define CMT_LUT_2_SIZE 0x00000600
239
240#define CMT_LUT_3_START_ADDR 0x0004c400
241#define CMT_LUT_3_SIZE 0x00000600
242
243#define CMT_LUT_4_START_ADDR 0x0004ca00
244#define CMT_LUT_4_SIZE 0x00000600
245
246#define CMT_LUT_5_START_ADDR 0x0004d000
247#define CMT_LUT_5_SIZE 0x00000600
248
249#define CMT_LUT_6_START_ADDR 0x0004d600
250#define CMT_LUT_6_SIZE 0x00000600
251
252#define DRC_TABLE_0_START_ADDR 0x0004dc00
253#define DRC_TABLE_0_SIZE 0x00000100
254
255#define SPLASH_0_START_ADDR 0x0004dd00
256#define SPLASH_0_SIZE 0x00032280
257
258#define SEQUENCE_7_START_ADDR 0x00080000
259#define SEQUENCE_7_SIZE 0x00000d10
260
261#define SEQUENCE_8_START_ADDR 0x00081800
262#define SEQUENCE_8_SIZE 0x00000d10
263
264#define SEQUENCE_9_START_ADDR 0x00083000
265#define SEQUENCE_9_SIZE 0x00000d10
266
267#define CMT_LUT_7_START_ADDR 0x0008e000
268#define CMT_LUT_7_SIZE 0x00000600
269
270#define CMT_LUT_8_START_ADDR 0x0008e800
271#define CMT_LUT_8_SIZE 0x00000600
272
273#define CMT_LUT_9_START_ADDR 0x0008f000
274#define CMT_LUT_9_SIZE 0x00000600
275
276#define SPLASH_1_START_ADDR 0x0009a000
277#define SPLASH_1_SIZE 0x00032280
278
279#define SPLASH_2_START_ADDR 0x000cd000
280#define SPLASH_2_SIZE 0x00032280
281
282#define SPLASH_3_START_ADDR 0x00100000
283#define SPLASH_3_SIZE 0x00032280
284
285#define OPT_SPLASH_0_START_ADDR 0x00134000
286#define OPT_SPLASH_0_SIZE 0x000cb100
287
288#endif
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index ca00843ed2fe..80c3f6ab1a94 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -35,26 +35,12 @@
35 35
36#include <video/omapdss.h> 36#include <video/omapdss.h>
37#include <video/omap-panel-nokia-dsi.h> 37#include <video/omap-panel-nokia-dsi.h>
38#include <video/mipi_display.h>
38 39
39/* DSI Virtual channel. Hardcoded for now. */ 40/* DSI Virtual channel. Hardcoded for now. */
40#define TCH 0 41#define TCH 0
41 42
42#define DCS_READ_NUM_ERRORS 0x05 43#define DCS_READ_NUM_ERRORS 0x05
43#define DCS_READ_POWER_MODE 0x0a
44#define DCS_READ_MADCTL 0x0b
45#define DCS_READ_PIXEL_FORMAT 0x0c
46#define DCS_RDDSDR 0x0f
47#define DCS_SLEEP_IN 0x10
48#define DCS_SLEEP_OUT 0x11
49#define DCS_DISPLAY_OFF 0x28
50#define DCS_DISPLAY_ON 0x29
51#define DCS_COLUMN_ADDR 0x2a
52#define DCS_PAGE_ADDR 0x2b
53#define DCS_MEMORY_WRITE 0x2c
54#define DCS_TEAR_OFF 0x34
55#define DCS_TEAR_ON 0x35
56#define DCS_MEM_ACC_CTRL 0x36
57#define DCS_PIXEL_FORMAT 0x3a
58#define DCS_BRIGHTNESS 0x51 44#define DCS_BRIGHTNESS 0x51
59#define DCS_CTRL_DISPLAY 0x53 45#define DCS_CTRL_DISPLAY 0x53
60#define DCS_WRITE_CABC 0x55 46#define DCS_WRITE_CABC 0x55
@@ -222,8 +208,6 @@ struct taal_data {
222 208
223 struct delayed_work te_timeout_work; 209 struct delayed_work te_timeout_work;
224 210
225 bool use_dsi_bl;
226
227 bool cabc_broken; 211 bool cabc_broken;
228 unsigned cabc_mode; 212 unsigned cabc_mode;
229 213
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
302 286
303 hw_guard_wait(td); 287 hw_guard_wait(td);
304 288
305 cmd = DCS_SLEEP_IN; 289 cmd = MIPI_DCS_ENTER_SLEEP_MODE;
306 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); 290 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
307 if (r) 291 if (r)
308 return r; 292 return r;
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
321 305
322 hw_guard_wait(td); 306 hw_guard_wait(td);
323 307
324 r = taal_dcs_write_0(td, DCS_SLEEP_OUT); 308 r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
325 if (r) 309 if (r)
326 return r; 310 return r;
327 311
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
356 u8 mode; 340 u8 mode;
357 int b5, b6, b7; 341 int b5, b6, b7;
358 342
359 r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); 343 r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
360 if (r) 344 if (r)
361 return r; 345 return r;
362 346
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
390 mode &= ~((1<<7) | (1<<6) | (1<<5)); 374 mode &= ~((1<<7) | (1<<6) | (1<<5));
391 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); 375 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
392 376
393 return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); 377 return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
394} 378}
395 379
396static int taal_set_update_window(struct taal_data *td, 380static int taal_set_update_window(struct taal_data *td,
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
403 u16 y2 = y + h - 1; 387 u16 y2 = y + h - 1;
404 388
405 u8 buf[5]; 389 u8 buf[5];
406 buf[0] = DCS_COLUMN_ADDR; 390 buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
407 buf[1] = (x1 >> 8) & 0xff; 391 buf[1] = (x1 >> 8) & 0xff;
408 buf[2] = (x1 >> 0) & 0xff; 392 buf[2] = (x1 >> 0) & 0xff;
409 buf[3] = (x2 >> 8) & 0xff; 393 buf[3] = (x2 >> 8) & 0xff;
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
413 if (r) 397 if (r)
414 return r; 398 return r;
415 399
416 buf[0] = DCS_PAGE_ADDR; 400 buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
417 buf[1] = (y1 >> 8) & 0xff; 401 buf[1] = (y1 >> 8) & 0xff;
418 buf[2] = (y1 >> 0) & 0xff; 402 buf[2] = (y1 >> 0) & 0xff;
419 buf[3] = (y2 >> 8) & 0xff; 403 buf[3] = (y2 >> 8) & 0xff;
@@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
555{ 539{
556 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 540 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
557 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 541 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
558 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
559 int r; 542 int r;
560 int level; 543 int level;
561 544
@@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
569 552
570 mutex_lock(&td->lock); 553 mutex_lock(&td->lock);
571 554
572 if (td->use_dsi_bl) { 555 if (td->enabled) {
573 if (td->enabled) { 556 dsi_bus_lock(dssdev);
574 dsi_bus_lock(dssdev);
575 557
576 r = taal_wake_up(dssdev); 558 r = taal_wake_up(dssdev);
577 if (!r) 559 if (!r)
578 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); 560 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
579 561
580 dsi_bus_unlock(dssdev); 562 dsi_bus_unlock(dssdev);
581 } else {
582 r = 0;
583 }
584 } else { 563 } else {
585 if (!panel_data->set_backlight) 564 r = 0;
586 r = -EINVAL;
587 else
588 r = panel_data->set_backlight(dssdev, level);
589 } 565 }
590 566
591 mutex_unlock(&td->lock); 567 mutex_unlock(&td->lock);
@@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
964{ 940{
965 struct backlight_properties props; 941 struct backlight_properties props;
966 struct taal_data *td; 942 struct taal_data *td;
967 struct backlight_device *bldev; 943 struct backlight_device *bldev = NULL;
968 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); 944 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
969 struct panel_config *panel_config = NULL; 945 struct panel_config *panel_config = NULL;
970 int r, i; 946 int r, i;
@@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
990 966
991 dssdev->panel.config = OMAP_DSS_LCD_TFT; 967 dssdev->panel.config = OMAP_DSS_LCD_TFT;
992 dssdev->panel.timings = panel_config->timings; 968 dssdev->panel.timings = panel_config->timings;
993 dssdev->ctrl.pixel_size = 24; 969 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
994 970
995 td = kzalloc(sizeof(*td), GFP_KERNEL); 971 td = kzalloc(sizeof(*td), GFP_KERNEL);
996 if (!td) { 972 if (!td) {
@@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
1025 1001
1026 taal_hw_reset(dssdev); 1002 taal_hw_reset(dssdev);
1027 1003
1028 /* if no platform set_backlight() defined, presume DSI backlight 1004 if (panel_data->use_dsi_backlight) {
1029 * control */ 1005 memset(&props, 0, sizeof(struct backlight_properties));
1030 memset(&props, 0, sizeof(struct backlight_properties));
1031 if (!panel_data->set_backlight)
1032 td->use_dsi_bl = true;
1033
1034 if (td->use_dsi_bl)
1035 props.max_brightness = 255; 1006 props.max_brightness = 255;
1036 else
1037 props.max_brightness = 127;
1038
1039 props.type = BACKLIGHT_RAW;
1040 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
1041 dssdev, &taal_bl_ops, &props);
1042 if (IS_ERR(bldev)) {
1043 r = PTR_ERR(bldev);
1044 goto err_bl;
1045 }
1046 1007
1047 td->bldev = bldev; 1008 props.type = BACKLIGHT_RAW;
1009 bldev = backlight_device_register(dev_name(&dssdev->dev),
1010 &dssdev->dev, dssdev, &taal_bl_ops, &props);
1011 if (IS_ERR(bldev)) {
1012 r = PTR_ERR(bldev);
1013 goto err_bl;
1014 }
1015
1016 td->bldev = bldev;
1048 1017
1049 bldev->props.fb_blank = FB_BLANK_UNBLANK; 1018 bldev->props.fb_blank = FB_BLANK_UNBLANK;
1050 bldev->props.power = FB_BLANK_UNBLANK; 1019 bldev->props.power = FB_BLANK_UNBLANK;
1051 if (td->use_dsi_bl)
1052 bldev->props.brightness = 255; 1020 bldev->props.brightness = 255;
1053 else
1054 bldev->props.brightness = 127;
1055 1021
1056 taal_bl_update_status(bldev); 1022 taal_bl_update_status(bldev);
1023 }
1057 1024
1058 if (panel_data->use_ext_te) { 1025 if (panel_data->use_ext_te) {
1059 int gpio = panel_data->ext_te_gpio; 1026 int gpio = panel_data->ext_te_gpio;
@@ -1111,7 +1078,8 @@ err_irq:
1111 if (panel_data->use_ext_te) 1078 if (panel_data->use_ext_te)
1112 gpio_free(panel_data->ext_te_gpio); 1079 gpio_free(panel_data->ext_te_gpio);
1113err_gpio: 1080err_gpio:
1114 backlight_device_unregister(bldev); 1081 if (bldev != NULL)
1082 backlight_device_unregister(bldev);
1115err_bl: 1083err_bl:
1116 destroy_workqueue(td->workqueue); 1084 destroy_workqueue(td->workqueue);
1117err_wq: 1085err_wq:
@@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1140 } 1108 }
1141 1109
1142 bldev = td->bldev; 1110 bldev = td->bldev;
1143 bldev->props.power = FB_BLANK_POWERDOWN; 1111 if (bldev != NULL) {
1144 taal_bl_update_status(bldev); 1112 bldev->props.power = FB_BLANK_POWERDOWN;
1145 backlight_device_unregister(bldev); 1113 taal_bl_update_status(bldev);
1114 backlight_device_unregister(bldev);
1115 }
1146 1116
1147 taal_cancel_ulps_work(dssdev); 1117 taal_cancel_ulps_work(dssdev);
1148 taal_cancel_esd_work(dssdev); 1118 taal_cancel_esd_work(dssdev);
@@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1195 if (r) 1165 if (r)
1196 goto err; 1166 goto err;
1197 1167
1198 r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ 1168 r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
1169 MIPI_DCS_PIXEL_FMT_24BIT);
1199 if (r) 1170 if (r)
1200 goto err; 1171 goto err;
1201 1172
@@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1209 goto err; 1180 goto err;
1210 } 1181 }
1211 1182
1212 r = taal_dcs_write_0(td, DCS_DISPLAY_ON); 1183 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
1213 if (r) 1184 if (r)
1214 goto err; 1185 goto err;
1215 1186
@@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
1246 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1217 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1247 int r; 1218 int r;
1248 1219
1249 r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); 1220 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
1250 if (!r) 1221 if (!r)
1251 r = taal_sleep_in(td); 1222 r = taal_sleep_in(td);
1252 1223
@@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1529 int r; 1500 int r;
1530 1501
1531 if (enable) 1502 if (enable)
1532 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); 1503 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1533 else 1504 else
1534 r = taal_dcs_write_0(td, DCS_TEAR_OFF); 1505 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
1535 1506
1536 if (!panel_data->use_ext_te) 1507 if (!panel_data->use_ext_te)
1537 omapdss_dsi_enable_te(dssdev, enable); 1508 omapdss_dsi_enable_te(dssdev, enable);
@@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
1851 goto err; 1822 goto err;
1852 } 1823 }
1853 1824
1854 r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); 1825 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
1855 if (r) { 1826 if (r) {
1856 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1827 dev_err(&dssdev->dev, "failed to read Taal status\n");
1857 goto err; 1828 goto err;
@@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
1864 goto err; 1835 goto err;
1865 } 1836 }
1866 1837
1867 r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); 1838 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
1868 if (r) { 1839 if (r) {
1869 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1840 dev_err(&dssdev->dev, "failed to read Taal status\n");
1870 goto err; 1841 goto err;
@@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
1880 /* Self-diagnostics result is also shown on TE GPIO line. We need 1851 /* Self-diagnostics result is also shown on TE GPIO line. We need
1881 * to re-enable TE after self diagnostics */ 1852 * to re-enable TE after self diagnostics */
1882 if (td->te_enabled && panel_data->use_ext_te) { 1853 if (td->te_enabled && panel_data->use_ext_te) {
1883 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); 1854 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1884 if (r) 1855 if (r)
1885 goto err; 1856 goto err;
1886 } 1857 }