diff options
Diffstat (limited to 'drivers/video/omap2/displays/panel-taal.c')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 108 |
1 files changed, 87 insertions, 21 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index eb95e97fd9b0..311bd5fb14a6 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -68,6 +68,58 @@ static irqreturn_t taal_te_isr(int irq, void *data); | |||
68 | static void taal_te_timeout_work_callback(struct work_struct *work); | 68 | static void taal_te_timeout_work_callback(struct work_struct *work); |
69 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | 69 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); |
70 | 70 | ||
71 | /** | ||
72 | * struct panel_config - panel configuration | ||
73 | * @name: panel name | ||
74 | * @type: panel type | ||
75 | * @timings: panel resolution | ||
76 | * @sleep: various panel specific delays, passed to msleep() if non-zero | ||
77 | * @reset_sequence: reset sequence timings, passed to udelay() if non-zero | ||
78 | */ | ||
79 | struct panel_config { | ||
80 | const char *name; | ||
81 | int type; | ||
82 | |||
83 | struct omap_video_timings timings; | ||
84 | |||
85 | struct { | ||
86 | unsigned int sleep_in; | ||
87 | unsigned int sleep_out; | ||
88 | unsigned int hw_reset; | ||
89 | unsigned int enable_te; | ||
90 | } sleep; | ||
91 | |||
92 | struct { | ||
93 | unsigned int high; | ||
94 | unsigned int low; | ||
95 | } reset_sequence; | ||
96 | }; | ||
97 | |||
98 | enum { | ||
99 | PANEL_TAAL, | ||
100 | }; | ||
101 | |||
102 | static struct panel_config panel_configs[] = { | ||
103 | { | ||
104 | .name = "taal", | ||
105 | .type = PANEL_TAAL, | ||
106 | .timings = { | ||
107 | .x_res = 864, | ||
108 | .y_res = 480, | ||
109 | }, | ||
110 | .sleep = { | ||
111 | .sleep_in = 5, | ||
112 | .sleep_out = 5, | ||
113 | .hw_reset = 5, | ||
114 | .enable_te = 100, /* possible panel bug */ | ||
115 | }, | ||
116 | .reset_sequence = { | ||
117 | .high = 10, | ||
118 | .low = 10, | ||
119 | }, | ||
120 | }, | ||
121 | }; | ||
122 | |||
71 | struct taal_data { | 123 | struct taal_data { |
72 | struct mutex lock; | 124 | struct mutex lock; |
73 | 125 | ||
@@ -104,6 +156,8 @@ struct taal_data { | |||
104 | 156 | ||
105 | struct workqueue_struct *esd_wq; | 157 | struct workqueue_struct *esd_wq; |
106 | struct delayed_work esd_work; | 158 | struct delayed_work esd_work; |
159 | |||
160 | struct panel_config *panel_config; | ||
107 | }; | 161 | }; |
108 | 162 | ||
109 | static inline struct nokia_dsi_panel_data | 163 | static inline struct nokia_dsi_panel_data |
@@ -173,7 +227,8 @@ static int taal_sleep_in(struct taal_data *td) | |||
173 | 227 | ||
174 | hw_guard_start(td, 120); | 228 | hw_guard_start(td, 120); |
175 | 229 | ||
176 | msleep(5); | 230 | if (td->panel_config->sleep.sleep_in) |
231 | msleep(td->panel_config->sleep.sleep_in); | ||
177 | 232 | ||
178 | return 0; | 233 | return 0; |
179 | } | 234 | } |
@@ -190,7 +245,8 @@ static int taal_sleep_out(struct taal_data *td) | |||
190 | 245 | ||
191 | hw_guard_start(td, 120); | 246 | hw_guard_start(td, 120); |
192 | 247 | ||
193 | msleep(5); | 248 | if (td->panel_config->sleep.sleep_out) |
249 | msleep(td->panel_config->sleep.sleep_out); | ||
194 | 250 | ||
195 | return 0; | 251 | return 0; |
196 | } | 252 | } |
@@ -509,20 +565,24 @@ static struct attribute_group taal_attr_group = { | |||
509 | 565 | ||
510 | static void taal_hw_reset(struct omap_dss_device *dssdev) | 566 | static void taal_hw_reset(struct omap_dss_device *dssdev) |
511 | { | 567 | { |
568 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
512 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 569 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
513 | 570 | ||
514 | if (panel_data->reset_gpio == -1) | 571 | if (panel_data->reset_gpio == -1) |
515 | return; | 572 | return; |
516 | 573 | ||
517 | gpio_set_value(panel_data->reset_gpio, 1); | 574 | gpio_set_value(panel_data->reset_gpio, 1); |
518 | udelay(10); | 575 | if (td->panel_config->reset_sequence.high) |
576 | udelay(td->panel_config->reset_sequence.high); | ||
519 | /* reset the panel */ | 577 | /* reset the panel */ |
520 | gpio_set_value(panel_data->reset_gpio, 0); | 578 | gpio_set_value(panel_data->reset_gpio, 0); |
521 | /* assert reset for at least 10us */ | 579 | /* assert reset */ |
522 | udelay(10); | 580 | if (td->panel_config->reset_sequence.low) |
581 | udelay(td->panel_config->reset_sequence.low); | ||
523 | gpio_set_value(panel_data->reset_gpio, 1); | 582 | gpio_set_value(panel_data->reset_gpio, 1); |
524 | /* wait 5ms after releasing reset */ | 583 | /* wait after releasing reset */ |
525 | msleep(5); | 584 | if (td->panel_config->sleep.hw_reset) |
585 | msleep(td->panel_config->sleep.hw_reset); | ||
526 | } | 586 | } |
527 | 587 | ||
528 | static int taal_probe(struct omap_dss_device *dssdev) | 588 | static int taal_probe(struct omap_dss_device *dssdev) |
@@ -531,12 +591,8 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
531 | struct taal_data *td; | 591 | struct taal_data *td; |
532 | struct backlight_device *bldev; | 592 | struct backlight_device *bldev; |
533 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 593 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
534 | int r; | 594 | struct panel_config *panel_config = NULL; |
535 | 595 | int r, i; | |
536 | const struct omap_video_timings taal_panel_timings = { | ||
537 | .x_res = 864, | ||
538 | .y_res = 480, | ||
539 | }; | ||
540 | 596 | ||
541 | dev_dbg(&dssdev->dev, "probe\n"); | 597 | dev_dbg(&dssdev->dev, "probe\n"); |
542 | 598 | ||
@@ -545,8 +601,20 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
545 | goto err; | 601 | goto err; |
546 | } | 602 | } |
547 | 603 | ||
604 | for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { | ||
605 | if (strcmp(panel_data->name, panel_configs[i].name) == 0) { | ||
606 | panel_config = &panel_configs[i]; | ||
607 | break; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | if (!panel_config) { | ||
612 | r = -EINVAL; | ||
613 | goto err; | ||
614 | } | ||
615 | |||
548 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | 616 | dssdev->panel.config = OMAP_DSS_LCD_TFT; |
549 | dssdev->panel.timings = taal_panel_timings; | 617 | dssdev->panel.timings = panel_config->timings; |
550 | dssdev->ctrl.pixel_size = 24; | 618 | dssdev->ctrl.pixel_size = 24; |
551 | 619 | ||
552 | td = kzalloc(sizeof(*td), GFP_KERNEL); | 620 | td = kzalloc(sizeof(*td), GFP_KERNEL); |
@@ -555,6 +623,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
555 | goto err; | 623 | goto err; |
556 | } | 624 | } |
557 | td->dssdev = dssdev; | 625 | td->dssdev = dssdev; |
626 | td->panel_config = panel_config; | ||
558 | 627 | ||
559 | mutex_init(&td->lock); | 628 | mutex_init(&td->lock); |
560 | 629 | ||
@@ -686,9 +755,6 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
686 | u8 id1, id2, id3; | 755 | u8 id1, id2, id3; |
687 | int r; | 756 | int r; |
688 | 757 | ||
689 | /* it seems we have to wait a bit until taal is ready */ | ||
690 | msleep(5); | ||
691 | |||
692 | r = omapdss_dsi_display_enable(dssdev); | 758 | r = omapdss_dsi_display_enable(dssdev); |
693 | if (r) { | 759 | if (r) { |
694 | dev_err(&dssdev->dev, "failed to enable DSI\n"); | 760 | dev_err(&dssdev->dev, "failed to enable DSI\n"); |
@@ -774,7 +840,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
774 | r = taal_dcs_write_0(DCS_DISPLAY_OFF); | 840 | r = taal_dcs_write_0(DCS_DISPLAY_OFF); |
775 | if (!r) { | 841 | if (!r) { |
776 | r = taal_sleep_in(td); | 842 | r = taal_sleep_in(td); |
777 | /* wait a bit so that the message goes through */ | 843 | /* HACK: wait a bit so that the message goes through */ |
778 | msleep(10); | 844 | msleep(10); |
779 | } | 845 | } |
780 | 846 | ||
@@ -1036,6 +1102,7 @@ static int taal_sync(struct omap_dss_device *dssdev) | |||
1036 | 1102 | ||
1037 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 1103 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) |
1038 | { | 1104 | { |
1105 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
1039 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 1106 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
1040 | int r; | 1107 | int r; |
1041 | 1108 | ||
@@ -1047,9 +1114,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1047 | if (!panel_data->use_ext_te) | 1114 | if (!panel_data->use_ext_te) |
1048 | omapdss_dsi_enable_te(dssdev, enable); | 1115 | omapdss_dsi_enable_te(dssdev, enable); |
1049 | 1116 | ||
1050 | /* XXX for some reason, DSI TE breaks if we don't wait here. | 1117 | if (td->panel_config->sleep.enable_te) |
1051 | * Panel bug? Needs more studying */ | 1118 | msleep(td->panel_config->sleep.enable_te); |
1052 | msleep(100); | ||
1053 | 1119 | ||
1054 | return r; | 1120 | return r; |
1055 | } | 1121 | } |