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>
11 #include <video/omapdss.h>
12 #include <video/omap-panel-n8x0.h>
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
40 /* Data source select */
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
47 #define BLIZZARD_SRC_WRITE_LCD 0x00
48 #define BLIZZARD_SRC_BLT_LCD 0x06
50 #define BLIZZARD_COLOR_RGB565 0x01
51 #define BLIZZARD_COLOR_YUV420 0x09
53 #define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
54 #define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
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
67 static struct panel_drv_data
{
70 struct omap_dss_device
*dssdev
;
71 struct spi_device
*spidev
;
72 struct backlight_device
*bldev
;
79 struct panel_n8x0_data
*get_board_data(const struct omap_dss_device
*dssdev
)
85 struct panel_drv_data
*get_drv_data(const struct omap_dss_device
*dssdev
)
91 static inline void blizzard_cmd(u8 cmd
)
93 omap_rfbi_write_command(&cmd
, 1);
96 static inline void blizzard_write(u8 cmd
, const u8
*buf
, int len
)
98 omap_rfbi_write_command(&cmd
, 1);
99 omap_rfbi_write_data(buf
, len
);
102 static inline void blizzard_read(u8 cmd
, u8
*buf
, int len
)
104 omap_rfbi_write_command(&cmd
, 1);
105 omap_rfbi_read_data(buf
, len
);
108 static u8
blizzard_read_reg(u8 cmd
)
111 blizzard_read(cmd
, &data
, 1);
115 static void blizzard_ctrl_setup_update(struct omap_dss_device
*dssdev
,
116 int x
, int y
, int w
, int h
)
118 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
140 tmp
[13] = x_end
>> 8;
142 tmp
[15] = y_end
>> 8;
144 tmp
[16] = BLIZZARD_COLOR_RGB565
;
146 if (ddata
->blizzard_ver
== BLIZZARD_VERSION_S1D13745
)
147 tmp
[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND
;
149 tmp
[17] = ddata
->blizzard_ver
== BLIZZARD_VERSION_S1D13744
?
150 BLIZZARD_SRC_WRITE_LCD
:
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE
;
153 omap_rfbi_configure(dssdev
, 16, 8);
155 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0
, tmp
, 18);
157 omap_rfbi_configure(dssdev
, 16, 16);
160 static void mipid_transfer(struct spi_device
*spi
, int cmd
, const u8
*wbuf
,
161 int wlen
, u8
*rbuf
, int rlen
)
163 struct spi_message m
;
164 struct spi_transfer
*x
, xfer
[4];
168 spi_message_init(&m
);
170 memset(xfer
, 0, sizeof(xfer
));
175 x
->bits_per_word
= 9;
177 spi_message_add_tail(x
, &m
);
183 x
->bits_per_word
= 9;
184 spi_message_add_tail(x
, &m
);
191 spi_message_add_tail(x
, &m
);
194 /* Arrange for the extra clock before the first
197 x
->bits_per_word
= 9;
201 x
->rx_buf
= &rbuf
[1];
203 spi_message_add_tail(x
, &m
);
207 r
= spi_sync(spi
, &m
);
209 dev_dbg(&spi
->dev
, "spi_sync %d\n", r
);
215 static inline void mipid_cmd(struct spi_device
*spi
, int cmd
)
217 mipid_transfer(spi
, cmd
, NULL
, 0, NULL
, 0);
220 static inline void mipid_write(struct spi_device
*spi
,
221 int reg
, const u8
*buf
, int len
)
223 mipid_transfer(spi
, reg
, buf
, len
, NULL
, 0);
226 static inline void mipid_read(struct spi_device
*spi
,
227 int reg
, u8
*buf
, int len
)
229 mipid_transfer(spi
, reg
, NULL
, 0, buf
, len
);
232 static void set_data_lines(struct spi_device
*spi
, int data_lines
)
236 switch (data_lines
) {
248 mipid_write(spi
, 0x3a, (u8
*)&par
, 2);
251 static void send_init_string(struct spi_device
*spi
)
253 u16 initpar
[] = { 0x0102, 0x0100, 0x0100 };
254 mipid_write(spi
, 0xc2, (u8
*)initpar
, sizeof(initpar
));
257 static void send_display_on(struct spi_device
*spi
)
259 mipid_cmd(spi
, MIPID_CMD_DISP_ON
);
262 static void send_display_off(struct spi_device
*spi
)
264 mipid_cmd(spi
, MIPID_CMD_DISP_OFF
);
267 static void send_sleep_out(struct spi_device
*spi
)
269 mipid_cmd(spi
, MIPID_CMD_SLEEP_OUT
);
273 static void send_sleep_in(struct spi_device
*spi
)
275 mipid_cmd(spi
, MIPID_CMD_SLEEP_IN
);
279 static int n8x0_panel_power_on(struct omap_dss_device
*dssdev
)
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
;
287 const char *panel_name
;
289 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
)
292 gpio_direction_output(bdata
->ctrl_pwrdown
, 1);
294 if (bdata
->platform_enable
) {
295 r
= bdata
->platform_enable(dssdev
);
300 r
= omapdss_rfbi_display_enable(dssdev
);
304 rev
= blizzard_read_reg(BLIZZARD_REV_CODE
);
305 conf
= blizzard_read_reg(BLIZZARD_CONFIG
);
307 switch (rev
& 0xfc) {
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);
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);
319 dev_err(&dssdev
->dev
, "invalid s1d1374x revision %02x\n", rev
);
326 gpio_direction_output(bdata
->panel_reset
, 1);
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]);
332 switch (display_id
[0]) {
334 panel_name
= "lph8923";
337 panel_name
= "ls041y3";
340 dev_err(&dssdev
->dev
, "invalid display ID 0x%x\n",
346 dev_info(&dssdev
->dev
, "%s rev %02x LCD detected\n",
347 panel_name
, display_id
[1]);
350 send_init_string(spi
);
351 set_data_lines(spi
, 24);
352 send_display_on(spi
);
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
362 /* gpio_direction_output(bdata->panel_reset, 0); */
364 omapdss_rfbi_display_disable(dssdev
);
366 if (bdata
->platform_disable
)
367 bdata
->platform_disable(dssdev
);
369 gpio_direction_output(bdata
->ctrl_pwrdown
, 0);
373 static void n8x0_panel_power_off(struct omap_dss_device
*dssdev
)
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
;
379 if (dssdev
->state
!= OMAP_DSS_DISPLAY_ACTIVE
)
382 send_display_off(spi
);
385 if (bdata
->platform_disable
)
386 bdata
->platform_disable(dssdev
);
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
393 /* gpio_direction_output(bdata->panel_reset, 0); */
394 gpio_direction_output(bdata
->ctrl_pwrdown
, 0);
395 omapdss_rfbi_display_disable(dssdev
);
398 static const struct rfbi_timings n8x0_panel_timings
= {
402 .we_off_time
= 18000,
403 .we_cycle_time
= 36000,
406 .re_off_time
= 27000,
407 .re_cycle_time
= 36000,
409 .access_time
= 27000,
410 .cs_off_time
= 36000,
415 static int n8x0_bl_update_status(struct backlight_device
*dev
)
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
);
423 mutex_lock(&ddata
->lock
);
425 if (dev
->props
.fb_blank
== FB_BLANK_UNBLANK
&&
426 dev
->props
.power
== FB_BLANK_UNBLANK
)
427 level
= dev
->props
.brightness
;
431 dev_dbg(&dssdev
->dev
, "update brightness to %d\n", level
);
433 if (!bdata
->set_backlight
)
436 r
= bdata
->set_backlight(dssdev
, level
);
438 mutex_unlock(&ddata
->lock
);
443 static int n8x0_bl_get_intensity(struct backlight_device
*dev
)
445 if (dev
->props
.fb_blank
== FB_BLANK_UNBLANK
&&
446 dev
->props
.power
== FB_BLANK_UNBLANK
)
447 return dev
->props
.brightness
;
452 static const struct backlight_ops n8x0_bl_ops
= {
453 .get_brightness
= n8x0_bl_get_intensity
,
454 .update_status
= n8x0_bl_update_status
,
457 static int n8x0_panel_probe(struct omap_dss_device
*dssdev
)
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
;
465 dev_dbg(&dssdev
->dev
, "probe\n");
470 s_drv_data
.dssdev
= dssdev
;
474 mutex_init(&ddata
->lock
);
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
;
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
);
489 dev_err(&dssdev
->dev
, "register backlight failed\n");
493 ddata
->bldev
= bldev
;
495 bldev
->props
.fb_blank
= FB_BLANK_UNBLANK
;
496 bldev
->props
.power
= FB_BLANK_UNBLANK
;
497 bldev
->props
.brightness
= 127;
499 n8x0_bl_update_status(bldev
);
504 static void n8x0_panel_remove(struct omap_dss_device
*dssdev
)
506 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
507 struct backlight_device
*bldev
;
509 dev_dbg(&dssdev
->dev
, "remove\n");
511 bldev
= ddata
->bldev
;
512 bldev
->props
.power
= FB_BLANK_POWERDOWN
;
513 n8x0_bl_update_status(bldev
);
514 backlight_device_unregister(bldev
);
516 dev_set_drvdata(&dssdev
->dev
, NULL
);
519 static int n8x0_panel_enable(struct omap_dss_device
*dssdev
)
521 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
524 dev_dbg(&dssdev
->dev
, "enable\n");
526 mutex_lock(&ddata
->lock
);
530 r
= n8x0_panel_power_on(dssdev
);
535 mutex_unlock(&ddata
->lock
);
539 dssdev
->state
= OMAP_DSS_DISPLAY_ACTIVE
;
541 mutex_unlock(&ddata
->lock
);
546 static void n8x0_panel_disable(struct omap_dss_device
*dssdev
)
548 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
550 dev_dbg(&dssdev
->dev
, "disable\n");
552 mutex_lock(&ddata
->lock
);
556 n8x0_panel_power_off(dssdev
);
560 dssdev
->state
= OMAP_DSS_DISPLAY_DISABLED
;
562 mutex_unlock(&ddata
->lock
);
565 static int n8x0_panel_suspend(struct omap_dss_device
*dssdev
)
567 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
569 dev_dbg(&dssdev
->dev
, "suspend\n");
571 mutex_lock(&ddata
->lock
);
575 n8x0_panel_power_off(dssdev
);
579 dssdev
->state
= OMAP_DSS_DISPLAY_SUSPENDED
;
581 mutex_unlock(&ddata
->lock
);
586 static int n8x0_panel_resume(struct omap_dss_device
*dssdev
)
588 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
591 dev_dbg(&dssdev
->dev
, "resume\n");
593 mutex_lock(&ddata
->lock
);
597 r
= n8x0_panel_power_on(dssdev
);
602 mutex_unlock(&ddata
->lock
);
606 dssdev
->state
= OMAP_DSS_DISPLAY_ACTIVE
;
608 mutex_unlock(&ddata
->lock
);
613 static void n8x0_panel_get_timings(struct omap_dss_device
*dssdev
,
614 struct omap_video_timings
*timings
)
616 *timings
= dssdev
->panel
.timings
;
619 static void n8x0_panel_get_resolution(struct omap_dss_device
*dssdev
,
620 u16
*xres
, u16
*yres
)
622 *xres
= dssdev
->panel
.timings
.x_res
;
623 *yres
= dssdev
->panel
.timings
.y_res
;
626 static void update_done(void *data
)
631 static int n8x0_panel_update(struct omap_dss_device
*dssdev
,
632 u16 x
, u16 y
, u16 w
, u16 h
)
634 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
636 dev_dbg(&dssdev
->dev
, "update\n");
638 mutex_lock(&ddata
->lock
);
641 omap_rfbi_prepare_update(dssdev
, &x
, &y
, &w
, &h
);
643 blizzard_ctrl_setup_update(dssdev
, x
, y
, w
, h
);
645 omap_rfbi_update(dssdev
, x
, y
, w
, h
, update_done
, NULL
);
647 mutex_unlock(&ddata
->lock
);
652 static int n8x0_panel_sync(struct omap_dss_device
*dssdev
)
654 struct panel_drv_data
*ddata
= get_drv_data(dssdev
);
656 dev_dbg(&dssdev
->dev
, "sync\n");
658 mutex_lock(&ddata
->lock
);
661 mutex_unlock(&ddata
->lock
);
666 static struct omap_dss_driver n8x0_panel_driver
= {
667 .probe
= n8x0_panel_probe
,
668 .remove
= n8x0_panel_remove
,
670 .enable
= n8x0_panel_enable
,
671 .disable
= n8x0_panel_disable
,
672 .suspend
= n8x0_panel_suspend
,
673 .resume
= n8x0_panel_resume
,
675 .update
= n8x0_panel_update
,
676 .sync
= n8x0_panel_sync
,
678 .get_resolution
= n8x0_panel_get_resolution
,
679 .get_recommended_bpp
= omapdss_default_get_recommended_bpp
,
681 .get_timings
= n8x0_panel_get_timings
,
684 .name
= "n8x0_panel",
685 .owner
= THIS_MODULE
,
691 static int mipid_spi_probe(struct spi_device
*spi
)
693 dev_dbg(&spi
->dev
, "mipid_spi_probe\n");
695 spi
->mode
= SPI_MODE_0
;
697 s_drv_data
.spidev
= spi
;
702 static int mipid_spi_remove(struct spi_device
*spi
)
704 dev_dbg(&spi
->dev
, "mipid_spi_remove\n");
708 static struct spi_driver mipid_spi_driver
= {
711 .owner
= THIS_MODULE
,
713 .probe
= mipid_spi_probe
,
714 .remove
= __devexit_p(mipid_spi_remove
),
717 static int __init
n8x0_panel_drv_init(void)
721 r
= spi_register_driver(&mipid_spi_driver
);
723 pr_err("n8x0_panel: spi driver registration failed\n");
727 r
= omap_dss_register_driver(&n8x0_panel_driver
);
729 pr_err("n8x0_panel: dss driver registration failed\n");
730 spi_unregister_driver(&mipid_spi_driver
);
737 static void __exit
n8x0_panel_drv_exit(void)
739 spi_unregister_driver(&mipid_spi_driver
);
741 omap_dss_unregister_driver(&n8x0_panel_driver
);
744 module_init(n8x0_panel_drv_init
);
745 module_exit(n8x0_panel_drv_exit
);
746 MODULE_LICENSE("GPL");