blob: 3fc5ad081a212906c92c69497436ddbe08a8807f [file] [log] [blame]
Tomi Valkeinen562a0602011-04-21 19:53:59 +03001/* #define DEBUG */
2
3#include <linux/module.h>
4#include <linux/delay.h>
5#include <linux/slab.h>
6#include <linux/gpio.h>
7#include <linux/spi/spi.h>
8#include <linux/backlight.h>
9#include <linux/fb.h>
10
11#include <video/omapdss.h>
12#include <video/omap-panel-n8x0.h>
13
14#define BLIZZARD_REV_CODE 0x00
15#define BLIZZARD_CONFIG 0x02
16#define BLIZZARD_PLL_DIV 0x04
17#define BLIZZARD_PLL_LOCK_RANGE 0x06
18#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
19#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
20#define BLIZZARD_PLL_MODE 0x0c
21#define BLIZZARD_CLK_SRC 0x0e
22#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
23#define BLIZZARD_MEM_BANK0_STATUS 0x14
24#define BLIZZARD_PANEL_CONFIGURATION 0x28
25#define BLIZZARD_HDISP 0x2a
26#define BLIZZARD_HNDP 0x2c
27#define BLIZZARD_VDISP0 0x2e
28#define BLIZZARD_VDISP1 0x30
29#define BLIZZARD_VNDP 0x32
30#define BLIZZARD_HSW 0x34
31#define BLIZZARD_VSW 0x38
32#define BLIZZARD_DISPLAY_MODE 0x68
33#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
34#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
35#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
36#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
37#define BLIZZARD_POWER_SAVE 0xE6
38#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
39
40/* Data source select */
41/* For S1D13745 */
42#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
43#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
44#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
45#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
46/* For S1D13744 */
47#define BLIZZARD_SRC_WRITE_LCD 0x00
48#define BLIZZARD_SRC_BLT_LCD 0x06
49
50#define BLIZZARD_COLOR_RGB565 0x01
51#define BLIZZARD_COLOR_YUV420 0x09
52
53#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
54#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
55
56#define MIPID_CMD_READ_DISP_ID 0x04
57#define MIPID_CMD_READ_RED 0x06
58#define MIPID_CMD_READ_GREEN 0x07
59#define MIPID_CMD_READ_BLUE 0x08
60#define MIPID_CMD_READ_DISP_STATUS 0x09
61#define MIPID_CMD_RDDSDR 0x0F
62#define MIPID_CMD_SLEEP_IN 0x10
63#define MIPID_CMD_SLEEP_OUT 0x11
64#define MIPID_CMD_DISP_OFF 0x28
65#define MIPID_CMD_DISP_ON 0x29
66
67static struct panel_drv_data {
68 struct mutex lock;
69
70 struct omap_dss_device *dssdev;
71 struct spi_device *spidev;
72 struct backlight_device *bldev;
73
74 int blizzard_ver;
75} s_drv_data;
76
77
78static inline
79struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
80{
81 return dssdev->data;
82}
83
84static inline
85struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
86{
87 return &s_drv_data;
88}
89
90
91static inline void blizzard_cmd(u8 cmd)
92{
93 omap_rfbi_write_command(&cmd, 1);
94}
95
96static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
97{
98 omap_rfbi_write_command(&cmd, 1);
99 omap_rfbi_write_data(buf, len);
100}
101
102static inline void blizzard_read(u8 cmd, u8 *buf, int len)
103{
104 omap_rfbi_write_command(&cmd, 1);
105 omap_rfbi_read_data(buf, len);
106}
107
108static u8 blizzard_read_reg(u8 cmd)
109{
110 u8 data;
111 blizzard_read(cmd, &data, 1);
112 return data;
113}
114
115static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
116 int x, int y, int w, int h)
117{
118 struct panel_drv_data *ddata = get_drv_data(dssdev);
119 u8 tmp[18];
120 int x_end, y_end;
121
122 x_end = x + w - 1;
123 y_end = y + h - 1;
124
125 tmp[0] = x;
126 tmp[1] = x >> 8;
127 tmp[2] = y;
128 tmp[3] = y >> 8;
129 tmp[4] = x_end;
130 tmp[5] = x_end >> 8;
131 tmp[6] = y_end;
132 tmp[7] = y_end >> 8;
133
134 /* scaling? */
135 tmp[8] = x;
136 tmp[9] = x >> 8;
137 tmp[10] = y;
138 tmp[11] = y >> 8;
139 tmp[12] = x_end;
140 tmp[13] = x_end >> 8;
141 tmp[14] = y_end;
142 tmp[15] = y_end >> 8;
143
144 tmp[16] = BLIZZARD_COLOR_RGB565;
145
146 if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
147 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
148 else
149 tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
150 BLIZZARD_SRC_WRITE_LCD :
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
152
Archit Tanejab02875b2012-08-13 15:26:49 +0530153 omapdss_rfbi_set_pixel_size(dssdev, 16);
Archit Taneja475989b2012-08-13 15:28:15 +0530154 omapdss_rfbi_set_data_lines(dssdev, 8);
Archit Tanejab02875b2012-08-13 15:26:49 +0530155
Archit Taneja475989b2012-08-13 15:28:15 +0530156 omap_rfbi_configure(dssdev);
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300157
158 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
159
Archit Tanejab02875b2012-08-13 15:26:49 +0530160 omapdss_rfbi_set_pixel_size(dssdev, 16);
Archit Taneja475989b2012-08-13 15:28:15 +0530161 omapdss_rfbi_set_data_lines(dssdev, 16);
Archit Tanejab02875b2012-08-13 15:26:49 +0530162
Archit Taneja475989b2012-08-13 15:28:15 +0530163 omap_rfbi_configure(dssdev);
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300164}
165
166static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
167 int wlen, u8 *rbuf, int rlen)
168{
169 struct spi_message m;
170 struct spi_transfer *x, xfer[4];
171 u16 w;
172 int r;
173
174 spi_message_init(&m);
175
176 memset(xfer, 0, sizeof(xfer));
177 x = &xfer[0];
178
179 cmd &= 0xff;
180 x->tx_buf = &cmd;
181 x->bits_per_word = 9;
182 x->len = 2;
183 spi_message_add_tail(x, &m);
184
185 if (wlen) {
186 x++;
187 x->tx_buf = wbuf;
188 x->len = wlen;
189 x->bits_per_word = 9;
190 spi_message_add_tail(x, &m);
191 }
192
193 if (rlen) {
194 x++;
195 x->rx_buf = &w;
196 x->len = 1;
197 spi_message_add_tail(x, &m);
198
199 if (rlen > 1) {
200 /* Arrange for the extra clock before the first
201 * data bit.
202 */
203 x->bits_per_word = 9;
204 x->len = 2;
205
206 x++;
207 x->rx_buf = &rbuf[1];
208 x->len = rlen - 1;
209 spi_message_add_tail(x, &m);
210 }
211 }
212
213 r = spi_sync(spi, &m);
214 if (r < 0)
215 dev_dbg(&spi->dev, "spi_sync %d\n", r);
216
217 if (rlen)
218 rbuf[0] = w & 0xff;
219}
220
221static inline void mipid_cmd(struct spi_device *spi, int cmd)
222{
223 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
224}
225
226static inline void mipid_write(struct spi_device *spi,
227 int reg, const u8 *buf, int len)
228{
229 mipid_transfer(spi, reg, buf, len, NULL, 0);
230}
231
232static inline void mipid_read(struct spi_device *spi,
233 int reg, u8 *buf, int len)
234{
235 mipid_transfer(spi, reg, NULL, 0, buf, len);
236}
237
238static void set_data_lines(struct spi_device *spi, int data_lines)
239{
240 u16 par;
241
242 switch (data_lines) {
243 case 16:
244 par = 0x150;
245 break;
246 case 18:
247 par = 0x160;
248 break;
249 case 24:
250 par = 0x170;
251 break;
252 }
253
254 mipid_write(spi, 0x3a, (u8 *)&par, 2);
255}
256
257static void send_init_string(struct spi_device *spi)
258{
259 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
260 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
261}
262
263static void send_display_on(struct spi_device *spi)
264{
265 mipid_cmd(spi, MIPID_CMD_DISP_ON);
266}
267
268static void send_display_off(struct spi_device *spi)
269{
270 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
271}
272
273static void send_sleep_out(struct spi_device *spi)
274{
275 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
276 msleep(120);
277}
278
279static void send_sleep_in(struct spi_device *spi)
280{
281 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
282 msleep(50);
283}
284
285static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
286{
287 int r;
288 struct panel_n8x0_data *bdata = get_board_data(dssdev);
289 struct panel_drv_data *ddata = get_drv_data(dssdev);
290 struct spi_device *spi = ddata->spidev;
291 u8 rev, conf;
292 u8 display_id[3];
293 const char *panel_name;
294
295 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
296 return 0;
297
298 gpio_direction_output(bdata->ctrl_pwrdown, 1);
299
300 if (bdata->platform_enable) {
301 r = bdata->platform_enable(dssdev);
302 if (r)
303 goto err_plat_en;
304 }
305
Archit Taneja6ff9dd52012-08-13 15:12:10 +0530306 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
307 dssdev->panel.timings.y_res);
Archit Tanejab02875b2012-08-13 15:26:49 +0530308 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
Archit Taneja475989b2012-08-13 15:28:15 +0530309 omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
Archit Taneja6e883322012-08-13 22:23:29 +0530310 omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
Archit Taneja6ff9dd52012-08-13 15:12:10 +0530311
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300312 r = omapdss_rfbi_display_enable(dssdev);
313 if (r)
314 goto err_rfbi_en;
315
316 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
317 conf = blizzard_read_reg(BLIZZARD_CONFIG);
318
319 switch (rev & 0xfc) {
320 case 0x9c:
321 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
322 dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
323 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
324 break;
325 case 0xa4:
326 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
327 dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
328 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
329 break;
330 default:
331 dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
332 r = -ENODEV;
333 goto err_inv_chip;
334 }
335
336 /* panel */
337
338 gpio_direction_output(bdata->panel_reset, 1);
339
340 mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
341 dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
342 display_id[0], display_id[1], display_id[2]);
343
344 switch (display_id[0]) {
345 case 0x45:
346 panel_name = "lph8923";
347 break;
348 case 0x83:
349 panel_name = "ls041y3";
350 break;
351 default:
352 dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
353 display_id[0]);
354 r = -ENODEV;
355 goto err_inv_panel;
356 }
357
358 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
359 panel_name, display_id[1]);
360
361 send_sleep_out(spi);
362 send_init_string(spi);
363 set_data_lines(spi, 24);
364 send_display_on(spi);
365
366 return 0;
367
368err_inv_panel:
369 /*
370 * HACK: we should turn off the panel here, but there is some problem
371 * with the initialization sequence, and we fail to init the panel if we
372 * have turned it off
373 */
374 /* gpio_direction_output(bdata->panel_reset, 0); */
375err_inv_chip:
376 omapdss_rfbi_display_disable(dssdev);
377err_rfbi_en:
378 if (bdata->platform_disable)
379 bdata->platform_disable(dssdev);
380err_plat_en:
381 gpio_direction_output(bdata->ctrl_pwrdown, 0);
382 return r;
383}
384
385static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
386{
387 struct panel_n8x0_data *bdata = get_board_data(dssdev);
388 struct panel_drv_data *ddata = get_drv_data(dssdev);
389 struct spi_device *spi = ddata->spidev;
390
391 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
392 return;
393
394 send_display_off(spi);
395 send_sleep_in(spi);
396
397 if (bdata->platform_disable)
398 bdata->platform_disable(dssdev);
399
400 /*
401 * HACK: we should turn off the panel here, but there is some problem
402 * with the initialization sequence, and we fail to init the panel if we
403 * have turned it off
404 */
405 /* gpio_direction_output(bdata->panel_reset, 0); */
406 gpio_direction_output(bdata->ctrl_pwrdown, 0);
407 omapdss_rfbi_display_disable(dssdev);
408}
409
410static const struct rfbi_timings n8x0_panel_timings = {
411 .cs_on_time = 0,
412
413 .we_on_time = 9000,
414 .we_off_time = 18000,
415 .we_cycle_time = 36000,
416
417 .re_on_time = 9000,
418 .re_off_time = 27000,
419 .re_cycle_time = 36000,
420
421 .access_time = 27000,
422 .cs_off_time = 36000,
423
424 .cs_pulse_width = 0,
425};
426
427static int n8x0_bl_update_status(struct backlight_device *dev)
428{
429 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
430 struct panel_n8x0_data *bdata = get_board_data(dssdev);
431 struct panel_drv_data *ddata = get_drv_data(dssdev);
432 int r;
433 int level;
434
435 mutex_lock(&ddata->lock);
436
437 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
438 dev->props.power == FB_BLANK_UNBLANK)
439 level = dev->props.brightness;
440 else
441 level = 0;
442
443 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
444
445 if (!bdata->set_backlight)
446 r = -EINVAL;
447 else
448 r = bdata->set_backlight(dssdev, level);
449
450 mutex_unlock(&ddata->lock);
451
452 return r;
453}
454
455static int n8x0_bl_get_intensity(struct backlight_device *dev)
456{
457 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
458 dev->props.power == FB_BLANK_UNBLANK)
459 return dev->props.brightness;
460
461 return 0;
462}
463
464static const struct backlight_ops n8x0_bl_ops = {
465 .get_brightness = n8x0_bl_get_intensity,
466 .update_status = n8x0_bl_update_status,
467};
468
469static int n8x0_panel_probe(struct omap_dss_device *dssdev)
470{
471 struct panel_n8x0_data *bdata = get_board_data(dssdev);
472 struct panel_drv_data *ddata;
473 struct backlight_device *bldev;
474 struct backlight_properties props;
475 int r;
476
477 dev_dbg(&dssdev->dev, "probe\n");
478
479 if (!bdata)
480 return -EINVAL;
481
482 s_drv_data.dssdev = dssdev;
483
484 ddata = &s_drv_data;
485
486 mutex_init(&ddata->lock);
487
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300488 dssdev->panel.timings.x_res = 800;
489 dssdev->panel.timings.y_res = 480;
490 dssdev->ctrl.pixel_size = 16;
491 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
Tomi Valkeinenab585252012-08-23 16:06:43 +0300492 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300493
494 memset(&props, 0, sizeof(props));
495 props.max_brightness = 127;
496 props.type = BACKLIGHT_PLATFORM;
497 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
498 dssdev, &n8x0_bl_ops, &props);
499 if (IS_ERR(bldev)) {
500 r = PTR_ERR(bldev);
501 dev_err(&dssdev->dev, "register backlight failed\n");
502 return r;
503 }
504
505 ddata->bldev = bldev;
506
507 bldev->props.fb_blank = FB_BLANK_UNBLANK;
508 bldev->props.power = FB_BLANK_UNBLANK;
509 bldev->props.brightness = 127;
510
511 n8x0_bl_update_status(bldev);
512
513 return 0;
514}
515
516static void n8x0_panel_remove(struct omap_dss_device *dssdev)
517{
518 struct panel_drv_data *ddata = get_drv_data(dssdev);
519 struct backlight_device *bldev;
520
521 dev_dbg(&dssdev->dev, "remove\n");
522
523 bldev = ddata->bldev;
524 bldev->props.power = FB_BLANK_POWERDOWN;
525 n8x0_bl_update_status(bldev);
526 backlight_device_unregister(bldev);
527
528 dev_set_drvdata(&dssdev->dev, NULL);
529}
530
531static int n8x0_panel_enable(struct omap_dss_device *dssdev)
532{
533 struct panel_drv_data *ddata = get_drv_data(dssdev);
534 int r;
535
536 dev_dbg(&dssdev->dev, "enable\n");
537
538 mutex_lock(&ddata->lock);
539
540 rfbi_bus_lock();
541
542 r = n8x0_panel_power_on(dssdev);
543
544 rfbi_bus_unlock();
545
546 if (r) {
547 mutex_unlock(&ddata->lock);
548 return r;
549 }
550
551 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
552
553 mutex_unlock(&ddata->lock);
554
555 return 0;
556}
557
558static void n8x0_panel_disable(struct omap_dss_device *dssdev)
559{
560 struct panel_drv_data *ddata = get_drv_data(dssdev);
561
562 dev_dbg(&dssdev->dev, "disable\n");
563
564 mutex_lock(&ddata->lock);
565
566 rfbi_bus_lock();
567
568 n8x0_panel_power_off(dssdev);
569
570 rfbi_bus_unlock();
571
572 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
573
574 mutex_unlock(&ddata->lock);
575}
576
577static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
578{
579 struct panel_drv_data *ddata = get_drv_data(dssdev);
580
581 dev_dbg(&dssdev->dev, "suspend\n");
582
583 mutex_lock(&ddata->lock);
584
585 rfbi_bus_lock();
586
587 n8x0_panel_power_off(dssdev);
588
589 rfbi_bus_unlock();
590
591 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
592
593 mutex_unlock(&ddata->lock);
594
595 return 0;
596}
597
598static int n8x0_panel_resume(struct omap_dss_device *dssdev)
599{
600 struct panel_drv_data *ddata = get_drv_data(dssdev);
601 int r;
602
603 dev_dbg(&dssdev->dev, "resume\n");
604
605 mutex_lock(&ddata->lock);
606
607 rfbi_bus_lock();
608
609 r = n8x0_panel_power_on(dssdev);
610
611 rfbi_bus_unlock();
612
613 if (r) {
614 mutex_unlock(&ddata->lock);
615 return r;
616 }
617
618 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
619
620 mutex_unlock(&ddata->lock);
621
622 return 0;
623}
624
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300625static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
626 u16 *xres, u16 *yres)
627{
628 *xres = dssdev->panel.timings.x_res;
629 *yres = dssdev->panel.timings.y_res;
630}
631
632static void update_done(void *data)
633{
634 rfbi_bus_unlock();
635}
636
637static int n8x0_panel_update(struct omap_dss_device *dssdev,
638 u16 x, u16 y, u16 w, u16 h)
639{
640 struct panel_drv_data *ddata = get_drv_data(dssdev);
Archit Taneja43eab862012-08-13 12:24:53 +0530641 u16 dw, dh;
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300642
643 dev_dbg(&dssdev->dev, "update\n");
644
Archit Taneja43eab862012-08-13 12:24:53 +0530645 dw = dssdev->panel.timings.x_res;
646 dh = dssdev->panel.timings.y_res;
647
648 if (x != 0 || y != 0 || w != dw || h != dh) {
649 dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
650 x, y, w, h);
651 return -EINVAL;
652 }
653
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300654 mutex_lock(&ddata->lock);
655 rfbi_bus_lock();
656
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300657 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
658
Archit Taneja43eab862012-08-13 12:24:53 +0530659 omap_rfbi_update(dssdev, update_done, NULL);
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300660
661 mutex_unlock(&ddata->lock);
662
663 return 0;
664}
665
666static int n8x0_panel_sync(struct omap_dss_device *dssdev)
667{
668 struct panel_drv_data *ddata = get_drv_data(dssdev);
669
670 dev_dbg(&dssdev->dev, "sync\n");
671
672 mutex_lock(&ddata->lock);
673 rfbi_bus_lock();
674 rfbi_bus_unlock();
675 mutex_unlock(&ddata->lock);
676
677 return 0;
678}
679
680static struct omap_dss_driver n8x0_panel_driver = {
681 .probe = n8x0_panel_probe,
682 .remove = n8x0_panel_remove,
683
684 .enable = n8x0_panel_enable,
685 .disable = n8x0_panel_disable,
686 .suspend = n8x0_panel_suspend,
687 .resume = n8x0_panel_resume,
688
689 .update = n8x0_panel_update,
690 .sync = n8x0_panel_sync,
691
692 .get_resolution = n8x0_panel_get_resolution,
693 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
694
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300695 .driver = {
696 .name = "n8x0_panel",
697 .owner = THIS_MODULE,
698 },
699};
700
701/* PANEL */
702
703static int mipid_spi_probe(struct spi_device *spi)
704{
705 dev_dbg(&spi->dev, "mipid_spi_probe\n");
706
707 spi->mode = SPI_MODE_0;
708
709 s_drv_data.spidev = spi;
710
711 return 0;
712}
713
714static int mipid_spi_remove(struct spi_device *spi)
715{
716 dev_dbg(&spi->dev, "mipid_spi_remove\n");
717 return 0;
718}
719
720static struct spi_driver mipid_spi_driver = {
721 .driver = {
722 .name = "lcd_mipid",
Tomi Valkeinen562a0602011-04-21 19:53:59 +0300723 .owner = THIS_MODULE,
724 },
725 .probe = mipid_spi_probe,
726 .remove = __devexit_p(mipid_spi_remove),
727};
728
729static int __init n8x0_panel_drv_init(void)
730{
731 int r;
732
733 r = spi_register_driver(&mipid_spi_driver);
734 if (r) {
735 pr_err("n8x0_panel: spi driver registration failed\n");
736 return r;
737 }
738
739 r = omap_dss_register_driver(&n8x0_panel_driver);
740 if (r) {
741 pr_err("n8x0_panel: dss driver registration failed\n");
742 spi_unregister_driver(&mipid_spi_driver);
743 return r;
744 }
745
746 return 0;
747}
748
749static void __exit n8x0_panel_drv_exit(void)
750{
751 spi_unregister_driver(&mipid_spi_driver);
752
753 omap_dss_unregister_driver(&n8x0_panel_driver);
754}
755
756module_init(n8x0_panel_drv_init);
757module_exit(n8x0_panel_drv_exit);
758MODULE_LICENSE("GPL");