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