aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-04-21 12:53:59 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-09-30 09:17:30 -0400
commit562a060611de60d6cceecb8a71847216679eef2a (patch)
treee3f798ebba9cd3d9a0b88cf98c10b93a5ba7db88
parent8d49fe74f59ca6305b7131e202aa08ba7ddc1137 (diff)
OMAPDSS: Add N800 panel driver
This is a driver for N800's display, ported from the old omapfb. This is a slightly lighter version of the driver as not all features of the old driver can be ported without big changes to DSS2, and also because some of the HW features used in the old driver are unclear (e.g. the power management part). That said, the new driver works fine for basic use. Architecturally the driver is not as neat as it could be. N800's display HW consists of a display buffer chip and a panel, and ideally they would be represented by separate, independent drivers. This is not currently possible, and this driver contains both buffer chip and panel driver. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/displays/Kconfig7
-rw-r--r--drivers/video/omap2/displays/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c747
-rw-r--r--include/video/omap-panel-n8x0.h15
4 files changed, 770 insertions, 0 deletions
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 16e3eab444c..0760c0448a0 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -62,4 +62,11 @@ config PANEL_ACX565AKM
62 select BACKLIGHT_CLASS_DEVICE 62 select BACKLIGHT_CLASS_DEVICE
63 help 63 help
64 This is the LCD panel used on Nokia N900 64 This is the LCD panel used on Nokia N900
65
66config PANEL_N8X0
67 tristate "N8X0 Panel"
68 depends on OMAP2_DSS_RFBI && SPI
69 select BACKLIGHT_CLASS_DEVICE
70 help
71 This is the LCD panel used on Nokia N8x0
65endmenu 72endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index abfda35d82d..fbfafc6eebb 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
8obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o 8obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
9obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 9obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
10obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o 10obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
11obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
new file mode 100644
index 00000000000..150e8bae35a
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -0,0 +1,747 @@
1/* #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
153 omap_rfbi_configure(dssdev, 16, 8);
154
155 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
156
157 omap_rfbi_configure(dssdev, 16, 16);
158}
159
160static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
161 int wlen, u8 *rbuf, int rlen)
162{
163 struct spi_message m;
164 struct spi_transfer *x, xfer[4];
165 u16 w;
166 int r;
167
168 spi_message_init(&m);
169
170 memset(xfer, 0, sizeof(xfer));
171 x = &xfer[0];
172
173 cmd &= 0xff;
174 x->tx_buf = &cmd;
175 x->bits_per_word = 9;
176 x->len = 2;
177 spi_message_add_tail(x, &m);
178
179 if (wlen) {
180 x++;
181 x->tx_buf = wbuf;
182 x->len = wlen;
183 x->bits_per_word = 9;
184 spi_message_add_tail(x, &m);
185 }
186
187 if (rlen) {
188 x++;
189 x->rx_buf = &w;
190 x->len = 1;
191 spi_message_add_tail(x, &m);
192
193 if (rlen > 1) {
194 /* Arrange for the extra clock before the first
195 * data bit.
196 */
197 x->bits_per_word = 9;
198 x->len = 2;
199
200 x++;
201 x->rx_buf = &rbuf[1];
202 x->len = rlen - 1;
203 spi_message_add_tail(x, &m);
204 }
205 }
206
207 r = spi_sync(spi, &m);
208 if (r < 0)
209 dev_dbg(&spi->dev, "spi_sync %d\n", r);
210
211 if (rlen)
212 rbuf[0] = w & 0xff;
213}
214
215static inline void mipid_cmd(struct spi_device *spi, int cmd)
216{
217 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
218}
219
220static inline void mipid_write(struct spi_device *spi,
221 int reg, const u8 *buf, int len)
222{
223 mipid_transfer(spi, reg, buf, len, NULL, 0);
224}
225
226static inline void mipid_read(struct spi_device *spi,
227 int reg, u8 *buf, int len)
228{
229 mipid_transfer(spi, reg, NULL, 0, buf, len);
230}
231
232static void set_data_lines(struct spi_device *spi, int data_lines)
233{
234 u16 par;
235
236 switch (data_lines) {
237 case 16:
238 par = 0x150;
239 break;
240 case 18:
241 par = 0x160;
242 break;
243 case 24:
244 par = 0x170;
245 break;
246 }
247
248 mipid_write(spi, 0x3a, (u8 *)&par, 2);
249}
250
251static void send_init_string(struct spi_device *spi)
252{
253 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
254 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
255}
256
257static void send_display_on(struct spi_device *spi)
258{
259 mipid_cmd(spi, MIPID_CMD_DISP_ON);
260}
261
262static void send_display_off(struct spi_device *spi)
263{
264 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
265}
266
267static void send_sleep_out(struct spi_device *spi)
268{
269 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
270 msleep(120);
271}
272
273static void send_sleep_in(struct spi_device *spi)
274{
275 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
276 msleep(50);
277}
278
279static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
280{
281 int r;
282 struct panel_n8x0_data *bdata = get_board_data(dssdev);
283 struct panel_drv_data *ddata = get_drv_data(dssdev);
284 struct spi_device *spi = ddata->spidev;
285 u8 rev, conf;
286 u8 display_id[3];
287 const char *panel_name;
288
289 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
290 return 0;
291
292 gpio_direction_output(bdata->ctrl_pwrdown, 1);
293
294 if (bdata->platform_enable) {
295 r = bdata->platform_enable(dssdev);
296 if (r)
297 goto err_plat_en;
298 }
299
300 r = omapdss_rfbi_display_enable(dssdev);
301 if (r)
302 goto err_rfbi_en;
303
304 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
305 conf = blizzard_read_reg(BLIZZARD_CONFIG);
306
307 switch (rev & 0xfc) {
308 case 0x9c:
309 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
310 dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
311 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
312 break;
313 case 0xa4:
314 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
315 dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
316 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
317 break;
318 default:
319 dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
320 r = -ENODEV;
321 goto err_inv_chip;
322 }
323
324 /* panel */
325
326 gpio_direction_output(bdata->panel_reset, 1);
327
328 mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
329 dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
330 display_id[0], display_id[1], display_id[2]);
331
332 switch (display_id[0]) {
333 case 0x45:
334 panel_name = "lph8923";
335 break;
336 case 0x83:
337 panel_name = "ls041y3";
338 break;
339 default:
340 dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
341 display_id[0]);
342 r = -ENODEV;
343 goto err_inv_panel;
344 }
345
346 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
347 panel_name, display_id[1]);
348
349 send_sleep_out(spi);
350 send_init_string(spi);
351 set_data_lines(spi, 24);
352 send_display_on(spi);
353
354 return 0;
355
356err_inv_panel:
357 /*
358 * HACK: we should turn off the panel here, but there is some problem
359 * with the initialization sequence, and we fail to init the panel if we
360 * have turned it off
361 */
362 /* gpio_direction_output(bdata->panel_reset, 0); */
363err_inv_chip:
364 omapdss_rfbi_display_disable(dssdev);
365err_rfbi_en:
366 if (bdata->platform_disable)
367 bdata->platform_disable(dssdev);
368err_plat_en:
369 gpio_direction_output(bdata->ctrl_pwrdown, 0);
370 return r;
371}
372
373static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
374{
375 struct panel_n8x0_data *bdata = get_board_data(dssdev);
376 struct panel_drv_data *ddata = get_drv_data(dssdev);
377 struct spi_device *spi = ddata->spidev;
378
379 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
380 return;
381
382 send_display_off(spi);
383 send_sleep_in(spi);
384
385 if (bdata->platform_disable)
386 bdata->platform_disable(dssdev);
387
388 /*
389 * HACK: we should turn off the panel here, but there is some problem
390 * with the initialization sequence, and we fail to init the panel if we
391 * have turned it off
392 */
393 /* gpio_direction_output(bdata->panel_reset, 0); */
394 gpio_direction_output(bdata->ctrl_pwrdown, 0);
395 omapdss_rfbi_display_disable(dssdev);
396}
397
398static const struct rfbi_timings n8x0_panel_timings = {
399 .cs_on_time = 0,
400
401 .we_on_time = 9000,
402 .we_off_time = 18000,
403 .we_cycle_time = 36000,
404
405 .re_on_time = 9000,
406 .re_off_time = 27000,
407 .re_cycle_time = 36000,
408
409 .access_time = 27000,
410 .cs_off_time = 36000,
411
412 .cs_pulse_width = 0,
413};
414
415static int n8x0_bl_update_status(struct backlight_device *dev)
416{
417 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
418 struct panel_n8x0_data *bdata = get_board_data(dssdev);
419 struct panel_drv_data *ddata = get_drv_data(dssdev);
420 int r;
421 int level;
422
423 mutex_lock(&ddata->lock);
424
425 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
426 dev->props.power == FB_BLANK_UNBLANK)
427 level = dev->props.brightness;
428 else
429 level = 0;
430
431 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
432
433 if (!bdata->set_backlight)
434 r = -EINVAL;
435 else
436 r = bdata->set_backlight(dssdev, level);
437
438 mutex_unlock(&ddata->lock);
439
440 return r;
441}
442
443static int n8x0_bl_get_intensity(struct backlight_device *dev)
444{
445 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
446 dev->props.power == FB_BLANK_UNBLANK)
447 return dev->props.brightness;
448
449 return 0;
450}
451
452static const struct backlight_ops n8x0_bl_ops = {
453 .get_brightness = n8x0_bl_get_intensity,
454 .update_status = n8x0_bl_update_status,
455};
456
457static int n8x0_panel_probe(struct omap_dss_device *dssdev)
458{
459 struct panel_n8x0_data *bdata = get_board_data(dssdev);
460 struct panel_drv_data *ddata;
461 struct backlight_device *bldev;
462 struct backlight_properties props;
463 int r;
464
465 dev_dbg(&dssdev->dev, "probe\n");
466
467 if (!bdata)
468 return -EINVAL;
469
470 s_drv_data.dssdev = dssdev;
471
472 ddata = &s_drv_data;
473
474 mutex_init(&ddata->lock);
475
476 dssdev->panel.config = OMAP_DSS_LCD_TFT;
477 dssdev->panel.timings.x_res = 800;
478 dssdev->panel.timings.y_res = 480;
479 dssdev->ctrl.pixel_size = 16;
480 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
481
482 memset(&props, 0, sizeof(props));
483 props.max_brightness = 127;
484 props.type = BACKLIGHT_PLATFORM;
485 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
486 dssdev, &n8x0_bl_ops, &props);
487 if (IS_ERR(bldev)) {
488 r = PTR_ERR(bldev);
489 dev_err(&dssdev->dev, "register backlight failed\n");
490 return r;
491 }
492
493 ddata->bldev = bldev;
494
495 bldev->props.fb_blank = FB_BLANK_UNBLANK;
496 bldev->props.power = FB_BLANK_UNBLANK;
497 bldev->props.brightness = 127;
498
499 n8x0_bl_update_status(bldev);
500
501 return 0;
502}
503
504static void n8x0_panel_remove(struct omap_dss_device *dssdev)
505{
506 struct panel_drv_data *ddata = get_drv_data(dssdev);
507 struct backlight_device *bldev;
508
509 dev_dbg(&dssdev->dev, "remove\n");
510
511 bldev = ddata->bldev;
512 bldev->props.power = FB_BLANK_POWERDOWN;
513 n8x0_bl_update_status(bldev);
514 backlight_device_unregister(bldev);
515
516 dev_set_drvdata(&dssdev->dev, NULL);
517}
518
519static int n8x0_panel_enable(struct omap_dss_device *dssdev)
520{
521 struct panel_drv_data *ddata = get_drv_data(dssdev);
522 int r;
523
524 dev_dbg(&dssdev->dev, "enable\n");
525
526 mutex_lock(&ddata->lock);
527
528 rfbi_bus_lock();
529
530 r = n8x0_panel_power_on(dssdev);
531
532 rfbi_bus_unlock();
533
534 if (r) {
535 mutex_unlock(&ddata->lock);
536 return r;
537 }
538
539 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
540
541 mutex_unlock(&ddata->lock);
542
543 return 0;
544}
545
546static void n8x0_panel_disable(struct omap_dss_device *dssdev)
547{
548 struct panel_drv_data *ddata = get_drv_data(dssdev);
549
550 dev_dbg(&dssdev->dev, "disable\n");
551
552 mutex_lock(&ddata->lock);
553
554 rfbi_bus_lock();
555
556 n8x0_panel_power_off(dssdev);
557
558 rfbi_bus_unlock();
559
560 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
561
562 mutex_unlock(&ddata->lock);
563}
564
565static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
566{
567 struct panel_drv_data *ddata = get_drv_data(dssdev);
568
569 dev_dbg(&dssdev->dev, "suspend\n");
570
571 mutex_lock(&ddata->lock);
572
573 rfbi_bus_lock();
574
575 n8x0_panel_power_off(dssdev);
576
577 rfbi_bus_unlock();
578
579 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
580
581 mutex_unlock(&ddata->lock);
582
583 return 0;
584}
585
586static int n8x0_panel_resume(struct omap_dss_device *dssdev)
587{
588 struct panel_drv_data *ddata = get_drv_data(dssdev);
589 int r;
590
591 dev_dbg(&dssdev->dev, "resume\n");
592
593 mutex_lock(&ddata->lock);
594
595 rfbi_bus_lock();
596
597 r = n8x0_panel_power_on(dssdev);
598
599 rfbi_bus_unlock();
600
601 if (r) {
602 mutex_unlock(&ddata->lock);
603 return r;
604 }
605
606 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
607
608 mutex_unlock(&ddata->lock);
609
610 return 0;
611}
612
613static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
614 struct omap_video_timings *timings)
615{
616 *timings = dssdev->panel.timings;
617}
618
619static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
620 u16 *xres, u16 *yres)
621{
622 *xres = dssdev->panel.timings.x_res;
623 *yres = dssdev->panel.timings.y_res;
624}
625
626static void update_done(void *data)
627{
628 rfbi_bus_unlock();
629}
630
631static int n8x0_panel_update(struct omap_dss_device *dssdev,
632 u16 x, u16 y, u16 w, u16 h)
633{
634 struct panel_drv_data *ddata = get_drv_data(dssdev);
635
636 dev_dbg(&dssdev->dev, "update\n");
637
638 mutex_lock(&ddata->lock);
639 rfbi_bus_lock();
640
641 omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
642
643 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
644
645 omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
646
647 mutex_unlock(&ddata->lock);
648
649 return 0;
650}
651
652static int n8x0_panel_sync(struct omap_dss_device *dssdev)
653{
654 struct panel_drv_data *ddata = get_drv_data(dssdev);
655
656 dev_dbg(&dssdev->dev, "sync\n");
657
658 mutex_lock(&ddata->lock);
659 rfbi_bus_lock();
660 rfbi_bus_unlock();
661 mutex_unlock(&ddata->lock);
662
663 return 0;
664}
665
666static struct omap_dss_driver n8x0_panel_driver = {
667 .probe = n8x0_panel_probe,
668 .remove = n8x0_panel_remove,
669
670 .enable = n8x0_panel_enable,
671 .disable = n8x0_panel_disable,
672 .suspend = n8x0_panel_suspend,
673 .resume = n8x0_panel_resume,
674
675 .update = n8x0_panel_update,
676 .sync = n8x0_panel_sync,
677
678 .get_resolution = n8x0_panel_get_resolution,
679 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
680
681 .get_timings = n8x0_panel_get_timings,
682
683 .driver = {
684 .name = "n8x0_panel",
685 .owner = THIS_MODULE,
686 },
687};
688
689/* PANEL */
690
691static int mipid_spi_probe(struct spi_device *spi)
692{
693 dev_dbg(&spi->dev, "mipid_spi_probe\n");
694
695 spi->mode = SPI_MODE_0;
696
697 s_drv_data.spidev = spi;
698
699 return 0;
700}
701
702static int mipid_spi_remove(struct spi_device *spi)
703{
704 dev_dbg(&spi->dev, "mipid_spi_remove\n");
705 return 0;
706}
707
708static struct spi_driver mipid_spi_driver = {
709 .driver = {
710 .name = "lcd_mipid",
711 .bus = &spi_bus_type,
712 .owner = THIS_MODULE,
713 },
714 .probe = mipid_spi_probe,
715 .remove = __devexit_p(mipid_spi_remove),
716};
717
718static int __init n8x0_panel_drv_init(void)
719{
720 int r;
721
722 r = spi_register_driver(&mipid_spi_driver);
723 if (r) {
724 pr_err("n8x0_panel: spi driver registration failed\n");
725 return r;
726 }
727
728 r = omap_dss_register_driver(&n8x0_panel_driver);
729 if (r) {
730 pr_err("n8x0_panel: dss driver registration failed\n");
731 spi_unregister_driver(&mipid_spi_driver);
732 return r;
733 }
734
735 return 0;
736}
737
738static void __exit n8x0_panel_drv_exit(void)
739{
740 spi_unregister_driver(&mipid_spi_driver);
741
742 omap_dss_unregister_driver(&n8x0_panel_driver);
743}
744
745module_init(n8x0_panel_drv_init);
746module_exit(n8x0_panel_drv_exit);
747MODULE_LICENSE("GPL");
diff --git a/include/video/omap-panel-n8x0.h b/include/video/omap-panel-n8x0.h
new file mode 100644
index 00000000000..50a1302e2cf
--- /dev/null
+++ b/include/video/omap-panel-n8x0.h
@@ -0,0 +1,15 @@
1#ifndef __OMAP_PANEL_N8X0_H
2#define __OMAP_PANEL_N8X0_H
3
4struct omap_dss_device;
5
6struct panel_n8x0_data {
7 int (*platform_enable)(struct omap_dss_device *dssdev);
8 void (*platform_disable)(struct omap_dss_device *dssdev);
9 int panel_reset;
10 int ctrl_pwrdown;
11
12 int (*set_backlight)(struct omap_dss_device *dssdev, int level);
13};
14
15#endif