]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/lcd_mipid.c
Merge branch 'omap-fixes'
[linux-2.6-omap-h63xx.git] / drivers / video / omap / lcd_mipid.c
1 /*
2  * LCD driver for MIPI DBI-C / DCS compatible LCDs
3  *
4  * Copyright (C) 2006 Nokia Corporation
5  * Author: Imre Deak <imre.deak@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 as published by the
9  * Free Software Foundation; either version 2 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21 #include <linux/device.h>
22 #include <linux/delay.h>
23 #include <linux/workqueue.h>
24 #include <linux/spi/spi.h>
25
26 #include <mach/omapfb.h>
27 #include <mach/lcd_mipid.h>
28
29 #include "../../cbus/tahvo.h"
30
31 #define MIPID_MODULE_NAME               "lcd_mipid"
32
33 #define MIPID_CMD_READ_DISP_ID          0x04
34 #define MIPID_CMD_READ_RED              0x06
35 #define MIPID_CMD_READ_GREEN            0x07
36 #define MIPID_CMD_READ_BLUE             0x08
37 #define MIPID_CMD_READ_DISP_STATUS      0x09
38 #define MIPID_CMD_RDDSDR                0x0F
39 #define MIPID_CMD_SLEEP_IN              0x10
40 #define MIPID_CMD_SLEEP_OUT             0x11
41 #define MIPID_CMD_DISP_OFF              0x28
42 #define MIPID_CMD_DISP_ON               0x29
43
44 #define MIPID_VER_LPH8923               3
45 #define MIPID_VER_LS041Y3               4
46
47 #define MIPID_ESD_CHECK_PERIOD          msecs_to_jiffies(5000)
48
49 #define to_mipid_device(p)              container_of(p, struct mipid_device, \
50                                                 panel)
51 struct mipid_device {
52         int             enabled;
53         int             model;
54         int             revision;
55         u8              display_id[3];
56         unsigned int    saved_bklight_level;
57         unsigned long   hw_guard_end;           /* next value of jiffies
58                                                    when we can issue the
59                                                    next sleep in/out command */
60         unsigned long   hw_guard_wait;          /* max guard time in jiffies */
61
62         struct omapfb_device    *fbdev;
63         struct spi_device       *spi;
64         struct mutex            mutex;
65         struct lcd_panel        panel;
66
67         struct workqueue_struct *esd_wq;
68         struct delayed_work     esd_work;
69         void                    (*esd_check)(struct mipid_device *m);
70 };
71
72 static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
73                            int wlen, u8 *rbuf, int rlen)
74 {
75         struct spi_message      m;
76         struct spi_transfer     *x, xfer[4];
77         u16                     w;
78         int                     r;
79
80         BUG_ON(md->spi == NULL);
81
82         spi_message_init(&m);
83
84         memset(xfer, 0, sizeof(xfer));
85         x = &xfer[0];
86
87         cmd &=  0xff;
88         x->tx_buf       = &cmd;
89         x->bits_per_word= 9;
90         x->len          = 2;
91         spi_message_add_tail(x, &m);
92
93         if (wlen) {
94                 x++;
95                 x->tx_buf       = wbuf;
96                 x->len          = wlen;
97                 x->bits_per_word= 9;
98                 spi_message_add_tail(x, &m);
99         }
100
101         if (rlen) {
102                 x++;
103                 x->rx_buf       = &w;
104                 x->len          = 1;
105                 spi_message_add_tail(x, &m);
106
107                 if (rlen > 1) {
108                         /* Arrange for the extra clock before the first
109                          * data bit.
110                          */
111                         x->bits_per_word = 9;
112                         x->len           = 2;
113
114                         x++;
115                         x->rx_buf        = &rbuf[1];
116                         x->len           = rlen - 1;
117                         spi_message_add_tail(x, &m);
118                 }
119         }
120
121         r = spi_sync(md->spi, &m);
122         if (r < 0)
123                 dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
124
125         if (rlen)
126                 rbuf[0] = w & 0xff;
127 }
128
129 static inline void mipid_cmd(struct mipid_device *md, int cmd)
130 {
131         mipid_transfer(md, cmd, NULL, 0, NULL, 0);
132 }
133
134 static inline void mipid_write(struct mipid_device *md,
135                                int reg, const u8 *buf, int len)
136 {
137         mipid_transfer(md, reg, buf, len, NULL, 0);
138 }
139
140 static inline void mipid_read(struct mipid_device *md,
141                               int reg, u8 *buf, int len)
142 {
143         mipid_transfer(md, reg, NULL, 0, buf, len);
144 }
145
146 static void set_data_lines(struct mipid_device *md, int data_lines)
147 {
148         u16 par;
149
150         switch (data_lines) {
151         case 16:
152                 par = 0x150;
153                 break;
154         case 18:
155                 par = 0x160;
156                 break;
157         case 24:
158                 par = 0x170;
159                 break;
160         }
161         mipid_write(md, 0x3a, (u8 *)&par, 2);
162 }
163
164 static void send_init_string(struct mipid_device *md)
165 {
166         u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
167
168         mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
169         set_data_lines(md, md->panel.data_lines);
170 }
171
172 static void hw_guard_start(struct mipid_device *md, int guard_msec)
173 {
174         md->hw_guard_wait = msecs_to_jiffies(guard_msec);
175         md->hw_guard_end = jiffies + md->hw_guard_wait;
176 }
177
178 static void hw_guard_wait(struct mipid_device *md)
179 {
180         unsigned long wait = md->hw_guard_end - jiffies;
181
182         if ((long)wait > 0 && wait <= md->hw_guard_wait) {
183                 set_current_state(TASK_UNINTERRUPTIBLE);
184                 schedule_timeout(wait);
185         }
186 }
187
188 static void set_sleep_mode(struct mipid_device *md, int on)
189 {
190         int cmd, sleep_time = 50;
191
192         if (on)
193                 cmd = MIPID_CMD_SLEEP_IN;
194         else
195                 cmd = MIPID_CMD_SLEEP_OUT;
196         hw_guard_wait(md);
197         mipid_cmd(md, cmd);
198         hw_guard_start(md, 120);
199         /*
200          * When we enable the panel, it seems we _have_ to sleep
201          * 120 ms before sending the init string. When disabling the
202          * panel we'll sleep for the duration of 2 frames, so that the
203          * controller can still provide the PCLK,HS,VS signals. */
204         if (!on)
205                 sleep_time = 120;
206         msleep(sleep_time);
207 }
208
209 static void set_display_state(struct mipid_device *md, int enabled)
210 {
211         int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
212
213         mipid_cmd(md, cmd);
214 }
215
216 static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
217 {
218         struct mipid_device *md = to_mipid_device(panel);
219
220         if (level > tahvo_get_max_backlight_level())
221                 return -EINVAL;
222         if (!md->enabled) {
223                 md->saved_bklight_level = level;
224                 return 0;
225         }
226         tahvo_set_backlight_level(level);
227
228         return 0;
229 }
230
231 static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
232 {
233         return tahvo_get_backlight_level();
234 }
235
236 static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
237 {
238         return tahvo_get_max_backlight_level();
239 }
240
241
242 static unsigned long mipid_get_caps(struct lcd_panel *panel)
243 {
244         return OMAPFB_CAPS_SET_BACKLIGHT;
245 }
246
247 static u16 read_first_pixel(struct mipid_device *md)
248 {
249         u16 pixel;
250         u8 red, green, blue;
251
252         mutex_lock(&md->mutex);
253         mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
254         mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
255         mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
256         mutex_unlock(&md->mutex);
257
258         switch (md->panel.data_lines) {
259         case 16:
260                 pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
261                 break;
262         case 24:
263                 /* 24 bit -> 16 bit */
264                 pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
265                         (blue >> 3);
266                 break;
267         default:
268                 BUG();
269         }
270
271         return pixel;
272 }
273
274 static int mipid_run_test(struct lcd_panel *panel, int test_num)
275 {
276         struct mipid_device *md = to_mipid_device(panel);
277         static const u16 test_values[4] = {
278                 0x0000, 0xffff, 0xaaaa, 0x5555,
279         };
280         int i;
281
282         if (test_num != MIPID_TEST_RGB_LINES)
283                 return MIPID_TEST_INVALID;
284
285         for (i = 0; i < ARRAY_SIZE(test_values); i++) {
286                 int delay;
287                 unsigned long tmo;
288
289                 omapfb_write_first_pixel(md->fbdev, test_values[i]);
290                 tmo = jiffies + msecs_to_jiffies(100);
291                 delay = 25;
292                 while (1) {
293                         u16 pixel;
294
295                         msleep(delay);
296                         pixel = read_first_pixel(md);
297                         if (pixel == test_values[i])
298                                 break;
299                         if (time_after(jiffies, tmo)) {
300                                 dev_err(&md->spi->dev,
301                                         "MIPI LCD RGB I/F test failed: "
302                                         "expecting %04x, got %04x\n",
303                                         test_values[i], pixel);
304                                 return MIPID_TEST_FAILED;
305                         }
306                         delay = 10;
307                 }
308         }
309
310         return 0;
311 }
312
313 static void ls041y3_esd_recover(struct mipid_device *md)
314 {
315         dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
316         set_sleep_mode(md, 1);
317         set_sleep_mode(md, 0);
318 }
319
320 static void ls041y3_esd_check_mode1(struct mipid_device *md)
321 {
322         u8 state1, state2;
323
324         mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
325         set_sleep_mode(md, 0);
326         mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
327         dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
328                 state1, state2);
329         /* Each sleep out command will trigger a self diagnostic and flip
330         * Bit6 if the test passes.
331         */
332         if (!((state1 ^ state2) & (1 << 6)))
333                 ls041y3_esd_recover(md);
334 }
335
336 static void ls041y3_esd_check_mode2(struct mipid_device *md)
337 {
338         int i;
339         u8 rbuf[2];
340         static const struct {
341                 int     cmd;
342                 int     wlen;
343                 u16     wbuf[3];
344         } *rd, rd_ctrl[7] = {
345                 { 0xb0, 4, { 0x0101, 0x01fe, } },
346                 { 0xb1, 4, { 0x01de, 0x0121, } },
347                 { 0xc2, 4, { 0x0100, 0x0100, } },
348                 { 0xbd, 2, { 0x0100, } },
349                 { 0xc2, 4, { 0x01fc, 0x0103, } },
350                 { 0xb4, 0, },
351                 { 0x00, 0, },
352         };
353
354         rd = rd_ctrl;
355         for (i = 0; i < 3; i++, rd++)
356                 mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
357
358         udelay(10);
359         mipid_read(md, rd->cmd, rbuf, 2);
360         rd++;
361
362         for (i = 0; i < 3; i++, rd++) {
363                 udelay(10);
364                 mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
365         }
366
367         dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
368         if (rbuf[1] == 0x00)
369                 ls041y3_esd_recover(md);
370 }
371
372 static void ls041y3_esd_check(struct mipid_device *md)
373 {
374         ls041y3_esd_check_mode1(md);
375         if (md->revision >= 0x88)
376                 ls041y3_esd_check_mode2(md);
377 }
378
379 static void mipid_esd_start_check(struct mipid_device *md)
380 {
381         if (md->esd_check != NULL)
382                 queue_delayed_work(md->esd_wq, &md->esd_work,
383                                    MIPID_ESD_CHECK_PERIOD);
384 }
385
386 static void mipid_esd_stop_check(struct mipid_device *md)
387 {
388         if (md->esd_check != NULL)
389                 cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work);
390 }
391
392 static void mipid_esd_work(struct work_struct *work)
393 {
394         struct mipid_device *md = container_of(work, struct mipid_device, esd_work.work);
395
396         mutex_lock(&md->mutex);
397         md->esd_check(md);
398         mutex_unlock(&md->mutex);
399         mipid_esd_start_check(md);
400 }
401
402 static int mipid_enable(struct lcd_panel *panel)
403 {
404         struct mipid_device *md = to_mipid_device(panel);
405
406         mutex_lock(&md->mutex);
407
408         if (md->enabled) {
409                 mutex_unlock(&md->mutex);
410                 return 0;
411         }
412         set_sleep_mode(md, 0);
413         md->enabled = 1;
414         send_init_string(md);
415         set_display_state(md, 1);
416         mipid_set_bklight_level(panel, md->saved_bklight_level);
417         mipid_esd_start_check(md);
418
419         mutex_unlock(&md->mutex);
420         return 0;
421 }
422
423 static void mipid_disable(struct lcd_panel *panel)
424 {
425         struct mipid_device *md = to_mipid_device(panel);
426
427         /*
428          * A final ESD work might be called before returning,
429          * so do this without holding the lock.
430          */
431         mipid_esd_stop_check(md);
432         mutex_lock(&md->mutex);
433
434         if (!md->enabled) {
435                 mutex_unlock(&md->mutex);
436                 return;
437         }
438         md->saved_bklight_level = mipid_get_bklight_level(panel);
439         mipid_set_bklight_level(panel, 0);
440         set_display_state(md, 0);
441         set_sleep_mode(md, 1);
442         md->enabled = 0;
443
444         mutex_unlock(&md->mutex);
445 }
446
447 static int panel_enabled(struct mipid_device *md)
448 {
449         u32 disp_status;
450         int enabled;
451
452         mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
453         disp_status = __be32_to_cpu(disp_status);
454         enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
455         dev_dbg(&md->spi->dev,
456                 "LCD panel %senabled by bootloader (status 0x%04x)\n",
457                 enabled ? "" : "not ", disp_status);
458         return enabled;
459 }
460
461 static int mipid_init(struct lcd_panel *panel,
462                             struct omapfb_device *fbdev)
463 {
464         struct mipid_device *md = to_mipid_device(panel);
465
466         md->fbdev = fbdev;
467         md->esd_wq = create_singlethread_workqueue("mipid_esd");
468         if (md->esd_wq == NULL) {
469                 dev_err(&md->spi->dev, "can't create ESD workqueue\n");
470                 return -ENOMEM;
471         }
472         INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
473         mutex_init(&md->mutex);
474
475         md->enabled = panel_enabled(md);
476
477         if (md->enabled)
478                 mipid_esd_start_check(md);
479         else
480                 md->saved_bklight_level = mipid_get_bklight_level(panel);
481
482         return 0;
483 }
484
485 static void mipid_cleanup(struct lcd_panel *panel)
486 {
487         struct mipid_device *md = to_mipid_device(panel);
488
489         if (md->enabled)
490                 mipid_esd_stop_check(md);
491         destroy_workqueue(md->esd_wq);
492 }
493
494 static struct lcd_panel mipid_panel = {
495         .config         = OMAP_LCDC_PANEL_TFT,
496
497         .bpp            = 16,
498         .x_res          = 800,
499         .y_res          = 480,
500         .pixel_clock    = 21940,
501         .hsw            = 50,
502         .hfp            = 20,
503         .hbp            = 15,
504         .vsw            = 2,
505         .vfp            = 1,
506         .vbp            = 3,
507
508         .init           = mipid_init,
509         .cleanup        = mipid_cleanup,
510         .enable         = mipid_enable,
511         .disable        = mipid_disable,
512         .get_caps       = mipid_get_caps,
513         .set_bklight_level= mipid_set_bklight_level,
514         .get_bklight_level= mipid_get_bklight_level,
515         .get_bklight_max= mipid_get_bklight_max,
516         .run_test       = mipid_run_test,
517 };
518
519 static int mipid_detect(struct mipid_device *md)
520 {
521         struct mipid_platform_data *pdata;
522
523         pdata = md->spi->dev.platform_data;
524         if (pdata == NULL) {
525                 dev_err(&md->spi->dev, "missing platform data\n");
526                 return -ENOENT;
527         }
528
529         mipid_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
530         dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
531                 md->display_id[0], md->display_id[1], md->display_id[2]);
532
533         switch (md->display_id[0]) {
534         case 0x45:
535                 md->model = MIPID_VER_LPH8923;
536                 md->panel.name = "lph8923";
537                 break;
538         case 0x83:
539                 md->model = MIPID_VER_LS041Y3;
540                 md->panel.name = "ls041y3";
541                 md->esd_check = ls041y3_esd_check;
542                 break;
543         default:
544                 md->panel.name = "unknown";
545                 dev_err(&md->spi->dev, "invalid display ID\n");
546                 return -ENODEV;
547         }
548
549         md->revision = md->display_id[1];
550         md->panel.data_lines = pdata->data_lines;
551         pr_info("omapfb: %s rev %02x LCD detected\n",
552                         md->panel.name, md->revision);
553
554         return 0;
555 }
556
557 static int mipid_spi_probe(struct spi_device *spi)
558 {
559         struct mipid_device *md;
560         int r;
561
562         md = kzalloc(sizeof(*md), GFP_KERNEL);
563         if (md == NULL) {
564                 dev_err(&spi->dev, "out of memory\n");
565                 return -ENOMEM;
566         }
567
568         spi->mode = SPI_MODE_0;
569         md->spi = spi;
570         dev_set_drvdata(&spi->dev, md);
571         md->panel = mipid_panel;
572
573         r = mipid_detect(md);
574         if (r < 0)
575                 return r;
576
577         omapfb_register_panel(&md->panel);
578
579         return 0;
580 }
581
582 static int mipid_spi_remove(struct spi_device *spi)
583 {
584         struct mipid_device *md = dev_get_drvdata(&spi->dev);
585
586         mipid_disable(&md->panel);
587         kfree(md);
588
589         return 0;
590 }
591
592 static struct spi_driver mipid_spi_driver = {
593         .driver = {
594                 .name   = MIPID_MODULE_NAME,
595                 .bus    = &spi_bus_type,
596                 .owner  = THIS_MODULE,
597         },
598         .probe  = mipid_spi_probe,
599         .remove = __devexit_p(mipid_spi_remove),
600 };
601
602 static int mipid_drv_init(void)
603 {
604         spi_register_driver(&mipid_spi_driver);
605
606         return 0;
607 }
608 module_init(mipid_drv_init);
609
610 static void mipid_drv_cleanup(void)
611 {
612         spi_unregister_driver(&mipid_spi_driver);
613 }
614 module_exit(mipid_drv_cleanup);
615
616 MODULE_DESCRIPTION("MIPI display driver");
617 MODULE_LICENSE("GPL");