diff options
Diffstat (limited to 'drivers/video/omap2/displays/panel-taal.c')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 127 |
1 files changed, 74 insertions, 53 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 125586490e3..4cf94161ff5 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -121,6 +121,18 @@ struct taal_data { | |||
121 | 121 | ||
122 | struct omap_dss_device *dssdev; | 122 | struct omap_dss_device *dssdev; |
123 | 123 | ||
124 | /* panel specific HW info */ | ||
125 | struct panel_config *panel_config; | ||
126 | |||
127 | /* panel HW configuration from DT or platform data */ | ||
128 | int reset_gpio; | ||
129 | int ext_te_gpio; | ||
130 | |||
131 | bool use_dsi_backlight; | ||
132 | |||
133 | struct omap_dsi_pin_config pin_config; | ||
134 | |||
135 | /* runtime variables */ | ||
124 | bool enabled; | 136 | bool enabled; |
125 | u8 rotate; | 137 | u8 rotate; |
126 | bool mirror; | 138 | bool mirror; |
@@ -145,16 +157,8 @@ struct taal_data { | |||
145 | bool ulps_enabled; | 157 | bool ulps_enabled; |
146 | unsigned ulps_timeout; | 158 | unsigned ulps_timeout; |
147 | struct delayed_work ulps_work; | 159 | struct delayed_work ulps_work; |
148 | |||
149 | struct panel_config *panel_config; | ||
150 | }; | 160 | }; |
151 | 161 | ||
152 | static inline struct nokia_dsi_panel_data | ||
153 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
154 | { | ||
155 | return (struct nokia_dsi_panel_data *) dssdev->data; | ||
156 | } | ||
157 | |||
158 | static void taal_esd_work(struct work_struct *work); | 162 | static void taal_esd_work(struct work_struct *work); |
159 | static void taal_ulps_work(struct work_struct *work); | 163 | static void taal_ulps_work(struct work_struct *work); |
160 | 164 | ||
@@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev) | |||
371 | static int taal_enter_ulps(struct omap_dss_device *dssdev) | 375 | static int taal_enter_ulps(struct omap_dss_device *dssdev) |
372 | { | 376 | { |
373 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 377 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
374 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
375 | int r; | 378 | int r; |
376 | 379 | ||
377 | if (td->ulps_enabled) | 380 | if (td->ulps_enabled) |
@@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev) | |||
383 | if (r) | 386 | if (r) |
384 | goto err; | 387 | goto err; |
385 | 388 | ||
386 | disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | 389 | if (gpio_is_valid(td->ext_te_gpio)) |
390 | disable_irq(gpio_to_irq(td->ext_te_gpio)); | ||
387 | 391 | ||
388 | omapdss_dsi_display_disable(dssdev, false, true); | 392 | omapdss_dsi_display_disable(dssdev, false, true); |
389 | 393 | ||
@@ -405,7 +409,6 @@ err: | |||
405 | static int taal_exit_ulps(struct omap_dss_device *dssdev) | 409 | static int taal_exit_ulps(struct omap_dss_device *dssdev) |
406 | { | 410 | { |
407 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 411 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
408 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
409 | int r; | 412 | int r; |
410 | 413 | ||
411 | if (!td->ulps_enabled) | 414 | if (!td->ulps_enabled) |
@@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev) | |||
425 | goto err2; | 428 | goto err2; |
426 | } | 429 | } |
427 | 430 | ||
428 | enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | 431 | if (gpio_is_valid(td->ext_te_gpio)) |
432 | enable_irq(gpio_to_irq(td->ext_te_gpio)); | ||
429 | 433 | ||
430 | taal_queue_ulps_work(dssdev); | 434 | taal_queue_ulps_work(dssdev); |
431 | 435 | ||
@@ -438,7 +442,8 @@ err2: | |||
438 | 442 | ||
439 | r = taal_panel_reset(dssdev); | 443 | r = taal_panel_reset(dssdev); |
440 | if (!r) { | 444 | if (!r) { |
441 | enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | 445 | if (gpio_is_valid(td->ext_te_gpio)) |
446 | enable_irq(gpio_to_irq(td->ext_te_gpio)); | ||
442 | td->ulps_enabled = false; | 447 | td->ulps_enabled = false; |
443 | } | 448 | } |
444 | err1: | 449 | err1: |
@@ -835,71 +840,93 @@ static struct attribute_group taal_attr_group = { | |||
835 | static void taal_hw_reset(struct omap_dss_device *dssdev) | 840 | static void taal_hw_reset(struct omap_dss_device *dssdev) |
836 | { | 841 | { |
837 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 842 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
838 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
839 | 843 | ||
840 | if (panel_data->reset_gpio == -1) | 844 | if (!gpio_is_valid(td->reset_gpio)) |
841 | return; | 845 | return; |
842 | 846 | ||
843 | gpio_set_value(panel_data->reset_gpio, 1); | 847 | gpio_set_value(td->reset_gpio, 1); |
844 | if (td->panel_config->reset_sequence.high) | 848 | if (td->panel_config->reset_sequence.high) |
845 | udelay(td->panel_config->reset_sequence.high); | 849 | udelay(td->panel_config->reset_sequence.high); |
846 | /* reset the panel */ | 850 | /* reset the panel */ |
847 | gpio_set_value(panel_data->reset_gpio, 0); | 851 | gpio_set_value(td->reset_gpio, 0); |
848 | /* assert reset */ | 852 | /* assert reset */ |
849 | if (td->panel_config->reset_sequence.low) | 853 | if (td->panel_config->reset_sequence.low) |
850 | udelay(td->panel_config->reset_sequence.low); | 854 | udelay(td->panel_config->reset_sequence.low); |
851 | gpio_set_value(panel_data->reset_gpio, 1); | 855 | gpio_set_value(td->reset_gpio, 1); |
852 | /* wait after releasing reset */ | 856 | /* wait after releasing reset */ |
853 | if (td->panel_config->sleep.hw_reset) | 857 | if (td->panel_config->sleep.hw_reset) |
854 | msleep(td->panel_config->sleep.hw_reset); | 858 | msleep(td->panel_config->sleep.hw_reset); |
855 | } | 859 | } |
856 | 860 | ||
861 | static void taal_probe_pdata(struct taal_data *td, | ||
862 | const struct nokia_dsi_panel_data *pdata) | ||
863 | { | ||
864 | td->reset_gpio = pdata->reset_gpio; | ||
865 | |||
866 | if (pdata->use_ext_te) | ||
867 | td->ext_te_gpio = pdata->ext_te_gpio; | ||
868 | else | ||
869 | td->ext_te_gpio = -1; | ||
870 | |||
871 | td->esd_interval = pdata->esd_interval; | ||
872 | td->ulps_timeout = pdata->ulps_timeout; | ||
873 | |||
874 | td->use_dsi_backlight = pdata->use_dsi_backlight; | ||
875 | |||
876 | td->pin_config = pdata->pin_config; | ||
877 | } | ||
878 | |||
857 | static int taal_probe(struct omap_dss_device *dssdev) | 879 | static int taal_probe(struct omap_dss_device *dssdev) |
858 | { | 880 | { |
859 | struct backlight_properties props; | 881 | struct backlight_properties props; |
860 | struct taal_data *td; | 882 | struct taal_data *td; |
861 | struct backlight_device *bldev = NULL; | 883 | struct backlight_device *bldev = NULL; |
862 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
863 | struct panel_config *panel_config = NULL; | ||
864 | int r, i; | 884 | int r, i; |
885 | const char *panel_name; | ||
865 | 886 | ||
866 | dev_dbg(&dssdev->dev, "probe\n"); | 887 | dev_dbg(&dssdev->dev, "probe\n"); |
867 | 888 | ||
868 | if (!panel_data || !panel_data->name) | 889 | td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL); |
890 | if (!td) | ||
891 | return -ENOMEM; | ||
892 | |||
893 | dev_set_drvdata(&dssdev->dev, td); | ||
894 | td->dssdev = dssdev; | ||
895 | |||
896 | if (dssdev->data) { | ||
897 | const struct nokia_dsi_panel_data *pdata = dssdev->data; | ||
898 | |||
899 | taal_probe_pdata(td, pdata); | ||
900 | |||
901 | panel_name = pdata->name; | ||
902 | } else { | ||
903 | return -ENODEV; | ||
904 | } | ||
905 | |||
906 | if (panel_name == NULL) | ||
869 | return -EINVAL; | 907 | return -EINVAL; |
870 | 908 | ||
871 | for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { | 909 | for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { |
872 | if (strcmp(panel_data->name, panel_configs[i].name) == 0) { | 910 | if (strcmp(panel_name, panel_configs[i].name) == 0) { |
873 | panel_config = &panel_configs[i]; | 911 | td->panel_config = &panel_configs[i]; |
874 | break; | 912 | break; |
875 | } | 913 | } |
876 | } | 914 | } |
877 | 915 | ||
878 | if (!panel_config) | 916 | if (!td->panel_config) |
879 | return -EINVAL; | 917 | return -EINVAL; |
880 | 918 | ||
881 | dssdev->panel.timings = panel_config->timings; | 919 | dssdev->panel.timings = td->panel_config->timings; |
882 | dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; | 920 | dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; |
883 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 921 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
884 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 922 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
885 | 923 | ||
886 | td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL); | ||
887 | if (!td) | ||
888 | return -ENOMEM; | ||
889 | td->dssdev = dssdev; | ||
890 | td->panel_config = panel_config; | ||
891 | td->esd_interval = panel_data->esd_interval; | ||
892 | td->ulps_enabled = false; | ||
893 | td->ulps_timeout = panel_data->ulps_timeout; | ||
894 | |||
895 | mutex_init(&td->lock); | 924 | mutex_init(&td->lock); |
896 | 925 | ||
897 | atomic_set(&td->do_update, 0); | 926 | atomic_set(&td->do_update, 0); |
898 | 927 | ||
899 | dev_set_drvdata(&dssdev->dev, td); | 928 | if (gpio_is_valid(td->reset_gpio)) { |
900 | 929 | r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio, | |
901 | if (gpio_is_valid(panel_data->reset_gpio)) { | ||
902 | r = devm_gpio_request_one(&dssdev->dev, panel_data->reset_gpio, | ||
903 | GPIOF_OUT_INIT_LOW, "taal rst"); | 930 | GPIOF_OUT_INIT_LOW, "taal rst"); |
904 | if (r) { | 931 | if (r) { |
905 | dev_err(&dssdev->dev, "failed to request reset gpio\n"); | 932 | dev_err(&dssdev->dev, "failed to request reset gpio\n"); |
@@ -907,17 +934,15 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
907 | } | 934 | } |
908 | } | 935 | } |
909 | 936 | ||
910 | if (panel_data->use_ext_te) { | 937 | if (gpio_is_valid(td->ext_te_gpio)) { |
911 | int gpio = panel_data->ext_te_gpio; | 938 | r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio, |
912 | 939 | GPIOF_IN, "taal irq"); | |
913 | r = devm_gpio_request_one(&dssdev->dev, gpio, GPIOF_IN, | ||
914 | "taal irq"); | ||
915 | if (r) { | 940 | if (r) { |
916 | dev_err(&dssdev->dev, "GPIO request failed\n"); | 941 | dev_err(&dssdev->dev, "GPIO request failed\n"); |
917 | return r; | 942 | return r; |
918 | } | 943 | } |
919 | 944 | ||
920 | r = devm_request_irq(&dssdev->dev, gpio_to_irq(gpio), | 945 | r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio), |
921 | taal_te_isr, | 946 | taal_te_isr, |
922 | IRQF_TRIGGER_RISING, | 947 | IRQF_TRIGGER_RISING, |
923 | "taal vsync", dssdev); | 948 | "taal vsync", dssdev); |
@@ -943,7 +968,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
943 | 968 | ||
944 | taal_hw_reset(dssdev); | 969 | taal_hw_reset(dssdev); |
945 | 970 | ||
946 | if (panel_data->use_dsi_backlight) { | 971 | if (td->use_dsi_backlight) { |
947 | memset(&props, 0, sizeof(struct backlight_properties)); | 972 | memset(&props, 0, sizeof(struct backlight_properties)); |
948 | props.max_brightness = 255; | 973 | props.max_brightness = 255; |
949 | 974 | ||
@@ -1022,11 +1047,10 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) | |||
1022 | static int taal_power_on(struct omap_dss_device *dssdev) | 1047 | static int taal_power_on(struct omap_dss_device *dssdev) |
1023 | { | 1048 | { |
1024 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1049 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1025 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1026 | u8 id1, id2, id3; | 1050 | u8 id1, id2, id3; |
1027 | int r; | 1051 | int r; |
1028 | 1052 | ||
1029 | r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config); | 1053 | r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); |
1030 | if (r) { | 1054 | if (r) { |
1031 | dev_err(&dssdev->dev, "failed to configure DSI pins\n"); | 1055 | dev_err(&dssdev->dev, "failed to configure DSI pins\n"); |
1032 | goto err0; | 1056 | goto err0; |
@@ -1339,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1339 | u16 x, u16 y, u16 w, u16 h) | 1363 | u16 x, u16 y, u16 w, u16 h) |
1340 | { | 1364 | { |
1341 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1365 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1342 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1343 | int r; | 1366 | int r; |
1344 | 1367 | ||
1345 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); | 1368 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); |
@@ -1363,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1363 | if (r) | 1386 | if (r) |
1364 | goto err; | 1387 | goto err; |
1365 | 1388 | ||
1366 | if (td->te_enabled && panel_data->use_ext_te) { | 1389 | if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) { |
1367 | schedule_delayed_work(&td->te_timeout_work, | 1390 | schedule_delayed_work(&td->te_timeout_work, |
1368 | msecs_to_jiffies(250)); | 1391 | msecs_to_jiffies(250)); |
1369 | atomic_set(&td->do_update, 1); | 1392 | atomic_set(&td->do_update, 1); |
@@ -1402,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev) | |||
1402 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 1425 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) |
1403 | { | 1426 | { |
1404 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1427 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1405 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1406 | int r; | 1428 | int r; |
1407 | 1429 | ||
1408 | if (enable) | 1430 | if (enable) |
@@ -1410,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1410 | else | 1432 | else |
1411 | r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); | 1433 | r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); |
1412 | 1434 | ||
1413 | if (!panel_data->use_ext_te) | 1435 | if (!gpio_is_valid(td->ext_te_gpio)) |
1414 | omapdss_dsi_enable_te(dssdev, enable); | 1436 | omapdss_dsi_enable_te(dssdev, enable); |
1415 | 1437 | ||
1416 | if (td->panel_config->sleep.enable_te) | 1438 | if (td->panel_config->sleep.enable_te) |
@@ -1720,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work) | |||
1720 | struct taal_data *td = container_of(work, struct taal_data, | 1742 | struct taal_data *td = container_of(work, struct taal_data, |
1721 | esd_work.work); | 1743 | esd_work.work); |
1722 | struct omap_dss_device *dssdev = td->dssdev; | 1744 | struct omap_dss_device *dssdev = td->dssdev; |
1723 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1724 | u8 state1, state2; | 1745 | u8 state1, state2; |
1725 | int r; | 1746 | int r; |
1726 | 1747 | ||
@@ -1767,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1767 | } | 1788 | } |
1768 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1789 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
1769 | * to re-enable TE after self diagnostics */ | 1790 | * to re-enable TE after self diagnostics */ |
1770 | if (td->te_enabled && panel_data->use_ext_te) { | 1791 | if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) { |
1771 | r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); | 1792 | r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); |
1772 | if (r) | 1793 | if (r) |
1773 | goto err; | 1794 | goto err; |