aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/Kconfig1
-rw-r--r--drivers/video/omap2/Makefile1
-rw-r--r--drivers/video/omap2/displays/Kconfig75
-rw-r--r--drivers/video/omap2/displays/Makefile11
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c798
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c744
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c262
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c616
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c290
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c559
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c198
-rw-r--r--drivers/video/omap2/displays/panel-taal.c1551
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c353
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c596
15 files changed, 0 insertions, 6343 deletions
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index 56cad0f5386c..63b23f87081d 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -5,7 +5,6 @@ if ARCH_OMAP2PLUS
5 5
6source "drivers/video/omap2/dss/Kconfig" 6source "drivers/video/omap2/dss/Kconfig"
7source "drivers/video/omap2/omapfb/Kconfig" 7source "drivers/video/omap2/omapfb/Kconfig"
8source "drivers/video/omap2/displays/Kconfig"
9source "drivers/video/omap2/displays-new/Kconfig" 8source "drivers/video/omap2/displays-new/Kconfig"
10 9
11endif 10endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 86873c2fbb27..bf8127df8c71 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,6 +1,5 @@
1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2 2
3obj-$(CONFIG_OMAP2_DSS) += dss/ 3obj-$(CONFIG_OMAP2_DSS) += dss/
4obj-y += displays/
5obj-y += displays-new/ 4obj-y += displays-new/
6obj-$(CONFIG_FB_OMAP2) += omapfb/ 5obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
deleted file mode 100644
index e80ac1c79561..000000000000
--- a/drivers/video/omap2/displays/Kconfig
+++ /dev/null
@@ -1,75 +0,0 @@
1menu "OMAP2/3 Display Device Drivers (old device model)"
2 depends on OMAP2_DSS
3
4config PANEL_GENERIC_DPI
5 tristate "Generic DPI Panel"
6 depends on OMAP2_DSS_DPI
7 help
8 Generic DPI panel driver.
9 Supports DVI output for Beagle and OMAP3 SDP.
10 Supports LCD Panel used in TI SDP3430 and EVM boards,
11 OMAP3517 EVM boards and CM-T35.
12
13config PANEL_TFP410
14 tristate "TFP410 DPI-to-DVI chip"
15 depends on OMAP2_DSS_DPI && I2C
16 help
17 Driver for TFP410 DPI-to-DVI chip. The driver uses i2c to read EDID
18 information from the monitor.
19
20config PANEL_LGPHILIPS_LB035Q02
21 tristate "LG.Philips LB035Q02 LCD Panel"
22 depends on OMAP2_DSS_DPI && SPI
23 help
24 LCD Panel used on the Gumstix Overo Palo35
25
26config PANEL_SHARP_LS037V7DW01
27 tristate "Sharp LS037V7DW01 LCD Panel"
28 depends on OMAP2_DSS_DPI
29 depends on BACKLIGHT_CLASS_DEVICE
30 help
31 LCD Panel used in TI's SDP3430 and EVM boards
32
33config PANEL_NEC_NL8048HL11_01B
34 tristate "NEC NL8048HL11-01B Panel"
35 depends on OMAP2_DSS_DPI
36 depends on SPI
37 depends on BACKLIGHT_CLASS_DEVICE
38 help
39 This NEC NL8048HL11-01B panel is TFT LCD
40 used in the Zoom2/3/3630 sdp boards.
41
42config PANEL_PICODLP
43 tristate "TI PICO DLP mini-projector"
44 depends on OMAP2_DSS_DPI && 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
49config PANEL_TAAL
50 tristate "Taal DSI Panel"
51 depends on OMAP2_DSS_DSI
52 depends on BACKLIGHT_CLASS_DEVICE
53 help
54 Taal DSI command mode panel from TPO.
55
56config PANEL_TPO_TD043MTEA1
57 tristate "TPO TD043MTEA1 LCD Panel"
58 depends on OMAP2_DSS_DPI && SPI
59 help
60 LCD Panel used in OMAP3 Pandora
61
62config PANEL_ACX565AKM
63 tristate "ACX565AKM Panel"
64 depends on OMAP2_DSS_SDI && SPI
65 depends on BACKLIGHT_CLASS_DEVICE
66 help
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
75endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
deleted file mode 100644
index 58a5176b07b0..000000000000
--- a/drivers/video/omap2/displays/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
2obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
3obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
4obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
5obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
6
7obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
8obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
9obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
10obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
11obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
deleted file mode 100644
index 3fd100fc853e..000000000000
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ /dev/null
@@ -1,798 +0,0 @@
1/*
2 * Support for ACX565AKM LCD Panel used on Nokia N900
3 *
4 * Copyright (C) 2010 Nokia Corporation
5 *
6 * Original Driver Author: Imre Deak <imre.deak@nokia.com>
7 * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
8 * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/spi/spi.h>
28#include <linux/jiffies.h>
29#include <linux/sched.h>
30#include <linux/backlight.h>
31#include <linux/fb.h>
32#include <linux/gpio.h>
33
34#include <video/omapdss.h>
35#include <video/omap-panel-data.h>
36
37#define MIPID_CMD_READ_DISP_ID 0x04
38#define MIPID_CMD_READ_RED 0x06
39#define MIPID_CMD_READ_GREEN 0x07
40#define MIPID_CMD_READ_BLUE 0x08
41#define MIPID_CMD_READ_DISP_STATUS 0x09
42#define MIPID_CMD_RDDSDR 0x0F
43#define MIPID_CMD_SLEEP_IN 0x10
44#define MIPID_CMD_SLEEP_OUT 0x11
45#define MIPID_CMD_DISP_OFF 0x28
46#define MIPID_CMD_DISP_ON 0x29
47#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
48#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
49#define MIPID_CMD_WRITE_CTRL_DISP 0x53
50
51#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
52#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
53#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
54#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
55
56#define MIPID_CMD_READ_CTRL_DISP 0x54
57#define MIPID_CMD_WRITE_CABC 0x55
58#define MIPID_CMD_READ_CABC 0x56
59
60#define MIPID_VER_LPH8923 3
61#define MIPID_VER_LS041Y3 4
62#define MIPID_VER_L4F00311 8
63#define MIPID_VER_ACX565AKM 9
64
65struct acx565akm_device {
66 char *name;
67 int enabled;
68 int model;
69 int revision;
70 u8 display_id[3];
71 unsigned has_bc:1;
72 unsigned has_cabc:1;
73 unsigned cabc_mode;
74 unsigned long hw_guard_end; /* next value of jiffies
75 when we can issue the
76 next sleep in/out command */
77 unsigned long hw_guard_wait; /* max guard time in jiffies */
78
79 struct spi_device *spi;
80 struct mutex mutex;
81
82 struct omap_dss_device *dssdev;
83 struct backlight_device *bl_dev;
84};
85
86static struct acx565akm_device acx_dev;
87static int acx565akm_bl_update_status(struct backlight_device *dev);
88
89/*--------------------MIPID interface-----------------------------*/
90
91static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
92 const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
93{
94 struct spi_message m;
95 struct spi_transfer *x, xfer[5];
96 int r;
97
98 BUG_ON(md->spi == NULL);
99
100 spi_message_init(&m);
101
102 memset(xfer, 0, sizeof(xfer));
103 x = &xfer[0];
104
105 cmd &= 0xff;
106 x->tx_buf = &cmd;
107 x->bits_per_word = 9;
108 x->len = 2;
109
110 if (rlen > 1 && wlen == 0) {
111 /*
112 * Between the command and the response data there is a
113 * dummy clock cycle. Add an extra bit after the command
114 * word to account for this.
115 */
116 x->bits_per_word = 10;
117 cmd <<= 1;
118 }
119 spi_message_add_tail(x, &m);
120
121 if (wlen) {
122 x++;
123 x->tx_buf = wbuf;
124 x->len = wlen;
125 x->bits_per_word = 9;
126 spi_message_add_tail(x, &m);
127 }
128
129 if (rlen) {
130 x++;
131 x->rx_buf = rbuf;
132 x->len = rlen;
133 spi_message_add_tail(x, &m);
134 }
135
136 r = spi_sync(md->spi, &m);
137 if (r < 0)
138 dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
139}
140
141static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
142{
143 acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
144}
145
146static inline void acx565akm_write(struct acx565akm_device *md,
147 int reg, const u8 *buf, int len)
148{
149 acx565akm_transfer(md, reg, buf, len, NULL, 0);
150}
151
152static inline void acx565akm_read(struct acx565akm_device *md,
153 int reg, u8 *buf, int len)
154{
155 acx565akm_transfer(md, reg, NULL, 0, buf, len);
156}
157
158static void hw_guard_start(struct acx565akm_device *md, int guard_msec)
159{
160 md->hw_guard_wait = msecs_to_jiffies(guard_msec);
161 md->hw_guard_end = jiffies + md->hw_guard_wait;
162}
163
164static void hw_guard_wait(struct acx565akm_device *md)
165{
166 unsigned long wait = md->hw_guard_end - jiffies;
167
168 if ((long)wait > 0 && wait <= md->hw_guard_wait) {
169 set_current_state(TASK_UNINTERRUPTIBLE);
170 schedule_timeout(wait);
171 }
172}
173
174/*----------------------MIPID wrappers----------------------------*/
175
176static void set_sleep_mode(struct acx565akm_device *md, int on)
177{
178 int cmd;
179
180 if (on)
181 cmd = MIPID_CMD_SLEEP_IN;
182 else
183 cmd = MIPID_CMD_SLEEP_OUT;
184 /*
185 * We have to keep 120msec between sleep in/out commands.
186 * (8.2.15, 8.2.16).
187 */
188 hw_guard_wait(md);
189 acx565akm_cmd(md, cmd);
190 hw_guard_start(md, 120);
191}
192
193static void set_display_state(struct acx565akm_device *md, int enabled)
194{
195 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
196
197 acx565akm_cmd(md, cmd);
198}
199
200static int panel_enabled(struct acx565akm_device *md)
201{
202 u32 disp_status;
203 int enabled;
204
205 acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
206 disp_status = __be32_to_cpu(disp_status);
207 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
208 dev_dbg(&md->spi->dev,
209 "LCD panel %senabled by bootloader (status 0x%04x)\n",
210 enabled ? "" : "not ", disp_status);
211 return enabled;
212}
213
214static int panel_detect(struct acx565akm_device *md)
215{
216 acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
217 dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
218 md->display_id[0], md->display_id[1], md->display_id[2]);
219
220 switch (md->display_id[0]) {
221 case 0x10:
222 md->model = MIPID_VER_ACX565AKM;
223 md->name = "acx565akm";
224 md->has_bc = 1;
225 md->has_cabc = 1;
226 break;
227 case 0x29:
228 md->model = MIPID_VER_L4F00311;
229 md->name = "l4f00311";
230 break;
231 case 0x45:
232 md->model = MIPID_VER_LPH8923;
233 md->name = "lph8923";
234 break;
235 case 0x83:
236 md->model = MIPID_VER_LS041Y3;
237 md->name = "ls041y3";
238 break;
239 default:
240 md->name = "unknown";
241 dev_err(&md->spi->dev, "invalid display ID\n");
242 return -ENODEV;
243 }
244
245 md->revision = md->display_id[1];
246
247 dev_info(&md->spi->dev, "omapfb: %s rev %02x LCD detected\n",
248 md->name, md->revision);
249
250 return 0;
251}
252
253/*----------------------Backlight Control-------------------------*/
254
255static void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
256{
257 u16 ctrl;
258
259 acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
260 if (enable) {
261 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
262 CTRL_DISP_BACKLIGHT_ON;
263 } else {
264 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
265 CTRL_DISP_BACKLIGHT_ON);
266 }
267
268 ctrl |= 1 << 8;
269 acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
270}
271
272static void set_cabc_mode(struct acx565akm_device *md, unsigned mode)
273{
274 u16 cabc_ctrl;
275
276 md->cabc_mode = mode;
277 if (!md->enabled)
278 return;
279 cabc_ctrl = 0;
280 acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
281 cabc_ctrl &= ~3;
282 cabc_ctrl |= (1 << 8) | (mode & 3);
283 acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
284}
285
286static unsigned get_cabc_mode(struct acx565akm_device *md)
287{
288 return md->cabc_mode;
289}
290
291static unsigned get_hw_cabc_mode(struct acx565akm_device *md)
292{
293 u8 cabc_ctrl;
294
295 acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
296 return cabc_ctrl & 3;
297}
298
299static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
300{
301 int bv;
302
303 bv = level | (1 << 8);
304 acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
305
306 if (level)
307 enable_backlight_ctrl(md, 1);
308 else
309 enable_backlight_ctrl(md, 0);
310}
311
312static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
313{
314 u8 bv;
315
316 acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
317
318 return bv;
319}
320
321
322static int acx565akm_bl_update_status(struct backlight_device *dev)
323{
324 struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
325 int r;
326 int level;
327
328 dev_dbg(&md->spi->dev, "%s\n", __func__);
329
330 mutex_lock(&md->mutex);
331
332 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
333 dev->props.power == FB_BLANK_UNBLANK)
334 level = dev->props.brightness;
335 else
336 level = 0;
337
338 r = 0;
339 if (md->has_bc)
340 acx565akm_set_brightness(md, level);
341 else
342 r = -ENODEV;
343
344 mutex_unlock(&md->mutex);
345
346 return r;
347}
348
349static int acx565akm_bl_get_intensity(struct backlight_device *dev)
350{
351 struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
352
353 dev_dbg(&dev->dev, "%s\n", __func__);
354
355 if (!md->has_bc)
356 return -ENODEV;
357
358 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
359 dev->props.power == FB_BLANK_UNBLANK) {
360 if (md->has_bc)
361 return acx565akm_get_actual_brightness(md);
362 else
363 return dev->props.brightness;
364 }
365
366 return 0;
367}
368
369static const struct backlight_ops acx565akm_bl_ops = {
370 .get_brightness = acx565akm_bl_get_intensity,
371 .update_status = acx565akm_bl_update_status,
372};
373
374/*--------------------Auto Brightness control via Sysfs---------------------*/
375
376static const char *cabc_modes[] = {
377 "off", /* always used when CABC is not supported */
378 "ui",
379 "still-image",
380 "moving-image",
381};
382
383static ssize_t show_cabc_mode(struct device *dev,
384 struct device_attribute *attr,
385 char *buf)
386{
387 struct acx565akm_device *md = dev_get_drvdata(dev);
388 const char *mode_str;
389 int mode;
390 int len;
391
392 if (!md->has_cabc)
393 mode = 0;
394 else
395 mode = get_cabc_mode(md);
396 mode_str = "unknown";
397 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
398 mode_str = cabc_modes[mode];
399 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
400
401 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
402}
403
404static ssize_t store_cabc_mode(struct device *dev,
405 struct device_attribute *attr,
406 const char *buf, size_t count)
407{
408 struct acx565akm_device *md = dev_get_drvdata(dev);
409 int i;
410
411 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
412 const char *mode_str = cabc_modes[i];
413 int cmp_len = strlen(mode_str);
414
415 if (count > 0 && buf[count - 1] == '\n')
416 count--;
417 if (count != cmp_len)
418 continue;
419
420 if (strncmp(buf, mode_str, cmp_len) == 0)
421 break;
422 }
423
424 if (i == ARRAY_SIZE(cabc_modes))
425 return -EINVAL;
426
427 if (!md->has_cabc && i != 0)
428 return -EINVAL;
429
430 mutex_lock(&md->mutex);
431 set_cabc_mode(md, i);
432 mutex_unlock(&md->mutex);
433
434 return count;
435}
436
437static ssize_t show_cabc_available_modes(struct device *dev,
438 struct device_attribute *attr,
439 char *buf)
440{
441 struct acx565akm_device *md = dev_get_drvdata(dev);
442 int len;
443 int i;
444
445 if (!md->has_cabc)
446 return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
447
448 for (i = 0, len = 0;
449 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
450 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
451 i ? " " : "", cabc_modes[i],
452 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
453
454 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
455}
456
457static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
458 show_cabc_mode, store_cabc_mode);
459static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
460 show_cabc_available_modes, NULL);
461
462static struct attribute *bldev_attrs[] = {
463 &dev_attr_cabc_mode.attr,
464 &dev_attr_cabc_available_modes.attr,
465 NULL,
466};
467
468static struct attribute_group bldev_attr_group = {
469 .attrs = bldev_attrs,
470};
471
472
473/*---------------------------ACX Panel----------------------------*/
474
475static int acx_get_recommended_bpp(struct omap_dss_device *dssdev)
476{
477 return 16;
478}
479
480static struct omap_video_timings acx_panel_timings = {
481 .x_res = 800,
482 .y_res = 480,
483 .pixel_clock = 24000,
484 .hfp = 28,
485 .hsw = 4,
486 .hbp = 24,
487 .vfp = 3,
488 .vsw = 3,
489 .vbp = 4,
490
491 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
492 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
493
494 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
495 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
496 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
497};
498
499static struct panel_acx565akm_data *get_panel_data(struct omap_dss_device *dssdev)
500{
501 return (struct panel_acx565akm_data *) dssdev->data;
502}
503
504static int acx_panel_probe(struct omap_dss_device *dssdev)
505{
506 int r;
507 struct acx565akm_device *md = &acx_dev;
508 struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
509 struct backlight_device *bldev;
510 int max_brightness, brightness;
511 struct backlight_properties props;
512
513 dev_dbg(dssdev->dev, "%s\n", __func__);
514
515 if (!panel_data)
516 return -EINVAL;
517
518 /* FIXME AC bias ? */
519 dssdev->panel.timings = acx_panel_timings;
520
521 if (gpio_is_valid(panel_data->reset_gpio)) {
522 r = devm_gpio_request_one(dssdev->dev, panel_data->reset_gpio,
523 GPIOF_OUT_INIT_LOW, "lcd reset");
524 if (r)
525 return r;
526 }
527
528 if (gpio_is_valid(panel_data->reset_gpio))
529 gpio_set_value(panel_data->reset_gpio, 1);
530
531 /*
532 * After reset we have to wait 5 msec before the first
533 * command can be sent.
534 */
535 msleep(5);
536
537 md->enabled = panel_enabled(md);
538
539 r = panel_detect(md);
540 if (r) {
541 dev_err(dssdev->dev, "%s panel detect error\n", __func__);
542 if (!md->enabled && gpio_is_valid(panel_data->reset_gpio))
543 gpio_set_value(panel_data->reset_gpio, 0);
544
545 return r;
546 }
547
548 mutex_lock(&acx_dev.mutex);
549 acx_dev.dssdev = dssdev;
550 mutex_unlock(&acx_dev.mutex);
551
552 if (!md->enabled) {
553 if (gpio_is_valid(panel_data->reset_gpio))
554 gpio_set_value(panel_data->reset_gpio, 0);
555 }
556
557 /*------- Backlight control --------*/
558
559 memset(&props, 0, sizeof(props));
560 props.fb_blank = FB_BLANK_UNBLANK;
561 props.power = FB_BLANK_UNBLANK;
562 props.type = BACKLIGHT_RAW;
563
564 bldev = backlight_device_register("acx565akm", &md->spi->dev,
565 md, &acx565akm_bl_ops, &props);
566 md->bl_dev = bldev;
567 if (md->has_cabc) {
568 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
569 if (r) {
570 dev_err(&bldev->dev,
571 "%s failed to create sysfs files\n", __func__);
572 backlight_device_unregister(bldev);
573 return r;
574 }
575 md->cabc_mode = get_hw_cabc_mode(md);
576 }
577
578 max_brightness = 255;
579
580 if (md->has_bc)
581 brightness = acx565akm_get_actual_brightness(md);
582 else
583 brightness = 0;
584
585 bldev->props.max_brightness = max_brightness;
586 bldev->props.brightness = brightness;
587
588 acx565akm_bl_update_status(bldev);
589 return 0;
590}
591
592static void acx_panel_remove(struct omap_dss_device *dssdev)
593{
594 struct acx565akm_device *md = &acx_dev;
595
596 dev_dbg(dssdev->dev, "%s\n", __func__);
597 sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group);
598 backlight_device_unregister(md->bl_dev);
599 mutex_lock(&acx_dev.mutex);
600 acx_dev.dssdev = NULL;
601 mutex_unlock(&acx_dev.mutex);
602}
603
604static int acx_panel_power_on(struct omap_dss_device *dssdev)
605{
606 struct acx565akm_device *md = &acx_dev;
607 struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
608 int r;
609
610 dev_dbg(dssdev->dev, "%s\n", __func__);
611
612 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
613 return 0;
614
615 mutex_lock(&md->mutex);
616
617 omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
618 omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
619
620 r = omapdss_sdi_display_enable(dssdev);
621 if (r) {
622 pr_err("%s sdi enable failed\n", __func__);
623 goto fail_unlock;
624 }
625
626 /*FIXME tweak me */
627 msleep(50);
628
629 if (gpio_is_valid(panel_data->reset_gpio))
630 gpio_set_value(panel_data->reset_gpio, 1);
631
632 if (md->enabled) {
633 dev_dbg(&md->spi->dev, "panel already enabled\n");
634 mutex_unlock(&md->mutex);
635 return 0;
636 }
637
638 /*
639 * We have to meet all the following delay requirements:
640 * 1. tRW: reset pulse width 10usec (7.12.1)
641 * 2. tRT: reset cancel time 5msec (7.12.1)
642 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
643 * case (7.6.2)
644 * 4. 120msec before the sleep out command (7.12.1)
645 */
646 msleep(120);
647
648 set_sleep_mode(md, 0);
649 md->enabled = 1;
650
651 /* 5msec between sleep out and the next command. (8.2.16) */
652 msleep(5);
653 set_display_state(md, 1);
654 set_cabc_mode(md, md->cabc_mode);
655
656 mutex_unlock(&md->mutex);
657
658 return acx565akm_bl_update_status(md->bl_dev);
659
660fail_unlock:
661 mutex_unlock(&md->mutex);
662 return r;
663}
664
665static void acx_panel_power_off(struct omap_dss_device *dssdev)
666{
667 struct acx565akm_device *md = &acx_dev;
668 struct panel_acx565akm_data *panel_data = get_panel_data(dssdev);
669
670 dev_dbg(dssdev->dev, "%s\n", __func__);
671
672 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
673 return;
674
675 mutex_lock(&md->mutex);
676
677 if (!md->enabled) {
678 mutex_unlock(&md->mutex);
679 return;
680 }
681 set_display_state(md, 0);
682 set_sleep_mode(md, 1);
683 md->enabled = 0;
684 /*
685 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
686 * ~50msec) after sending the sleep in command and asserting the
687 * reset signal. We probably could assert the reset w/o the delay
688 * but we still delay to avoid possible artifacts. (7.6.1)
689 */
690 msleep(50);
691
692 if (gpio_is_valid(panel_data->reset_gpio))
693 gpio_set_value(panel_data->reset_gpio, 0);
694
695 /* FIXME need to tweak this delay */
696 msleep(100);
697
698 omapdss_sdi_display_disable(dssdev);
699
700 mutex_unlock(&md->mutex);
701}
702
703static int acx_panel_enable(struct omap_dss_device *dssdev)
704{
705 int r;
706
707 dev_dbg(dssdev->dev, "%s\n", __func__);
708 r = acx_panel_power_on(dssdev);
709
710 if (r)
711 return r;
712
713 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
714 return 0;
715}
716
717static void acx_panel_disable(struct omap_dss_device *dssdev)
718{
719 dev_dbg(dssdev->dev, "%s\n", __func__);
720 acx_panel_power_off(dssdev);
721 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
722}
723
724static void acx_panel_set_timings(struct omap_dss_device *dssdev,
725 struct omap_video_timings *timings)
726{
727 omapdss_sdi_set_timings(dssdev, timings);
728
729 dssdev->panel.timings = *timings;
730}
731
732static int acx_panel_check_timings(struct omap_dss_device *dssdev,
733 struct omap_video_timings *timings)
734{
735 return 0;
736}
737
738
739static struct omap_dss_driver acx_panel_driver = {
740 .probe = acx_panel_probe,
741 .remove = acx_panel_remove,
742
743 .enable = acx_panel_enable,
744 .disable = acx_panel_disable,
745
746 .set_timings = acx_panel_set_timings,
747 .check_timings = acx_panel_check_timings,
748
749 .get_recommended_bpp = acx_get_recommended_bpp,
750
751 .driver = {
752 .name = "panel-acx565akm",
753 .owner = THIS_MODULE,
754 },
755};
756
757/*--------------------SPI probe-------------------------*/
758
759static int acx565akm_spi_probe(struct spi_device *spi)
760{
761 struct acx565akm_device *md = &acx_dev;
762
763 dev_dbg(&spi->dev, "%s\n", __func__);
764
765 spi->mode = SPI_MODE_3;
766 md->spi = spi;
767 mutex_init(&md->mutex);
768 dev_set_drvdata(&spi->dev, md);
769
770 omap_dss_register_driver(&acx_panel_driver);
771
772 return 0;
773}
774
775static int acx565akm_spi_remove(struct spi_device *spi)
776{
777 struct acx565akm_device *md = dev_get_drvdata(&spi->dev);
778
779 dev_dbg(&md->spi->dev, "%s\n", __func__);
780 omap_dss_unregister_driver(&acx_panel_driver);
781
782 return 0;
783}
784
785static struct spi_driver acx565akm_spi_driver = {
786 .driver = {
787 .name = "acx565akm",
788 .owner = THIS_MODULE,
789 },
790 .probe = acx565akm_spi_probe,
791 .remove = acx565akm_spi_remove,
792};
793
794module_spi_driver(acx565akm_spi_driver);
795
796MODULE_AUTHOR("Nokia Corporation");
797MODULE_DESCRIPTION("acx565akm LCD Driver");
798MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
deleted file mode 100644
index bebebd45847f..000000000000
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ /dev/null
@@ -1,744 +0,0 @@
1/*
2 * Generic DPI Panels support
3 *
4 * Copyright (C) 2010 Canonical Ltd.
5 * Author: Bryan Wu <bryan.wu@canonical.com>
6 *
7 * LCD panel driver for Sharp LQ043T1DG01
8 *
9 * Copyright (C) 2009 Texas Instruments Inc
10 * Author: Vaibhav Hiremath <hvaibhav@ti.com>
11 *
12 * LCD panel driver for Toppoly TDO35S
13 *
14 * Copyright (C) 2009 CompuLab, Ltd.
15 * Author: Mike Rapoport <mike@compulab.co.il>
16 *
17 * Copyright (C) 2008 Nokia Corporation
18 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
19 *
20 * This program is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License version 2 as published by
22 * the Free Software Foundation.
23 *
24 * This program is distributed in the hope that it will be useful, but WITHOUT
25 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
27 * more details.
28 *
29 * You should have received a copy of the GNU General Public License along with
30 * this program. If not, see <http://www.gnu.org/licenses/>.
31 */
32
33#include <linux/module.h>
34#include <linux/delay.h>
35#include <linux/slab.h>
36#include <linux/gpio.h>
37#include <video/omapdss.h>
38
39#include <video/omap-panel-data.h>
40
41struct panel_config {
42 struct omap_video_timings timings;
43
44 int power_on_delay;
45 int power_off_delay;
46
47 /*
48 * Used to match device to panel configuration
49 * when use generic panel driver
50 */
51 const char *name;
52};
53
54/* Panel configurations */
55static struct panel_config generic_dpi_panels[] = {
56 /* Sharp LQ043T1DG01 */
57 {
58 {
59 .x_res = 480,
60 .y_res = 272,
61
62 .pixel_clock = 9000,
63
64 .hsw = 42,
65 .hfp = 3,
66 .hbp = 2,
67
68 .vsw = 11,
69 .vfp = 3,
70 .vbp = 2,
71
72 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
73 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
74 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
75 .de_level = OMAPDSS_SIG_ACTIVE_LOW,
76 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
77 },
78 .power_on_delay = 50,
79 .power_off_delay = 100,
80 .name = "sharp_lq",
81 },
82
83 /* Sharp LS037V7DW01 */
84 {
85 {
86 .x_res = 480,
87 .y_res = 640,
88
89 .pixel_clock = 19200,
90
91 .hsw = 2,
92 .hfp = 1,
93 .hbp = 28,
94
95 .vsw = 1,
96 .vfp = 1,
97 .vbp = 1,
98
99 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
100 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
101 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
102 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
103 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
104 },
105 .power_on_delay = 50,
106 .power_off_delay = 100,
107 .name = "sharp_ls",
108 },
109
110 /* Toppoly TDO35S */
111 {
112 {
113 .x_res = 480,
114 .y_res = 640,
115
116 .pixel_clock = 26000,
117
118 .hfp = 104,
119 .hsw = 8,
120 .hbp = 8,
121
122 .vfp = 4,
123 .vsw = 2,
124 .vbp = 2,
125
126 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
127 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
128 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
129 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
130 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
131 },
132 .power_on_delay = 0,
133 .power_off_delay = 0,
134 .name = "toppoly_tdo35s",
135 },
136
137 /* Samsung LTE430WQ-F0C */
138 {
139 {
140 .x_res = 480,
141 .y_res = 272,
142
143 .pixel_clock = 9200,
144
145 .hfp = 8,
146 .hsw = 41,
147 .hbp = 45 - 41,
148
149 .vfp = 4,
150 .vsw = 10,
151 .vbp = 12 - 10,
152
153 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
154 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
155 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
156 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
157 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
158 },
159 .power_on_delay = 0,
160 .power_off_delay = 0,
161 .name = "samsung_lte430wq_f0c",
162 },
163
164 /* Seiko 70WVW1TZ3Z3 */
165 {
166 {
167 .x_res = 800,
168 .y_res = 480,
169
170 .pixel_clock = 33000,
171
172 .hsw = 128,
173 .hfp = 10,
174 .hbp = 10,
175
176 .vsw = 2,
177 .vfp = 4,
178 .vbp = 11,
179
180 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
181 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
182 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
183 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
184 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
185 },
186 .power_on_delay = 0,
187 .power_off_delay = 0,
188 .name = "seiko_70wvw1tz3",
189 },
190
191 /* Powertip PH480272T */
192 {
193 {
194 .x_res = 480,
195 .y_res = 272,
196
197 .pixel_clock = 9000,
198
199 .hsw = 40,
200 .hfp = 2,
201 .hbp = 2,
202
203 .vsw = 10,
204 .vfp = 2,
205 .vbp = 2,
206
207 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
208 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
209 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
210 .de_level = OMAPDSS_SIG_ACTIVE_LOW,
211 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
212 },
213 .power_on_delay = 0,
214 .power_off_delay = 0,
215 .name = "powertip_ph480272t",
216 },
217
218 /* Innolux AT070TN83 */
219 {
220 {
221 .x_res = 800,
222 .y_res = 480,
223
224 .pixel_clock = 40000,
225
226 .hsw = 48,
227 .hfp = 1,
228 .hbp = 1,
229
230 .vsw = 3,
231 .vfp = 12,
232 .vbp = 25,
233
234 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
235 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
236 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
237 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
238 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
239 },
240 .power_on_delay = 0,
241 .power_off_delay = 0,
242 .name = "innolux_at070tn83",
243 },
244
245 /* NEC NL2432DR22-11B */
246 {
247 {
248 .x_res = 240,
249 .y_res = 320,
250
251 .pixel_clock = 5400,
252
253 .hsw = 3,
254 .hfp = 3,
255 .hbp = 39,
256
257 .vsw = 1,
258 .vfp = 2,
259 .vbp = 7,
260
261 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
262 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
263 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
264 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
265 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
266 },
267 .name = "nec_nl2432dr22-11b",
268 },
269
270 /* Unknown panel used in OMAP H4 */
271 {
272 {
273 .x_res = 240,
274 .y_res = 320,
275
276 .pixel_clock = 6250,
277
278 .hsw = 15,
279 .hfp = 15,
280 .hbp = 60,
281
282 .vsw = 1,
283 .vfp = 1,
284 .vbp = 1,
285
286 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
287 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
288 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
289 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
290 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
291 },
292 .name = "h4",
293 },
294
295 /* FocalTech ETM070003DH6 */
296 {
297 {
298 .x_res = 800,
299 .y_res = 480,
300
301 .pixel_clock = 28000,
302
303 .hsw = 48,
304 .hfp = 40,
305 .hbp = 40,
306
307 .vsw = 3,
308 .vfp = 13,
309 .vbp = 29,
310
311 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
312 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
313 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
314 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
315 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
316 },
317 .name = "focaltech_etm070003dh6",
318 },
319
320 /* Microtips Technologies - UMSH-8173MD */
321 {
322 {
323 .x_res = 800,
324 .y_res = 480,
325
326 .pixel_clock = 34560,
327
328 .hsw = 13,
329 .hfp = 101,
330 .hbp = 101,
331
332 .vsw = 23,
333 .vfp = 1,
334 .vbp = 1,
335
336 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
337 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
338 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
339 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
340 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
341 },
342 .power_on_delay = 0,
343 .power_off_delay = 0,
344 .name = "microtips_umsh_8173md",
345 },
346
347 /* OrtusTech COM43H4M10XTC */
348 {
349 {
350 .x_res = 480,
351 .y_res = 272,
352
353 .pixel_clock = 8000,
354
355 .hsw = 41,
356 .hfp = 8,
357 .hbp = 4,
358
359 .vsw = 10,
360 .vfp = 4,
361 .vbp = 2,
362
363 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
364 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
365 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
366 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
367 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
368 },
369 .name = "ortustech_com43h4m10xtc",
370 },
371
372 /* Innolux AT080TN52 */
373 {
374 {
375 .x_res = 800,
376 .y_res = 600,
377
378 .pixel_clock = 41142,
379
380 .hsw = 20,
381 .hfp = 210,
382 .hbp = 46,
383
384 .vsw = 10,
385 .vfp = 12,
386 .vbp = 23,
387
388 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
389 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
390 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
391 .de_level = OMAPDSS_SIG_ACTIVE_LOW,
392 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
393 },
394 .name = "innolux_at080tn52",
395 },
396
397 /* Mitsubishi AA084SB01 */
398 {
399 {
400 .x_res = 800,
401 .y_res = 600,
402 .pixel_clock = 40000,
403
404 .hsw = 1,
405 .hfp = 254,
406 .hbp = 1,
407
408 .vsw = 1,
409 .vfp = 26,
410 .vbp = 1,
411
412 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
413 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
414 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
415 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
416 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
417 },
418 .name = "mitsubishi_aa084sb01",
419 },
420 /* EDT ET0500G0DH6 */
421 {
422 {
423 .x_res = 800,
424 .y_res = 480,
425 .pixel_clock = 33260,
426
427 .hsw = 128,
428 .hfp = 216,
429 .hbp = 40,
430
431 .vsw = 2,
432 .vfp = 35,
433 .vbp = 10,
434
435 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
436 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
437 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
438 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
439 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
440 },
441 .name = "edt_et0500g0dh6",
442 },
443
444 /* Prime-View PD050VL1 */
445 {
446 {
447 .x_res = 640,
448 .y_res = 480,
449
450 .pixel_clock = 25000,
451
452 .hsw = 96,
453 .hfp = 18,
454 .hbp = 46,
455
456 .vsw = 2,
457 .vfp = 10,
458 .vbp = 33,
459
460 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
461 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
462 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
463 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
464 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
465 },
466 .name = "primeview_pd050vl1",
467 },
468
469 /* Prime-View PM070WL4 */
470 {
471 {
472 .x_res = 800,
473 .y_res = 480,
474
475 .pixel_clock = 32000,
476
477 .hsw = 128,
478 .hfp = 42,
479 .hbp = 86,
480
481 .vsw = 2,
482 .vfp = 10,
483 .vbp = 33,
484
485 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
486 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
487 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
488 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
489 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
490 },
491 .name = "primeview_pm070wl4",
492 },
493
494 /* Prime-View PD104SLF */
495 {
496 {
497 .x_res = 800,
498 .y_res = 600,
499
500 .pixel_clock = 40000,
501
502 .hsw = 128,
503 .hfp = 42,
504 .hbp = 86,
505
506 .vsw = 4,
507 .vfp = 1,
508 .vbp = 23,
509
510 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
511 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
512 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
513 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
514 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
515 },
516 .name = "primeview_pd104slf",
517 },
518};
519
520struct panel_drv_data {
521
522 struct omap_dss_device *dssdev;
523
524 struct panel_config *panel_config;
525
526 struct mutex lock;
527};
528
529static inline struct panel_generic_dpi_data
530*get_panel_data(const struct omap_dss_device *dssdev)
531{
532 return (struct panel_generic_dpi_data *) dssdev->data;
533}
534
535static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
536{
537 int r, i;
538 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
539 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
540 struct panel_config *panel_config = drv_data->panel_config;
541
542 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
543 return 0;
544
545 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
546 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
547
548 r = omapdss_dpi_display_enable(dssdev);
549 if (r)
550 goto err0;
551
552 /* wait couple of vsyncs until enabling the LCD */
553 if (panel_config->power_on_delay)
554 msleep(panel_config->power_on_delay);
555
556 for (i = 0; i < panel_data->num_gpios; ++i) {
557 gpio_set_value_cansleep(panel_data->gpios[i],
558 panel_data->gpio_invert[i] ? 0 : 1);
559 }
560
561 return 0;
562
563err0:
564 return r;
565}
566
567static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
568{
569 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
570 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
571 struct panel_config *panel_config = drv_data->panel_config;
572 int i;
573
574 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
575 return;
576
577 for (i = panel_data->num_gpios - 1; i >= 0; --i) {
578 gpio_set_value_cansleep(panel_data->gpios[i],
579 panel_data->gpio_invert[i] ? 1 : 0);
580 }
581
582 /* wait couple of vsyncs after disabling the LCD */
583 if (panel_config->power_off_delay)
584 msleep(panel_config->power_off_delay);
585
586 omapdss_dpi_display_disable(dssdev);
587}
588
589static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
590{
591 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
592 struct panel_config *panel_config = NULL;
593 struct panel_drv_data *drv_data = NULL;
594 int i, r;
595
596 dev_dbg(dssdev->dev, "probe\n");
597
598 if (!panel_data || !panel_data->name)
599 return -EINVAL;
600
601 for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) {
602 if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) {
603 panel_config = &generic_dpi_panels[i];
604 break;
605 }
606 }
607
608 if (!panel_config)
609 return -EINVAL;
610
611 for (i = 0; i < panel_data->num_gpios; ++i) {
612 r = devm_gpio_request_one(dssdev->dev, panel_data->gpios[i],
613 panel_data->gpio_invert[i] ?
614 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
615 "panel gpio");
616 if (r)
617 return r;
618 }
619
620 dssdev->panel.timings = panel_config->timings;
621
622 drv_data = devm_kzalloc(dssdev->dev, sizeof(*drv_data), GFP_KERNEL);
623 if (!drv_data)
624 return -ENOMEM;
625
626 drv_data->dssdev = dssdev;
627 drv_data->panel_config = panel_config;
628
629 mutex_init(&drv_data->lock);
630
631 dev_set_drvdata(dssdev->dev, drv_data);
632
633 return 0;
634}
635
636static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
637{
638 dev_dbg(dssdev->dev, "remove\n");
639
640 dev_set_drvdata(dssdev->dev, NULL);
641}
642
643static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
644{
645 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
646 int r;
647
648 mutex_lock(&drv_data->lock);
649
650 r = generic_dpi_panel_power_on(dssdev);
651 if (r)
652 goto err;
653
654 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
655err:
656 mutex_unlock(&drv_data->lock);
657
658 return r;
659}
660
661static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
662{
663 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
664
665 mutex_lock(&drv_data->lock);
666
667 generic_dpi_panel_power_off(dssdev);
668
669 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
670
671 mutex_unlock(&drv_data->lock);
672}
673
674static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
675 struct omap_video_timings *timings)
676{
677 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
678
679 mutex_lock(&drv_data->lock);
680
681 omapdss_dpi_set_timings(dssdev, timings);
682
683 dssdev->panel.timings = *timings;
684
685 mutex_unlock(&drv_data->lock);
686}
687
688static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
689 struct omap_video_timings *timings)
690{
691 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
692
693 mutex_lock(&drv_data->lock);
694
695 *timings = dssdev->panel.timings;
696
697 mutex_unlock(&drv_data->lock);
698}
699
700static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
701 struct omap_video_timings *timings)
702{
703 struct panel_drv_data *drv_data = dev_get_drvdata(dssdev->dev);
704 int r;
705
706 mutex_lock(&drv_data->lock);
707
708 r = dpi_check_timings(dssdev, timings);
709
710 mutex_unlock(&drv_data->lock);
711
712 return r;
713}
714
715static struct omap_dss_driver dpi_driver = {
716 .probe = generic_dpi_panel_probe,
717 .remove = __exit_p(generic_dpi_panel_remove),
718
719 .enable = generic_dpi_panel_enable,
720 .disable = generic_dpi_panel_disable,
721
722 .set_timings = generic_dpi_panel_set_timings,
723 .get_timings = generic_dpi_panel_get_timings,
724 .check_timings = generic_dpi_panel_check_timings,
725
726 .driver = {
727 .name = "generic_dpi_panel",
728 .owner = THIS_MODULE,
729 },
730};
731
732static int __init generic_dpi_panel_drv_init(void)
733{
734 return omap_dss_register_driver(&dpi_driver);
735}
736
737static void __exit generic_dpi_panel_drv_exit(void)
738{
739 omap_dss_unregister_driver(&dpi_driver);
740}
741
742module_init(generic_dpi_panel_drv_init);
743module_exit(generic_dpi_panel_drv_exit);
744MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
deleted file mode 100644
index 6c51430ddb37..000000000000
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ /dev/null
@@ -1,262 +0,0 @@
1/*
2 * LCD panel driver for LG.Philips LB035Q02
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/spi/spi.h>
22#include <linux/mutex.h>
23#include <linux/gpio.h>
24
25#include <video/omapdss.h>
26#include <video/omap-panel-data.h>
27
28struct lb035q02_data {
29 struct mutex lock;
30};
31
32static struct omap_video_timings lb035q02_timings = {
33 .x_res = 320,
34 .y_res = 240,
35
36 .pixel_clock = 6500,
37
38 .hsw = 2,
39 .hfp = 20,
40 .hbp = 68,
41
42 .vsw = 2,
43 .vfp = 4,
44 .vbp = 18,
45
46 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
47 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
48 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
49 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
50 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
51};
52
53static inline struct panel_generic_dpi_data
54*get_panel_data(const struct omap_dss_device *dssdev)
55{
56 return (struct panel_generic_dpi_data *) dssdev->data;
57}
58
59static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
60{
61 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
62 int r, i;
63
64 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
65 return 0;
66
67 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
68 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
69
70 r = omapdss_dpi_display_enable(dssdev);
71 if (r)
72 goto err0;
73
74 for (i = 0; i < panel_data->num_gpios; ++i) {
75 gpio_set_value_cansleep(panel_data->gpios[i],
76 panel_data->gpio_invert[i] ? 0 : 1);
77 }
78
79 return 0;
80
81err0:
82 return r;
83}
84
85static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
86{
87 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
88 int i;
89
90 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
91 return;
92
93 for (i = panel_data->num_gpios - 1; i >= 0; --i) {
94 gpio_set_value_cansleep(panel_data->gpios[i],
95 panel_data->gpio_invert[i] ? 1 : 0);
96 }
97
98 omapdss_dpi_display_disable(dssdev);
99}
100
101static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
102{
103 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
104 struct lb035q02_data *ld;
105 int r, i;
106
107 if (!panel_data)
108 return -EINVAL;
109
110 dssdev->panel.timings = lb035q02_timings;
111
112 ld = devm_kzalloc(dssdev->dev, sizeof(*ld), GFP_KERNEL);
113 if (!ld)
114 return -ENOMEM;
115
116 for (i = 0; i < panel_data->num_gpios; ++i) {
117 r = devm_gpio_request_one(dssdev->dev, panel_data->gpios[i],
118 panel_data->gpio_invert[i] ?
119 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
120 "panel gpio");
121 if (r)
122 return r;
123 }
124
125 mutex_init(&ld->lock);
126 dev_set_drvdata(dssdev->dev, ld);
127
128 return 0;
129}
130
131static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
132{
133}
134
135static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
136{
137 struct lb035q02_data *ld = dev_get_drvdata(dssdev->dev);
138 int r;
139
140 mutex_lock(&ld->lock);
141
142 r = lb035q02_panel_power_on(dssdev);
143 if (r)
144 goto err;
145 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
146
147 mutex_unlock(&ld->lock);
148 return 0;
149err:
150 mutex_unlock(&ld->lock);
151 return r;
152}
153
154static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
155{
156 struct lb035q02_data *ld = dev_get_drvdata(dssdev->dev);
157
158 mutex_lock(&ld->lock);
159
160 lb035q02_panel_power_off(dssdev);
161 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
162
163 mutex_unlock(&ld->lock);
164}
165
166static struct omap_dss_driver lb035q02_driver = {
167 .probe = lb035q02_panel_probe,
168 .remove = lb035q02_panel_remove,
169
170 .enable = lb035q02_panel_enable,
171 .disable = lb035q02_panel_disable,
172
173 .driver = {
174 .name = "lgphilips_lb035q02_panel",
175 .owner = THIS_MODULE,
176 },
177};
178
179static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val)
180{
181 struct spi_message msg;
182 struct spi_transfer index_xfer = {
183 .len = 3,
184 .cs_change = 1,
185 };
186 struct spi_transfer value_xfer = {
187 .len = 3,
188 };
189 u8 buffer[16];
190
191 spi_message_init(&msg);
192
193 /* register index */
194 buffer[0] = 0x70;
195 buffer[1] = 0x00;
196 buffer[2] = reg & 0x7f;
197 index_xfer.tx_buf = buffer;
198 spi_message_add_tail(&index_xfer, &msg);
199
200 /* register value */
201 buffer[4] = 0x72;
202 buffer[5] = val >> 8;
203 buffer[6] = val;
204 value_xfer.tx_buf = buffer + 4;
205 spi_message_add_tail(&value_xfer, &msg);
206
207 return spi_sync(spi, &msg);
208}
209
210static void init_lb035q02_panel(struct spi_device *spi)
211{
212 /* Init sequence from page 28 of the lb035q02 spec */
213 lb035q02_write_reg(spi, 0x01, 0x6300);
214 lb035q02_write_reg(spi, 0x02, 0x0200);
215 lb035q02_write_reg(spi, 0x03, 0x0177);
216 lb035q02_write_reg(spi, 0x04, 0x04c7);
217 lb035q02_write_reg(spi, 0x05, 0xffc0);
218 lb035q02_write_reg(spi, 0x06, 0xe806);
219 lb035q02_write_reg(spi, 0x0a, 0x4008);
220 lb035q02_write_reg(spi, 0x0b, 0x0000);
221 lb035q02_write_reg(spi, 0x0d, 0x0030);
222 lb035q02_write_reg(spi, 0x0e, 0x2800);
223 lb035q02_write_reg(spi, 0x0f, 0x0000);
224 lb035q02_write_reg(spi, 0x16, 0x9f80);
225 lb035q02_write_reg(spi, 0x17, 0x0a0f);
226 lb035q02_write_reg(spi, 0x1e, 0x00c1);
227 lb035q02_write_reg(spi, 0x30, 0x0300);
228 lb035q02_write_reg(spi, 0x31, 0x0007);
229 lb035q02_write_reg(spi, 0x32, 0x0000);
230 lb035q02_write_reg(spi, 0x33, 0x0000);
231 lb035q02_write_reg(spi, 0x34, 0x0707);
232 lb035q02_write_reg(spi, 0x35, 0x0004);
233 lb035q02_write_reg(spi, 0x36, 0x0302);
234 lb035q02_write_reg(spi, 0x37, 0x0202);
235 lb035q02_write_reg(spi, 0x3a, 0x0a0d);
236 lb035q02_write_reg(spi, 0x3b, 0x0806);
237}
238
239static int lb035q02_panel_spi_probe(struct spi_device *spi)
240{
241 init_lb035q02_panel(spi);
242 return omap_dss_register_driver(&lb035q02_driver);
243}
244
245static int lb035q02_panel_spi_remove(struct spi_device *spi)
246{
247 omap_dss_unregister_driver(&lb035q02_driver);
248 return 0;
249}
250
251static struct spi_driver lb035q02_spi_driver = {
252 .driver = {
253 .name = "lgphilips_lb035q02_panel-spi",
254 .owner = THIS_MODULE,
255 },
256 .probe = lb035q02_panel_spi_probe,
257 .remove = lb035q02_panel_spi_remove,
258};
259
260module_spi_driver(lb035q02_spi_driver);
261
262MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
deleted file mode 100644
index 1d525fc84db9..000000000000
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ /dev/null
@@ -1,616 +0,0 @@
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/fb.h>
9
10#include <video/omapdss.h>
11#include <video/omap-panel-data.h>
12
13#define BLIZZARD_REV_CODE 0x00
14#define BLIZZARD_CONFIG 0x02
15#define BLIZZARD_PLL_DIV 0x04
16#define BLIZZARD_PLL_LOCK_RANGE 0x06
17#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
18#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
19#define BLIZZARD_PLL_MODE 0x0c
20#define BLIZZARD_CLK_SRC 0x0e
21#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
22#define BLIZZARD_MEM_BANK0_STATUS 0x14
23#define BLIZZARD_PANEL_CONFIGURATION 0x28
24#define BLIZZARD_HDISP 0x2a
25#define BLIZZARD_HNDP 0x2c
26#define BLIZZARD_VDISP0 0x2e
27#define BLIZZARD_VDISP1 0x30
28#define BLIZZARD_VNDP 0x32
29#define BLIZZARD_HSW 0x34
30#define BLIZZARD_VSW 0x38
31#define BLIZZARD_DISPLAY_MODE 0x68
32#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
33#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
34#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
35#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
36#define BLIZZARD_POWER_SAVE 0xE6
37#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
38
39/* Data source select */
40/* For S1D13745 */
41#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
42#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
43#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
44#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
45/* For S1D13744 */
46#define BLIZZARD_SRC_WRITE_LCD 0x00
47#define BLIZZARD_SRC_BLT_LCD 0x06
48
49#define BLIZZARD_COLOR_RGB565 0x01
50#define BLIZZARD_COLOR_YUV420 0x09
51
52#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
53#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
54
55#define MIPID_CMD_READ_DISP_ID 0x04
56#define MIPID_CMD_READ_RED 0x06
57#define MIPID_CMD_READ_GREEN 0x07
58#define MIPID_CMD_READ_BLUE 0x08
59#define MIPID_CMD_READ_DISP_STATUS 0x09
60#define MIPID_CMD_RDDSDR 0x0F
61#define MIPID_CMD_SLEEP_IN 0x10
62#define MIPID_CMD_SLEEP_OUT 0x11
63#define MIPID_CMD_DISP_OFF 0x28
64#define MIPID_CMD_DISP_ON 0x29
65
66static struct panel_drv_data {
67 struct mutex lock;
68
69 struct omap_dss_device *dssdev;
70 struct spi_device *spidev;
71
72 int blizzard_ver;
73} s_drv_data;
74
75
76static inline
77struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
78{
79 return dssdev->data;
80}
81
82static inline
83struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
84{
85 return &s_drv_data;
86}
87
88
89static inline void blizzard_cmd(u8 cmd)
90{
91 omap_rfbi_write_command(&cmd, 1);
92}
93
94static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
95{
96 omap_rfbi_write_command(&cmd, 1);
97 omap_rfbi_write_data(buf, len);
98}
99
100static inline void blizzard_read(u8 cmd, u8 *buf, int len)
101{
102 omap_rfbi_write_command(&cmd, 1);
103 omap_rfbi_read_data(buf, len);
104}
105
106static u8 blizzard_read_reg(u8 cmd)
107{
108 u8 data;
109 blizzard_read(cmd, &data, 1);
110 return data;
111}
112
113static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
114 int x, int y, int w, int h)
115{
116 struct panel_drv_data *ddata = get_drv_data(dssdev);
117 u8 tmp[18];
118 int x_end, y_end;
119
120 x_end = x + w - 1;
121 y_end = y + h - 1;
122
123 tmp[0] = x;
124 tmp[1] = x >> 8;
125 tmp[2] = y;
126 tmp[3] = y >> 8;
127 tmp[4] = x_end;
128 tmp[5] = x_end >> 8;
129 tmp[6] = y_end;
130 tmp[7] = y_end >> 8;
131
132 /* scaling? */
133 tmp[8] = x;
134 tmp[9] = x >> 8;
135 tmp[10] = y;
136 tmp[11] = y >> 8;
137 tmp[12] = x_end;
138 tmp[13] = x_end >> 8;
139 tmp[14] = y_end;
140 tmp[15] = y_end >> 8;
141
142 tmp[16] = BLIZZARD_COLOR_RGB565;
143
144 if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
145 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
146 else
147 tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
148 BLIZZARD_SRC_WRITE_LCD :
149 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
150
151 omapdss_rfbi_set_pixel_size(dssdev, 16);
152 omapdss_rfbi_set_data_lines(dssdev, 8);
153
154 omap_rfbi_configure(dssdev);
155
156 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
157
158 omapdss_rfbi_set_pixel_size(dssdev, 16);
159 omapdss_rfbi_set_data_lines(dssdev, 16);
160
161 omap_rfbi_configure(dssdev);
162}
163
164static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
165 int wlen, u8 *rbuf, int rlen)
166{
167 struct spi_message m;
168 struct spi_transfer *x, xfer[4];
169 u16 w;
170 int r;
171
172 spi_message_init(&m);
173
174 memset(xfer, 0, sizeof(xfer));
175 x = &xfer[0];
176
177 cmd &= 0xff;
178 x->tx_buf = &cmd;
179 x->bits_per_word = 9;
180 x->len = 2;
181 spi_message_add_tail(x, &m);
182
183 if (wlen) {
184 x++;
185 x->tx_buf = wbuf;
186 x->len = wlen;
187 x->bits_per_word = 9;
188 spi_message_add_tail(x, &m);
189 }
190
191 if (rlen) {
192 x++;
193 x->rx_buf = &w;
194 x->len = 1;
195 spi_message_add_tail(x, &m);
196
197 if (rlen > 1) {
198 /* Arrange for the extra clock before the first
199 * data bit.
200 */
201 x->bits_per_word = 9;
202 x->len = 2;
203
204 x++;
205 x->rx_buf = &rbuf[1];
206 x->len = rlen - 1;
207 spi_message_add_tail(x, &m);
208 }
209 }
210
211 r = spi_sync(spi, &m);
212 if (r < 0)
213 dev_dbg(&spi->dev, "spi_sync %d\n", r);
214
215 if (rlen)
216 rbuf[0] = w & 0xff;
217}
218
219static inline void mipid_cmd(struct spi_device *spi, int cmd)
220{
221 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
222}
223
224static inline void mipid_write(struct spi_device *spi,
225 int reg, const u8 *buf, int len)
226{
227 mipid_transfer(spi, reg, buf, len, NULL, 0);
228}
229
230static inline void mipid_read(struct spi_device *spi,
231 int reg, u8 *buf, int len)
232{
233 mipid_transfer(spi, reg, NULL, 0, buf, len);
234}
235
236static void set_data_lines(struct spi_device *spi, int data_lines)
237{
238 u16 par;
239
240 switch (data_lines) {
241 case 16:
242 par = 0x150;
243 break;
244 case 18:
245 par = 0x160;
246 break;
247 case 24:
248 par = 0x170;
249 break;
250 }
251
252 mipid_write(spi, 0x3a, (u8 *)&par, 2);
253}
254
255static void send_init_string(struct spi_device *spi)
256{
257 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
258 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
259}
260
261static void send_display_on(struct spi_device *spi)
262{
263 mipid_cmd(spi, MIPID_CMD_DISP_ON);
264}
265
266static void send_display_off(struct spi_device *spi)
267{
268 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
269}
270
271static void send_sleep_out(struct spi_device *spi)
272{
273 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
274 msleep(120);
275}
276
277static void send_sleep_in(struct spi_device *spi)
278{
279 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
280 msleep(50);
281}
282
283static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
284{
285 int r;
286 struct panel_n8x0_data *bdata = get_board_data(dssdev);
287 struct panel_drv_data *ddata = get_drv_data(dssdev);
288 struct spi_device *spi = ddata->spidev;
289 u8 rev, conf;
290 u8 display_id[3];
291 const char *panel_name;
292
293 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
294 return 0;
295
296 gpio_direction_output(bdata->ctrl_pwrdown, 1);
297
298 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
299 dssdev->panel.timings.y_res);
300 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
301 omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
302 omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
303
304 r = omapdss_rfbi_display_enable(dssdev);
305 if (r)
306 goto err_rfbi_en;
307
308 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
309 conf = blizzard_read_reg(BLIZZARD_CONFIG);
310
311 switch (rev & 0xfc) {
312 case 0x9c:
313 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
314 dev_info(dssdev->dev, "s1d13744 LCD controller rev %d "
315 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
316 break;
317 case 0xa4:
318 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
319 dev_info(dssdev->dev, "s1d13745 LCD controller rev %d "
320 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
321 break;
322 default:
323 dev_err(dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
324 r = -ENODEV;
325 goto err_inv_chip;
326 }
327
328 /* panel */
329
330 gpio_direction_output(bdata->panel_reset, 1);
331
332 mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
333 dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
334 display_id[0], display_id[1], display_id[2]);
335
336 switch (display_id[0]) {
337 case 0x45:
338 panel_name = "lph8923";
339 break;
340 case 0x83:
341 panel_name = "ls041y3";
342 break;
343 default:
344 dev_err(dssdev->dev, "invalid display ID 0x%x\n",
345 display_id[0]);
346 r = -ENODEV;
347 goto err_inv_panel;
348 }
349
350 dev_info(dssdev->dev, "%s rev %02x LCD detected\n",
351 panel_name, display_id[1]);
352
353 send_sleep_out(spi);
354 send_init_string(spi);
355 set_data_lines(spi, 24);
356 send_display_on(spi);
357
358 return 0;
359
360err_inv_panel:
361 /*
362 * HACK: we should turn off the panel here, but there is some problem
363 * with the initialization sequence, and we fail to init the panel if we
364 * have turned it off
365 */
366 /* gpio_direction_output(bdata->panel_reset, 0); */
367err_inv_chip:
368 omapdss_rfbi_display_disable(dssdev);
369err_rfbi_en:
370 gpio_direction_output(bdata->ctrl_pwrdown, 0);
371 return r;
372}
373
374static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
375{
376 struct panel_n8x0_data *bdata = get_board_data(dssdev);
377 struct panel_drv_data *ddata = get_drv_data(dssdev);
378 struct spi_device *spi = ddata->spidev;
379
380 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
381 return;
382
383 send_display_off(spi);
384 send_sleep_in(spi);
385
386 /*
387 * HACK: we should turn off the panel here, but there is some problem
388 * with the initialization sequence, and we fail to init the panel if we
389 * have turned it off
390 */
391 /* gpio_direction_output(bdata->panel_reset, 0); */
392 gpio_direction_output(bdata->ctrl_pwrdown, 0);
393 omapdss_rfbi_display_disable(dssdev);
394}
395
396static const struct rfbi_timings n8x0_panel_timings = {
397 .cs_on_time = 0,
398
399 .we_on_time = 9000,
400 .we_off_time = 18000,
401 .we_cycle_time = 36000,
402
403 .re_on_time = 9000,
404 .re_off_time = 27000,
405 .re_cycle_time = 36000,
406
407 .access_time = 27000,
408 .cs_off_time = 36000,
409
410 .cs_pulse_width = 0,
411};
412
413static int n8x0_panel_probe(struct omap_dss_device *dssdev)
414{
415 struct panel_n8x0_data *bdata = get_board_data(dssdev);
416 struct panel_drv_data *ddata;
417 int r;
418
419 dev_dbg(dssdev->dev, "probe\n");
420
421 if (!bdata)
422 return -EINVAL;
423
424 s_drv_data.dssdev = dssdev;
425
426 ddata = &s_drv_data;
427
428 mutex_init(&ddata->lock);
429
430 dssdev->panel.timings.x_res = 800;
431 dssdev->panel.timings.y_res = 480;
432 dssdev->ctrl.pixel_size = 16;
433 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
434 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
435
436 if (gpio_is_valid(bdata->panel_reset)) {
437 r = devm_gpio_request_one(dssdev->dev, bdata->panel_reset,
438 GPIOF_OUT_INIT_LOW, "PANEL RESET");
439 if (r)
440 return r;
441 }
442
443 if (gpio_is_valid(bdata->ctrl_pwrdown)) {
444 r = devm_gpio_request_one(dssdev->dev, bdata->ctrl_pwrdown,
445 GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN");
446 if (r)
447 return r;
448 }
449
450 return 0;
451}
452
453static void n8x0_panel_remove(struct omap_dss_device *dssdev)
454{
455 dev_dbg(dssdev->dev, "remove\n");
456
457 dev_set_drvdata(dssdev->dev, NULL);
458}
459
460static int n8x0_panel_enable(struct omap_dss_device *dssdev)
461{
462 struct panel_drv_data *ddata = get_drv_data(dssdev);
463 int r;
464
465 dev_dbg(dssdev->dev, "enable\n");
466
467 mutex_lock(&ddata->lock);
468
469 rfbi_bus_lock();
470
471 r = n8x0_panel_power_on(dssdev);
472
473 rfbi_bus_unlock();
474
475 if (r) {
476 mutex_unlock(&ddata->lock);
477 return r;
478 }
479
480 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
481
482 mutex_unlock(&ddata->lock);
483
484 return 0;
485}
486
487static void n8x0_panel_disable(struct omap_dss_device *dssdev)
488{
489 struct panel_drv_data *ddata = get_drv_data(dssdev);
490
491 dev_dbg(dssdev->dev, "disable\n");
492
493 mutex_lock(&ddata->lock);
494
495 rfbi_bus_lock();
496
497 n8x0_panel_power_off(dssdev);
498
499 rfbi_bus_unlock();
500
501 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
502
503 mutex_unlock(&ddata->lock);
504}
505
506static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
507 u16 *xres, u16 *yres)
508{
509 *xres = dssdev->panel.timings.x_res;
510 *yres = dssdev->panel.timings.y_res;
511}
512
513static void update_done(void *data)
514{
515 rfbi_bus_unlock();
516}
517
518static int n8x0_panel_update(struct omap_dss_device *dssdev,
519 u16 x, u16 y, u16 w, u16 h)
520{
521 struct panel_drv_data *ddata = get_drv_data(dssdev);
522 u16 dw, dh;
523
524 dev_dbg(dssdev->dev, "update\n");
525
526 dw = dssdev->panel.timings.x_res;
527 dh = dssdev->panel.timings.y_res;
528
529 if (x != 0 || y != 0 || w != dw || h != dh) {
530 dev_err(dssdev->dev, "invalid update region %d, %d, %d, %d\n",
531 x, y, w, h);
532 return -EINVAL;
533 }
534
535 mutex_lock(&ddata->lock);
536 rfbi_bus_lock();
537
538 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
539
540 omap_rfbi_update(dssdev, update_done, NULL);
541
542 mutex_unlock(&ddata->lock);
543
544 return 0;
545}
546
547static int n8x0_panel_sync(struct omap_dss_device *dssdev)
548{
549 struct panel_drv_data *ddata = get_drv_data(dssdev);
550
551 dev_dbg(dssdev->dev, "sync\n");
552
553 mutex_lock(&ddata->lock);
554 rfbi_bus_lock();
555 rfbi_bus_unlock();
556 mutex_unlock(&ddata->lock);
557
558 return 0;
559}
560
561static struct omap_dss_driver n8x0_panel_driver = {
562 .probe = n8x0_panel_probe,
563 .remove = n8x0_panel_remove,
564
565 .enable = n8x0_panel_enable,
566 .disable = n8x0_panel_disable,
567
568 .update = n8x0_panel_update,
569 .sync = n8x0_panel_sync,
570
571 .get_resolution = n8x0_panel_get_resolution,
572 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
573
574 .driver = {
575 .name = "n8x0_panel",
576 .owner = THIS_MODULE,
577 },
578};
579
580/* PANEL */
581
582static int mipid_spi_probe(struct spi_device *spi)
583{
584 int r;
585
586 dev_dbg(&spi->dev, "mipid_spi_probe\n");
587
588 spi->mode = SPI_MODE_0;
589
590 s_drv_data.spidev = spi;
591
592 r = omap_dss_register_driver(&n8x0_panel_driver);
593 if (r)
594 pr_err("n8x0_panel: dss driver registration failed\n");
595
596 return r;
597}
598
599static int mipid_spi_remove(struct spi_device *spi)
600{
601 dev_dbg(&spi->dev, "mipid_spi_remove\n");
602 omap_dss_unregister_driver(&n8x0_panel_driver);
603 return 0;
604}
605
606static struct spi_driver mipid_spi_driver = {
607 .driver = {
608 .name = "lcd_mipid",
609 .owner = THIS_MODULE,
610 },
611 .probe = mipid_spi_probe,
612 .remove = mipid_spi_remove,
613};
614module_spi_driver(mipid_spi_driver);
615
616MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
deleted file mode 100644
index 6b9f7925e918..000000000000
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ /dev/null
@@ -1,290 +0,0 @@
1/*
2 * Support for NEC-nl8048hl11-01b panel driver
3 *
4 * Copyright (C) 2010 Texas Instruments Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/spi/spi.h>
22#include <linux/fb.h>
23#include <linux/gpio.h>
24
25#include <video/omapdss.h>
26#include <video/omap-panel-data.h>
27
28#define LCD_XRES 800
29#define LCD_YRES 480
30/*
31 * NEC PIX Clock Ratings
32 * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz
33 */
34#define LCD_PIXEL_CLOCK 23800
35
36static const struct {
37 unsigned char addr;
38 unsigned char dat;
39} nec_8048_init_seq[] = {
40 { 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 },
41 { 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 },
42 { 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 }, { 24, 0x25 },
43 { 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F },
44 { 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F }, { 38, 0x0F },
45 { 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 }, { 43, 0x0F },
46 { 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F }, { 48, 0x0F },
47 { 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 },
48 { 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 }, { 86, 0x14 },
49 { 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 }, { 93, 0x0C },
50 { 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 },
51 { 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 },
52 { 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 },
53 { 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 },
54 { 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC },
55 { 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 },
56 { 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 },
57 { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
58};
59
60/*
61 * NEC NL8048HL11-01B Manual
62 * defines HFB, HSW, HBP, VFP, VSW, VBP as shown below
63 */
64
65static struct omap_video_timings nec_8048_panel_timings = {
66 /* 800 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
67 .x_res = LCD_XRES,
68 .y_res = LCD_YRES,
69 .pixel_clock = LCD_PIXEL_CLOCK,
70 .hfp = 6,
71 .hsw = 1,
72 .hbp = 4,
73 .vfp = 3,
74 .vsw = 1,
75 .vbp = 4,
76
77 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
78 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
79 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
80 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
81 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
82};
83
84static inline struct panel_nec_nl8048_data
85*get_panel_data(const struct omap_dss_device *dssdev)
86{
87 return (struct panel_nec_nl8048_data *) dssdev->data;
88}
89
90static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
91{
92 struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
93 int r;
94
95 if (!pd)
96 return -EINVAL;
97
98 dssdev->panel.timings = nec_8048_panel_timings;
99
100 if (gpio_is_valid(pd->qvga_gpio)) {
101 r = devm_gpio_request_one(dssdev->dev, pd->qvga_gpio,
102 GPIOF_OUT_INIT_HIGH, "lcd QVGA");
103 if (r)
104 return r;
105 }
106
107 if (gpio_is_valid(pd->res_gpio)) {
108 r = devm_gpio_request_one(dssdev->dev, pd->res_gpio,
109 GPIOF_OUT_INIT_LOW, "lcd RES");
110 if (r)
111 return r;
112 }
113
114 return 0;
115}
116
117static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
118{
119}
120
121static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
122{
123 struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
124 int r;
125
126 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
127 return 0;
128
129 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
130 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
131
132 r = omapdss_dpi_display_enable(dssdev);
133 if (r)
134 goto err0;
135
136 if (gpio_is_valid(pd->res_gpio))
137 gpio_set_value_cansleep(pd->res_gpio, 1);
138
139 return 0;
140
141err0:
142 return r;
143}
144
145static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
146{
147 struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
148
149 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
150 return;
151
152 if (gpio_is_valid(pd->res_gpio))
153 gpio_set_value_cansleep(pd->res_gpio, 0);
154
155 omapdss_dpi_display_disable(dssdev);
156}
157
158static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
159{
160 int r;
161
162 r = nec_8048_panel_power_on(dssdev);
163 if (r)
164 return r;
165
166 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
167
168 return 0;
169}
170
171static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
172{
173 nec_8048_panel_power_off(dssdev);
174
175 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
176}
177
178static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
179{
180 return 16;
181}
182
183static struct omap_dss_driver nec_8048_driver = {
184 .probe = nec_8048_panel_probe,
185 .remove = nec_8048_panel_remove,
186 .enable = nec_8048_panel_enable,
187 .disable = nec_8048_panel_disable,
188 .get_recommended_bpp = nec_8048_recommended_bpp,
189
190 .driver = {
191 .name = "NEC_8048_panel",
192 .owner = THIS_MODULE,
193 },
194};
195
196static int nec_8048_spi_send(struct spi_device *spi, unsigned char reg_addr,
197 unsigned char reg_data)
198{
199 int ret = 0;
200 unsigned int cmd = 0, data = 0;
201
202 cmd = 0x0000 | reg_addr; /* register address write */
203 data = 0x0100 | reg_data ; /* register data write */
204 data = (cmd << 16) | data;
205
206 ret = spi_write(spi, (unsigned char *)&data, 4);
207 if (ret)
208 pr_err("error in spi_write %x\n", data);
209
210 return ret;
211}
212
213static int init_nec_8048_wvga_lcd(struct spi_device *spi)
214{
215 unsigned int i;
216 /* Initialization Sequence */
217 /* nec_8048_spi_send(spi, REG, VAL) */
218 for (i = 0; i < (ARRAY_SIZE(nec_8048_init_seq) - 1); i++)
219 nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
220 nec_8048_init_seq[i].dat);
221 udelay(20);
222 nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
223 nec_8048_init_seq[i].dat);
224 return 0;
225}
226
227static int nec_8048_spi_probe(struct spi_device *spi)
228{
229 spi->mode = SPI_MODE_0;
230 spi->bits_per_word = 32;
231 spi_setup(spi);
232
233 init_nec_8048_wvga_lcd(spi);
234
235 return omap_dss_register_driver(&nec_8048_driver);
236}
237
238static int nec_8048_spi_remove(struct spi_device *spi)
239{
240 omap_dss_unregister_driver(&nec_8048_driver);
241
242 return 0;
243}
244
245#ifdef CONFIG_PM_SLEEP
246
247static int nec_8048_spi_suspend(struct device *dev)
248{
249 struct spi_device *spi = to_spi_device(dev);
250
251 nec_8048_spi_send(spi, 2, 0x01);
252 mdelay(40);
253
254 return 0;
255}
256
257static int nec_8048_spi_resume(struct device *dev)
258{
259 struct spi_device *spi = to_spi_device(dev);
260
261 /* reinitialize the panel */
262 spi_setup(spi);
263 nec_8048_spi_send(spi, 2, 0x00);
264 init_nec_8048_wvga_lcd(spi);
265
266 return 0;
267}
268
269static SIMPLE_DEV_PM_OPS(nec_8048_spi_pm_ops, nec_8048_spi_suspend,
270 nec_8048_spi_resume);
271#define NEC_8048_SPI_PM_OPS (&nec_8048_spi_pm_ops)
272#else
273#define NEC_8048_SPI_PM_OPS NULL
274#endif
275
276static struct spi_driver nec_8048_spi_driver = {
277 .probe = nec_8048_spi_probe,
278 .remove = nec_8048_spi_remove,
279 .driver = {
280 .name = "nec_8048_spi",
281 .owner = THIS_MODULE,
282 .pm = NEC_8048_SPI_PM_OPS,
283 },
284};
285
286module_spi_driver(nec_8048_spi_driver);
287
288MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
289MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
290MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
deleted file mode 100644
index 153e9bea0f6e..000000000000
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ /dev/null
@@ -1,559 +0,0 @@
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-data.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};
55
56struct picodlp_i2c_command {
57 u8 reg;
58 u32 value;
59};
60
61static struct omap_video_timings pico_ls_timings = {
62 .x_res = 864,
63 .y_res = 480,
64 .hsw = 7,
65 .hfp = 11,
66 .hbp = 7,
67
68 .pixel_clock = 19200,
69
70 .vsw = 2,
71 .vfp = 3,
72 .vbp = 14,
73
74 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
75 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
76 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
77 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
78 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
79};
80
81static inline struct picodlp_panel_data
82 *get_panel_data(const struct omap_dss_device *dssdev)
83{
84 return (struct picodlp_panel_data *) dssdev->data;
85}
86
87static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
88{
89 u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
90 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
91 struct i2c_msg msg[2];
92
93 mutex_lock(&picodlp_i2c_data->xfer_lock);
94
95 msg[0].addr = client->addr;
96 msg[0].flags = 0;
97 msg[0].len = 2;
98 msg[0].buf = read_cmd;
99
100 msg[1].addr = client->addr;
101 msg[1].flags = I2C_M_RD;
102 msg[1].len = 4;
103 msg[1].buf = data;
104
105 i2c_transfer(client->adapter, msg, 2);
106 mutex_unlock(&picodlp_i2c_data->xfer_lock);
107 return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
108}
109
110static int picodlp_i2c_write_block(struct i2c_client *client,
111 u8 *data, int len)
112{
113 struct i2c_msg msg;
114 int i, r, msg_count = 1;
115
116 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
117
118 if (len < 1 || len > 32) {
119 dev_err(&client->dev,
120 "too long syn_write_block len %d\n", len);
121 return -EIO;
122 }
123 mutex_lock(&picodlp_i2c_data->xfer_lock);
124
125 msg.addr = client->addr;
126 msg.flags = 0;
127 msg.len = len;
128 msg.buf = data;
129 r = i2c_transfer(client->adapter, &msg, msg_count);
130 mutex_unlock(&picodlp_i2c_data->xfer_lock);
131
132 /*
133 * i2c_transfer returns:
134 * number of messages sent in case of success
135 * a negative error number in case of failure
136 */
137 if (r != msg_count)
138 goto err;
139
140 /* In case of success */
141 for (i = 0; i < len; i++)
142 dev_dbg(&client->dev,
143 "addr %x bw 0x%02x[%d]: 0x%02x\n",
144 client->addr, data[0] + i, i, data[i]);
145
146 return 0;
147err:
148 dev_err(&client->dev, "picodlp_i2c_write error\n");
149 return r;
150}
151
152static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
153{
154 u8 data[5];
155 int i;
156
157 data[0] = reg;
158 for (i = 1; i < 5; i++)
159 data[i] = (value >> (32 - (i) * 8)) & 0xFF;
160
161 return picodlp_i2c_write_block(client, data, 5);
162}
163
164static int picodlp_i2c_write_array(struct i2c_client *client,
165 const struct picodlp_i2c_command commands[],
166 int count)
167{
168 int i, r = 0;
169 for (i = 0; i < count; i++) {
170 r = picodlp_i2c_write(client, commands[i].reg,
171 commands[i].value);
172 if (r)
173 return r;
174 }
175 return r;
176}
177
178static int picodlp_wait_for_dma_done(struct i2c_client *client)
179{
180 u8 trial = 100;
181
182 do {
183 msleep(1);
184 if (!trial--)
185 return -ETIMEDOUT;
186 } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
187
188 return 0;
189}
190
191/**
192 * picodlp_i2c_init: i2c_initialization routine
193 * client: i2c_client for communication
194 *
195 * return
196 * 0 : Success, no error
197 * error code : Failure
198 */
199static int picodlp_i2c_init(struct i2c_client *client)
200{
201 int r;
202 static const struct picodlp_i2c_command init_cmd_set1[] = {
203 {SOFT_RESET, 1},
204 {DMD_PARK_TRIGGER, 1},
205 {MISC_REG, 5},
206 {SEQ_CONTROL, 0},
207 {SEQ_VECTOR, 0x100},
208 {DMD_BLOCK_COUNT, 7},
209 {DMD_VCC_CONTROL, 0x109},
210 {DMD_PARK_PULSE_COUNT, 0xA},
211 {DMD_PARK_PULSE_WIDTH, 0xB},
212 {DMD_PARK_DELAY, 0x2ED},
213 {DMD_SHADOW_ENABLE, 0},
214 {FLASH_OPCODE, 0xB},
215 {FLASH_DUMMY_BYTES, 1},
216 {FLASH_ADDR_BYTES, 3},
217 {PBC_CONTROL, 0},
218 {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
219 {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
220 {CMT_SPLASH_LUT_START_ADDR, 0},
221 {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
222 {PBC_CONTROL, 1},
223 };
224
225 static const struct picodlp_i2c_command init_cmd_set2[] = {
226 {PBC_CONTROL, 0},
227 {CMT_SPLASH_LUT_DEST_SELECT, 0},
228 {PBC_CONTROL, 0},
229 {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
230 {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
231 {SEQ_RESET_LUT_START_ADDR, 0},
232 {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
233 {PBC_CONTROL, 1},
234 };
235
236 static const struct picodlp_i2c_command init_cmd_set3[] = {
237 {PBC_CONTROL, 0},
238 {SEQ_RESET_LUT_DEST_SELECT, 0},
239 {PBC_CONTROL, 0},
240 {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
241 {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
242 {SEQ_RESET_LUT_START_ADDR, 0},
243 {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
244 {PBC_CONTROL, 1},
245 };
246
247 static const struct picodlp_i2c_command init_cmd_set4[] = {
248 {PBC_CONTROL, 0},
249 {SEQ_RESET_LUT_DEST_SELECT, 0},
250 {SDC_ENABLE, 1},
251 {AGC_CTRL, 7},
252 {CCA_C1A, 0x100},
253 {CCA_C1B, 0x0},
254 {CCA_C1C, 0x0},
255 {CCA_C2A, 0x0},
256 {CCA_C2B, 0x100},
257 {CCA_C2C, 0x0},
258 {CCA_C3A, 0x0},
259 {CCA_C3B, 0x0},
260 {CCA_C3C, 0x100},
261 {CCA_C7A, 0x100},
262 {CCA_C7B, 0x100},
263 {CCA_C7C, 0x100},
264 {CCA_ENABLE, 1},
265 {CPU_IF_MODE, 1},
266 {SHORT_FLIP, 1},
267 {CURTAIN_CONTROL, 0},
268 {DMD_PARK_TRIGGER, 0},
269 {R_DRIVE_CURRENT, 0x298},
270 {G_DRIVE_CURRENT, 0x298},
271 {B_DRIVE_CURRENT, 0x298},
272 {RGB_DRIVER_ENABLE, 7},
273 {SEQ_CONTROL, 0},
274 {ACTGEN_CONTROL, 0x10},
275 {SEQUENCE_MODE, SEQ_LOCK},
276 {DATA_FORMAT, RGB888},
277 {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
278 {INPUT_SOURCE, PARALLEL_RGB},
279 {CPU_IF_SYNC_METHOD, 1},
280 {SEQ_CONTROL, 1}
281 };
282
283 r = picodlp_i2c_write_array(client, init_cmd_set1,
284 ARRAY_SIZE(init_cmd_set1));
285 if (r)
286 return r;
287
288 r = picodlp_wait_for_dma_done(client);
289 if (r)
290 return r;
291
292 r = picodlp_i2c_write_array(client, init_cmd_set2,
293 ARRAY_SIZE(init_cmd_set2));
294 if (r)
295 return r;
296
297 r = picodlp_wait_for_dma_done(client);
298 if (r)
299 return r;
300
301 r = picodlp_i2c_write_array(client, init_cmd_set3,
302 ARRAY_SIZE(init_cmd_set3));
303 if (r)
304 return r;
305
306 r = picodlp_wait_for_dma_done(client);
307 if (r)
308 return r;
309
310 r = picodlp_i2c_write_array(client, init_cmd_set4,
311 ARRAY_SIZE(init_cmd_set4));
312 if (r)
313 return r;
314
315 return 0;
316}
317
318static int picodlp_i2c_probe(struct i2c_client *client,
319 const struct i2c_device_id *id)
320{
321 struct picodlp_i2c_data *picodlp_i2c_data;
322
323 picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
324
325 if (!picodlp_i2c_data)
326 return -ENOMEM;
327
328 mutex_init(&picodlp_i2c_data->xfer_lock);
329 i2c_set_clientdata(client, picodlp_i2c_data);
330
331 return 0;
332}
333
334static int picodlp_i2c_remove(struct i2c_client *client)
335{
336 struct picodlp_i2c_data *picodlp_i2c_data =
337 i2c_get_clientdata(client);
338 kfree(picodlp_i2c_data);
339 return 0;
340}
341
342static struct i2c_driver picodlp_i2c_driver = {
343 .driver = {
344 .name = "picodlp_i2c_driver",
345 },
346 .probe = picodlp_i2c_probe,
347 .remove = picodlp_i2c_remove,
348 .id_table = picodlp_i2c_id,
349};
350
351static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
352{
353 int r, trial = 100;
354 struct picodlp_data *picod = dev_get_drvdata(dssdev->dev);
355 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
356
357 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
358 msleep(1);
359 gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
360
361 while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
362 if (!trial--) {
363 dev_err(dssdev->dev, "emu_done signal not"
364 " going high\n");
365 return -ETIMEDOUT;
366 }
367 msleep(5);
368 }
369 /*
370 * As per dpp2600 programming guide,
371 * it is required to sleep for 1000ms after emu_done signal goes high
372 * then only i2c commands can be successfully sent to dpp2600
373 */
374 msleep(1000);
375
376 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
377 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
378
379 r = omapdss_dpi_display_enable(dssdev);
380 if (r) {
381 dev_err(dssdev->dev, "failed to enable DPI\n");
382 goto err1;
383 }
384
385 r = picodlp_i2c_init(picod->picodlp_i2c_client);
386 if (r)
387 goto err;
388
389 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
390
391 return r;
392err:
393 omapdss_dpi_display_disable(dssdev);
394err1:
395 return r;
396}
397
398static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
399{
400 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
401
402 omapdss_dpi_display_disable(dssdev);
403
404 gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
405 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
406}
407
408static int picodlp_panel_probe(struct omap_dss_device *dssdev)
409{
410 struct picodlp_data *picod;
411 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
412 struct i2c_adapter *adapter;
413 struct i2c_client *picodlp_i2c_client;
414 int r, picodlp_adapter_id;
415
416 dssdev->panel.timings = pico_ls_timings;
417
418 if (!picodlp_pdata)
419 return -EINVAL;
420
421 picod = devm_kzalloc(dssdev->dev, sizeof(*picod), GFP_KERNEL);
422 if (!picod)
423 return -ENOMEM;
424
425 mutex_init(&picod->lock);
426
427 picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
428
429 adapter = i2c_get_adapter(picodlp_adapter_id);
430 if (!adapter) {
431 dev_err(dssdev->dev, "can't get i2c adapter\n");
432 return -ENODEV;
433 }
434
435 picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
436 if (!picodlp_i2c_client) {
437 dev_err(dssdev->dev, "can't add i2c device::"
438 " picodlp_i2c_client is NULL\n");
439 return -ENODEV;
440 }
441
442 picod->picodlp_i2c_client = picodlp_i2c_client;
443
444 dev_set_drvdata(dssdev->dev, picod);
445
446 if (gpio_is_valid(picodlp_pdata->emu_done_gpio)) {
447 r = devm_gpio_request_one(dssdev->dev,
448 picodlp_pdata->emu_done_gpio,
449 GPIOF_IN, "DLP EMU DONE");
450 if (r)
451 return r;
452 }
453
454 if (gpio_is_valid(picodlp_pdata->pwrgood_gpio)) {
455 r = devm_gpio_request_one(dssdev->dev,
456 picodlp_pdata->pwrgood_gpio,
457 GPIOF_OUT_INIT_LOW, "DLP PWRGOOD");
458 if (r)
459 return r;
460 }
461
462 return 0;
463}
464
465static void picodlp_panel_remove(struct omap_dss_device *dssdev)
466{
467 struct picodlp_data *picod = dev_get_drvdata(dssdev->dev);
468
469 i2c_unregister_device(picod->picodlp_i2c_client);
470 dev_set_drvdata(dssdev->dev, NULL);
471 dev_dbg(dssdev->dev, "removing picodlp panel\n");
472}
473
474static int picodlp_panel_enable(struct omap_dss_device *dssdev)
475{
476 struct picodlp_data *picod = dev_get_drvdata(dssdev->dev);
477 int r;
478
479 dev_dbg(dssdev->dev, "enabling picodlp panel\n");
480
481 mutex_lock(&picod->lock);
482 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
483 mutex_unlock(&picod->lock);
484 return -EINVAL;
485 }
486
487 r = picodlp_panel_power_on(dssdev);
488 mutex_unlock(&picod->lock);
489
490 return r;
491}
492
493static void picodlp_panel_disable(struct omap_dss_device *dssdev)
494{
495 struct picodlp_data *picod = dev_get_drvdata(dssdev->dev);
496
497 mutex_lock(&picod->lock);
498 /* Turn off DLP Power */
499 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
500 picodlp_panel_power_off(dssdev);
501
502 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
503 mutex_unlock(&picod->lock);
504
505 dev_dbg(dssdev->dev, "disabling picodlp panel\n");
506}
507
508static void picodlp_get_resolution(struct omap_dss_device *dssdev,
509 u16 *xres, u16 *yres)
510{
511 *xres = dssdev->panel.timings.x_res;
512 *yres = dssdev->panel.timings.y_res;
513}
514
515static struct omap_dss_driver picodlp_driver = {
516 .probe = picodlp_panel_probe,
517 .remove = picodlp_panel_remove,
518
519 .enable = picodlp_panel_enable,
520 .disable = picodlp_panel_disable,
521
522 .get_resolution = picodlp_get_resolution,
523
524 .driver = {
525 .name = "picodlp_panel",
526 .owner = THIS_MODULE,
527 },
528};
529
530static int __init picodlp_init(void)
531{
532 int r = 0;
533
534 r = i2c_add_driver(&picodlp_i2c_driver);
535 if (r) {
536 printk(KERN_WARNING "picodlp_i2c_driver" \
537 " registration failed\n");
538 return r;
539 }
540
541 r = omap_dss_register_driver(&picodlp_driver);
542 if (r)
543 i2c_del_driver(&picodlp_i2c_driver);
544
545 return r;
546}
547
548static void __exit picodlp_exit(void)
549{
550 i2c_del_driver(&picodlp_i2c_driver);
551 omap_dss_unregister_driver(&picodlp_driver);
552}
553
554module_init(picodlp_init);
555module_exit(picodlp_exit);
556
557MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
558MODULE_DESCRIPTION("picodlp driver");
559MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
deleted file mode 100644
index a34b431a7267..000000000000
--- a/drivers/video/omap2/displays/panel-picodlp.h
+++ /dev/null
@@ -1,288 +0,0 @@
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-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
deleted file mode 100644
index 78f0a6779756..000000000000
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ /dev/null
@@ -1,198 +0,0 @@
1/*
2 * LCD panel driver for Sharp LS037V7DW01
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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/delay.h>
22#include <linux/device.h>
23#include <linux/fb.h>
24#include <linux/err.h>
25#include <linux/slab.h>
26#include <linux/gpio.h>
27
28#include <video/omapdss.h>
29#include <video/omap-panel-data.h>
30
31static struct omap_video_timings sharp_ls_timings = {
32 .x_res = 480,
33 .y_res = 640,
34
35 .pixel_clock = 19200,
36
37 .hsw = 2,
38 .hfp = 1,
39 .hbp = 28,
40
41 .vsw = 1,
42 .vfp = 1,
43 .vbp = 1,
44
45 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
46 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
47 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
48 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
49 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
50};
51
52static inline struct panel_sharp_ls037v7dw01_data
53*get_panel_data(const struct omap_dss_device *dssdev)
54{
55 return (struct panel_sharp_ls037v7dw01_data *) dssdev->data;
56}
57
58static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
59{
60 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
61 int r;
62
63 if (!pd)
64 return -EINVAL;
65
66 dssdev->panel.timings = sharp_ls_timings;
67
68 if (gpio_is_valid(pd->mo_gpio)) {
69 r = devm_gpio_request_one(dssdev->dev, pd->mo_gpio,
70 GPIOF_OUT_INIT_LOW, "lcd MO");
71 if (r)
72 return r;
73 }
74
75 if (gpio_is_valid(pd->lr_gpio)) {
76 r = devm_gpio_request_one(dssdev->dev, pd->lr_gpio,
77 GPIOF_OUT_INIT_HIGH, "lcd LR");
78 if (r)
79 return r;
80 }
81
82 if (gpio_is_valid(pd->ud_gpio)) {
83 r = devm_gpio_request_one(dssdev->dev, pd->ud_gpio,
84 GPIOF_OUT_INIT_HIGH, "lcd UD");
85 if (r)
86 return r;
87 }
88
89 if (gpio_is_valid(pd->resb_gpio)) {
90 r = devm_gpio_request_one(dssdev->dev, pd->resb_gpio,
91 GPIOF_OUT_INIT_LOW, "lcd RESB");
92 if (r)
93 return r;
94 }
95
96 if (gpio_is_valid(pd->ini_gpio)) {
97 r = devm_gpio_request_one(dssdev->dev, pd->ini_gpio,
98 GPIOF_OUT_INIT_LOW, "lcd INI");
99 if (r)
100 return r;
101 }
102
103 return 0;
104}
105
106static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
107{
108}
109
110static int sharp_ls_power_on(struct omap_dss_device *dssdev)
111{
112 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
113 int r = 0;
114
115 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
116 return 0;
117
118 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
119 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
120
121 r = omapdss_dpi_display_enable(dssdev);
122 if (r)
123 goto err0;
124
125 /* wait couple of vsyncs until enabling the LCD */
126 msleep(50);
127
128 if (gpio_is_valid(pd->resb_gpio))
129 gpio_set_value_cansleep(pd->resb_gpio, 1);
130
131 if (gpio_is_valid(pd->ini_gpio))
132 gpio_set_value_cansleep(pd->ini_gpio, 1);
133
134 return 0;
135err0:
136 return r;
137}
138
139static void sharp_ls_power_off(struct omap_dss_device *dssdev)
140{
141 struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev);
142
143 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
144 return;
145
146 if (gpio_is_valid(pd->ini_gpio))
147 gpio_set_value_cansleep(pd->ini_gpio, 0);
148
149 if (gpio_is_valid(pd->resb_gpio))
150 gpio_set_value_cansleep(pd->resb_gpio, 0);
151
152 /* wait at least 5 vsyncs after disabling the LCD */
153
154 msleep(100);
155
156 omapdss_dpi_display_disable(dssdev);
157}
158
159static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
160{
161 int r;
162 r = sharp_ls_power_on(dssdev);
163 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
164 return r;
165}
166
167static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
168{
169 sharp_ls_power_off(dssdev);
170 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
171}
172
173static struct omap_dss_driver sharp_ls_driver = {
174 .probe = sharp_ls_panel_probe,
175 .remove = __exit_p(sharp_ls_panel_remove),
176
177 .enable = sharp_ls_panel_enable,
178 .disable = sharp_ls_panel_disable,
179
180 .driver = {
181 .name = "sharp_ls_panel",
182 .owner = THIS_MODULE,
183 },
184};
185
186static int __init sharp_ls_panel_drv_init(void)
187{
188 return omap_dss_register_driver(&sharp_ls_driver);
189}
190
191static void __exit sharp_ls_panel_drv_exit(void)
192{
193 omap_dss_unregister_driver(&sharp_ls_driver);
194}
195
196module_init(sharp_ls_panel_drv_init);
197module_exit(sharp_ls_panel_drv_exit);
198MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
deleted file mode 100644
index 54a07da8587a..000000000000
--- a/drivers/video/omap2/displays/panel-taal.c
+++ /dev/null
@@ -1,1551 +0,0 @@
1/*
2 * Taal DSI command mode panel
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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/*#define DEBUG*/
21
22#include <linux/module.h>
23#include <linux/delay.h>
24#include <linux/err.h>
25#include <linux/jiffies.h>
26#include <linux/sched.h>
27#include <linux/backlight.h>
28#include <linux/fb.h>
29#include <linux/interrupt.h>
30#include <linux/gpio.h>
31#include <linux/workqueue.h>
32#include <linux/slab.h>
33#include <linux/mutex.h>
34
35#include <video/omapdss.h>
36#include <video/omap-panel-data.h>
37#include <video/mipi_display.h>
38
39/* DSI Virtual channel. Hardcoded for now. */
40#define TCH 0
41
42#define DCS_READ_NUM_ERRORS 0x05
43#define DCS_BRIGHTNESS 0x51
44#define DCS_CTRL_DISPLAY 0x53
45#define DCS_WRITE_CABC 0x55
46#define DCS_READ_CABC 0x56
47#define DCS_GET_ID1 0xda
48#define DCS_GET_ID2 0xdb
49#define DCS_GET_ID3 0xdc
50
51static irqreturn_t taal_te_isr(int irq, void *data);
52static void taal_te_timeout_work_callback(struct work_struct *work);
53static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
54
55static int taal_panel_reset(struct omap_dss_device *dssdev);
56
57struct taal_data {
58 struct mutex lock;
59
60 struct backlight_device *bldev;
61
62 unsigned long hw_guard_end; /* next value of jiffies when we can
63 * issue the next sleep in/out command
64 */
65 unsigned long hw_guard_wait; /* max guard time in jiffies */
66
67 struct omap_dss_device *dssdev;
68
69 /* panel HW configuration from DT or platform data */
70 int reset_gpio;
71 int ext_te_gpio;
72
73 bool use_dsi_backlight;
74
75 struct omap_dsi_pin_config pin_config;
76
77 /* runtime variables */
78 bool enabled;
79
80 bool te_enabled;
81
82 atomic_t do_update;
83 int channel;
84
85 struct delayed_work te_timeout_work;
86
87 bool cabc_broken;
88 unsigned cabc_mode;
89
90 bool intro_printed;
91
92 struct workqueue_struct *workqueue;
93
94 struct delayed_work esd_work;
95 unsigned esd_interval;
96
97 bool ulps_enabled;
98 unsigned ulps_timeout;
99 struct delayed_work ulps_work;
100};
101
102static void taal_esd_work(struct work_struct *work);
103static void taal_ulps_work(struct work_struct *work);
104
105static void hw_guard_start(struct taal_data *td, int guard_msec)
106{
107 td->hw_guard_wait = msecs_to_jiffies(guard_msec);
108 td->hw_guard_end = jiffies + td->hw_guard_wait;
109}
110
111static void hw_guard_wait(struct taal_data *td)
112{
113 unsigned long wait = td->hw_guard_end - jiffies;
114
115 if ((long)wait > 0 && wait <= td->hw_guard_wait) {
116 set_current_state(TASK_UNINTERRUPTIBLE);
117 schedule_timeout(wait);
118 }
119}
120
121static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data)
122{
123 int r;
124 u8 buf[1];
125
126 r = dsi_vc_dcs_read(td->dssdev, td->channel, dcs_cmd, buf, 1);
127
128 if (r < 0)
129 return r;
130
131 *data = buf[0];
132
133 return 0;
134}
135
136static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd)
137{
138 return dsi_vc_dcs_write(td->dssdev, td->channel, &dcs_cmd, 1);
139}
140
141static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param)
142{
143 u8 buf[2];
144 buf[0] = dcs_cmd;
145 buf[1] = param;
146 return dsi_vc_dcs_write(td->dssdev, td->channel, buf, 2);
147}
148
149static int taal_sleep_in(struct taal_data *td)
150
151{
152 u8 cmd;
153 int r;
154
155 hw_guard_wait(td);
156
157 cmd = MIPI_DCS_ENTER_SLEEP_MODE;
158 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
159 if (r)
160 return r;
161
162 hw_guard_start(td, 120);
163
164 msleep(5);
165
166 return 0;
167}
168
169static int taal_sleep_out(struct taal_data *td)
170{
171 int r;
172
173 hw_guard_wait(td);
174
175 r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
176 if (r)
177 return r;
178
179 hw_guard_start(td, 120);
180
181 msleep(5);
182
183 return 0;
184}
185
186static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3)
187{
188 int r;
189
190 r = taal_dcs_read_1(td, DCS_GET_ID1, id1);
191 if (r)
192 return r;
193 r = taal_dcs_read_1(td, DCS_GET_ID2, id2);
194 if (r)
195 return r;
196 r = taal_dcs_read_1(td, DCS_GET_ID3, id3);
197 if (r)
198 return r;
199
200 return 0;
201}
202
203static int taal_set_update_window(struct taal_data *td,
204 u16 x, u16 y, u16 w, u16 h)
205{
206 int r;
207 u16 x1 = x;
208 u16 x2 = x + w - 1;
209 u16 y1 = y;
210 u16 y2 = y + h - 1;
211
212 u8 buf[5];
213 buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
214 buf[1] = (x1 >> 8) & 0xff;
215 buf[2] = (x1 >> 0) & 0xff;
216 buf[3] = (x2 >> 8) & 0xff;
217 buf[4] = (x2 >> 0) & 0xff;
218
219 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf));
220 if (r)
221 return r;
222
223 buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
224 buf[1] = (y1 >> 8) & 0xff;
225 buf[2] = (y1 >> 0) & 0xff;
226 buf[3] = (y2 >> 8) & 0xff;
227 buf[4] = (y2 >> 0) & 0xff;
228
229 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf));
230 if (r)
231 return r;
232
233 dsi_vc_send_bta_sync(td->dssdev, td->channel);
234
235 return r;
236}
237
238static void taal_queue_esd_work(struct omap_dss_device *dssdev)
239{
240 struct taal_data *td = dev_get_drvdata(dssdev->dev);
241
242 if (td->esd_interval > 0)
243 queue_delayed_work(td->workqueue, &td->esd_work,
244 msecs_to_jiffies(td->esd_interval));
245}
246
247static void taal_cancel_esd_work(struct omap_dss_device *dssdev)
248{
249 struct taal_data *td = dev_get_drvdata(dssdev->dev);
250
251 cancel_delayed_work(&td->esd_work);
252}
253
254static void taal_queue_ulps_work(struct omap_dss_device *dssdev)
255{
256 struct taal_data *td = dev_get_drvdata(dssdev->dev);
257
258 if (td->ulps_timeout > 0)
259 queue_delayed_work(td->workqueue, &td->ulps_work,
260 msecs_to_jiffies(td->ulps_timeout));
261}
262
263static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
264{
265 struct taal_data *td = dev_get_drvdata(dssdev->dev);
266
267 cancel_delayed_work(&td->ulps_work);
268}
269
270static int taal_enter_ulps(struct omap_dss_device *dssdev)
271{
272 struct taal_data *td = dev_get_drvdata(dssdev->dev);
273 int r;
274
275 if (td->ulps_enabled)
276 return 0;
277
278 taal_cancel_ulps_work(dssdev);
279
280 r = _taal_enable_te(dssdev, false);
281 if (r)
282 goto err;
283
284 if (gpio_is_valid(td->ext_te_gpio))
285 disable_irq(gpio_to_irq(td->ext_te_gpio));
286
287 omapdss_dsi_display_disable(dssdev, false, true);
288
289 td->ulps_enabled = true;
290
291 return 0;
292
293err:
294 dev_err(dssdev->dev, "enter ULPS failed");
295 taal_panel_reset(dssdev);
296
297 td->ulps_enabled = false;
298
299 taal_queue_ulps_work(dssdev);
300
301 return r;
302}
303
304static int taal_exit_ulps(struct omap_dss_device *dssdev)
305{
306 struct taal_data *td = dev_get_drvdata(dssdev->dev);
307 int r;
308
309 if (!td->ulps_enabled)
310 return 0;
311
312 r = omapdss_dsi_display_enable(dssdev);
313 if (r) {
314 dev_err(dssdev->dev, "failed to enable DSI\n");
315 goto err1;
316 }
317
318 omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
319
320 r = _taal_enable_te(dssdev, true);
321 if (r) {
322 dev_err(dssdev->dev, "failed to re-enable TE");
323 goto err2;
324 }
325
326 if (gpio_is_valid(td->ext_te_gpio))
327 enable_irq(gpio_to_irq(td->ext_te_gpio));
328
329 taal_queue_ulps_work(dssdev);
330
331 td->ulps_enabled = false;
332
333 return 0;
334
335err2:
336 dev_err(dssdev->dev, "failed to exit ULPS");
337
338 r = taal_panel_reset(dssdev);
339 if (!r) {
340 if (gpio_is_valid(td->ext_te_gpio))
341 enable_irq(gpio_to_irq(td->ext_te_gpio));
342 td->ulps_enabled = false;
343 }
344err1:
345 taal_queue_ulps_work(dssdev);
346
347 return r;
348}
349
350static int taal_wake_up(struct omap_dss_device *dssdev)
351{
352 struct taal_data *td = dev_get_drvdata(dssdev->dev);
353
354 if (td->ulps_enabled)
355 return taal_exit_ulps(dssdev);
356
357 taal_cancel_ulps_work(dssdev);
358 taal_queue_ulps_work(dssdev);
359 return 0;
360}
361
362static int taal_bl_update_status(struct backlight_device *dev)
363{
364 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
365 struct taal_data *td = dev_get_drvdata(dssdev->dev);
366 int r;
367 int level;
368
369 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
370 dev->props.power == FB_BLANK_UNBLANK)
371 level = dev->props.brightness;
372 else
373 level = 0;
374
375 dev_dbg(dssdev->dev, "update brightness to %d\n", level);
376
377 mutex_lock(&td->lock);
378
379 if (td->enabled) {
380 dsi_bus_lock(dssdev);
381
382 r = taal_wake_up(dssdev);
383 if (!r)
384 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
385
386 dsi_bus_unlock(dssdev);
387 } else {
388 r = 0;
389 }
390
391 mutex_unlock(&td->lock);
392
393 return r;
394}
395
396static int taal_bl_get_intensity(struct backlight_device *dev)
397{
398 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
399 dev->props.power == FB_BLANK_UNBLANK)
400 return dev->props.brightness;
401
402 return 0;
403}
404
405static const struct backlight_ops taal_bl_ops = {
406 .get_brightness = taal_bl_get_intensity,
407 .update_status = taal_bl_update_status,
408};
409
410static void taal_get_resolution(struct omap_dss_device *dssdev,
411 u16 *xres, u16 *yres)
412{
413 *xres = dssdev->panel.timings.x_res;
414 *yres = dssdev->panel.timings.y_res;
415}
416
417static ssize_t taal_num_errors_show(struct device *dev,
418 struct device_attribute *attr, char *buf)
419{
420 struct omap_dss_device *dssdev = to_dss_device(dev);
421 struct taal_data *td = dev_get_drvdata(dssdev->dev);
422 u8 errors = 0;
423 int r;
424
425 mutex_lock(&td->lock);
426
427 if (td->enabled) {
428 dsi_bus_lock(dssdev);
429
430 r = taal_wake_up(dssdev);
431 if (!r)
432 r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
433
434 dsi_bus_unlock(dssdev);
435 } else {
436 r = -ENODEV;
437 }
438
439 mutex_unlock(&td->lock);
440
441 if (r)
442 return r;
443
444 return snprintf(buf, PAGE_SIZE, "%d\n", errors);
445}
446
447static ssize_t taal_hw_revision_show(struct device *dev,
448 struct device_attribute *attr, char *buf)
449{
450 struct omap_dss_device *dssdev = to_dss_device(dev);
451 struct taal_data *td = dev_get_drvdata(dssdev->dev);
452 u8 id1, id2, id3;
453 int r;
454
455 mutex_lock(&td->lock);
456
457 if (td->enabled) {
458 dsi_bus_lock(dssdev);
459
460 r = taal_wake_up(dssdev);
461 if (!r)
462 r = taal_get_id(td, &id1, &id2, &id3);
463
464 dsi_bus_unlock(dssdev);
465 } else {
466 r = -ENODEV;
467 }
468
469 mutex_unlock(&td->lock);
470
471 if (r)
472 return r;
473
474 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
475}
476
477static const char *cabc_modes[] = {
478 "off", /* used also always when CABC is not supported */
479 "ui",
480 "still-image",
481 "moving-image",
482};
483
484static ssize_t show_cabc_mode(struct device *dev,
485 struct device_attribute *attr,
486 char *buf)
487{
488 struct omap_dss_device *dssdev = to_dss_device(dev);
489 struct taal_data *td = dev_get_drvdata(dssdev->dev);
490 const char *mode_str;
491 int mode;
492 int len;
493
494 mode = td->cabc_mode;
495
496 mode_str = "unknown";
497 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
498 mode_str = cabc_modes[mode];
499 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
500
501 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
502}
503
504static ssize_t store_cabc_mode(struct device *dev,
505 struct device_attribute *attr,
506 const char *buf, size_t count)
507{
508 struct omap_dss_device *dssdev = to_dss_device(dev);
509 struct taal_data *td = dev_get_drvdata(dssdev->dev);
510 int i;
511 int r;
512
513 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
514 if (sysfs_streq(cabc_modes[i], buf))
515 break;
516 }
517
518 if (i == ARRAY_SIZE(cabc_modes))
519 return -EINVAL;
520
521 mutex_lock(&td->lock);
522
523 if (td->enabled) {
524 dsi_bus_lock(dssdev);
525
526 if (!td->cabc_broken) {
527 r = taal_wake_up(dssdev);
528 if (r)
529 goto err;
530
531 r = taal_dcs_write_1(td, DCS_WRITE_CABC, i);
532 if (r)
533 goto err;
534 }
535
536 dsi_bus_unlock(dssdev);
537 }
538
539 td->cabc_mode = i;
540
541 mutex_unlock(&td->lock);
542
543 return count;
544err:
545 dsi_bus_unlock(dssdev);
546 mutex_unlock(&td->lock);
547 return r;
548}
549
550static ssize_t show_cabc_available_modes(struct device *dev,
551 struct device_attribute *attr,
552 char *buf)
553{
554 int len;
555 int i;
556
557 for (i = 0, len = 0;
558 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
559 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
560 i ? " " : "", cabc_modes[i],
561 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
562
563 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
564}
565
566static ssize_t taal_store_esd_interval(struct device *dev,
567 struct device_attribute *attr,
568 const char *buf, size_t count)
569{
570 struct omap_dss_device *dssdev = to_dss_device(dev);
571 struct taal_data *td = dev_get_drvdata(dssdev->dev);
572
573 unsigned long t;
574 int r;
575
576 r = kstrtoul(buf, 10, &t);
577 if (r)
578 return r;
579
580 mutex_lock(&td->lock);
581 taal_cancel_esd_work(dssdev);
582 td->esd_interval = t;
583 if (td->enabled)
584 taal_queue_esd_work(dssdev);
585 mutex_unlock(&td->lock);
586
587 return count;
588}
589
590static ssize_t taal_show_esd_interval(struct device *dev,
591 struct device_attribute *attr,
592 char *buf)
593{
594 struct omap_dss_device *dssdev = to_dss_device(dev);
595 struct taal_data *td = dev_get_drvdata(dssdev->dev);
596 unsigned t;
597
598 mutex_lock(&td->lock);
599 t = td->esd_interval;
600 mutex_unlock(&td->lock);
601
602 return snprintf(buf, PAGE_SIZE, "%u\n", t);
603}
604
605static ssize_t taal_store_ulps(struct device *dev,
606 struct device_attribute *attr,
607 const char *buf, size_t count)
608{
609 struct omap_dss_device *dssdev = to_dss_device(dev);
610 struct taal_data *td = dev_get_drvdata(dssdev->dev);
611 unsigned long t;
612 int r;
613
614 r = kstrtoul(buf, 10, &t);
615 if (r)
616 return r;
617
618 mutex_lock(&td->lock);
619
620 if (td->enabled) {
621 dsi_bus_lock(dssdev);
622
623 if (t)
624 r = taal_enter_ulps(dssdev);
625 else
626 r = taal_wake_up(dssdev);
627
628 dsi_bus_unlock(dssdev);
629 }
630
631 mutex_unlock(&td->lock);
632
633 if (r)
634 return r;
635
636 return count;
637}
638
639static ssize_t taal_show_ulps(struct device *dev,
640 struct device_attribute *attr,
641 char *buf)
642{
643 struct omap_dss_device *dssdev = to_dss_device(dev);
644 struct taal_data *td = dev_get_drvdata(dssdev->dev);
645 unsigned t;
646
647 mutex_lock(&td->lock);
648 t = td->ulps_enabled;
649 mutex_unlock(&td->lock);
650
651 return snprintf(buf, PAGE_SIZE, "%u\n", t);
652}
653
654static ssize_t taal_store_ulps_timeout(struct device *dev,
655 struct device_attribute *attr,
656 const char *buf, size_t count)
657{
658 struct omap_dss_device *dssdev = to_dss_device(dev);
659 struct taal_data *td = dev_get_drvdata(dssdev->dev);
660 unsigned long t;
661 int r;
662
663 r = kstrtoul(buf, 10, &t);
664 if (r)
665 return r;
666
667 mutex_lock(&td->lock);
668 td->ulps_timeout = t;
669
670 if (td->enabled) {
671 /* taal_wake_up will restart the timer */
672 dsi_bus_lock(dssdev);
673 r = taal_wake_up(dssdev);
674 dsi_bus_unlock(dssdev);
675 }
676
677 mutex_unlock(&td->lock);
678
679 if (r)
680 return r;
681
682 return count;
683}
684
685static ssize_t taal_show_ulps_timeout(struct device *dev,
686 struct device_attribute *attr,
687 char *buf)
688{
689 struct omap_dss_device *dssdev = to_dss_device(dev);
690 struct taal_data *td = dev_get_drvdata(dssdev->dev);
691 unsigned t;
692
693 mutex_lock(&td->lock);
694 t = td->ulps_timeout;
695 mutex_unlock(&td->lock);
696
697 return snprintf(buf, PAGE_SIZE, "%u\n", t);
698}
699
700static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
701static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
702static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
703 show_cabc_mode, store_cabc_mode);
704static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
705 show_cabc_available_modes, NULL);
706static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR,
707 taal_show_esd_interval, taal_store_esd_interval);
708static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
709 taal_show_ulps, taal_store_ulps);
710static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
711 taal_show_ulps_timeout, taal_store_ulps_timeout);
712
713static struct attribute *taal_attrs[] = {
714 &dev_attr_num_dsi_errors.attr,
715 &dev_attr_hw_revision.attr,
716 &dev_attr_cabc_mode.attr,
717 &dev_attr_cabc_available_modes.attr,
718 &dev_attr_esd_interval.attr,
719 &dev_attr_ulps.attr,
720 &dev_attr_ulps_timeout.attr,
721 NULL,
722};
723
724static struct attribute_group taal_attr_group = {
725 .attrs = taal_attrs,
726};
727
728static void taal_hw_reset(struct omap_dss_device *dssdev)
729{
730 struct taal_data *td = dev_get_drvdata(dssdev->dev);
731
732 if (!gpio_is_valid(td->reset_gpio))
733 return;
734
735 gpio_set_value(td->reset_gpio, 1);
736 udelay(10);
737 /* reset the panel */
738 gpio_set_value(td->reset_gpio, 0);
739 /* assert reset */
740 udelay(10);
741 gpio_set_value(td->reset_gpio, 1);
742 /* wait after releasing reset */
743 msleep(5);
744}
745
746static void taal_probe_pdata(struct taal_data *td,
747 const struct nokia_dsi_panel_data *pdata)
748{
749 td->reset_gpio = pdata->reset_gpio;
750
751 if (pdata->use_ext_te)
752 td->ext_te_gpio = pdata->ext_te_gpio;
753 else
754 td->ext_te_gpio = -1;
755
756 td->esd_interval = pdata->esd_interval;
757 td->ulps_timeout = pdata->ulps_timeout;
758
759 td->use_dsi_backlight = pdata->use_dsi_backlight;
760
761 td->pin_config = pdata->pin_config;
762}
763
764static int taal_probe(struct omap_dss_device *dssdev)
765{
766 struct backlight_properties props;
767 struct taal_data *td;
768 struct backlight_device *bldev = NULL;
769 int r;
770
771 dev_dbg(dssdev->dev, "probe\n");
772
773 td = devm_kzalloc(dssdev->dev, sizeof(*td), GFP_KERNEL);
774 if (!td)
775 return -ENOMEM;
776
777 dev_set_drvdata(dssdev->dev, td);
778 td->dssdev = dssdev;
779
780 if (dssdev->data) {
781 const struct nokia_dsi_panel_data *pdata = dssdev->data;
782
783 taal_probe_pdata(td, pdata);
784 } else {
785 return -ENODEV;
786 }
787
788 dssdev->panel.timings.x_res = 864;
789 dssdev->panel.timings.y_res = 480;
790 dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
791 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
792 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
793 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
794
795 mutex_init(&td->lock);
796
797 atomic_set(&td->do_update, 0);
798
799 if (gpio_is_valid(td->reset_gpio)) {
800 r = devm_gpio_request_one(dssdev->dev, td->reset_gpio,
801 GPIOF_OUT_INIT_LOW, "taal rst");
802 if (r) {
803 dev_err(dssdev->dev, "failed to request reset gpio\n");
804 return r;
805 }
806 }
807
808 if (gpio_is_valid(td->ext_te_gpio)) {
809 r = devm_gpio_request_one(dssdev->dev, td->ext_te_gpio,
810 GPIOF_IN, "taal irq");
811 if (r) {
812 dev_err(dssdev->dev, "GPIO request failed\n");
813 return r;
814 }
815
816 r = devm_request_irq(dssdev->dev, gpio_to_irq(td->ext_te_gpio),
817 taal_te_isr,
818 IRQF_TRIGGER_RISING,
819 "taal vsync", dssdev);
820
821 if (r) {
822 dev_err(dssdev->dev, "IRQ request failed\n");
823 return r;
824 }
825
826 INIT_DEFERRABLE_WORK(&td->te_timeout_work,
827 taal_te_timeout_work_callback);
828
829 dev_dbg(dssdev->dev, "Using GPIO TE\n");
830 }
831
832 td->workqueue = create_singlethread_workqueue("taal_esd");
833 if (td->workqueue == NULL) {
834 dev_err(dssdev->dev, "can't create ESD workqueue\n");
835 return -ENOMEM;
836 }
837 INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work);
838 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
839
840 taal_hw_reset(dssdev);
841
842 if (td->use_dsi_backlight) {
843 memset(&props, 0, sizeof(struct backlight_properties));
844 props.max_brightness = 255;
845
846 props.type = BACKLIGHT_RAW;
847 bldev = backlight_device_register(dev_name(dssdev->dev),
848 dssdev->dev, dssdev, &taal_bl_ops, &props);
849 if (IS_ERR(bldev)) {
850 r = PTR_ERR(bldev);
851 goto err_bl;
852 }
853
854 td->bldev = bldev;
855
856 bldev->props.fb_blank = FB_BLANK_UNBLANK;
857 bldev->props.power = FB_BLANK_UNBLANK;
858 bldev->props.brightness = 255;
859
860 taal_bl_update_status(bldev);
861 }
862
863 r = omap_dsi_request_vc(dssdev, &td->channel);
864 if (r) {
865 dev_err(dssdev->dev, "failed to get virtual channel\n");
866 goto err_req_vc;
867 }
868
869 r = omap_dsi_set_vc_id(dssdev, td->channel, TCH);
870 if (r) {
871 dev_err(dssdev->dev, "failed to set VC_ID\n");
872 goto err_vc_id;
873 }
874
875 r = sysfs_create_group(&dssdev->dev->kobj, &taal_attr_group);
876 if (r) {
877 dev_err(dssdev->dev, "failed to create sysfs files\n");
878 goto err_vc_id;
879 }
880
881 return 0;
882
883err_vc_id:
884 omap_dsi_release_vc(dssdev, td->channel);
885err_req_vc:
886 if (bldev != NULL)
887 backlight_device_unregister(bldev);
888err_bl:
889 destroy_workqueue(td->workqueue);
890 return r;
891}
892
893static void __exit taal_remove(struct omap_dss_device *dssdev)
894{
895 struct taal_data *td = dev_get_drvdata(dssdev->dev);
896 struct backlight_device *bldev;
897
898 dev_dbg(dssdev->dev, "remove\n");
899
900 sysfs_remove_group(&dssdev->dev->kobj, &taal_attr_group);
901 omap_dsi_release_vc(dssdev, td->channel);
902
903 bldev = td->bldev;
904 if (bldev != NULL) {
905 bldev->props.power = FB_BLANK_POWERDOWN;
906 taal_bl_update_status(bldev);
907 backlight_device_unregister(bldev);
908 }
909
910 taal_cancel_ulps_work(dssdev);
911 taal_cancel_esd_work(dssdev);
912 destroy_workqueue(td->workqueue);
913
914 /* reset, to be sure that the panel is in a valid state */
915 taal_hw_reset(dssdev);
916}
917
918static int taal_power_on(struct omap_dss_device *dssdev)
919{
920 struct taal_data *td = dev_get_drvdata(dssdev->dev);
921 u8 id1, id2, id3;
922 int r;
923 struct omap_dss_dsi_config dsi_config = {
924 .mode = OMAP_DSS_DSI_CMD_MODE,
925 .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
926 .timings = &dssdev->panel.timings,
927 .hs_clk_min = 150000000,
928 .hs_clk_max = 300000000,
929 .lp_clk_min = 7000000,
930 .lp_clk_max = 10000000,
931 };
932
933 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
934 if (r) {
935 dev_err(dssdev->dev, "failed to configure DSI pins\n");
936 goto err0;
937 };
938
939 r = omapdss_dsi_set_config(dssdev, &dsi_config);
940 if (r) {
941 dev_err(dssdev->dev, "failed to configure DSI\n");
942 goto err0;
943 }
944
945 r = omapdss_dsi_display_enable(dssdev);
946 if (r) {
947 dev_err(dssdev->dev, "failed to enable DSI\n");
948 goto err0;
949 }
950
951 taal_hw_reset(dssdev);
952
953 omapdss_dsi_vc_enable_hs(dssdev, td->channel, false);
954
955 r = taal_sleep_out(td);
956 if (r)
957 goto err;
958
959 r = taal_get_id(td, &id1, &id2, &id3);
960 if (r)
961 goto err;
962
963 /* on early Taal revisions CABC is broken */
964 if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
965 td->cabc_broken = true;
966
967 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff);
968 if (r)
969 goto err;
970
971 r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY,
972 (1<<2) | (1<<5)); /* BL | BCTRL */
973 if (r)
974 goto err;
975
976 r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
977 MIPI_DCS_PIXEL_FMT_24BIT);
978 if (r)
979 goto err;
980
981 if (!td->cabc_broken) {
982 r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode);
983 if (r)
984 goto err;
985 }
986
987 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
988 if (r)
989 goto err;
990
991 r = _taal_enable_te(dssdev, td->te_enabled);
992 if (r)
993 goto err;
994
995 r = dsi_enable_video_output(dssdev, td->channel);
996 if (r)
997 goto err;
998
999 td->enabled = 1;
1000
1001 if (!td->intro_printed) {
1002 dev_info(dssdev->dev, "panel revision %02x.%02x.%02x\n",
1003 id1, id2, id3);
1004 if (td->cabc_broken)
1005 dev_info(dssdev->dev,
1006 "old Taal version, CABC disabled\n");
1007 td->intro_printed = true;
1008 }
1009
1010 omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
1011
1012 return 0;
1013err:
1014 dev_err(dssdev->dev, "error while enabling panel, issuing HW reset\n");
1015
1016 taal_hw_reset(dssdev);
1017
1018 omapdss_dsi_display_disable(dssdev, true, false);
1019err0:
1020 return r;
1021}
1022
1023static void taal_power_off(struct omap_dss_device *dssdev)
1024{
1025 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1026 int r;
1027
1028 dsi_disable_video_output(dssdev, td->channel);
1029
1030 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
1031 if (!r)
1032 r = taal_sleep_in(td);
1033
1034 if (r) {
1035 dev_err(dssdev->dev,
1036 "error disabling panel, issuing HW reset\n");
1037 taal_hw_reset(dssdev);
1038 }
1039
1040 omapdss_dsi_display_disable(dssdev, true, false);
1041
1042 td->enabled = 0;
1043}
1044
1045static int taal_panel_reset(struct omap_dss_device *dssdev)
1046{
1047 dev_err(dssdev->dev, "performing LCD reset\n");
1048
1049 taal_power_off(dssdev);
1050 taal_hw_reset(dssdev);
1051 return taal_power_on(dssdev);
1052}
1053
1054static int taal_enable(struct omap_dss_device *dssdev)
1055{
1056 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1057 int r;
1058
1059 dev_dbg(dssdev->dev, "enable\n");
1060
1061 mutex_lock(&td->lock);
1062
1063 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
1064 r = -EINVAL;
1065 goto err;
1066 }
1067
1068 dsi_bus_lock(dssdev);
1069
1070 r = taal_power_on(dssdev);
1071
1072 dsi_bus_unlock(dssdev);
1073
1074 if (r)
1075 goto err;
1076
1077 taal_queue_esd_work(dssdev);
1078
1079 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
1080
1081 mutex_unlock(&td->lock);
1082
1083 return 0;
1084err:
1085 dev_dbg(dssdev->dev, "enable failed\n");
1086 mutex_unlock(&td->lock);
1087 return r;
1088}
1089
1090static void taal_disable(struct omap_dss_device *dssdev)
1091{
1092 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1093
1094 dev_dbg(dssdev->dev, "disable\n");
1095
1096 mutex_lock(&td->lock);
1097
1098 taal_cancel_ulps_work(dssdev);
1099 taal_cancel_esd_work(dssdev);
1100
1101 dsi_bus_lock(dssdev);
1102
1103 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
1104 int r;
1105
1106 r = taal_wake_up(dssdev);
1107 if (!r)
1108 taal_power_off(dssdev);
1109 }
1110
1111 dsi_bus_unlock(dssdev);
1112
1113 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
1114
1115 mutex_unlock(&td->lock);
1116}
1117
1118static void taal_framedone_cb(int err, void *data)
1119{
1120 struct omap_dss_device *dssdev = data;
1121 dev_dbg(dssdev->dev, "framedone, err %d\n", err);
1122 dsi_bus_unlock(dssdev);
1123}
1124
1125static irqreturn_t taal_te_isr(int irq, void *data)
1126{
1127 struct omap_dss_device *dssdev = data;
1128 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1129 int old;
1130 int r;
1131
1132 old = atomic_cmpxchg(&td->do_update, 1, 0);
1133
1134 if (old) {
1135 cancel_delayed_work(&td->te_timeout_work);
1136
1137 r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
1138 dssdev);
1139 if (r)
1140 goto err;
1141 }
1142
1143 return IRQ_HANDLED;
1144err:
1145 dev_err(dssdev->dev, "start update failed\n");
1146 dsi_bus_unlock(dssdev);
1147 return IRQ_HANDLED;
1148}
1149
1150static void taal_te_timeout_work_callback(struct work_struct *work)
1151{
1152 struct taal_data *td = container_of(work, struct taal_data,
1153 te_timeout_work.work);
1154 struct omap_dss_device *dssdev = td->dssdev;
1155
1156 dev_err(dssdev->dev, "TE not received for 250ms!\n");
1157
1158 atomic_set(&td->do_update, 0);
1159 dsi_bus_unlock(dssdev);
1160}
1161
1162static int taal_update(struct omap_dss_device *dssdev,
1163 u16 x, u16 y, u16 w, u16 h)
1164{
1165 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1166 int r;
1167
1168 dev_dbg(dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
1169
1170 mutex_lock(&td->lock);
1171 dsi_bus_lock(dssdev);
1172
1173 r = taal_wake_up(dssdev);
1174 if (r)
1175 goto err;
1176
1177 if (!td->enabled) {
1178 r = 0;
1179 goto err;
1180 }
1181
1182 /* XXX no need to send this every frame, but dsi break if not done */
1183 r = taal_set_update_window(td, 0, 0,
1184 dssdev->panel.timings.x_res,
1185 dssdev->panel.timings.y_res);
1186 if (r)
1187 goto err;
1188
1189 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
1190 schedule_delayed_work(&td->te_timeout_work,
1191 msecs_to_jiffies(250));
1192 atomic_set(&td->do_update, 1);
1193 } else {
1194 r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
1195 dssdev);
1196 if (r)
1197 goto err;
1198 }
1199
1200 /* note: no bus_unlock here. unlock is in framedone_cb */
1201 mutex_unlock(&td->lock);
1202 return 0;
1203err:
1204 dsi_bus_unlock(dssdev);
1205 mutex_unlock(&td->lock);
1206 return r;
1207}
1208
1209static int taal_sync(struct omap_dss_device *dssdev)
1210{
1211 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1212
1213 dev_dbg(dssdev->dev, "sync\n");
1214
1215 mutex_lock(&td->lock);
1216 dsi_bus_lock(dssdev);
1217 dsi_bus_unlock(dssdev);
1218 mutex_unlock(&td->lock);
1219
1220 dev_dbg(dssdev->dev, "sync done\n");
1221
1222 return 0;
1223}
1224
1225static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1226{
1227 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1228 int r;
1229
1230 if (enable)
1231 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1232 else
1233 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
1234
1235 if (!gpio_is_valid(td->ext_te_gpio))
1236 omapdss_dsi_enable_te(dssdev, enable);
1237
1238 /* possible panel bug */
1239 msleep(100);
1240
1241 return r;
1242}
1243
1244static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1245{
1246 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1247 int r;
1248
1249 mutex_lock(&td->lock);
1250
1251 if (td->te_enabled == enable)
1252 goto end;
1253
1254 dsi_bus_lock(dssdev);
1255
1256 if (td->enabled) {
1257 r = taal_wake_up(dssdev);
1258 if (r)
1259 goto err;
1260
1261 r = _taal_enable_te(dssdev, enable);
1262 if (r)
1263 goto err;
1264 }
1265
1266 td->te_enabled = enable;
1267
1268 dsi_bus_unlock(dssdev);
1269end:
1270 mutex_unlock(&td->lock);
1271
1272 return 0;
1273err:
1274 dsi_bus_unlock(dssdev);
1275 mutex_unlock(&td->lock);
1276
1277 return r;
1278}
1279
1280static int taal_get_te(struct omap_dss_device *dssdev)
1281{
1282 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1283 int r;
1284
1285 mutex_lock(&td->lock);
1286 r = td->te_enabled;
1287 mutex_unlock(&td->lock);
1288
1289 return r;
1290}
1291
1292static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
1293{
1294 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1295 u8 id1, id2, id3;
1296 int r;
1297
1298 mutex_lock(&td->lock);
1299
1300 if (!td->enabled) {
1301 r = -ENODEV;
1302 goto err1;
1303 }
1304
1305 dsi_bus_lock(dssdev);
1306
1307 r = taal_wake_up(dssdev);
1308 if (r)
1309 goto err2;
1310
1311 r = taal_dcs_read_1(td, DCS_GET_ID1, &id1);
1312 if (r)
1313 goto err2;
1314 r = taal_dcs_read_1(td, DCS_GET_ID2, &id2);
1315 if (r)
1316 goto err2;
1317 r = taal_dcs_read_1(td, DCS_GET_ID3, &id3);
1318 if (r)
1319 goto err2;
1320
1321 dsi_bus_unlock(dssdev);
1322 mutex_unlock(&td->lock);
1323 return 0;
1324err2:
1325 dsi_bus_unlock(dssdev);
1326err1:
1327 mutex_unlock(&td->lock);
1328 return r;
1329}
1330
1331static int taal_memory_read(struct omap_dss_device *dssdev,
1332 void *buf, size_t size,
1333 u16 x, u16 y, u16 w, u16 h)
1334{
1335 int r;
1336 int first = 1;
1337 int plen;
1338 unsigned buf_used = 0;
1339 struct taal_data *td = dev_get_drvdata(dssdev->dev);
1340
1341 if (size < w * h * 3)
1342 return -ENOMEM;
1343
1344 mutex_lock(&td->lock);
1345
1346 if (!td->enabled) {
1347 r = -ENODEV;
1348 goto err1;
1349 }
1350
1351 size = min(w * h * 3,
1352 dssdev->panel.timings.x_res *
1353 dssdev->panel.timings.y_res * 3);
1354
1355 dsi_bus_lock(dssdev);
1356
1357 r = taal_wake_up(dssdev);
1358 if (r)
1359 goto err2;
1360
1361 /* plen 1 or 2 goes into short packet. until checksum error is fixed,
1362 * use short packets. plen 32 works, but bigger packets seem to cause
1363 * an error. */
1364 if (size % 2)
1365 plen = 1;
1366 else
1367 plen = 2;
1368
1369 taal_set_update_window(td, x, y, w, h);
1370
1371 r = dsi_vc_set_max_rx_packet_size(dssdev, td->channel, plen);
1372 if (r)
1373 goto err2;
1374
1375 while (buf_used < size) {
1376 u8 dcs_cmd = first ? 0x2e : 0x3e;
1377 first = 0;
1378
1379 r = dsi_vc_dcs_read(dssdev, td->channel, dcs_cmd,
1380 buf + buf_used, size - buf_used);
1381
1382 if (r < 0) {
1383 dev_err(dssdev->dev, "read error\n");
1384 goto err3;
1385 }
1386
1387 buf_used += r;
1388
1389 if (r < plen) {
1390 dev_err(dssdev->dev, "short read\n");
1391 break;
1392 }
1393
1394 if (signal_pending(current)) {
1395 dev_err(dssdev->dev, "signal pending, "
1396 "aborting memory read\n");
1397 r = -ERESTARTSYS;
1398 goto err3;
1399 }
1400 }
1401
1402 r = buf_used;
1403
1404err3:
1405 dsi_vc_set_max_rx_packet_size(dssdev, td->channel, 1);
1406err2:
1407 dsi_bus_unlock(dssdev);
1408err1:
1409 mutex_unlock(&td->lock);
1410 return r;
1411}
1412
1413static void taal_ulps_work(struct work_struct *work)
1414{
1415 struct taal_data *td = container_of(work, struct taal_data,
1416 ulps_work.work);
1417 struct omap_dss_device *dssdev = td->dssdev;
1418
1419 mutex_lock(&td->lock);
1420
1421 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) {
1422 mutex_unlock(&td->lock);
1423 return;
1424 }
1425
1426 dsi_bus_lock(dssdev);
1427
1428 taal_enter_ulps(dssdev);
1429
1430 dsi_bus_unlock(dssdev);
1431 mutex_unlock(&td->lock);
1432}
1433
1434static void taal_esd_work(struct work_struct *work)
1435{
1436 struct taal_data *td = container_of(work, struct taal_data,
1437 esd_work.work);
1438 struct omap_dss_device *dssdev = td->dssdev;
1439 u8 state1, state2;
1440 int r;
1441
1442 mutex_lock(&td->lock);
1443
1444 if (!td->enabled) {
1445 mutex_unlock(&td->lock);
1446 return;
1447 }
1448
1449 dsi_bus_lock(dssdev);
1450
1451 r = taal_wake_up(dssdev);
1452 if (r) {
1453 dev_err(dssdev->dev, "failed to exit ULPS\n");
1454 goto err;
1455 }
1456
1457 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
1458 if (r) {
1459 dev_err(dssdev->dev, "failed to read Taal status\n");
1460 goto err;
1461 }
1462
1463 /* Run self diagnostics */
1464 r = taal_sleep_out(td);
1465 if (r) {
1466 dev_err(dssdev->dev, "failed to run Taal self-diagnostics\n");
1467 goto err;
1468 }
1469
1470 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
1471 if (r) {
1472 dev_err(dssdev->dev, "failed to read Taal status\n");
1473 goto err;
1474 }
1475
1476 /* Each sleep out command will trigger a self diagnostic and flip
1477 * Bit6 if the test passes.
1478 */
1479 if (!((state1 ^ state2) & (1 << 6))) {
1480 dev_err(dssdev->dev, "LCD self diagnostics failed\n");
1481 goto err;
1482 }
1483 /* Self-diagnostics result is also shown on TE GPIO line. We need
1484 * to re-enable TE after self diagnostics */
1485 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
1486 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1487 if (r)
1488 goto err;
1489 }
1490
1491 dsi_bus_unlock(dssdev);
1492
1493 taal_queue_esd_work(dssdev);
1494
1495 mutex_unlock(&td->lock);
1496 return;
1497err:
1498 dev_err(dssdev->dev, "performing LCD reset\n");
1499
1500 taal_panel_reset(dssdev);
1501
1502 dsi_bus_unlock(dssdev);
1503
1504 taal_queue_esd_work(dssdev);
1505
1506 mutex_unlock(&td->lock);
1507}
1508
1509static struct omap_dss_driver taal_driver = {
1510 .probe = taal_probe,
1511 .remove = __exit_p(taal_remove),
1512
1513 .enable = taal_enable,
1514 .disable = taal_disable,
1515
1516 .update = taal_update,
1517 .sync = taal_sync,
1518
1519 .get_resolution = taal_get_resolution,
1520 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
1521
1522 .enable_te = taal_enable_te,
1523 .get_te = taal_get_te,
1524
1525 .run_test = taal_run_test,
1526 .memory_read = taal_memory_read,
1527
1528 .driver = {
1529 .name = "taal",
1530 .owner = THIS_MODULE,
1531 },
1532};
1533
1534static int __init taal_init(void)
1535{
1536 omap_dss_register_driver(&taal_driver);
1537
1538 return 0;
1539}
1540
1541static void __exit taal_exit(void)
1542{
1543 omap_dss_unregister_driver(&taal_driver);
1544}
1545
1546module_init(taal_init);
1547module_exit(taal_exit);
1548
1549MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
1550MODULE_DESCRIPTION("Taal Driver");
1551MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
deleted file mode 100644
index 1fdfb158a2a9..000000000000
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ /dev/null
@@ -1,353 +0,0 @@
1/*
2 * TFP410 DPI-to-DVI chip
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 <linux/gpio.h>
25#include <drm/drm_edid.h>
26
27#include <video/omap-panel-data.h>
28
29static const struct omap_video_timings tfp410_default_timings = {
30 .x_res = 640,
31 .y_res = 480,
32
33 .pixel_clock = 23500,
34
35 .hfp = 48,
36 .hsw = 32,
37 .hbp = 80,
38
39 .vfp = 3,
40 .vsw = 4,
41 .vbp = 7,
42
43 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
44 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
45 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
46 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
47 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
48};
49
50struct panel_drv_data {
51 struct omap_dss_device *dssdev;
52
53 struct mutex lock;
54
55 int pd_gpio;
56
57 struct i2c_adapter *i2c_adapter;
58};
59
60static int tfp410_power_on(struct omap_dss_device *dssdev)
61{
62 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
63 int r;
64
65 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
66 return 0;
67
68 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
69 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
70
71 r = omapdss_dpi_display_enable(dssdev);
72 if (r)
73 goto err0;
74
75 if (gpio_is_valid(ddata->pd_gpio))
76 gpio_set_value_cansleep(ddata->pd_gpio, 1);
77
78 return 0;
79err0:
80 return r;
81}
82
83static void tfp410_power_off(struct omap_dss_device *dssdev)
84{
85 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
86
87 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
88 return;
89
90 if (gpio_is_valid(ddata->pd_gpio))
91 gpio_set_value_cansleep(ddata->pd_gpio, 0);
92
93 omapdss_dpi_display_disable(dssdev);
94}
95
96static int tfp410_probe(struct omap_dss_device *dssdev)
97{
98 struct panel_drv_data *ddata;
99 int r;
100 int i2c_bus_num;
101
102 ddata = devm_kzalloc(dssdev->dev, sizeof(*ddata), GFP_KERNEL);
103 if (!ddata)
104 return -ENOMEM;
105
106 dssdev->panel.timings = tfp410_default_timings;
107
108 ddata->dssdev = dssdev;
109 mutex_init(&ddata->lock);
110
111 if (dssdev->data) {
112 struct tfp410_platform_data *pdata = dssdev->data;
113
114 ddata->pd_gpio = pdata->power_down_gpio;
115 i2c_bus_num = pdata->i2c_bus_num;
116 } else {
117 ddata->pd_gpio = -1;
118 i2c_bus_num = -1;
119 }
120
121 if (gpio_is_valid(ddata->pd_gpio)) {
122 r = devm_gpio_request_one(dssdev->dev, ddata->pd_gpio,
123 GPIOF_OUT_INIT_LOW, "tfp410 pd");
124 if (r) {
125 dev_err(dssdev->dev, "Failed to request PD GPIO %d\n",
126 ddata->pd_gpio);
127 return r;
128 }
129 }
130
131 if (i2c_bus_num != -1) {
132 struct i2c_adapter *adapter;
133
134 adapter = i2c_get_adapter(i2c_bus_num);
135 if (!adapter) {
136 dev_err(dssdev->dev, "Failed to get I2C adapter, bus %d\n",
137 i2c_bus_num);
138 return -EPROBE_DEFER;
139 }
140
141 ddata->i2c_adapter = adapter;
142 }
143
144 dev_set_drvdata(dssdev->dev, ddata);
145
146 return 0;
147}
148
149static void __exit tfp410_remove(struct omap_dss_device *dssdev)
150{
151 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
152
153 mutex_lock(&ddata->lock);
154
155 if (ddata->i2c_adapter)
156 i2c_put_adapter(ddata->i2c_adapter);
157
158 dev_set_drvdata(dssdev->dev, NULL);
159
160 mutex_unlock(&ddata->lock);
161}
162
163static int tfp410_enable(struct omap_dss_device *dssdev)
164{
165 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
166 int r;
167
168 mutex_lock(&ddata->lock);
169
170 r = tfp410_power_on(dssdev);
171 if (r == 0)
172 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
173
174 mutex_unlock(&ddata->lock);
175
176 return r;
177}
178
179static void tfp410_disable(struct omap_dss_device *dssdev)
180{
181 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
182
183 mutex_lock(&ddata->lock);
184
185 tfp410_power_off(dssdev);
186
187 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
188
189 mutex_unlock(&ddata->lock);
190}
191
192static void tfp410_set_timings(struct omap_dss_device *dssdev,
193 struct omap_video_timings *timings)
194{
195 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
196
197 mutex_lock(&ddata->lock);
198 omapdss_dpi_set_timings(dssdev, timings);
199 dssdev->panel.timings = *timings;
200 mutex_unlock(&ddata->lock);
201}
202
203static void tfp410_get_timings(struct omap_dss_device *dssdev,
204 struct omap_video_timings *timings)
205{
206 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
207
208 mutex_lock(&ddata->lock);
209 *timings = dssdev->panel.timings;
210 mutex_unlock(&ddata->lock);
211}
212
213static int tfp410_check_timings(struct omap_dss_device *dssdev,
214 struct omap_video_timings *timings)
215{
216 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
217 int r;
218
219 mutex_lock(&ddata->lock);
220 r = dpi_check_timings(dssdev, timings);
221 mutex_unlock(&ddata->lock);
222
223 return r;
224}
225
226
227static int tfp410_ddc_read(struct i2c_adapter *adapter,
228 unsigned char *buf, u16 count, u8 offset)
229{
230 int r, retries;
231
232 for (retries = 3; retries > 0; retries--) {
233 struct i2c_msg msgs[] = {
234 {
235 .addr = DDC_ADDR,
236 .flags = 0,
237 .len = 1,
238 .buf = &offset,
239 }, {
240 .addr = DDC_ADDR,
241 .flags = I2C_M_RD,
242 .len = count,
243 .buf = buf,
244 }
245 };
246
247 r = i2c_transfer(adapter, msgs, 2);
248 if (r == 2)
249 return 0;
250
251 if (r != -EAGAIN)
252 break;
253 }
254
255 return r < 0 ? r : -EIO;
256}
257
258static int tfp410_read_edid(struct omap_dss_device *dssdev,
259 u8 *edid, int len)
260{
261 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
262 int r, l, bytes_read;
263
264 mutex_lock(&ddata->lock);
265
266 if (!ddata->i2c_adapter) {
267 r = -ENODEV;
268 goto err;
269 }
270
271 l = min(EDID_LENGTH, len);
272 r = tfp410_ddc_read(ddata->i2c_adapter, edid, l, 0);
273 if (r)
274 goto err;
275
276 bytes_read = l;
277
278 /* if there are extensions, read second block */
279 if (len > EDID_LENGTH && edid[0x7e] > 0) {
280 l = min(EDID_LENGTH, len - EDID_LENGTH);
281
282 r = tfp410_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
283 l, EDID_LENGTH);
284 if (r)
285 goto err;
286
287 bytes_read += l;
288 }
289
290 mutex_unlock(&ddata->lock);
291
292 return bytes_read;
293
294err:
295 mutex_unlock(&ddata->lock);
296 return r;
297}
298
299static bool tfp410_detect(struct omap_dss_device *dssdev)
300{
301 struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
302 unsigned char out;
303 int r;
304
305 mutex_lock(&ddata->lock);
306
307 if (!ddata->i2c_adapter)
308 goto out;
309
310 r = tfp410_ddc_read(ddata->i2c_adapter, &out, 1, 0);
311
312 mutex_unlock(&ddata->lock);
313
314 return r == 0;
315
316out:
317 mutex_unlock(&ddata->lock);
318 return true;
319}
320
321static struct omap_dss_driver tfp410_driver = {
322 .probe = tfp410_probe,
323 .remove = __exit_p(tfp410_remove),
324
325 .enable = tfp410_enable,
326 .disable = tfp410_disable,
327
328 .set_timings = tfp410_set_timings,
329 .get_timings = tfp410_get_timings,
330 .check_timings = tfp410_check_timings,
331
332 .read_edid = tfp410_read_edid,
333 .detect = tfp410_detect,
334
335 .driver = {
336 .name = "tfp410",
337 .owner = THIS_MODULE,
338 },
339};
340
341static int __init tfp410_init(void)
342{
343 return omap_dss_register_driver(&tfp410_driver);
344}
345
346static void __exit tfp410_exit(void)
347{
348 omap_dss_unregister_driver(&tfp410_driver);
349}
350
351module_init(tfp410_init);
352module_exit(tfp410_exit);
353MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
deleted file mode 100644
index 7729b6fa6f97..000000000000
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ /dev/null
@@ -1,596 +0,0 @@
1/*
2 * LCD panel driver for TPO TD043MTEA1
3 *
4 * Author: GraÅžvydas Ignotas <notasas@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/spi/spi.h>
15#include <linux/regulator/consumer.h>
16#include <linux/gpio.h>
17#include <linux/err.h>
18#include <linux/slab.h>
19
20#include <video/omapdss.h>
21#include <video/omap-panel-data.h>
22
23#define TPO_R02_MODE(x) ((x) & 7)
24#define TPO_R02_MODE_800x480 7
25#define TPO_R02_NCLK_RISING BIT(3)
26#define TPO_R02_HSYNC_HIGH BIT(4)
27#define TPO_R02_VSYNC_HIGH BIT(5)
28
29#define TPO_R03_NSTANDBY BIT(0)
30#define TPO_R03_EN_CP_CLK BIT(1)
31#define TPO_R03_EN_VGL_PUMP BIT(2)
32#define TPO_R03_EN_PWM BIT(3)
33#define TPO_R03_DRIVING_CAP_100 BIT(4)
34#define TPO_R03_EN_PRE_CHARGE BIT(6)
35#define TPO_R03_SOFTWARE_CTL BIT(7)
36
37#define TPO_R04_NFLIP_H BIT(0)
38#define TPO_R04_NFLIP_V BIT(1)
39#define TPO_R04_CP_CLK_FREQ_1H BIT(2)
40#define TPO_R04_VGL_FREQ_1H BIT(4)
41
42#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
43 TPO_R03_EN_VGL_PUMP | TPO_R03_EN_PWM | \
44 TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
45 TPO_R03_SOFTWARE_CTL)
46
47#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
48 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
49
50static const u16 tpo_td043_def_gamma[12] = {
51 105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
52};
53
54struct tpo_td043_device {
55 struct spi_device *spi;
56 struct regulator *vcc_reg;
57 int nreset_gpio;
58 u16 gamma[12];
59 u32 mode;
60 u32 hmirror:1;
61 u32 vmirror:1;
62 u32 powered_on:1;
63 u32 spi_suspended:1;
64 u32 power_on_resume:1;
65};
66
67/* used to pass spi_device from SPI to DSS portion of the driver */
68static struct tpo_td043_device *g_tpo_td043;
69
70static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
71{
72 struct spi_message m;
73 struct spi_transfer xfer;
74 u16 w;
75 int r;
76
77 spi_message_init(&m);
78
79 memset(&xfer, 0, sizeof(xfer));
80
81 w = ((u16)addr << 10) | (1 << 8) | data;
82 xfer.tx_buf = &w;
83 xfer.bits_per_word = 16;
84 xfer.len = 2;
85 spi_message_add_tail(&xfer, &m);
86
87 r = spi_sync(spi, &m);
88 if (r < 0)
89 dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
90 return r;
91}
92
93static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
94{
95 u8 i, val;
96
97 /* gamma bits [9:8] */
98 for (val = i = 0; i < 4; i++)
99 val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
100 tpo_td043_write(spi, 0x11, val);
101
102 for (val = i = 0; i < 4; i++)
103 val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
104 tpo_td043_write(spi, 0x12, val);
105
106 for (val = i = 0; i < 4; i++)
107 val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
108 tpo_td043_write(spi, 0x13, val);
109
110 /* gamma bits [7:0] */
111 for (val = i = 0; i < 12; i++)
112 tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
113}
114
115static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
116{
117 u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V | \
118 TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
119 if (h)
120 reg4 &= ~TPO_R04_NFLIP_H;
121 if (v)
122 reg4 &= ~TPO_R04_NFLIP_V;
123
124 return tpo_td043_write(spi, 4, reg4);
125}
126
127static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
128{
129 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dssdev->dev);
130
131 tpo_td043->hmirror = enable;
132 return tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
133 tpo_td043->vmirror);
134}
135
136static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
137{
138 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dssdev->dev);
139
140 return tpo_td043->hmirror;
141}
142
143static ssize_t tpo_td043_vmirror_show(struct device *dev,
144 struct device_attribute *attr, char *buf)
145{
146 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
147
148 return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->vmirror);
149}
150
151static ssize_t tpo_td043_vmirror_store(struct device *dev,
152 struct device_attribute *attr, const char *buf, size_t count)
153{
154 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
155 int val;
156 int ret;
157
158 ret = kstrtoint(buf, 0, &val);
159 if (ret < 0)
160 return ret;
161
162 val = !!val;
163
164 ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
165 if (ret < 0)
166 return ret;
167
168 tpo_td043->vmirror = val;
169
170 return count;
171}
172
173static ssize_t tpo_td043_mode_show(struct device *dev,
174 struct device_attribute *attr, char *buf)
175{
176 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
177
178 return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->mode);
179}
180
181static ssize_t tpo_td043_mode_store(struct device *dev,
182 struct device_attribute *attr, const char *buf, size_t count)
183{
184 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
185 long val;
186 int ret;
187
188 ret = kstrtol(buf, 0, &val);
189 if (ret != 0 || val & ~7)
190 return -EINVAL;
191
192 tpo_td043->mode = val;
193
194 val |= TPO_R02_NCLK_RISING;
195 tpo_td043_write(tpo_td043->spi, 2, val);
196
197 return count;
198}
199
200static ssize_t tpo_td043_gamma_show(struct device *dev,
201 struct device_attribute *attr, char *buf)
202{
203 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
204 ssize_t len = 0;
205 int ret;
206 int i;
207
208 for (i = 0; i < ARRAY_SIZE(tpo_td043->gamma); i++) {
209 ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
210 tpo_td043->gamma[i]);
211 if (ret < 0)
212 return ret;
213 len += ret;
214 }
215 buf[len - 1] = '\n';
216
217 return len;
218}
219
220static ssize_t tpo_td043_gamma_store(struct device *dev,
221 struct device_attribute *attr, const char *buf, size_t count)
222{
223 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
224 unsigned int g[12];
225 int ret;
226 int i;
227
228 ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
229 &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
230 &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
231
232 if (ret != 12)
233 return -EINVAL;
234
235 for (i = 0; i < 12; i++)
236 tpo_td043->gamma[i] = g[i];
237
238 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
239
240 return count;
241}
242
243static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
244 tpo_td043_vmirror_show, tpo_td043_vmirror_store);
245static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
246 tpo_td043_mode_show, tpo_td043_mode_store);
247static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
248 tpo_td043_gamma_show, tpo_td043_gamma_store);
249
250static struct attribute *tpo_td043_attrs[] = {
251 &dev_attr_vmirror.attr,
252 &dev_attr_mode.attr,
253 &dev_attr_gamma.attr,
254 NULL,
255};
256
257static struct attribute_group tpo_td043_attr_group = {
258 .attrs = tpo_td043_attrs,
259};
260
261static const struct omap_video_timings tpo_td043_timings = {
262 .x_res = 800,
263 .y_res = 480,
264
265 .pixel_clock = 36000,
266
267 .hsw = 1,
268 .hfp = 68,
269 .hbp = 214,
270
271 .vsw = 1,
272 .vfp = 39,
273 .vbp = 34,
274
275 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
276 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
277 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
278 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
279 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
280};
281
282static inline struct panel_tpo_td043_data
283*get_panel_data(const struct omap_dss_device *dssdev)
284{
285 return (struct panel_tpo_td043_data *) dssdev->data;
286}
287
288static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
289{
290 int r;
291
292 if (tpo_td043->powered_on)
293 return 0;
294
295 r = regulator_enable(tpo_td043->vcc_reg);
296 if (r != 0)
297 return r;
298
299 /* wait for panel to stabilize */
300 msleep(160);
301
302 if (gpio_is_valid(tpo_td043->nreset_gpio))
303 gpio_set_value(tpo_td043->nreset_gpio, 1);
304
305 tpo_td043_write(tpo_td043->spi, 2,
306 TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
307 tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_NORMAL);
308 tpo_td043_write(tpo_td043->spi, 0x20, 0xf0);
309 tpo_td043_write(tpo_td043->spi, 0x21, 0xf0);
310 tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
311 tpo_td043->vmirror);
312 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
313
314 tpo_td043->powered_on = 1;
315 return 0;
316}
317
318static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
319{
320 if (!tpo_td043->powered_on)
321 return;
322
323 tpo_td043_write(tpo_td043->spi, 3,
324 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
325
326 if (gpio_is_valid(tpo_td043->nreset_gpio))
327 gpio_set_value(tpo_td043->nreset_gpio, 0);
328
329 /* wait for at least 2 vsyncs before cutting off power */
330 msleep(50);
331
332 tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_STANDBY);
333
334 regulator_disable(tpo_td043->vcc_reg);
335
336 tpo_td043->powered_on = 0;
337}
338
339static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
340{
341 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dssdev->dev);
342 int r;
343
344 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
345 return 0;
346
347 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
348 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
349
350 r = omapdss_dpi_display_enable(dssdev);
351 if (r)
352 goto err0;
353
354 /*
355 * If we are resuming from system suspend, SPI clocks might not be
356 * enabled yet, so we'll program the LCD from SPI PM resume callback.
357 */
358 if (!tpo_td043->spi_suspended) {
359 r = tpo_td043_power_on(tpo_td043);
360 if (r)
361 goto err1;
362 }
363
364 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
365
366 return 0;
367err1:
368 omapdss_dpi_display_disable(dssdev);
369err0:
370 return r;
371}
372
373static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
374{
375 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dssdev->dev);
376
377 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
378 return;
379
380 omapdss_dpi_display_disable(dssdev);
381
382 if (!tpo_td043->spi_suspended)
383 tpo_td043_power_off(tpo_td043);
384}
385
386static int tpo_td043_enable(struct omap_dss_device *dssdev)
387{
388 dev_dbg(dssdev->dev, "enable\n");
389
390 return tpo_td043_enable_dss(dssdev);
391}
392
393static void tpo_td043_disable(struct omap_dss_device *dssdev)
394{
395 dev_dbg(dssdev->dev, "disable\n");
396
397 tpo_td043_disable_dss(dssdev);
398
399 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
400}
401
402static int tpo_td043_probe(struct omap_dss_device *dssdev)
403{
404 struct tpo_td043_device *tpo_td043 = g_tpo_td043;
405 struct panel_tpo_td043_data *pdata = get_panel_data(dssdev);
406 int ret = 0;
407
408 dev_dbg(dssdev->dev, "probe\n");
409
410 if (tpo_td043 == NULL) {
411 dev_err(dssdev->dev, "missing tpo_td043_device\n");
412 return -ENODEV;
413 }
414
415 if (!pdata)
416 return -EINVAL;
417
418 tpo_td043->nreset_gpio = pdata->nreset_gpio;
419
420 dssdev->panel.timings = tpo_td043_timings;
421 dssdev->ctrl.pixel_size = 24;
422
423 tpo_td043->mode = TPO_R02_MODE_800x480;
424 memcpy(tpo_td043->gamma, tpo_td043_def_gamma, sizeof(tpo_td043->gamma));
425
426 tpo_td043->vcc_reg = regulator_get(dssdev->dev, "vcc");
427 if (IS_ERR(tpo_td043->vcc_reg)) {
428 dev_err(dssdev->dev, "failed to get LCD VCC regulator\n");
429 ret = PTR_ERR(tpo_td043->vcc_reg);
430 goto fail_regulator;
431 }
432
433 if (gpio_is_valid(tpo_td043->nreset_gpio)) {
434 ret = devm_gpio_request_one(dssdev->dev,
435 tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW,
436 "lcd reset");
437 if (ret < 0) {
438 dev_err(dssdev->dev, "couldn't request reset GPIO\n");
439 goto fail_gpio_req;
440 }
441 }
442
443 ret = sysfs_create_group(&dssdev->dev->kobj, &tpo_td043_attr_group);
444 if (ret)
445 dev_warn(dssdev->dev, "failed to create sysfs files\n");
446
447 dev_set_drvdata(dssdev->dev, tpo_td043);
448
449 return 0;
450
451fail_gpio_req:
452 regulator_put(tpo_td043->vcc_reg);
453fail_regulator:
454 kfree(tpo_td043);
455 return ret;
456}
457
458static void tpo_td043_remove(struct omap_dss_device *dssdev)
459{
460 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dssdev->dev);
461
462 dev_dbg(dssdev->dev, "remove\n");
463
464 sysfs_remove_group(&dssdev->dev->kobj, &tpo_td043_attr_group);
465 regulator_put(tpo_td043->vcc_reg);
466}
467
468static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
469 struct omap_video_timings *timings)
470{
471 omapdss_dpi_set_timings(dssdev, timings);
472
473 dssdev->panel.timings = *timings;
474}
475
476static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
477 struct omap_video_timings *timings)
478{
479 return dpi_check_timings(dssdev, timings);
480}
481
482static struct omap_dss_driver tpo_td043_driver = {
483 .probe = tpo_td043_probe,
484 .remove = tpo_td043_remove,
485
486 .enable = tpo_td043_enable,
487 .disable = tpo_td043_disable,
488 .set_mirror = tpo_td043_set_hmirror,
489 .get_mirror = tpo_td043_get_hmirror,
490
491 .set_timings = tpo_td043_set_timings,
492 .check_timings = tpo_td043_check_timings,
493
494 .driver = {
495 .name = "tpo_td043mtea1_panel",
496 .owner = THIS_MODULE,
497 },
498};
499
500static int tpo_td043_spi_probe(struct spi_device *spi)
501{
502 struct omap_dss_device *dssdev = spi->dev.platform_data;
503 struct tpo_td043_device *tpo_td043;
504 int ret;
505
506 if (dssdev == NULL) {
507 dev_err(&spi->dev, "missing dssdev\n");
508 return -ENODEV;
509 }
510
511 if (g_tpo_td043 != NULL)
512 return -EBUSY;
513
514 spi->bits_per_word = 16;
515 spi->mode = SPI_MODE_0;
516
517 ret = spi_setup(spi);
518 if (ret < 0) {
519 dev_err(&spi->dev, "spi_setup failed: %d\n", ret);
520 return ret;
521 }
522
523 tpo_td043 = kzalloc(sizeof(*tpo_td043), GFP_KERNEL);
524 if (tpo_td043 == NULL)
525 return -ENOMEM;
526
527 tpo_td043->spi = spi;
528 dev_set_drvdata(&spi->dev, tpo_td043);
529 g_tpo_td043 = tpo_td043;
530
531 omap_dss_register_driver(&tpo_td043_driver);
532
533 return 0;
534}
535
536static int tpo_td043_spi_remove(struct spi_device *spi)
537{
538 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
539
540 omap_dss_unregister_driver(&tpo_td043_driver);
541 kfree(tpo_td043);
542 g_tpo_td043 = NULL;
543
544 return 0;
545}
546
547#ifdef CONFIG_PM_SLEEP
548static int tpo_td043_spi_suspend(struct device *dev)
549{
550 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
551
552 dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", tpo_td043);
553
554 tpo_td043->power_on_resume = tpo_td043->powered_on;
555 tpo_td043_power_off(tpo_td043);
556 tpo_td043->spi_suspended = 1;
557
558 return 0;
559}
560
561static int tpo_td043_spi_resume(struct device *dev)
562{
563 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
564 int ret;
565
566 dev_dbg(dev, "tpo_td043_spi_resume\n");
567
568 if (tpo_td043->power_on_resume) {
569 ret = tpo_td043_power_on(tpo_td043);
570 if (ret)
571 return ret;
572 }
573 tpo_td043->spi_suspended = 0;
574
575 return 0;
576}
577#endif
578
579static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
580 tpo_td043_spi_suspend, tpo_td043_spi_resume);
581
582static struct spi_driver tpo_td043_spi_driver = {
583 .driver = {
584 .name = "tpo_td043mtea1_panel_spi",
585 .owner = THIS_MODULE,
586 .pm = &tpo_td043_spi_pm,
587 },
588 .probe = tpo_td043_spi_probe,
589 .remove = tpo_td043_spi_remove,
590};
591
592module_spi_driver(tpo_td043_spi_driver);
593
594MODULE_AUTHOR("GraÅžvydas Ignotas <notasas@gmail.com>");
595MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
596MODULE_LICENSE("GPL");