aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 18:20:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 18:20:57 -0400
commit1f7f314bf2a77f1d499b41001ebdafb261f00f30 (patch)
treeaa7eddcf09fe38abb274dffb457e3c0949cfbb3d /drivers/video
parent2a8ba8f032160552a3beffab8aae9019ff477504 (diff)
parentfce064cbda85dda330150e8d4d9f6db1a3300023 (diff)
Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux
* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux: (23 commits) OMAP: DSS2: Fix omap_dss_probe() error path OMAP: DSS2: omap_dss_probe() conditional compilation cleanup board-omap3-beagle: add DSS2 support OMAP2: DSS: Add missing line for update bg color OMAP3630: DSS2: Updating MAX divider value OMAP: RX51: Update board defconfig OMAP: DSS2: Add ACX565AKM Panel Driver OMAP: RX51: Add Touch Controller in SPI board info OMAP: RX51: Add LCD Panel support OMAP: DSS2: TPO-TD03MTEA1: fix Kconfig dependency OMAP: LCD LS037V7DW01: Add Backlight driver support OMAP: DSS2: Taal: Fix DSI bus locking problem OMAP: DSS2: Taal: add mutex to protect panel data OMAP: DSS2: Make partial update width even OMAP: DSS2: Fix device disable when driver is not loaded OMAP: DSS2: VENC: don't call platform_enable/disable() twice OMAP: DSS2: check lock_fb_info() return value OMAP: DSS2: fix lock_fb_info() and omapfb_lock() locking order OMAP: DSS2: Use vdds_sdi regulator supply in SDI OMAP: DSS2: Remove redundant enable/disable calls from SDI ...
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/displays/Kconfig9
-rw-r--r--drivers/video/omap2/displays/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c819
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c78
-rw-r--r--drivers/video/omap2/displays/panel-taal.c143
-rw-r--r--drivers/video/omap2/dss/Kconfig6
-rw-r--r--drivers/video/omap2/dss/Makefile3
-rw-r--r--drivers/video/omap2/dss/core.c85
-rw-r--r--drivers/video/omap2/dss/display.c9
-rw-r--r--drivers/video/omap2/dss/dss.c24
-rw-r--r--drivers/video/omap2/dss/dss.h50
-rw-r--r--drivers/video/omap2/dss/manager.c21
-rw-r--r--drivers/video/omap2/dss/sdi.c26
-rw-r--r--drivers/video/omap2/dss/venc.c15
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c5
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c25
16 files changed, 1219 insertions, 100 deletions
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index dfb57ee50861..881c9f77c75a 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,7 @@ config PANEL_GENERIC
10config PANEL_SHARP_LS037V7DW01 10config PANEL_SHARP_LS037V7DW01
11 tristate "Sharp LS037V7DW01 LCD Panel" 11 tristate "Sharp LS037V7DW01 LCD Panel"
12 depends on OMAP2_DSS 12 depends on OMAP2_DSS
13 select BACKLIGHT_CLASS_DEVICE
13 help 14 help
14 LCD Panel used in TI's SDP3430 and EVM boards 15 LCD Panel used in TI's SDP3430 and EVM boards
15 16
@@ -33,8 +34,14 @@ config PANEL_TOPPOLY_TDO35S
33 34
34config PANEL_TPO_TD043MTEA1 35config PANEL_TPO_TD043MTEA1
35 tristate "TPO TD043MTEA1 LCD Panel" 36 tristate "TPO TD043MTEA1 LCD Panel"
36 depends on OMAP2_DSS && I2C 37 depends on OMAP2_DSS && SPI
37 help 38 help
38 LCD Panel used in OMAP3 Pandora 39 LCD Panel used in OMAP3 Pandora
39 40
41config PANEL_ACX565AKM
42 tristate "ACX565AKM Panel"
43 depends on OMAP2_DSS_SDI
44 select BACKLIGHT_CLASS_DEVICE
45 help
46 This is the LCD panel used on Nokia N900
40endmenu 47endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index e2bb32168dee..aa386095d7c4 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
5obj-$(CONFIG_PANEL_TAAL) += panel-taal.o 5obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
6obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o 6obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
new file mode 100644
index 000000000000..1f8eb70e2937
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -0,0 +1,819 @@
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
33#include <plat/display.h>
34
35#define MIPID_CMD_READ_DISP_ID 0x04
36#define MIPID_CMD_READ_RED 0x06
37#define MIPID_CMD_READ_GREEN 0x07
38#define MIPID_CMD_READ_BLUE 0x08
39#define MIPID_CMD_READ_DISP_STATUS 0x09
40#define MIPID_CMD_RDDSDR 0x0F
41#define MIPID_CMD_SLEEP_IN 0x10
42#define MIPID_CMD_SLEEP_OUT 0x11
43#define MIPID_CMD_DISP_OFF 0x28
44#define MIPID_CMD_DISP_ON 0x29
45#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
46#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
47#define MIPID_CMD_WRITE_CTRL_DISP 0x53
48
49#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
50#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
51#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
52#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
53
54#define MIPID_CMD_READ_CTRL_DISP 0x54
55#define MIPID_CMD_WRITE_CABC 0x55
56#define MIPID_CMD_READ_CABC 0x56
57
58#define MIPID_VER_LPH8923 3
59#define MIPID_VER_LS041Y3 4
60#define MIPID_VER_L4F00311 8
61#define MIPID_VER_ACX565AKM 9
62
63struct acx565akm_device {
64 char *name;
65 int enabled;
66 int model;
67 int revision;
68 u8 display_id[3];
69 unsigned has_bc:1;
70 unsigned has_cabc:1;
71 unsigned cabc_mode;
72 unsigned long hw_guard_end; /* next value of jiffies
73 when we can issue the
74 next sleep in/out command */
75 unsigned long hw_guard_wait; /* max guard time in jiffies */
76
77 struct spi_device *spi;
78 struct mutex mutex;
79
80 struct omap_dss_device *dssdev;
81 struct backlight_device *bl_dev;
82};
83
84static struct acx565akm_device acx_dev;
85static int acx565akm_bl_update_status(struct backlight_device *dev);
86
87/*--------------------MIPID interface-----------------------------*/
88
89static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
90 const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
91{
92 struct spi_message m;
93 struct spi_transfer *x, xfer[5];
94 int r;
95
96 BUG_ON(md->spi == NULL);
97
98 spi_message_init(&m);
99
100 memset(xfer, 0, sizeof(xfer));
101 x = &xfer[0];
102
103 cmd &= 0xff;
104 x->tx_buf = &cmd;
105 x->bits_per_word = 9;
106 x->len = 2;
107
108 if (rlen > 1 && wlen == 0) {
109 /*
110 * Between the command and the response data there is a
111 * dummy clock cycle. Add an extra bit after the command
112 * word to account for this.
113 */
114 x->bits_per_word = 10;
115 cmd <<= 1;
116 }
117 spi_message_add_tail(x, &m);
118
119 if (wlen) {
120 x++;
121 x->tx_buf = wbuf;
122 x->len = wlen;
123 x->bits_per_word = 9;
124 spi_message_add_tail(x, &m);
125 }
126
127 if (rlen) {
128 x++;
129 x->rx_buf = rbuf;
130 x->len = rlen;
131 spi_message_add_tail(x, &m);
132 }
133
134 r = spi_sync(md->spi, &m);
135 if (r < 0)
136 dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
137}
138
139static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
140{
141 acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
142}
143
144static inline void acx565akm_write(struct acx565akm_device *md,
145 int reg, const u8 *buf, int len)
146{
147 acx565akm_transfer(md, reg, buf, len, NULL, 0);
148}
149
150static inline void acx565akm_read(struct acx565akm_device *md,
151 int reg, u8 *buf, int len)
152{
153 acx565akm_transfer(md, reg, NULL, 0, buf, len);
154}
155
156static void hw_guard_start(struct acx565akm_device *md, int guard_msec)
157{
158 md->hw_guard_wait = msecs_to_jiffies(guard_msec);
159 md->hw_guard_end = jiffies + md->hw_guard_wait;
160}
161
162static void hw_guard_wait(struct acx565akm_device *md)
163{
164 unsigned long wait = md->hw_guard_end - jiffies;
165
166 if ((long)wait > 0 && wait <= md->hw_guard_wait) {
167 set_current_state(TASK_UNINTERRUPTIBLE);
168 schedule_timeout(wait);
169 }
170}
171
172/*----------------------MIPID wrappers----------------------------*/
173
174static void set_sleep_mode(struct acx565akm_device *md, int on)
175{
176 int cmd;
177
178 if (on)
179 cmd = MIPID_CMD_SLEEP_IN;
180 else
181 cmd = MIPID_CMD_SLEEP_OUT;
182 /*
183 * We have to keep 120msec between sleep in/out commands.
184 * (8.2.15, 8.2.16).
185 */
186 hw_guard_wait(md);
187 acx565akm_cmd(md, cmd);
188 hw_guard_start(md, 120);
189}
190
191static void set_display_state(struct acx565akm_device *md, int enabled)
192{
193 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
194
195 acx565akm_cmd(md, cmd);
196}
197
198static int panel_enabled(struct acx565akm_device *md)
199{
200 u32 disp_status;
201 int enabled;
202
203 acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
204 disp_status = __be32_to_cpu(disp_status);
205 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
206 dev_dbg(&md->spi->dev,
207 "LCD panel %senabled by bootloader (status 0x%04x)\n",
208 enabled ? "" : "not ", disp_status);
209 return enabled;
210}
211
212static int panel_detect(struct acx565akm_device *md)
213{
214 acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
215 dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
216 md->display_id[0], md->display_id[1], md->display_id[2]);
217
218 switch (md->display_id[0]) {
219 case 0x10:
220 md->model = MIPID_VER_ACX565AKM;
221 md->name = "acx565akm";
222 md->has_bc = 1;
223 md->has_cabc = 1;
224 break;
225 case 0x29:
226 md->model = MIPID_VER_L4F00311;
227 md->name = "l4f00311";
228 break;
229 case 0x45:
230 md->model = MIPID_VER_LPH8923;
231 md->name = "lph8923";
232 break;
233 case 0x83:
234 md->model = MIPID_VER_LS041Y3;
235 md->name = "ls041y3";
236 break;
237 default:
238 md->name = "unknown";
239 dev_err(&md->spi->dev, "invalid display ID\n");
240 return -ENODEV;
241 }
242
243 md->revision = md->display_id[1];
244
245 dev_info(&md->spi->dev, "omapfb: %s rev %02x LCD detected\n",
246 md->name, md->revision);
247
248 return 0;
249}
250
251/*----------------------Backlight Control-------------------------*/
252
253static void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
254{
255 u16 ctrl;
256
257 acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
258 if (enable) {
259 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
260 CTRL_DISP_BACKLIGHT_ON;
261 } else {
262 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
263 CTRL_DISP_BACKLIGHT_ON);
264 }
265
266 ctrl |= 1 << 8;
267 acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
268}
269
270static void set_cabc_mode(struct acx565akm_device *md, unsigned mode)
271{
272 u16 cabc_ctrl;
273
274 md->cabc_mode = mode;
275 if (!md->enabled)
276 return;
277 cabc_ctrl = 0;
278 acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
279 cabc_ctrl &= ~3;
280 cabc_ctrl |= (1 << 8) | (mode & 3);
281 acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
282}
283
284static unsigned get_cabc_mode(struct acx565akm_device *md)
285{
286 return md->cabc_mode;
287}
288
289static unsigned get_hw_cabc_mode(struct acx565akm_device *md)
290{
291 u8 cabc_ctrl;
292
293 acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
294 return cabc_ctrl & 3;
295}
296
297static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
298{
299 int bv;
300
301 bv = level | (1 << 8);
302 acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
303
304 if (level)
305 enable_backlight_ctrl(md, 1);
306 else
307 enable_backlight_ctrl(md, 0);
308}
309
310static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
311{
312 u8 bv;
313
314 acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
315
316 return bv;
317}
318
319
320static int acx565akm_bl_update_status(struct backlight_device *dev)
321{
322 struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
323 int r;
324 int level;
325
326 dev_dbg(&md->spi->dev, "%s\n", __func__);
327
328 mutex_lock(&md->mutex);
329
330 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
331 dev->props.power == FB_BLANK_UNBLANK)
332 level = dev->props.brightness;
333 else
334 level = 0;
335
336 r = 0;
337 if (md->has_bc)
338 acx565akm_set_brightness(md, level);
339 else if (md->dssdev->set_backlight)
340 r = md->dssdev->set_backlight(md->dssdev, 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 && md->dssdev->set_backlight == NULL)
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
492static int acx_panel_probe(struct omap_dss_device *dssdev)
493{
494 int r;
495 struct acx565akm_device *md = &acx_dev;
496 struct backlight_device *bldev;
497 int max_brightness, brightness;
498 struct backlight_properties props;
499
500 dev_dbg(&dssdev->dev, "%s\n", __func__);
501 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
502 OMAP_DSS_LCD_IHS;
503 /* FIXME AC bias ? */
504 dssdev->panel.timings = acx_panel_timings;
505
506 if (dssdev->platform_enable)
507 dssdev->platform_enable(dssdev);
508 /*
509 * After reset we have to wait 5 msec before the first
510 * command can be sent.
511 */
512 msleep(5);
513
514 md->enabled = panel_enabled(md);
515
516 r = panel_detect(md);
517 if (r) {
518 dev_err(&dssdev->dev, "%s panel detect error\n", __func__);
519 if (!md->enabled && dssdev->platform_disable)
520 dssdev->platform_disable(dssdev);
521 return r;
522 }
523
524 mutex_lock(&acx_dev.mutex);
525 acx_dev.dssdev = dssdev;
526 mutex_unlock(&acx_dev.mutex);
527
528 if (!md->enabled) {
529 if (dssdev->platform_disable)
530 dssdev->platform_disable(dssdev);
531 }
532
533 /*------- Backlight control --------*/
534
535 props.fb_blank = FB_BLANK_UNBLANK;
536 props.power = FB_BLANK_UNBLANK;
537
538 bldev = backlight_device_register("acx565akm", &md->spi->dev,
539 md, &acx565akm_bl_ops, &props);
540 md->bl_dev = bldev;
541 if (md->has_cabc) {
542 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
543 if (r) {
544 dev_err(&bldev->dev,
545 "%s failed to create sysfs files\n", __func__);
546 backlight_device_unregister(bldev);
547 return r;
548 }
549 md->cabc_mode = get_hw_cabc_mode(md);
550 }
551
552 if (md->has_bc)
553 max_brightness = 255;
554 else
555 max_brightness = dssdev->max_backlight_level;
556
557 if (md->has_bc)
558 brightness = acx565akm_get_actual_brightness(md);
559 else if (dssdev->get_backlight)
560 brightness = dssdev->get_backlight(dssdev);
561 else
562 brightness = 0;
563
564 bldev->props.max_brightness = max_brightness;
565 bldev->props.brightness = brightness;
566
567 acx565akm_bl_update_status(bldev);
568 return 0;
569}
570
571static void acx_panel_remove(struct omap_dss_device *dssdev)
572{
573 struct acx565akm_device *md = &acx_dev;
574
575 dev_dbg(&dssdev->dev, "%s\n", __func__);
576 sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group);
577 backlight_device_unregister(md->bl_dev);
578 mutex_lock(&acx_dev.mutex);
579 acx_dev.dssdev = NULL;
580 mutex_unlock(&acx_dev.mutex);
581}
582
583static int acx_panel_power_on(struct omap_dss_device *dssdev)
584{
585 struct acx565akm_device *md = &acx_dev;
586 int r;
587
588 dev_dbg(&dssdev->dev, "%s\n", __func__);
589
590 mutex_lock(&md->mutex);
591
592 r = omapdss_sdi_display_enable(dssdev);
593 if (r) {
594 pr_err("%s sdi enable failed\n", __func__);
595 return r;
596 }
597
598 /*FIXME tweak me */
599 msleep(50);
600
601 if (dssdev->platform_enable) {
602 r = dssdev->platform_enable(dssdev);
603 if (r)
604 goto fail;
605 }
606
607 if (md->enabled) {
608 dev_dbg(&md->spi->dev, "panel already enabled\n");
609 mutex_unlock(&md->mutex);
610 return 0;
611 }
612
613 /*
614 * We have to meet all the following delay requirements:
615 * 1. tRW: reset pulse width 10usec (7.12.1)
616 * 2. tRT: reset cancel time 5msec (7.12.1)
617 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
618 * case (7.6.2)
619 * 4. 120msec before the sleep out command (7.12.1)
620 */
621 msleep(120);
622
623 set_sleep_mode(md, 0);
624 md->enabled = 1;
625
626 /* 5msec between sleep out and the next command. (8.2.16) */
627 msleep(5);
628 set_display_state(md, 1);
629 set_cabc_mode(md, md->cabc_mode);
630
631 mutex_unlock(&md->mutex);
632
633 return acx565akm_bl_update_status(md->bl_dev);
634fail:
635 omapdss_sdi_display_disable(dssdev);
636 return r;
637}
638
639static void acx_panel_power_off(struct omap_dss_device *dssdev)
640{
641 struct acx565akm_device *md = &acx_dev;
642
643 dev_dbg(&dssdev->dev, "%s\n", __func__);
644
645 mutex_lock(&md->mutex);
646
647 if (!md->enabled) {
648 mutex_unlock(&md->mutex);
649 return;
650 }
651 set_display_state(md, 0);
652 set_sleep_mode(md, 1);
653 md->enabled = 0;
654 /*
655 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
656 * ~50msec) after sending the sleep in command and asserting the
657 * reset signal. We probably could assert the reset w/o the delay
658 * but we still delay to avoid possible artifacts. (7.6.1)
659 */
660 msleep(50);
661
662 if (dssdev->platform_disable)
663 dssdev->platform_disable(dssdev);
664
665 /* FIXME need to tweak this delay */
666 msleep(100);
667
668 omapdss_sdi_display_disable(dssdev);
669
670 mutex_unlock(&md->mutex);
671}
672
673static int acx_panel_enable(struct omap_dss_device *dssdev)
674{
675 int r;
676
677 dev_dbg(&dssdev->dev, "%s\n", __func__);
678 r = acx_panel_power_on(dssdev);
679
680 if (r)
681 return r;
682
683 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
684 return 0;
685}
686
687static void acx_panel_disable(struct omap_dss_device *dssdev)
688{
689 dev_dbg(&dssdev->dev, "%s\n", __func__);
690 acx_panel_power_off(dssdev);
691 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
692}
693
694static int acx_panel_suspend(struct omap_dss_device *dssdev)
695{
696 dev_dbg(&dssdev->dev, "%s\n", __func__);
697 acx_panel_power_off(dssdev);
698 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
699 return 0;
700}
701
702static int acx_panel_resume(struct omap_dss_device *dssdev)
703{
704 int r;
705
706 dev_dbg(&dssdev->dev, "%s\n", __func__);
707 r = acx_panel_power_on(dssdev);
708 if (r)
709 return r;
710
711 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
712 return 0;
713}
714
715static void acx_panel_set_timings(struct omap_dss_device *dssdev,
716 struct omap_video_timings *timings)
717{
718 int r;
719
720 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
721 omapdss_sdi_display_disable(dssdev);
722
723 dssdev->panel.timings = *timings;
724
725 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
726 r = omapdss_sdi_display_enable(dssdev);
727 if (r)
728 dev_err(&dssdev->dev, "%s enable failed\n", __func__);
729 }
730}
731
732static void acx_panel_get_timings(struct omap_dss_device *dssdev,
733 struct omap_video_timings *timings)
734{
735 *timings = dssdev->panel.timings;
736}
737
738static int acx_panel_check_timings(struct omap_dss_device *dssdev,
739 struct omap_video_timings *timings)
740{
741 return 0;
742}
743
744
745static struct omap_dss_driver acx_panel_driver = {
746 .probe = acx_panel_probe,
747 .remove = acx_panel_remove,
748
749 .enable = acx_panel_enable,
750 .disable = acx_panel_disable,
751 .suspend = acx_panel_suspend,
752 .resume = acx_panel_resume,
753
754 .set_timings = acx_panel_set_timings,
755 .get_timings = acx_panel_get_timings,
756 .check_timings = acx_panel_check_timings,
757
758 .get_recommended_bpp = acx_get_recommended_bpp,
759
760 .driver = {
761 .name = "panel-acx565akm",
762 .owner = THIS_MODULE,
763 },
764};
765
766/*--------------------SPI probe-------------------------*/
767
768static int acx565akm_spi_probe(struct spi_device *spi)
769{
770 struct acx565akm_device *md = &acx_dev;
771
772 dev_dbg(&spi->dev, "%s\n", __func__);
773
774 spi->mode = SPI_MODE_3;
775 md->spi = spi;
776 mutex_init(&md->mutex);
777 dev_set_drvdata(&spi->dev, md);
778
779 omap_dss_register_driver(&acx_panel_driver);
780
781 return 0;
782}
783
784static int acx565akm_spi_remove(struct spi_device *spi)
785{
786 struct acx565akm_device *md = dev_get_drvdata(&spi->dev);
787
788 dev_dbg(&md->spi->dev, "%s\n", __func__);
789 omap_dss_unregister_driver(&acx_panel_driver);
790
791 return 0;
792}
793
794static struct spi_driver acx565akm_spi_driver = {
795 .driver = {
796 .name = "acx565akm",
797 .bus = &spi_bus_type,
798 .owner = THIS_MODULE,
799 },
800 .probe = acx565akm_spi_probe,
801 .remove = __devexit_p(acx565akm_spi_remove),
802};
803
804static int __init acx565akm_init(void)
805{
806 return spi_register_driver(&acx565akm_spi_driver);
807}
808
809static void __exit acx565akm_exit(void)
810{
811 spi_unregister_driver(&acx565akm_spi_driver);
812}
813
814module_init(acx565akm_init);
815module_exit(acx565akm_exit);
816
817MODULE_AUTHOR("Nokia Corporation");
818MODULE_DESCRIPTION("acx565akm LCD Driver");
819MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 8d51a5e6341c..7d9eb2b1f5af 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -20,10 +20,17 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/device.h> 22#include <linux/device.h>
23#include <linux/backlight.h>
24#include <linux/fb.h>
23#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/slab.h>
24 27
25#include <plat/display.h> 28#include <plat/display.h>
26 29
30struct sharp_data {
31 struct backlight_device *bl;
32};
33
27static struct omap_video_timings sharp_ls_timings = { 34static struct omap_video_timings sharp_ls_timings = {
28 .x_res = 480, 35 .x_res = 480,
29 .y_res = 640, 36 .y_res = 640,
@@ -39,18 +46,89 @@ static struct omap_video_timings sharp_ls_timings = {
39 .vbp = 1, 46 .vbp = 1,
40}; 47};
41 48
49static int sharp_ls_bl_update_status(struct backlight_device *bl)
50{
51 struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
52 int level;
53
54 if (!dssdev->set_backlight)
55 return -EINVAL;
56
57 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
58 bl->props.power == FB_BLANK_UNBLANK)
59 level = bl->props.brightness;
60 else
61 level = 0;
62
63 return dssdev->set_backlight(dssdev, level);
64}
65
66static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
67{
68 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
69 bl->props.power == FB_BLANK_UNBLANK)
70 return bl->props.brightness;
71
72 return 0;
73}
74
75static const struct backlight_ops sharp_ls_bl_ops = {
76 .get_brightness = sharp_ls_bl_get_brightness,
77 .update_status = sharp_ls_bl_update_status,
78};
79
80
81
42static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) 82static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
43{ 83{
84 struct backlight_properties props;
85 struct backlight_device *bl;
86 struct sharp_data *sd;
87 int r;
88
44 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | 89 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
45 OMAP_DSS_LCD_IHS; 90 OMAP_DSS_LCD_IHS;
46 dssdev->panel.acb = 0x28; 91 dssdev->panel.acb = 0x28;
47 dssdev->panel.timings = sharp_ls_timings; 92 dssdev->panel.timings = sharp_ls_timings;
48 93
94 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
95 if (!sd)
96 return -ENOMEM;
97
98 dev_set_drvdata(&dssdev->dev, sd);
99
100 memset(&props, 0, sizeof(struct backlight_properties));
101 props.max_brightness = dssdev->max_backlight_level;
102
103 bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
104 &sharp_ls_bl_ops, &props);
105 if (IS_ERR(bl)) {
106 r = PTR_ERR(bl);
107 kfree(sd);
108 return r;
109 }
110 sd->bl = bl;
111
112 bl->props.fb_blank = FB_BLANK_UNBLANK;
113 bl->props.power = FB_BLANK_UNBLANK;
114 bl->props.brightness = dssdev->max_backlight_level;
115 r = sharp_ls_bl_update_status(bl);
116 if (r < 0)
117 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
118
49 return 0; 119 return 0;
50} 120}
51 121
52static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) 122static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
53{ 123{
124 struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
125 struct backlight_device *bl = sd->bl;
126
127 bl->props.power = FB_BLANK_POWERDOWN;
128 sharp_ls_bl_update_status(bl);
129 backlight_device_unregister(bl);
130
131 kfree(sd);
54} 132}
55 133
56static int sharp_ls_power_on(struct omap_dss_device *dssdev) 134static int sharp_ls_power_on(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4f3988a41082..aaf5d308a046 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -31,6 +31,7 @@
31#include <linux/completion.h> 31#include <linux/completion.h>
32#include <linux/workqueue.h> 32#include <linux/workqueue.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/mutex.h>
34 35
35#include <plat/display.h> 36#include <plat/display.h>
36 37
@@ -67,6 +68,8 @@
67static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
68 69
69struct taal_data { 70struct taal_data {
71 struct mutex lock;
72
70 struct backlight_device *bldev; 73 struct backlight_device *bldev;
71 74
72 unsigned long hw_guard_end; /* next value of jiffies when we can 75 unsigned long hw_guard_end; /* next value of jiffies when we can
@@ -510,6 +513,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
510 } 513 }
511 td->dssdev = dssdev; 514 td->dssdev = dssdev;
512 515
516 mutex_init(&td->lock);
517
513 td->esd_wq = create_singlethread_workqueue("taal_esd"); 518 td->esd_wq = create_singlethread_workqueue("taal_esd");
514 if (td->esd_wq == NULL) { 519 if (td->esd_wq == NULL) {
515 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 520 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
@@ -697,10 +702,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
697 702
698 return 0; 703 return 0;
699err: 704err:
700 dsi_bus_unlock();
701
702 omapdss_dsi_display_disable(dssdev); 705 omapdss_dsi_display_disable(dssdev);
703err0: 706err0:
707 dsi_bus_unlock();
704 if (dssdev->platform_disable) 708 if (dssdev->platform_disable)
705 dssdev->platform_disable(dssdev); 709 dssdev->platform_disable(dssdev);
706 710
@@ -733,54 +737,96 @@ static void taal_power_off(struct omap_dss_device *dssdev)
733 737
734static int taal_enable(struct omap_dss_device *dssdev) 738static int taal_enable(struct omap_dss_device *dssdev)
735{ 739{
740 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
736 int r; 741 int r;
742
737 dev_dbg(&dssdev->dev, "enable\n"); 743 dev_dbg(&dssdev->dev, "enable\n");
738 744
739 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) 745 mutex_lock(&td->lock);
740 return -EINVAL; 746
747 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
748 r = -EINVAL;
749 goto err;
750 }
741 751
742 r = taal_power_on(dssdev); 752 r = taal_power_on(dssdev);
743 if (r) 753 if (r)
744 return r; 754 goto err;
745 755
746 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 756 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
747 757
758 mutex_unlock(&td->lock);
759
760 return 0;
761err:
762 dev_dbg(&dssdev->dev, "enable failed\n");
763 mutex_unlock(&td->lock);
748 return r; 764 return r;
749} 765}
750 766
751static void taal_disable(struct omap_dss_device *dssdev) 767static void taal_disable(struct omap_dss_device *dssdev)
752{ 768{
769 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
770
753 dev_dbg(&dssdev->dev, "disable\n"); 771 dev_dbg(&dssdev->dev, "disable\n");
754 772
773 mutex_lock(&td->lock);
774
755 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 775 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
756 taal_power_off(dssdev); 776 taal_power_off(dssdev);
757 777
758 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 778 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
779
780 mutex_unlock(&td->lock);
759} 781}
760 782
761static int taal_suspend(struct omap_dss_device *dssdev) 783static int taal_suspend(struct omap_dss_device *dssdev)
762{ 784{
785 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
786 int r;
787
763 dev_dbg(&dssdev->dev, "suspend\n"); 788 dev_dbg(&dssdev->dev, "suspend\n");
764 789
765 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 790 mutex_lock(&td->lock);
766 return -EINVAL; 791
792 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
793 r = -EINVAL;
794 goto err;
795 }
767 796
768 taal_power_off(dssdev); 797 taal_power_off(dssdev);
769 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 798 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
770 799
800 mutex_unlock(&td->lock);
801
771 return 0; 802 return 0;
803err:
804 mutex_unlock(&td->lock);
805 return r;
772} 806}
773 807
774static int taal_resume(struct omap_dss_device *dssdev) 808static int taal_resume(struct omap_dss_device *dssdev)
775{ 809{
810 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
776 int r; 811 int r;
812
777 dev_dbg(&dssdev->dev, "resume\n"); 813 dev_dbg(&dssdev->dev, "resume\n");
778 814
779 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) 815 mutex_lock(&td->lock);
780 return -EINVAL; 816
817 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
818 r = -EINVAL;
819 goto err;
820 }
781 821
782 r = taal_power_on(dssdev); 822 r = taal_power_on(dssdev);
783 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 823 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
824
825 mutex_unlock(&td->lock);
826
827 return r;
828err:
829 mutex_unlock(&td->lock);
784 return r; 830 return r;
785} 831}
786 832
@@ -799,6 +845,7 @@ static int taal_update(struct omap_dss_device *dssdev,
799 845
800 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 846 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
801 847
848 mutex_lock(&td->lock);
802 dsi_bus_lock(); 849 dsi_bus_lock();
803 850
804 if (!td->enabled) { 851 if (!td->enabled) {
@@ -820,18 +867,24 @@ static int taal_update(struct omap_dss_device *dssdev,
820 goto err; 867 goto err;
821 868
822 /* note: no bus_unlock here. unlock is in framedone_cb */ 869 /* note: no bus_unlock here. unlock is in framedone_cb */
870 mutex_unlock(&td->lock);
823 return 0; 871 return 0;
824err: 872err:
825 dsi_bus_unlock(); 873 dsi_bus_unlock();
874 mutex_unlock(&td->lock);
826 return r; 875 return r;
827} 876}
828 877
829static int taal_sync(struct omap_dss_device *dssdev) 878static int taal_sync(struct omap_dss_device *dssdev)
830{ 879{
880 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
881
831 dev_dbg(&dssdev->dev, "sync\n"); 882 dev_dbg(&dssdev->dev, "sync\n");
832 883
884 mutex_lock(&td->lock);
833 dsi_bus_lock(); 885 dsi_bus_lock();
834 dsi_bus_unlock(); 886 dsi_bus_unlock();
887 mutex_unlock(&td->lock);
835 888
836 dev_dbg(&dssdev->dev, "sync done\n"); 889 dev_dbg(&dssdev->dev, "sync done\n");
837 890
@@ -861,13 +914,16 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
861 914
862static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) 915static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
863{ 916{
917 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
864 int r; 918 int r;
865 919
920 mutex_lock(&td->lock);
866 dsi_bus_lock(); 921 dsi_bus_lock();
867 922
868 r = _taal_enable_te(dssdev, enable); 923 r = _taal_enable_te(dssdev, enable);
869 924
870 dsi_bus_unlock(); 925 dsi_bus_unlock();
926 mutex_unlock(&td->lock);
871 927
872 return r; 928 return r;
873} 929}
@@ -875,7 +931,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
875static int taal_get_te(struct omap_dss_device *dssdev) 931static int taal_get_te(struct omap_dss_device *dssdev)
876{ 932{
877 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 933 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
878 return td->te_enabled; 934 int r;
935
936 mutex_lock(&td->lock);
937 r = td->te_enabled;
938 mutex_unlock(&td->lock);
939
940 return r;
879} 941}
880 942
881static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) 943static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
@@ -885,6 +947,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
885 947
886 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 948 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
887 949
950 mutex_lock(&td->lock);
888 dsi_bus_lock(); 951 dsi_bus_lock();
889 952
890 if (td->enabled) { 953 if (td->enabled) {
@@ -896,16 +959,24 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
896 td->rotate = rotate; 959 td->rotate = rotate;
897 960
898 dsi_bus_unlock(); 961 dsi_bus_unlock();
962 mutex_unlock(&td->lock);
899 return 0; 963 return 0;
900err: 964err:
901 dsi_bus_unlock(); 965 dsi_bus_unlock();
966 mutex_unlock(&td->lock);
902 return r; 967 return r;
903} 968}
904 969
905static u8 taal_get_rotate(struct omap_dss_device *dssdev) 970static u8 taal_get_rotate(struct omap_dss_device *dssdev)
906{ 971{
907 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 972 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
908 return td->rotate; 973 int r;
974
975 mutex_lock(&td->lock);
976 r = td->rotate;
977 mutex_unlock(&td->lock);
978
979 return r;
909} 980}
910 981
911static int taal_mirror(struct omap_dss_device *dssdev, bool enable) 982static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
@@ -915,6 +986,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
915 986
916 dev_dbg(&dssdev->dev, "mirror %d\n", enable); 987 dev_dbg(&dssdev->dev, "mirror %d\n", enable);
917 988
989 mutex_lock(&td->lock);
918 dsi_bus_lock(); 990 dsi_bus_lock();
919 if (td->enabled) { 991 if (td->enabled) {
920 r = taal_set_addr_mode(td->rotate, enable); 992 r = taal_set_addr_mode(td->rotate, enable);
@@ -925,23 +997,33 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
925 td->mirror = enable; 997 td->mirror = enable;
926 998
927 dsi_bus_unlock(); 999 dsi_bus_unlock();
1000 mutex_unlock(&td->lock);
928 return 0; 1001 return 0;
929err: 1002err:
930 dsi_bus_unlock(); 1003 dsi_bus_unlock();
1004 mutex_unlock(&td->lock);
931 return r; 1005 return r;
932} 1006}
933 1007
934static bool taal_get_mirror(struct omap_dss_device *dssdev) 1008static bool taal_get_mirror(struct omap_dss_device *dssdev)
935{ 1009{
936 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1010 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
937 return td->mirror; 1011 int r;
1012
1013 mutex_lock(&td->lock);
1014 r = td->mirror;
1015 mutex_unlock(&td->lock);
1016
1017 return r;
938} 1018}
939 1019
940static int taal_run_test(struct omap_dss_device *dssdev, int test_num) 1020static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
941{ 1021{
1022 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
942 u8 id1, id2, id3; 1023 u8 id1, id2, id3;
943 int r; 1024 int r;
944 1025
1026 mutex_lock(&td->lock);
945 dsi_bus_lock(); 1027 dsi_bus_lock();
946 1028
947 r = taal_dcs_read_1(DCS_GET_ID1, &id1); 1029 r = taal_dcs_read_1(DCS_GET_ID1, &id1);
@@ -955,9 +1037,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
955 goto err; 1037 goto err;
956 1038
957 dsi_bus_unlock(); 1039 dsi_bus_unlock();
1040 mutex_unlock(&td->lock);
958 return 0; 1041 return 0;
959err: 1042err:
960 dsi_bus_unlock(); 1043 dsi_bus_unlock();
1044 mutex_unlock(&td->lock);
961 return r; 1045 return r;
962} 1046}
963 1047
@@ -971,12 +1055,16 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
971 unsigned buf_used = 0; 1055 unsigned buf_used = 0;
972 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1056 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
973 1057
974 if (!td->enabled)
975 return -ENODEV;
976
977 if (size < w * h * 3) 1058 if (size < w * h * 3)
978 return -ENOMEM; 1059 return -ENOMEM;
979 1060
1061 mutex_lock(&td->lock);
1062
1063 if (!td->enabled) {
1064 r = -ENODEV;
1065 goto err1;
1066 }
1067
980 size = min(w * h * 3, 1068 size = min(w * h * 3,
981 dssdev->panel.timings.x_res * 1069 dssdev->panel.timings.x_res *
982 dssdev->panel.timings.y_res * 3); 1070 dssdev->panel.timings.y_res * 3);
@@ -995,7 +1083,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
995 1083
996 r = dsi_vc_set_max_rx_packet_size(TCH, plen); 1084 r = dsi_vc_set_max_rx_packet_size(TCH, plen);
997 if (r) 1085 if (r)
998 goto err0; 1086 goto err2;
999 1087
1000 while (buf_used < size) { 1088 while (buf_used < size) {
1001 u8 dcs_cmd = first ? 0x2e : 0x3e; 1089 u8 dcs_cmd = first ? 0x2e : 0x3e;
@@ -1006,7 +1094,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1006 1094
1007 if (r < 0) { 1095 if (r < 0) {
1008 dev_err(&dssdev->dev, "read error\n"); 1096 dev_err(&dssdev->dev, "read error\n");
1009 goto err; 1097 goto err3;
1010 } 1098 }
1011 1099
1012 buf_used += r; 1100 buf_used += r;
@@ -1020,16 +1108,18 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1020 dev_err(&dssdev->dev, "signal pending, " 1108 dev_err(&dssdev->dev, "signal pending, "
1021 "aborting memory read\n"); 1109 "aborting memory read\n");
1022 r = -ERESTARTSYS; 1110 r = -ERESTARTSYS;
1023 goto err; 1111 goto err3;
1024 } 1112 }
1025 } 1113 }
1026 1114
1027 r = buf_used; 1115 r = buf_used;
1028 1116
1029err: 1117err3:
1030 dsi_vc_set_max_rx_packet_size(TCH, 1); 1118 dsi_vc_set_max_rx_packet_size(TCH, 1);
1031err0: 1119err2:
1032 dsi_bus_unlock(); 1120 dsi_bus_unlock();
1121err1:
1122 mutex_unlock(&td->lock);
1033 return r; 1123 return r;
1034} 1124}
1035 1125
@@ -1041,8 +1131,12 @@ static void taal_esd_work(struct work_struct *work)
1041 u8 state1, state2; 1131 u8 state1, state2;
1042 int r; 1132 int r;
1043 1133
1044 if (!td->enabled) 1134 mutex_lock(&td->lock);
1135
1136 if (!td->enabled) {
1137 mutex_unlock(&td->lock);
1045 return; 1138 return;
1139 }
1046 1140
1047 dsi_bus_lock(); 1141 dsi_bus_lock();
1048 1142
@@ -1084,16 +1178,19 @@ static void taal_esd_work(struct work_struct *work)
1084 1178
1085 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); 1179 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1086 1180
1181 mutex_unlock(&td->lock);
1087 return; 1182 return;
1088err: 1183err:
1089 dev_err(&dssdev->dev, "performing LCD reset\n"); 1184 dev_err(&dssdev->dev, "performing LCD reset\n");
1090 1185
1091 taal_disable(dssdev); 1186 taal_power_off(dssdev);
1092 taal_enable(dssdev); 1187 taal_power_on(dssdev);
1093 1188
1094 dsi_bus_unlock(); 1189 dsi_bus_unlock();
1095 1190
1096 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); 1191 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1192
1193 mutex_unlock(&td->lock);
1097} 1194}
1098 1195
1099static int taal_set_update_mode(struct omap_dss_device *dssdev, 1196static int taal_set_update_mode(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 87afb81b2c44..43b64403eaa4 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -36,6 +36,12 @@ config OMAP2_DSS_COLLECT_IRQ_STATS
36 <debugfs>/omapdss/dispc_irq for DISPC interrupts, and 36 <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
37 <debugfs>/omapdss/dsi_irq for DSI interrupts. 37 <debugfs>/omapdss/dsi_irq for DSI interrupts.
38 38
39config OMAP2_DSS_DPI
40 bool "DPI support"
41 default y
42 help
43 DPI Interface. This is the Parallel Display Interface.
44
39config OMAP2_DSS_RFBI 45config OMAP2_DSS_RFBI
40 bool "RFBI support" 46 bool "RFBI support"
41 default n 47 default n
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 980c72c2db98..d71b5d9d71b1 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o 2omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o
3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
3omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
4omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
5omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 7ebe50b335ed..b3a498f22d36 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -482,6 +482,14 @@ static void dss_uninitialize_debugfs(void)
482 if (dss_debugfs_dir) 482 if (dss_debugfs_dir)
483 debugfs_remove_recursive(dss_debugfs_dir); 483 debugfs_remove_recursive(dss_debugfs_dir);
484} 484}
485#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
486static inline int dss_initialize_debugfs(void)
487{
488 return 0;
489}
490static inline void dss_uninitialize_debugfs(void)
491{
492}
485#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 493#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
486 494
487/* PLATFORM DEVICE */ 495/* PLATFORM DEVICE */
@@ -499,7 +507,7 @@ static int omap_dss_probe(struct platform_device *pdev)
499 507
500 r = dss_get_clocks(); 508 r = dss_get_clocks();
501 if (r) 509 if (r)
502 goto fail0; 510 goto err_clocks;
503 511
504 dss_clk_enable_all_no_ctx(); 512 dss_clk_enable_all_no_ctx();
505 513
@@ -515,64 +523,64 @@ static int omap_dss_probe(struct platform_device *pdev)
515 r = dss_init(skip_init); 523 r = dss_init(skip_init);
516 if (r) { 524 if (r) {
517 DSSERR("Failed to initialize DSS\n"); 525 DSSERR("Failed to initialize DSS\n");
518 goto fail0; 526 goto err_dss;
519 } 527 }
520 528
521#ifdef CONFIG_OMAP2_DSS_RFBI
522 r = rfbi_init(); 529 r = rfbi_init();
523 if (r) { 530 if (r) {
524 DSSERR("Failed to initialize rfbi\n"); 531 DSSERR("Failed to initialize rfbi\n");
525 goto fail0; 532 goto err_rfbi;
526 } 533 }
527#endif
528 534
529 r = dpi_init(pdev); 535 r = dpi_init(pdev);
530 if (r) { 536 if (r) {
531 DSSERR("Failed to initialize dpi\n"); 537 DSSERR("Failed to initialize dpi\n");
532 goto fail0; 538 goto err_dpi;
533 } 539 }
534 540
535 r = dispc_init(); 541 r = dispc_init();
536 if (r) { 542 if (r) {
537 DSSERR("Failed to initialize dispc\n"); 543 DSSERR("Failed to initialize dispc\n");
538 goto fail0; 544 goto err_dispc;
539 } 545 }
540#ifdef CONFIG_OMAP2_DSS_VENC 546
541 r = venc_init(pdev); 547 r = venc_init(pdev);
542 if (r) { 548 if (r) {
543 DSSERR("Failed to initialize venc\n"); 549 DSSERR("Failed to initialize venc\n");
544 goto fail0; 550 goto err_venc;
545 } 551 }
546#endif 552
547 if (cpu_is_omap34xx()) { 553 if (cpu_is_omap34xx()) {
548#ifdef CONFIG_OMAP2_DSS_SDI
549 r = sdi_init(skip_init); 554 r = sdi_init(skip_init);
550 if (r) { 555 if (r) {
551 DSSERR("Failed to initialize SDI\n"); 556 DSSERR("Failed to initialize SDI\n");
552 goto fail0; 557 goto err_sdi;
553 } 558 }
554#endif 559
555#ifdef CONFIG_OMAP2_DSS_DSI
556 r = dsi_init(pdev); 560 r = dsi_init(pdev);
557 if (r) { 561 if (r) {
558 DSSERR("Failed to initialize DSI\n"); 562 DSSERR("Failed to initialize DSI\n");
559 goto fail0; 563 goto err_dsi;
560 } 564 }
561#endif
562 } 565 }
563 566
564#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
565 r = dss_initialize_debugfs(); 567 r = dss_initialize_debugfs();
566 if (r) 568 if (r)
567 goto fail0; 569 goto err_debugfs;
568#endif
569 570
570 for (i = 0; i < pdata->num_devices; ++i) { 571 for (i = 0; i < pdata->num_devices; ++i) {
571 struct omap_dss_device *dssdev = pdata->devices[i]; 572 struct omap_dss_device *dssdev = pdata->devices[i];
572 573
573 r = omap_dss_register_device(dssdev); 574 r = omap_dss_register_device(dssdev);
574 if (r) 575 if (r) {
575 DSSERR("device reg failed %d\n", i); 576 DSSERR("device %d %s register failed %d\n", i,
577 dssdev->name ?: "unnamed", r);
578
579 while (--i >= 0)
580 omap_dss_unregister_device(pdata->devices[i]);
581
582 goto err_register;
583 }
576 584
577 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) 585 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
578 pdata->default_device = dssdev; 586 pdata->default_device = dssdev;
@@ -582,8 +590,29 @@ static int omap_dss_probe(struct platform_device *pdev)
582 590
583 return 0; 591 return 0;
584 592
585 /* XXX fail correctly */ 593err_register:
586fail0: 594 dss_uninitialize_debugfs();
595err_debugfs:
596 if (cpu_is_omap34xx())
597 dsi_exit();
598err_dsi:
599 if (cpu_is_omap34xx())
600 sdi_exit();
601err_sdi:
602 venc_exit();
603err_venc:
604 dispc_exit();
605err_dispc:
606 dpi_exit();
607err_dpi:
608 rfbi_exit();
609err_rfbi:
610 dss_exit();
611err_dss:
612 dss_clk_disable_all_no_ctx();
613 dss_put_clocks();
614err_clocks:
615
587 return r; 616 return r;
588} 617}
589 618
@@ -593,25 +622,15 @@ static int omap_dss_remove(struct platform_device *pdev)
593 int i; 622 int i;
594 int c; 623 int c;
595 624
596#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
597 dss_uninitialize_debugfs(); 625 dss_uninitialize_debugfs();
598#endif
599 626
600#ifdef CONFIG_OMAP2_DSS_VENC
601 venc_exit(); 627 venc_exit();
602#endif
603 dispc_exit(); 628 dispc_exit();
604 dpi_exit(); 629 dpi_exit();
605#ifdef CONFIG_OMAP2_DSS_RFBI
606 rfbi_exit(); 630 rfbi_exit();
607#endif
608 if (cpu_is_omap34xx()) { 631 if (cpu_is_omap34xx()) {
609#ifdef CONFIG_OMAP2_DSS_DSI
610 dsi_exit(); 632 dsi_exit();
611#endif
612#ifdef CONFIG_OMAP2_DSS_SDI
613 sdi_exit(); 633 sdi_exit();
614#endif
615 } 634 }
616 635
617 dss_exit(); 636 dss_exit();
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 6a74ea116d29..ef8c8529dda2 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -392,7 +392,9 @@ void dss_init_device(struct platform_device *pdev,
392 int r; 392 int r;
393 393
394 switch (dssdev->type) { 394 switch (dssdev->type) {
395#ifdef CONFIG_OMAP2_DSS_DPI
395 case OMAP_DISPLAY_TYPE_DPI: 396 case OMAP_DISPLAY_TYPE_DPI:
397#endif
396#ifdef CONFIG_OMAP2_DSS_RFBI 398#ifdef CONFIG_OMAP2_DSS_RFBI
397 case OMAP_DISPLAY_TYPE_DBI: 399 case OMAP_DISPLAY_TYPE_DBI:
398#endif 400#endif
@@ -413,9 +415,11 @@ void dss_init_device(struct platform_device *pdev,
413 } 415 }
414 416
415 switch (dssdev->type) { 417 switch (dssdev->type) {
418#ifdef CONFIG_OMAP2_DSS_DPI
416 case OMAP_DISPLAY_TYPE_DPI: 419 case OMAP_DISPLAY_TYPE_DPI:
417 r = dpi_init_display(dssdev); 420 r = dpi_init_display(dssdev);
418 break; 421 break;
422#endif
419#ifdef CONFIG_OMAP2_DSS_RFBI 423#ifdef CONFIG_OMAP2_DSS_RFBI
420 case OMAP_DISPLAY_TYPE_DBI: 424 case OMAP_DISPLAY_TYPE_DBI:
421 r = rfbi_init_display(dssdev); 425 r = rfbi_init_display(dssdev);
@@ -541,7 +545,10 @@ int dss_resume_all_devices(void)
541static int dss_disable_device(struct device *dev, void *data) 545static int dss_disable_device(struct device *dev, void *data)
542{ 546{
543 struct omap_dss_device *dssdev = to_dss_device(dev); 547 struct omap_dss_device *dssdev = to_dss_device(dev);
544 dssdev->driver->disable(dssdev); 548
549 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
550 dssdev->driver->disable(dssdev);
551
545 return 0; 552 return 0;
546} 553}
547 554
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 54344184dd73..24b18258654f 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -223,7 +223,13 @@ void dss_dump_clocks(struct seq_file *s)
223 223
224 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 224 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
225 225
226 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", 226 if (cpu_is_omap3630())
227 seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n",
228 dpll4_ck_rate,
229 dpll4_ck_rate / dpll4_m4_ck_rate,
230 dss_clk_get_rate(DSS_CLK_FCK1));
231 else
232 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
227 dpll4_ck_rate, 233 dpll4_ck_rate,
228 dpll4_ck_rate / dpll4_m4_ck_rate, 234 dpll4_ck_rate / dpll4_m4_ck_rate,
229 dss_clk_get_rate(DSS_CLK_FCK1)); 235 dss_clk_get_rate(DSS_CLK_FCK1));
@@ -293,7 +299,8 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
293{ 299{
294 unsigned long prate; 300 unsigned long prate;
295 301
296 if (cinfo->fck_div > 16 || cinfo->fck_div == 0) 302 if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) ||
303 cinfo->fck_div == 0)
297 return -EINVAL; 304 return -EINVAL;
298 305
299 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 306 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -329,7 +336,10 @@ int dss_get_clock_div(struct dss_clock_info *cinfo)
329 if (cpu_is_omap34xx()) { 336 if (cpu_is_omap34xx()) {
330 unsigned long prate; 337 unsigned long prate;
331 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 338 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
332 cinfo->fck_div = prate / (cinfo->fck / 2); 339 if (cpu_is_omap3630())
340 cinfo->fck_div = prate / (cinfo->fck);
341 else
342 cinfo->fck_div = prate / (cinfo->fck / 2);
333 } else { 343 } else {
334 cinfo->fck_div = 0; 344 cinfo->fck_div = 0;
335 } 345 }
@@ -402,10 +412,14 @@ retry:
402 412
403 goto found; 413 goto found;
404 } else if (cpu_is_omap34xx()) { 414 } else if (cpu_is_omap34xx()) {
405 for (fck_div = 16; fck_div > 0; --fck_div) { 415 for (fck_div = (cpu_is_omap3630() ? 32 : 16);
416 fck_div > 0; --fck_div) {
406 struct dispc_clock_info cur_dispc; 417 struct dispc_clock_info cur_dispc;
407 418
408 fck = prate / fck_div * 2; 419 if (cpu_is_omap3630())
420 fck = prate / fck_div;
421 else
422 fck = prate / fck_div * 2;
409 423
410 if (fck > DISPC_MAX_FCK) 424 if (fck > DISPC_MAX_FCK)
411 continue; 425 continue;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 24326a5fd292..786f433fd571 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -242,11 +242,22 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
242 struct dispc_clock_info *dispc_cinfo); 242 struct dispc_clock_info *dispc_cinfo);
243 243
244/* SDI */ 244/* SDI */
245#ifdef CONFIG_OMAP2_DSS_SDI
245int sdi_init(bool skip_init); 246int sdi_init(bool skip_init);
246void sdi_exit(void); 247void sdi_exit(void);
247int sdi_init_display(struct omap_dss_device *display); 248int sdi_init_display(struct omap_dss_device *display);
249#else
250static inline int sdi_init(bool skip_init)
251{
252 return 0;
253}
254static inline void sdi_exit(void)
255{
256}
257#endif
248 258
249/* DSI */ 259/* DSI */
260#ifdef CONFIG_OMAP2_DSS_DSI
250int dsi_init(struct platform_device *pdev); 261int dsi_init(struct platform_device *pdev);
251void dsi_exit(void); 262void dsi_exit(void);
252 263
@@ -270,11 +281,30 @@ void dsi_pll_uninit(void);
270void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, 281void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
271 u32 fifo_size, enum omap_burst_size *burst_size, 282 u32 fifo_size, enum omap_burst_size *burst_size,
272 u32 *fifo_low, u32 *fifo_high); 283 u32 *fifo_low, u32 *fifo_high);
284#else
285static inline int dsi_init(struct platform_device *pdev)
286{
287 return 0;
288}
289static inline void dsi_exit(void)
290{
291}
292#endif
273 293
274/* DPI */ 294/* DPI */
295#ifdef CONFIG_OMAP2_DSS_DPI
275int dpi_init(struct platform_device *pdev); 296int dpi_init(struct platform_device *pdev);
276void dpi_exit(void); 297void dpi_exit(void);
277int dpi_init_display(struct omap_dss_device *dssdev); 298int dpi_init_display(struct omap_dss_device *dssdev);
299#else
300static inline int dpi_init(struct platform_device *pdev)
301{
302 return 0;
303}
304static inline void dpi_exit(void)
305{
306}
307#endif
278 308
279/* DISPC */ 309/* DISPC */
280int dispc_init(void); 310int dispc_init(void);
@@ -362,12 +392,23 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo);
362 392
363 393
364/* VENC */ 394/* VENC */
395#ifdef CONFIG_OMAP2_DSS_VENC
365int venc_init(struct platform_device *pdev); 396int venc_init(struct platform_device *pdev);
366void venc_exit(void); 397void venc_exit(void);
367void venc_dump_regs(struct seq_file *s); 398void venc_dump_regs(struct seq_file *s);
368int venc_init_display(struct omap_dss_device *display); 399int venc_init_display(struct omap_dss_device *display);
400#else
401static inline int venc_init(struct platform_device *pdev)
402{
403 return 0;
404}
405static inline void venc_exit(void)
406{
407}
408#endif
369 409
370/* RFBI */ 410/* RFBI */
411#ifdef CONFIG_OMAP2_DSS_RFBI
371int rfbi_init(void); 412int rfbi_init(void);
372void rfbi_exit(void); 413void rfbi_exit(void);
373void rfbi_dump_regs(struct seq_file *s); 414void rfbi_dump_regs(struct seq_file *s);
@@ -379,6 +420,15 @@ void rfbi_transfer_area(u16 width, u16 height,
379void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); 420void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
380unsigned long rfbi_get_max_tx_rate(void); 421unsigned long rfbi_get_max_tx_rate(void);
381int rfbi_init_display(struct omap_dss_device *display); 422int rfbi_init_display(struct omap_dss_device *display);
423#else
424static inline int rfbi_init(void)
425{
426 return 0;
427}
428static inline void rfbi_exit(void)
429{
430}
431#endif
382 432
383 433
384#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 434#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 0820986d4a68..9e1fbe531bf0 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -843,6 +843,7 @@ static void configure_manager(enum omap_channel channel)
843 843
844 c = &dss_cache.manager_cache[channel]; 844 c = &dss_cache.manager_cache[channel];
845 845
846 dispc_set_default_color(channel, c->default_color);
846 dispc_set_trans_key(channel, c->trans_key_type, c->trans_key); 847 dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
847 dispc_enable_trans_key(channel, c->trans_enabled); 848 dispc_enable_trans_key(channel, c->trans_enabled);
848 dispc_enable_alpha_blending(channel, c->alpha_enabled); 849 dispc_enable_alpha_blending(channel, c->alpha_enabled);
@@ -940,6 +941,22 @@ static int configure_dispc(void)
940 return r; 941 return r;
941} 942}
942 943
944/* Make the coordinates even. There are some strange problems with OMAP and
945 * partial DSI update when the update widths are odd. */
946static void make_even(u16 *x, u16 *w)
947{
948 u16 x1, x2;
949
950 x1 = *x;
951 x2 = *x + *w;
952
953 x1 &= ~1;
954 x2 = ALIGN(x2, 2);
955
956 *x = x1;
957 *w = x2 - x1;
958}
959
943/* Configure dispc for partial update. Return possibly modified update 960/* Configure dispc for partial update. Return possibly modified update
944 * area */ 961 * area */
945void dss_setup_partial_planes(struct omap_dss_device *dssdev, 962void dss_setup_partial_planes(struct omap_dss_device *dssdev,
@@ -968,6 +985,8 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
968 return; 985 return;
969 } 986 }
970 987
988 make_even(&x, &w);
989
971 spin_lock_irqsave(&dss_cache.lock, flags); 990 spin_lock_irqsave(&dss_cache.lock, flags);
972 991
973 /* We need to show the whole overlay if it is scaled. So look for 992 /* We need to show the whole overlay if it is scaled. So look for
@@ -1029,6 +1048,8 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
1029 w = x2 - x1; 1048 w = x2 - x1;
1030 h = y2 - y1; 1049 h = y2 - y1;
1031 1050
1051 make_even(&x, &w);
1052
1032 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", 1053 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
1033 i, x, y, w, h); 1054 i, x, y, w, h);
1034 } 1055 }
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 12eb4042dd82..ee07a3cc22ef 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -23,13 +23,16 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/regulator/consumer.h>
26 27
27#include <plat/display.h> 28#include <plat/display.h>
29#include <plat/cpu.h>
28#include "dss.h" 30#include "dss.h"
29 31
30static struct { 32static struct {
31 bool skip_init; 33 bool skip_init;
32 bool update_enabled; 34 bool update_enabled;
35 struct regulator *vdds_sdi_reg;
33} sdi; 36} sdi;
34 37
35static void sdi_basic_init(void) 38static void sdi_basic_init(void)
@@ -57,6 +60,10 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
57 goto err0; 60 goto err0;
58 } 61 }
59 62
63 r = regulator_enable(sdi.vdds_sdi_reg);
64 if (r)
65 goto err1;
66
60 /* In case of skip_init sdi_init has already enabled the clocks */ 67 /* In case of skip_init sdi_init has already enabled the clocks */
61 if (!sdi.skip_init) 68 if (!sdi.skip_init)
62 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 69 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
@@ -115,19 +122,12 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
115 122
116 dssdev->manager->enable(dssdev->manager); 123 dssdev->manager->enable(dssdev->manager);
117 124
118 if (dssdev->driver->enable) {
119 r = dssdev->driver->enable(dssdev);
120 if (r)
121 goto err3;
122 }
123
124 sdi.skip_init = 0; 125 sdi.skip_init = 0;
125 126
126 return 0; 127 return 0;
127err3:
128 dssdev->manager->disable(dssdev->manager);
129err2: 128err2:
130 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 129 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
130 regulator_disable(sdi.vdds_sdi_reg);
131err1: 131err1:
132 omap_dss_stop_device(dssdev); 132 omap_dss_stop_device(dssdev);
133err0: 133err0:
@@ -137,15 +137,14 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
137 137
138void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 138void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
139{ 139{
140 if (dssdev->driver->disable)
141 dssdev->driver->disable(dssdev);
142
143 dssdev->manager->disable(dssdev->manager); 140 dssdev->manager->disable(dssdev->manager);
144 141
145 dss_sdi_disable(); 142 dss_sdi_disable();
146 143
147 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 144 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
148 145
146 regulator_disable(sdi.vdds_sdi_reg);
147
149 omap_dss_stop_device(dssdev); 148 omap_dss_stop_device(dssdev);
150} 149}
151EXPORT_SYMBOL(omapdss_sdi_display_disable); 150EXPORT_SYMBOL(omapdss_sdi_display_disable);
@@ -162,6 +161,11 @@ int sdi_init(bool skip_init)
162 /* we store this for first display enable, then clear it */ 161 /* we store this for first display enable, then clear it */
163 sdi.skip_init = skip_init; 162 sdi.skip_init = skip_init;
164 163
164 sdi.vdds_sdi_reg = dss_get_vdds_sdi();
165 if (IS_ERR(sdi.vdds_sdi_reg)) {
166 DSSERR("can't get VDDS_SDI regulator\n");
167 return PTR_ERR(sdi.vdds_sdi_reg);
168 }
165 /* 169 /*
166 * Enable clocks already here, otherwise there would be a toggle 170 * Enable clocks already here, otherwise there would be a toggle
167 * of them until sdi_display_enable is called. 171 * of them until sdi_display_enable is called.
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index f0ba5732d84a..eff35050e28a 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -479,12 +479,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
479 goto err1; 479 goto err1;
480 } 480 }
481 481
482 if (dssdev->platform_enable) {
483 r = dssdev->platform_enable(dssdev);
484 if (r)
485 goto err2;
486 }
487
488 venc_power_on(dssdev); 482 venc_power_on(dssdev);
489 483
490 venc.wss_data = 0; 484 venc.wss_data = 0;
@@ -494,13 +488,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
494 /* wait couple of vsyncs until enabling the LCD */ 488 /* wait couple of vsyncs until enabling the LCD */
495 msleep(50); 489 msleep(50);
496 490
497 mutex_unlock(&venc.venc_lock);
498
499 return r;
500err2:
501 venc_power_off(dssdev);
502err1: 491err1:
503 mutex_unlock(&venc.venc_lock); 492 mutex_unlock(&venc.venc_lock);
493
504 return r; 494 return r;
505} 495}
506 496
@@ -524,9 +514,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
524 /* wait at least 5 vsyncs after disabling the LCD */ 514 /* wait at least 5 vsyncs after disabling the LCD */
525 msleep(100); 515 msleep(100);
526 516
527 if (dssdev->platform_disable)
528 dssdev->platform_disable(dssdev);
529
530 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 517 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
531end: 518end:
532 mutex_unlock(&venc.venc_lock); 519 mutex_unlock(&venc.venc_lock);
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 1ffa760b8545..9c7361871d78 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -183,13 +183,14 @@ int omapfb_update_window(struct fb_info *fbi,
183 struct omapfb2_device *fbdev = ofbi->fbdev; 183 struct omapfb2_device *fbdev = ofbi->fbdev;
184 int r; 184 int r;
185 185
186 if (!lock_fb_info(fbi))
187 return -ENODEV;
186 omapfb_lock(fbdev); 188 omapfb_lock(fbdev);
187 lock_fb_info(fbi);
188 189
189 r = omapfb_update_window_nolock(fbi, x, y, w, h); 190 r = omapfb_update_window_nolock(fbi, x, y, w, h);
190 191
191 unlock_fb_info(fbi);
192 omapfb_unlock(fbdev); 192 omapfb_unlock(fbdev);
193 unlock_fb_info(fbi);
193 194
194 return r; 195 return r;
195} 196}
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 62bb88f5c192..5179219128bd 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -57,7 +57,8 @@ static ssize_t store_rotate_type(struct device *dev,
57 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) 57 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
58 return -EINVAL; 58 return -EINVAL;
59 59
60 lock_fb_info(fbi); 60 if (!lock_fb_info(fbi))
61 return -ENODEV;
61 62
62 r = 0; 63 r = 0;
63 if (rot_type == ofbi->rotation_type) 64 if (rot_type == ofbi->rotation_type)
@@ -105,7 +106,8 @@ static ssize_t store_mirror(struct device *dev,
105 if (mirror != 0 && mirror != 1) 106 if (mirror != 0 && mirror != 1)
106 return -EINVAL; 107 return -EINVAL;
107 108
108 lock_fb_info(fbi); 109 if (!lock_fb_info(fbi))
110 return -ENODEV;
109 111
110 ofbi->mirror = mirror; 112 ofbi->mirror = mirror;
111 113
@@ -137,8 +139,9 @@ static ssize_t show_overlays(struct device *dev,
137 ssize_t l = 0; 139 ssize_t l = 0;
138 int t; 140 int t;
139 141
142 if (!lock_fb_info(fbi))
143 return -ENODEV;
140 omapfb_lock(fbdev); 144 omapfb_lock(fbdev);
141 lock_fb_info(fbi);
142 145
143 for (t = 0; t < ofbi->num_overlays; t++) { 146 for (t = 0; t < ofbi->num_overlays; t++) {
144 struct omap_overlay *ovl = ofbi->overlays[t]; 147 struct omap_overlay *ovl = ofbi->overlays[t];
@@ -154,8 +157,8 @@ static ssize_t show_overlays(struct device *dev,
154 157
155 l += snprintf(buf + l, PAGE_SIZE - l, "\n"); 158 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
156 159
157 unlock_fb_info(fbi);
158 omapfb_unlock(fbdev); 160 omapfb_unlock(fbdev);
161 unlock_fb_info(fbi);
159 162
160 return l; 163 return l;
161} 164}
@@ -195,8 +198,9 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
195 if (buf[len - 1] == '\n') 198 if (buf[len - 1] == '\n')
196 len = len - 1; 199 len = len - 1;
197 200
201 if (!lock_fb_info(fbi))
202 return -ENODEV;
198 omapfb_lock(fbdev); 203 omapfb_lock(fbdev);
199 lock_fb_info(fbi);
200 204
201 if (len > 0) { 205 if (len > 0) {
202 char *p = (char *)buf; 206 char *p = (char *)buf;
@@ -303,8 +307,8 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
303 307
304 r = count; 308 r = count;
305out: 309out:
306 unlock_fb_info(fbi);
307 omapfb_unlock(fbdev); 310 omapfb_unlock(fbdev);
311 unlock_fb_info(fbi);
308 312
309 return r; 313 return r;
310} 314}
@@ -317,7 +321,8 @@ static ssize_t show_overlays_rotate(struct device *dev,
317 ssize_t l = 0; 321 ssize_t l = 0;
318 int t; 322 int t;
319 323
320 lock_fb_info(fbi); 324 if (!lock_fb_info(fbi))
325 return -ENODEV;
321 326
322 for (t = 0; t < ofbi->num_overlays; t++) { 327 for (t = 0; t < ofbi->num_overlays; t++) {
323 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", 328 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
@@ -345,7 +350,8 @@ static ssize_t store_overlays_rotate(struct device *dev,
345 if (buf[len - 1] == '\n') 350 if (buf[len - 1] == '\n')
346 len = len - 1; 351 len = len - 1;
347 352
348 lock_fb_info(fbi); 353 if (!lock_fb_info(fbi))
354 return -ENODEV;
349 355
350 if (len > 0) { 356 if (len > 0) {
351 char *p = (char *)buf; 357 char *p = (char *)buf;
@@ -416,7 +422,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
416 422
417 size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); 423 size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
418 424
419 lock_fb_info(fbi); 425 if (!lock_fb_info(fbi))
426 return -ENODEV;
420 427
421 for (i = 0; i < ofbi->num_overlays; i++) { 428 for (i = 0; i < ofbi->num_overlays; i++) {
422 if (ofbi->overlays[i]->info.enabled) { 429 if (ofbi->overlays[i]->info.enabled) {