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 omapdss_rfbi_set_pixel_size(dssdev, 16);
154 omapdss_rfbi_set_data_lines(dssdev, 8);
156 omap_rfbi_configure(dssdev);
158 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
160 omapdss_rfbi_set_pixel_size(dssdev, 16);
161 omapdss_rfbi_set_data_lines(dssdev, 16);
163 omap_rfbi_configure(dssdev);
166 static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
167 int wlen, u8 *rbuf, int rlen)
169 struct spi_message m;
170 struct spi_transfer *x, xfer[4];
174 spi_message_init(&m);
176 memset(xfer, 0, sizeof(xfer));
181 x->bits_per_word = 9;
183 spi_message_add_tail(x, &m);
189 x->bits_per_word = 9;
190 spi_message_add_tail(x, &m);
197 spi_message_add_tail(x, &m);
200 /* Arrange for the extra clock before the first
203 x->bits_per_word = 9;
207 x->rx_buf = &rbuf[1];
209 spi_message_add_tail(x, &m);
213 r = spi_sync(spi, &m);
215 dev_dbg(&spi->dev, "spi_sync %d\n", r);
221 static inline void mipid_cmd(struct spi_device *spi, int cmd)
223 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
226 static inline void mipid_write(struct spi_device *spi,
227 int reg, const u8 *buf, int len)
229 mipid_transfer(spi, reg, buf, len, NULL, 0);
232 static inline void mipid_read(struct spi_device *spi,
233 int reg, u8 *buf, int len)
235 mipid_transfer(spi, reg, NULL, 0, buf, len);
238 static void set_data_lines(struct spi_device *spi, int data_lines)
242 switch (data_lines) {
254 mipid_write(spi, 0x3a, (u8 *)&par, 2);
257 static void send_init_string(struct spi_device *spi)
259 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
260 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
263 static void send_display_on(struct spi_device *spi)
265 mipid_cmd(spi, MIPID_CMD_DISP_ON);
268 static void send_display_off(struct spi_device *spi)
270 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
273 static void send_sleep_out(struct spi_device *spi)
275 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
279 static void send_sleep_in(struct spi_device *spi)
281 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
285 static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
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;
293 const char *panel_name;
295 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
298 gpio_direction_output(bdata->ctrl_pwrdown, 1);
300 if (bdata->platform_enable) {
301 r = bdata->platform_enable(dssdev);
306 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
307 dssdev->panel.timings.y_res);
308 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
309 omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
310 omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
312 r = omapdss_rfbi_display_enable(dssdev);
316 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
317 conf = blizzard_read_reg(BLIZZARD_CONFIG);
319 switch (rev & 0xfc) {
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);
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);
331 dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
338 gpio_direction_output(bdata->panel_reset, 1);
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]);
344 switch (display_id[0]) {
346 panel_name = "lph8923";
349 panel_name = "ls041y3";
352 dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
358 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
359 panel_name, display_id[1]);
362 send_init_string(spi);
363 set_data_lines(spi, 24);
364 send_display_on(spi);
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
374 /* gpio_direction_output(bdata->panel_reset, 0); */
376 omapdss_rfbi_display_disable(dssdev);
378 if (bdata->platform_disable)
379 bdata->platform_disable(dssdev);
381 gpio_direction_output(bdata->ctrl_pwrdown, 0);
385 static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
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;
391 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
394 send_display_off(spi);
397 if (bdata->platform_disable)
398 bdata->platform_disable(dssdev);
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
405 /* gpio_direction_output(bdata->panel_reset, 0); */
406 gpio_direction_output(bdata->ctrl_pwrdown, 0);
407 omapdss_rfbi_display_disable(dssdev);
410 static const struct rfbi_timings n8x0_panel_timings = {
414 .we_off_time = 18000,
415 .we_cycle_time = 36000,
418 .re_off_time = 27000,
419 .re_cycle_time = 36000,
421 .access_time = 27000,
422 .cs_off_time = 36000,
427 static int n8x0_bl_update_status(struct backlight_device *dev)
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);
435 mutex_lock(&ddata->lock);
437 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
438 dev->props.power == FB_BLANK_UNBLANK)
439 level = dev->props.brightness;
443 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
445 if (!bdata->set_backlight)
448 r = bdata->set_backlight(dssdev, level);
450 mutex_unlock(&ddata->lock);
455 static int n8x0_bl_get_intensity(struct backlight_device *dev)
457 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
458 dev->props.power == FB_BLANK_UNBLANK)
459 return dev->props.brightness;
464 static const struct backlight_ops n8x0_bl_ops = {
465 .get_brightness = n8x0_bl_get_intensity,
466 .update_status = n8x0_bl_update_status,
469 static int n8x0_panel_probe(struct omap_dss_device *dssdev)
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;
477 dev_dbg(&dssdev->dev, "probe\n");
482 s_drv_data.dssdev = dssdev;
486 mutex_init(&ddata->lock);
488 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;
492 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
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);
501 dev_err(&dssdev->dev, "register backlight failed\n");
505 ddata->bldev = bldev;
507 bldev->props.fb_blank = FB_BLANK_UNBLANK;
508 bldev->props.power = FB_BLANK_UNBLANK;
509 bldev->props.brightness = 127;
511 n8x0_bl_update_status(bldev);
516 static void n8x0_panel_remove(struct omap_dss_device *dssdev)
518 struct panel_drv_data *ddata = get_drv_data(dssdev);
519 struct backlight_device *bldev;
521 dev_dbg(&dssdev->dev, "remove\n");
523 bldev = ddata->bldev;
524 bldev->props.power = FB_BLANK_POWERDOWN;
525 n8x0_bl_update_status(bldev);
526 backlight_device_unregister(bldev);
528 dev_set_drvdata(&dssdev->dev, NULL);
531 static int n8x0_panel_enable(struct omap_dss_device *dssdev)
533 struct panel_drv_data *ddata = get_drv_data(dssdev);
536 dev_dbg(&dssdev->dev, "enable\n");
538 mutex_lock(&ddata->lock);
542 r = n8x0_panel_power_on(dssdev);
547 mutex_unlock(&ddata->lock);
551 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
553 mutex_unlock(&ddata->lock);
558 static void n8x0_panel_disable(struct omap_dss_device *dssdev)
560 struct panel_drv_data *ddata = get_drv_data(dssdev);
562 dev_dbg(&dssdev->dev, "disable\n");
564 mutex_lock(&ddata->lock);
568 n8x0_panel_power_off(dssdev);
572 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
574 mutex_unlock(&ddata->lock);
577 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
578 u16 *xres, u16 *yres)
580 *xres = dssdev->panel.timings.x_res;
581 *yres = dssdev->panel.timings.y_res;
584 static void update_done(void *data)
589 static int n8x0_panel_update(struct omap_dss_device *dssdev,
590 u16 x, u16 y, u16 w, u16 h)
592 struct panel_drv_data *ddata = get_drv_data(dssdev);
595 dev_dbg(&dssdev->dev, "update\n");
597 dw = dssdev->panel.timings.x_res;
598 dh = dssdev->panel.timings.y_res;
600 if (x != 0 || y != 0 || w != dw || h != dh) {
601 dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
606 mutex_lock(&ddata->lock);
609 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
611 omap_rfbi_update(dssdev, update_done, NULL);
613 mutex_unlock(&ddata->lock);
618 static int n8x0_panel_sync(struct omap_dss_device *dssdev)
620 struct panel_drv_data *ddata = get_drv_data(dssdev);
622 dev_dbg(&dssdev->dev, "sync\n");
624 mutex_lock(&ddata->lock);
627 mutex_unlock(&ddata->lock);
632 static struct omap_dss_driver n8x0_panel_driver = {
633 .probe = n8x0_panel_probe,
634 .remove = n8x0_panel_remove,
636 .enable = n8x0_panel_enable,
637 .disable = n8x0_panel_disable,
639 .update = n8x0_panel_update,
640 .sync = n8x0_panel_sync,
642 .get_resolution = n8x0_panel_get_resolution,
643 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
646 .name = "n8x0_panel",
647 .owner = THIS_MODULE,
653 static int mipid_spi_probe(struct spi_device *spi)
657 dev_dbg(&spi->dev, "mipid_spi_probe\n");
659 spi->mode = SPI_MODE_0;
661 s_drv_data.spidev = spi;
663 r = omap_dss_register_driver(&n8x0_panel_driver);
665 pr_err("n8x0_panel: dss driver registration failed\n");
670 static int mipid_spi_remove(struct spi_device *spi)
672 dev_dbg(&spi->dev, "mipid_spi_remove\n");
673 omap_dss_unregister_driver(&n8x0_panel_driver);
677 static struct spi_driver mipid_spi_driver = {
680 .owner = THIS_MODULE,
682 .probe = mipid_spi_probe,
683 .remove = mipid_spi_remove,
685 module_spi_driver(mipid_spi_driver);
687 MODULE_LICENSE("GPL");