Avoid beyond bounds copy while caching ACL
[zen-stable.git] / drivers / video / omap2 / displays / panel-n8x0.c
blobdc9408dc93d1ed36f702187aebab9e5d7605b84b
1 /* #define DEBUG */
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>
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 */
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
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 {
68 struct mutex lock;
70 struct omap_dss_device *dssdev;
71 struct spi_device *spidev;
72 struct backlight_device *bldev;
74 int blizzard_ver;
75 } s_drv_data;
78 static inline
79 struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
81 return dssdev->data;
84 static inline
85 struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
87 return &s_drv_data;
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)
110 u8 data;
111 blizzard_read(cmd, &data, 1);
112 return data;
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);
119 u8 tmp[18];
120 int x_end, y_end;
122 x_end = x + w - 1;
123 y_end = y + h - 1;
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;
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;
144 tmp[16] = BLIZZARD_COLOR_RGB565;
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;
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];
165 u16 w;
166 int r;
168 spi_message_init(&m);
170 memset(xfer, 0, sizeof(xfer));
171 x = &xfer[0];
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);
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);
187 if (rlen) {
188 x++;
189 x->rx_buf = &w;
190 x->len = 1;
191 spi_message_add_tail(x, &m);
193 if (rlen > 1) {
194 /* Arrange for the extra clock before the first
195 * data bit.
197 x->bits_per_word = 9;
198 x->len = 2;
200 x++;
201 x->rx_buf = &rbuf[1];
202 x->len = rlen - 1;
203 spi_message_add_tail(x, &m);
207 r = spi_sync(spi, &m);
208 if (r < 0)
209 dev_dbg(&spi->dev, "spi_sync %d\n", r);
211 if (rlen)
212 rbuf[0] = w & 0xff;
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)
234 u16 par;
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;
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);
270 msleep(120);
273 static void send_sleep_in(struct spi_device *spi)
275 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
276 msleep(50);
279 static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
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;
289 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
290 return 0;
292 gpio_direction_output(bdata->ctrl_pwrdown, 1);
294 if (bdata->platform_enable) {
295 r = bdata->platform_enable(dssdev);
296 if (r)
297 goto err_plat_en;
300 r = omapdss_rfbi_display_enable(dssdev);
301 if (r)
302 goto err_rfbi_en;
304 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
305 conf = blizzard_read_reg(BLIZZARD_CONFIG);
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;
324 /* panel */
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]) {
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;
346 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
347 panel_name, display_id[1]);
349 send_sleep_out(spi);
350 send_init_string(spi);
351 set_data_lines(spi, 24);
352 send_display_on(spi);
354 return 0;
356 err_inv_panel:
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
362 /* gpio_direction_output(bdata->panel_reset, 0); */
363 err_inv_chip:
364 omapdss_rfbi_display_disable(dssdev);
365 err_rfbi_en:
366 if (bdata->platform_disable)
367 bdata->platform_disable(dssdev);
368 err_plat_en:
369 gpio_direction_output(bdata->ctrl_pwrdown, 0);
370 return r;
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)
380 return;
382 send_display_off(spi);
383 send_sleep_in(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
391 * have turned it off
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 = {
399 .cs_on_time = 0,
401 .we_on_time = 9000,
402 .we_off_time = 18000,
403 .we_cycle_time = 36000,
405 .re_on_time = 9000,
406 .re_off_time = 27000,
407 .re_cycle_time = 36000,
409 .access_time = 27000,
410 .cs_off_time = 36000,
412 .cs_pulse_width = 0,
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);
420 int r;
421 int level;
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;
428 else
429 level = 0;
431 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
433 if (!bdata->set_backlight)
434 r = -EINVAL;
435 else
436 r = bdata->set_backlight(dssdev, level);
438 mutex_unlock(&ddata->lock);
440 return r;
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;
449 return 0;
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;
463 int r;
465 dev_dbg(&dssdev->dev, "probe\n");
467 if (!bdata)
468 return -EINVAL;
470 s_drv_data.dssdev = dssdev;
472 ddata = &s_drv_data;
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);
487 if (IS_ERR(bldev)) {
488 r = PTR_ERR(bldev);
489 dev_err(&dssdev->dev, "register backlight failed\n");
490 return r;
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);
501 return 0;
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);
522 int r;
524 dev_dbg(&dssdev->dev, "enable\n");
526 mutex_lock(&ddata->lock);
528 rfbi_bus_lock();
530 r = n8x0_panel_power_on(dssdev);
532 rfbi_bus_unlock();
534 if (r) {
535 mutex_unlock(&ddata->lock);
536 return r;
539 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
541 mutex_unlock(&ddata->lock);
543 return 0;
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);
554 rfbi_bus_lock();
556 n8x0_panel_power_off(dssdev);
558 rfbi_bus_unlock();
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);
573 rfbi_bus_lock();
575 n8x0_panel_power_off(dssdev);
577 rfbi_bus_unlock();
579 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
581 mutex_unlock(&ddata->lock);
583 return 0;
586 static int n8x0_panel_resume(struct omap_dss_device *dssdev)
588 struct panel_drv_data *ddata = get_drv_data(dssdev);
589 int r;
591 dev_dbg(&dssdev->dev, "resume\n");
593 mutex_lock(&ddata->lock);
595 rfbi_bus_lock();
597 r = n8x0_panel_power_on(dssdev);
599 rfbi_bus_unlock();
601 if (r) {
602 mutex_unlock(&ddata->lock);
603 return r;
606 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
608 mutex_unlock(&ddata->lock);
610 return 0;
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)
628 rfbi_bus_unlock();
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);
639 rfbi_bus_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);
649 return 0;
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);
659 rfbi_bus_lock();
660 rfbi_bus_unlock();
661 mutex_unlock(&ddata->lock);
663 return 0;
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,
683 .driver = {
684 .name = "n8x0_panel",
685 .owner = THIS_MODULE,
689 /* PANEL */
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;
699 return 0;
702 static int mipid_spi_remove(struct spi_device *spi)
704 dev_dbg(&spi->dev, "mipid_spi_remove\n");
705 return 0;
708 static struct spi_driver mipid_spi_driver = {
709 .driver = {
710 .name = "lcd_mipid",
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)
719 int r;
721 r = spi_register_driver(&mipid_spi_driver);
722 if (r) {
723 pr_err("n8x0_panel: spi driver registration failed\n");
724 return r;
727 r = omap_dss_register_driver(&n8x0_panel_driver);
728 if (r) {
729 pr_err("n8x0_panel: dss driver registration failed\n");
730 spi_unregister_driver(&mipid_spi_driver);
731 return r;
734 return 0;
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");