]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/video/omap2/displays/panel-taal.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / video / omap2 / displays / panel-taal.c
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/completion.h>
32 #include <linux/workqueue.h>
33 #include <linux/slab.h>
34
35 #include <plat/display.h>
36
37 /* DSI Virtual channel. Hardcoded for now. */
38 #define TCH 0
39
40 #define DCS_READ_NUM_ERRORS     0x05
41 #define DCS_READ_POWER_MODE     0x0a
42 #define DCS_READ_MADCTL         0x0b
43 #define DCS_READ_PIXEL_FORMAT   0x0c
44 #define DCS_RDDSDR              0x0f
45 #define DCS_SLEEP_IN            0x10
46 #define DCS_SLEEP_OUT           0x11
47 #define DCS_DISPLAY_OFF         0x28
48 #define DCS_DISPLAY_ON          0x29
49 #define DCS_COLUMN_ADDR         0x2a
50 #define DCS_PAGE_ADDR           0x2b
51 #define DCS_MEMORY_WRITE        0x2c
52 #define DCS_TEAR_OFF            0x34
53 #define DCS_TEAR_ON             0x35
54 #define DCS_MEM_ACC_CTRL        0x36
55 #define DCS_PIXEL_FORMAT        0x3a
56 #define DCS_BRIGHTNESS          0x51
57 #define DCS_CTRL_DISPLAY        0x53
58 #define DCS_WRITE_CABC          0x55
59 #define DCS_READ_CABC           0x56
60 #define DCS_GET_ID1             0xda
61 #define DCS_GET_ID2             0xdb
62 #define DCS_GET_ID3             0xdc
63
64 /* #define TAAL_USE_ESD_CHECK */
65 #define TAAL_ESD_CHECK_PERIOD   msecs_to_jiffies(5000)
66
67 static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
68
69 struct taal_data {
70         struct backlight_device *bldev;
71
72         unsigned long   hw_guard_end;   /* next value of jiffies when we can
73                                          * issue the next sleep in/out command
74                                          */
75         unsigned long   hw_guard_wait;  /* max guard time in jiffies */
76
77         struct omap_dss_device *dssdev;
78
79         bool enabled;
80         u8 rotate;
81         bool mirror;
82
83         bool te_enabled;
84         bool use_ext_te;
85         struct completion te_completion;
86
87         bool use_dsi_bl;
88
89         bool cabc_broken;
90         unsigned cabc_mode;
91
92         bool intro_printed;
93
94         struct workqueue_struct *esd_wq;
95         struct delayed_work esd_work;
96 };
97
98 static void taal_esd_work(struct work_struct *work);
99
100 static void hw_guard_start(struct taal_data *td, int guard_msec)
101 {
102         td->hw_guard_wait = msecs_to_jiffies(guard_msec);
103         td->hw_guard_end = jiffies + td->hw_guard_wait;
104 }
105
106 static void hw_guard_wait(struct taal_data *td)
107 {
108         unsigned long wait = td->hw_guard_end - jiffies;
109
110         if ((long)wait > 0 && wait <= td->hw_guard_wait) {
111                 set_current_state(TASK_UNINTERRUPTIBLE);
112                 schedule_timeout(wait);
113         }
114 }
115
116 static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
117 {
118         int r;
119         u8 buf[1];
120
121         r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
122
123         if (r < 0)
124                 return r;
125
126         *data = buf[0];
127
128         return 0;
129 }
130
131 static int taal_dcs_write_0(u8 dcs_cmd)
132 {
133         return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
134 }
135
136 static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
137 {
138         u8 buf[2];
139         buf[0] = dcs_cmd;
140         buf[1] = param;
141         return dsi_vc_dcs_write(TCH, buf, 2);
142 }
143
144 static int taal_sleep_in(struct taal_data *td)
145
146 {
147         u8 cmd;
148         int r;
149
150         hw_guard_wait(td);
151
152         cmd = DCS_SLEEP_IN;
153         r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
154         if (r)
155                 return r;
156
157         hw_guard_start(td, 120);
158
159         msleep(5);
160
161         return 0;
162 }
163
164 static int taal_sleep_out(struct taal_data *td)
165 {
166         int r;
167
168         hw_guard_wait(td);
169
170         r = taal_dcs_write_0(DCS_SLEEP_OUT);
171         if (r)
172                 return r;
173
174         hw_guard_start(td, 120);
175
176         msleep(5);
177
178         return 0;
179 }
180
181 static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
182 {
183         int r;
184
185         r = taal_dcs_read_1(DCS_GET_ID1, id1);
186         if (r)
187                 return r;
188         r = taal_dcs_read_1(DCS_GET_ID2, id2);
189         if (r)
190                 return r;
191         r = taal_dcs_read_1(DCS_GET_ID3, id3);
192         if (r)
193                 return r;
194
195         return 0;
196 }
197
198 static int taal_set_addr_mode(u8 rotate, bool mirror)
199 {
200         int r;
201         u8 mode;
202         int b5, b6, b7;
203
204         r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
205         if (r)
206                 return r;
207
208         switch (rotate) {
209         default:
210         case 0:
211                 b7 = 0;
212                 b6 = 0;
213                 b5 = 0;
214                 break;
215         case 1:
216                 b7 = 0;
217                 b6 = 1;
218                 b5 = 1;
219                 break;
220         case 2:
221                 b7 = 1;
222                 b6 = 1;
223                 b5 = 0;
224                 break;
225         case 3:
226                 b7 = 1;
227                 b6 = 0;
228                 b5 = 1;
229                 break;
230         }
231
232         if (mirror)
233                 b6 = !b6;
234
235         mode &= ~((1<<7) | (1<<6) | (1<<5));
236         mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
237
238         return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
239 }
240
241 static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
242 {
243         int r;
244         u16 x1 = x;
245         u16 x2 = x + w - 1;
246         u16 y1 = y;
247         u16 y2 = y + h - 1;
248
249         u8 buf[5];
250         buf[0] = DCS_COLUMN_ADDR;
251         buf[1] = (x1 >> 8) & 0xff;
252         buf[2] = (x1 >> 0) & 0xff;
253         buf[3] = (x2 >> 8) & 0xff;
254         buf[4] = (x2 >> 0) & 0xff;
255
256         r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
257         if (r)
258                 return r;
259
260         buf[0] = DCS_PAGE_ADDR;
261         buf[1] = (y1 >> 8) & 0xff;
262         buf[2] = (y1 >> 0) & 0xff;
263         buf[3] = (y2 >> 8) & 0xff;
264         buf[4] = (y2 >> 0) & 0xff;
265
266         r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
267         if (r)
268                 return r;
269
270         dsi_vc_send_bta_sync(TCH);
271
272         return r;
273 }
274
275 static int taal_bl_update_status(struct backlight_device *dev)
276 {
277         struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
278         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
279         int r;
280         int level;
281
282         if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
283                         dev->props.power == FB_BLANK_UNBLANK)
284                 level = dev->props.brightness;
285         else
286                 level = 0;
287
288         dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
289
290         if (td->use_dsi_bl) {
291                 if (td->enabled) {
292                         dsi_bus_lock();
293                         r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
294                         dsi_bus_unlock();
295                         if (r)
296                                 return r;
297                 }
298         } else {
299                 if (!dssdev->set_backlight)
300                         return -EINVAL;
301
302                 r = dssdev->set_backlight(dssdev, level);
303                 if (r)
304                         return r;
305         }
306
307         return 0;
308 }
309
310 static int taal_bl_get_intensity(struct backlight_device *dev)
311 {
312         if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
313                         dev->props.power == FB_BLANK_UNBLANK)
314                 return dev->props.brightness;
315
316         return 0;
317 }
318
319 static struct backlight_ops taal_bl_ops = {
320         .get_brightness = taal_bl_get_intensity,
321         .update_status  = taal_bl_update_status,
322 };
323
324 static void taal_get_timings(struct omap_dss_device *dssdev,
325                         struct omap_video_timings *timings)
326 {
327         *timings = dssdev->panel.timings;
328 }
329
330 static void taal_get_resolution(struct omap_dss_device *dssdev,
331                 u16 *xres, u16 *yres)
332 {
333         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
334
335         if (td->rotate == 0 || td->rotate == 2) {
336                 *xres = dssdev->panel.timings.x_res;
337                 *yres = dssdev->panel.timings.y_res;
338         } else {
339                 *yres = dssdev->panel.timings.x_res;
340                 *xres = dssdev->panel.timings.y_res;
341         }
342 }
343
344 static irqreturn_t taal_te_isr(int irq, void *data)
345 {
346         struct omap_dss_device *dssdev = data;
347         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
348
349         complete_all(&td->te_completion);
350
351         return IRQ_HANDLED;
352 }
353
354 static ssize_t taal_num_errors_show(struct device *dev,
355                 struct device_attribute *attr, char *buf)
356 {
357         struct omap_dss_device *dssdev = to_dss_device(dev);
358         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
359         u8 errors;
360         int r;
361
362         if (td->enabled) {
363                 dsi_bus_lock();
364                 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
365                 dsi_bus_unlock();
366         } else {
367                 r = -ENODEV;
368         }
369
370         if (r)
371                 return r;
372
373         return snprintf(buf, PAGE_SIZE, "%d\n", errors);
374 }
375
376 static ssize_t taal_hw_revision_show(struct device *dev,
377                 struct device_attribute *attr, char *buf)
378 {
379         struct omap_dss_device *dssdev = to_dss_device(dev);
380         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
381         u8 id1, id2, id3;
382         int r;
383
384         if (td->enabled) {
385                 dsi_bus_lock();
386                 r = taal_get_id(&id1, &id2, &id3);
387                 dsi_bus_unlock();
388         } else {
389                 r = -ENODEV;
390         }
391
392         if (r)
393                 return r;
394
395         return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
396 }
397
398 static const char *cabc_modes[] = {
399         "off",          /* used also always when CABC is not supported */
400         "ui",
401         "still-image",
402         "moving-image",
403 };
404
405 static ssize_t show_cabc_mode(struct device *dev,
406                 struct device_attribute *attr,
407                 char *buf)
408 {
409         struct omap_dss_device *dssdev = to_dss_device(dev);
410         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
411         const char *mode_str;
412         int mode;
413         int len;
414
415         mode = td->cabc_mode;
416
417         mode_str = "unknown";
418         if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
419                 mode_str = cabc_modes[mode];
420         len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
421
422         return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
423 }
424
425 static ssize_t store_cabc_mode(struct device *dev,
426                 struct device_attribute *attr,
427                 const char *buf, size_t count)
428 {
429         struct omap_dss_device *dssdev = to_dss_device(dev);
430         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
431         int i;
432
433         for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
434                 if (sysfs_streq(cabc_modes[i], buf))
435                         break;
436         }
437
438         if (i == ARRAY_SIZE(cabc_modes))
439                 return -EINVAL;
440
441         if (td->enabled) {
442                 dsi_bus_lock();
443                 if (!td->cabc_broken)
444                         taal_dcs_write_1(DCS_WRITE_CABC, i);
445                 dsi_bus_unlock();
446         }
447
448         td->cabc_mode = i;
449
450         return count;
451 }
452
453 static ssize_t show_cabc_available_modes(struct device *dev,
454                 struct device_attribute *attr,
455                 char *buf)
456 {
457         int len;
458         int i;
459
460         for (i = 0, len = 0;
461              len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
462                 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
463                         i ? " " : "", cabc_modes[i],
464                         i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
465
466         return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
467 }
468
469 static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
470 static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
471 static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
472                 show_cabc_mode, store_cabc_mode);
473 static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
474                 show_cabc_available_modes, NULL);
475
476 static struct attribute *taal_attrs[] = {
477         &dev_attr_num_dsi_errors.attr,
478         &dev_attr_hw_revision.attr,
479         &dev_attr_cabc_mode.attr,
480         &dev_attr_cabc_available_modes.attr,
481         NULL,
482 };
483
484 static struct attribute_group taal_attr_group = {
485         .attrs = taal_attrs,
486 };
487
488 static int taal_probe(struct omap_dss_device *dssdev)
489 {
490         struct backlight_properties props;
491         struct taal_data *td;
492         struct backlight_device *bldev;
493         int r;
494
495         const struct omap_video_timings taal_panel_timings = {
496                 .x_res          = 864,
497                 .y_res          = 480,
498         };
499
500         dev_dbg(&dssdev->dev, "probe\n");
501
502         dssdev->panel.config = OMAP_DSS_LCD_TFT;
503         dssdev->panel.timings = taal_panel_timings;
504         dssdev->ctrl.pixel_size = 24;
505
506         td = kzalloc(sizeof(*td), GFP_KERNEL);
507         if (!td) {
508                 r = -ENOMEM;
509                 goto err0;
510         }
511         td->dssdev = dssdev;
512
513         td->esd_wq = create_singlethread_workqueue("taal_esd");
514         if (td->esd_wq == NULL) {
515                 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
516                 r = -ENOMEM;
517                 goto err1;
518         }
519         INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
520
521         dev_set_drvdata(&dssdev->dev, td);
522
523         /* if no platform set_backlight() defined, presume DSI backlight
524          * control */
525         memset(&props, 0, sizeof(struct backlight_properties));
526         if (!dssdev->set_backlight)
527                 td->use_dsi_bl = true;
528
529         if (td->use_dsi_bl)
530                 props.max_brightness = 255;
531         else
532                 props.max_brightness = 127;
533         bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
534                                           &taal_bl_ops, &props);
535         if (IS_ERR(bldev)) {
536                 r = PTR_ERR(bldev);
537                 goto err2;
538         }
539
540         td->bldev = bldev;
541
542         bldev->props.fb_blank = FB_BLANK_UNBLANK;
543         bldev->props.power = FB_BLANK_UNBLANK;
544         if (td->use_dsi_bl)
545                 bldev->props.brightness = 255;
546         else
547                 bldev->props.brightness = 127;
548
549         taal_bl_update_status(bldev);
550
551         if (dssdev->phy.dsi.ext_te) {
552                 int gpio = dssdev->phy.dsi.ext_te_gpio;
553
554                 r = gpio_request(gpio, "taal irq");
555                 if (r) {
556                         dev_err(&dssdev->dev, "GPIO request failed\n");
557                         goto err3;
558                 }
559
560                 gpio_direction_input(gpio);
561
562                 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
563                                 IRQF_DISABLED | IRQF_TRIGGER_RISING,
564                                 "taal vsync", dssdev);
565
566                 if (r) {
567                         dev_err(&dssdev->dev, "IRQ request failed\n");
568                         gpio_free(gpio);
569                         goto err3;
570                 }
571
572                 init_completion(&td->te_completion);
573
574                 td->use_ext_te = true;
575         }
576
577         r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
578         if (r) {
579                 dev_err(&dssdev->dev, "failed to create sysfs files\n");
580                 goto err4;
581         }
582
583         return 0;
584 err4:
585         if (td->use_ext_te) {
586                 int gpio = dssdev->phy.dsi.ext_te_gpio;
587                 free_irq(gpio_to_irq(gpio), dssdev);
588                 gpio_free(gpio);
589         }
590 err3:
591         backlight_device_unregister(bldev);
592 err2:
593         cancel_delayed_work_sync(&td->esd_work);
594         destroy_workqueue(td->esd_wq);
595 err1:
596         kfree(td);
597 err0:
598         return r;
599 }
600
601 static void taal_remove(struct omap_dss_device *dssdev)
602 {
603         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
604         struct backlight_device *bldev;
605
606         dev_dbg(&dssdev->dev, "remove\n");
607
608         sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
609
610         if (td->use_ext_te) {
611                 int gpio = dssdev->phy.dsi.ext_te_gpio;
612                 free_irq(gpio_to_irq(gpio), dssdev);
613                 gpio_free(gpio);
614         }
615
616         bldev = td->bldev;
617         bldev->props.power = FB_BLANK_POWERDOWN;
618         taal_bl_update_status(bldev);
619         backlight_device_unregister(bldev);
620
621         cancel_delayed_work_sync(&td->esd_work);
622         destroy_workqueue(td->esd_wq);
623
624         kfree(td);
625 }
626
627 static int taal_power_on(struct omap_dss_device *dssdev)
628 {
629         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
630         u8 id1, id2, id3;
631         int r;
632
633         if (dssdev->platform_enable) {
634                 r = dssdev->platform_enable(dssdev);
635                 if (r)
636                         return r;
637         }
638
639         /* it seems we have to wait a bit until taal is ready */
640         msleep(5);
641
642         dsi_bus_lock();
643
644         r = omapdss_dsi_display_enable(dssdev);
645         if (r) {
646                 dev_err(&dssdev->dev, "failed to enable DSI\n");
647                 goto err0;
648         }
649
650         omapdss_dsi_vc_enable_hs(TCH, false);
651
652         r = taal_sleep_out(td);
653         if (r)
654                 goto err;
655
656         r = taal_get_id(&id1, &id2, &id3);
657         if (r)
658                 goto err;
659
660         /* on early revisions CABC is broken */
661         if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
662                 td->cabc_broken = true;
663
664         taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
665         taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
666
667         taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
668
669         taal_set_addr_mode(td->rotate, td->mirror);
670         if (!td->cabc_broken)
671                 taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
672
673         taal_dcs_write_0(DCS_DISPLAY_ON);
674
675         r = _taal_enable_te(dssdev, td->te_enabled);
676         if (r)
677                 goto err;
678
679 #ifdef TAAL_USE_ESD_CHECK
680         queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
681 #endif
682
683         td->enabled = 1;
684
685         if (!td->intro_printed) {
686                 dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
687                                 id1, id2, id3);
688                 if (td->cabc_broken)
689                         dev_info(&dssdev->dev,
690                                         "old Taal version, CABC disabled\n");
691                 td->intro_printed = true;
692         }
693
694         omapdss_dsi_vc_enable_hs(TCH, true);
695
696         dsi_bus_unlock();
697
698         return 0;
699 err:
700         dsi_bus_unlock();
701
702         omapdss_dsi_display_disable(dssdev);
703 err0:
704         if (dssdev->platform_disable)
705                 dssdev->platform_disable(dssdev);
706
707         return r;
708 }
709
710 static void taal_power_off(struct omap_dss_device *dssdev)
711 {
712         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
713
714         dsi_bus_lock();
715
716         cancel_delayed_work(&td->esd_work);
717
718         taal_dcs_write_0(DCS_DISPLAY_OFF);
719         taal_sleep_in(td);
720
721         /* wait a bit so that the message goes through */
722         msleep(10);
723
724         omapdss_dsi_display_disable(dssdev);
725
726         if (dssdev->platform_disable)
727                 dssdev->platform_disable(dssdev);
728
729         td->enabled = 0;
730
731         dsi_bus_unlock();
732 }
733
734 static int taal_enable(struct omap_dss_device *dssdev)
735 {
736         int r;
737         dev_dbg(&dssdev->dev, "enable\n");
738
739         if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
740                 return -EINVAL;
741
742         r = taal_power_on(dssdev);
743         if (r)
744                 return r;
745
746         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
747
748         return r;
749 }
750
751 static void taal_disable(struct omap_dss_device *dssdev)
752 {
753         dev_dbg(&dssdev->dev, "disable\n");
754
755         if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
756                 taal_power_off(dssdev);
757
758         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
759 }
760
761 static int taal_suspend(struct omap_dss_device *dssdev)
762 {
763         dev_dbg(&dssdev->dev, "suspend\n");
764
765         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
766                 return -EINVAL;
767
768         taal_power_off(dssdev);
769         dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
770
771         return 0;
772 }
773
774 static int taal_resume(struct omap_dss_device *dssdev)
775 {
776         int r;
777         dev_dbg(&dssdev->dev, "resume\n");
778
779         if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
780                 return -EINVAL;
781
782         r = taal_power_on(dssdev);
783         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
784         return r;
785 }
786
787 static void taal_framedone_cb(int err, void *data)
788 {
789         struct omap_dss_device *dssdev = data;
790         dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
791         dsi_bus_unlock();
792 }
793
794 static int taal_update(struct omap_dss_device *dssdev,
795                                     u16 x, u16 y, u16 w, u16 h)
796 {
797         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
798         int r;
799
800         dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
801
802         dsi_bus_lock();
803
804         if (!td->enabled) {
805                 r = 0;
806                 goto err;
807         }
808
809         r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h);
810         if (r)
811                 goto err;
812
813         r = taal_set_update_window(x, y, w, h);
814         if (r)
815                 goto err;
816
817         r = omap_dsi_update(dssdev, TCH, x, y, w, h,
818                         taal_framedone_cb, dssdev);
819         if (r)
820                 goto err;
821
822         /* note: no bus_unlock here. unlock is in framedone_cb */
823         return 0;
824 err:
825         dsi_bus_unlock();
826         return r;
827 }
828
829 static int taal_sync(struct omap_dss_device *dssdev)
830 {
831         dev_dbg(&dssdev->dev, "sync\n");
832
833         dsi_bus_lock();
834         dsi_bus_unlock();
835
836         dev_dbg(&dssdev->dev, "sync done\n");
837
838         return 0;
839 }
840
841 static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
842 {
843         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
844         int r;
845
846         td->te_enabled = enable;
847
848         if (enable)
849                 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
850         else
851                 r = taal_dcs_write_0(DCS_TEAR_OFF);
852
853         omapdss_dsi_enable_te(dssdev, enable);
854
855         /* XXX for some reason, DSI TE breaks if we don't wait here.
856          * Panel bug? Needs more studying */
857         msleep(100);
858
859         return r;
860 }
861
862 static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
863 {
864         int r;
865
866         dsi_bus_lock();
867
868         r = _taal_enable_te(dssdev, enable);
869
870         dsi_bus_unlock();
871
872         return r;
873 }
874
875 static int taal_get_te(struct omap_dss_device *dssdev)
876 {
877         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
878         return td->te_enabled;
879 }
880
881 static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
882 {
883         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
884         int r;
885
886         dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
887
888         dsi_bus_lock();
889
890         if (td->enabled) {
891                 r = taal_set_addr_mode(rotate, td->mirror);
892                 if (r)
893                         goto err;
894         }
895
896         td->rotate = rotate;
897
898         dsi_bus_unlock();
899         return 0;
900 err:
901         dsi_bus_unlock();
902         return r;
903 }
904
905 static u8 taal_get_rotate(struct omap_dss_device *dssdev)
906 {
907         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
908         return td->rotate;
909 }
910
911 static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
912 {
913         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
914         int r;
915
916         dev_dbg(&dssdev->dev, "mirror %d\n", enable);
917
918         dsi_bus_lock();
919         if (td->enabled) {
920                 r = taal_set_addr_mode(td->rotate, enable);
921                 if (r)
922                         goto err;
923         }
924
925         td->mirror = enable;
926
927         dsi_bus_unlock();
928         return 0;
929 err:
930         dsi_bus_unlock();
931         return r;
932 }
933
934 static bool taal_get_mirror(struct omap_dss_device *dssdev)
935 {
936         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
937         return td->mirror;
938 }
939
940 static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
941 {
942         u8 id1, id2, id3;
943         int r;
944
945         dsi_bus_lock();
946
947         r = taal_dcs_read_1(DCS_GET_ID1, &id1);
948         if (r)
949                 goto err;
950         r = taal_dcs_read_1(DCS_GET_ID2, &id2);
951         if (r)
952                 goto err;
953         r = taal_dcs_read_1(DCS_GET_ID3, &id3);
954         if (r)
955                 goto err;
956
957         dsi_bus_unlock();
958         return 0;
959 err:
960         dsi_bus_unlock();
961         return r;
962 }
963
964 static int taal_memory_read(struct omap_dss_device *dssdev,
965                 void *buf, size_t size,
966                 u16 x, u16 y, u16 w, u16 h)
967 {
968         int r;
969         int first = 1;
970         int plen;
971         unsigned buf_used = 0;
972         struct taal_data *td = dev_get_drvdata(&dssdev->dev);
973
974         if (!td->enabled)
975                 return -ENODEV;
976
977         if (size < w * h * 3)
978                 return -ENOMEM;
979
980         size = min(w * h * 3,
981                         dssdev->panel.timings.x_res *
982                         dssdev->panel.timings.y_res * 3);
983
984         dsi_bus_lock();
985
986         /* plen 1 or 2 goes into short packet. until checksum error is fixed,
987          * use short packets. plen 32 works, but bigger packets seem to cause
988          * an error. */
989         if (size % 2)
990                 plen = 1;
991         else
992                 plen = 2;
993
994         taal_set_update_window(x, y, w, h);
995
996         r = dsi_vc_set_max_rx_packet_size(TCH, plen);
997         if (r)
998                 goto err0;
999
1000         while (buf_used < size) {
1001                 u8 dcs_cmd = first ? 0x2e : 0x3e;
1002                 first = 0;
1003
1004                 r = dsi_vc_dcs_read(TCH, dcs_cmd,
1005                                 buf + buf_used, size - buf_used);
1006
1007                 if (r < 0) {
1008                         dev_err(&dssdev->dev, "read error\n");
1009                         goto err;
1010                 }
1011
1012                 buf_used += r;
1013
1014                 if (r < plen) {
1015                         dev_err(&dssdev->dev, "short read\n");
1016                         break;
1017                 }
1018
1019                 if (signal_pending(current)) {
1020                         dev_err(&dssdev->dev, "signal pending, "
1021                                         "aborting memory read\n");
1022                         r = -ERESTARTSYS;
1023                         goto err;
1024                 }
1025         }
1026
1027         r = buf_used;
1028
1029 err:
1030         dsi_vc_set_max_rx_packet_size(TCH, 1);
1031 err0:
1032         dsi_bus_unlock();
1033         return r;
1034 }
1035
1036 static void taal_esd_work(struct work_struct *work)
1037 {
1038         struct taal_data *td = container_of(work, struct taal_data,
1039                         esd_work.work);
1040         struct omap_dss_device *dssdev = td->dssdev;
1041         u8 state1, state2;
1042         int r;
1043
1044         if (!td->enabled)
1045                 return;
1046
1047         dsi_bus_lock();
1048
1049         r = taal_dcs_read_1(DCS_RDDSDR, &state1);
1050         if (r) {
1051                 dev_err(&dssdev->dev, "failed to read Taal status\n");
1052                 goto err;
1053         }
1054
1055         /* Run self diagnostics */
1056         r = taal_sleep_out(td);
1057         if (r) {
1058                 dev_err(&dssdev->dev, "failed to run Taal self-diagnostics\n");
1059                 goto err;
1060         }
1061
1062         r = taal_dcs_read_1(DCS_RDDSDR, &state2);
1063         if (r) {
1064                 dev_err(&dssdev->dev, "failed to read Taal status\n");
1065                 goto err;
1066         }
1067
1068         /* Each sleep out command will trigger a self diagnostic and flip
1069          * Bit6 if the test passes.
1070          */
1071         if (!((state1 ^ state2) & (1 << 6))) {
1072                 dev_err(&dssdev->dev, "LCD self diagnostics failed\n");
1073                 goto err;
1074         }
1075         /* Self-diagnostics result is also shown on TE GPIO line. We need
1076          * to re-enable TE after self diagnostics */
1077         if (td->use_ext_te && td->te_enabled) {
1078                 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
1079                 if (r)
1080                         goto err;
1081         }
1082
1083         dsi_bus_unlock();
1084
1085         queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1086
1087         return;
1088 err:
1089         dev_err(&dssdev->dev, "performing LCD reset\n");
1090
1091         taal_disable(dssdev);
1092         taal_enable(dssdev);
1093
1094         dsi_bus_unlock();
1095
1096         queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1097 }
1098
1099 static int taal_set_update_mode(struct omap_dss_device *dssdev,
1100                 enum omap_dss_update_mode mode)
1101 {
1102         if (mode != OMAP_DSS_UPDATE_MANUAL)
1103                 return -EINVAL;
1104         return 0;
1105 }
1106
1107 static enum omap_dss_update_mode taal_get_update_mode(
1108                 struct omap_dss_device *dssdev)
1109 {
1110         return OMAP_DSS_UPDATE_MANUAL;
1111 }
1112
1113 static struct omap_dss_driver taal_driver = {
1114         .probe          = taal_probe,
1115         .remove         = taal_remove,
1116
1117         .enable         = taal_enable,
1118         .disable        = taal_disable,
1119         .suspend        = taal_suspend,
1120         .resume         = taal_resume,
1121
1122         .set_update_mode = taal_set_update_mode,
1123         .get_update_mode = taal_get_update_mode,
1124
1125         .update         = taal_update,
1126         .sync           = taal_sync,
1127
1128         .get_resolution = taal_get_resolution,
1129         .get_recommended_bpp = omapdss_default_get_recommended_bpp,
1130
1131         .enable_te      = taal_enable_te,
1132         .get_te         = taal_get_te,
1133
1134         .set_rotate     = taal_rotate,
1135         .get_rotate     = taal_get_rotate,
1136         .set_mirror     = taal_mirror,
1137         .get_mirror     = taal_get_mirror,
1138         .run_test       = taal_run_test,
1139         .memory_read    = taal_memory_read,
1140
1141         .get_timings    = taal_get_timings,
1142
1143         .driver         = {
1144                 .name   = "taal",
1145                 .owner  = THIS_MODULE,
1146         },
1147 };
1148
1149 static int __init taal_init(void)
1150 {
1151         omap_dss_register_driver(&taal_driver);
1152
1153         return 0;
1154 }
1155
1156 static void __exit taal_exit(void)
1157 {
1158         omap_dss_unregister_driver(&taal_driver);
1159 }
1160
1161 module_init(taal_init);
1162 module_exit(taal_exit);
1163
1164 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
1165 MODULE_DESCRIPTION("Taal Driver");
1166 MODULE_LICENSE("GPL");