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