aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-03-24 08:53:27 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-05-11 07:20:48 -0400
commit1abf78145412ef185d553dccfab661e7c88c0b20 (patch)
treef2f036f23d16846f686cc38f607f042933a55203 /drivers/video/omap2
parent883b9ac95e2075fa8edd9260d8818b756f96440b (diff)
OMAP: DSS2: Taal: Implement ULPS functionality
ULPS is a low power state where the DSI lanes are kept at ground. This patch implements ULPS by having a DSI bus inactivity timer which triggers the entry to ULPS. ULPS exit will happen automatically when the driver needs to do something on the DSI lanes. The ulps_timeout is configurable from board file or via sysfs. Additionally another sysfs file, "ulps", can be used to check the current ULPS state, or to manually enter or exit ULPS. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/displays/panel-taal.c310
1 files changed, 303 insertions, 7 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index a743b7cee7a..be230b3ff87 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -67,6 +67,8 @@ static irqreturn_t taal_te_isr(int irq, void *data);
67static void taal_te_timeout_work_callback(struct work_struct *work); 67static void taal_te_timeout_work_callback(struct work_struct *work);
68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
69 69
70static int taal_panel_reset(struct omap_dss_device *dssdev);
71
70struct panel_regulator { 72struct panel_regulator {
71 struct regulator *regulator; 73 struct regulator *regulator;
72 const char *name; 74 const char *name;
@@ -232,6 +234,10 @@ struct taal_data {
232 struct delayed_work esd_work; 234 struct delayed_work esd_work;
233 unsigned esd_interval; 235 unsigned esd_interval;
234 236
237 bool ulps_enabled;
238 unsigned ulps_timeout;
239 struct delayed_work ulps_work;
240
235 struct panel_config *panel_config; 241 struct panel_config *panel_config;
236}; 242};
237 243
@@ -242,6 +248,7 @@ static inline struct nokia_dsi_panel_data
242} 248}
243 249
244static void taal_esd_work(struct work_struct *work); 250static void taal_esd_work(struct work_struct *work);
251static void taal_ulps_work(struct work_struct *work);
245 252
246static void hw_guard_start(struct taal_data *td, int guard_msec) 253static void hw_guard_start(struct taal_data *td, int guard_msec)
247{ 254{
@@ -437,6 +444,107 @@ static void taal_cancel_esd_work(struct omap_dss_device *dssdev)
437 cancel_delayed_work(&td->esd_work); 444 cancel_delayed_work(&td->esd_work);
438} 445}
439 446
447static void taal_queue_ulps_work(struct omap_dss_device *dssdev)
448{
449 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
450
451 if (td->ulps_timeout > 0)
452 queue_delayed_work(td->workqueue, &td->ulps_work,
453 msecs_to_jiffies(td->ulps_timeout));
454}
455
456static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
457{
458 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
459
460 cancel_delayed_work(&td->ulps_work);
461}
462
463static int taal_enter_ulps(struct omap_dss_device *dssdev)
464{
465 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
466 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
467 int r;
468
469 if (td->ulps_enabled)
470 return 0;
471
472 taal_cancel_ulps_work(dssdev);
473
474 r = _taal_enable_te(dssdev, false);
475 if (r)
476 goto err;
477
478 disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
479
480 omapdss_dsi_display_disable(dssdev, false, true);
481
482 td->ulps_enabled = true;
483
484 return 0;
485
486err:
487 dev_err(&dssdev->dev, "enter ULPS failed");
488 taal_panel_reset(dssdev);
489
490 td->ulps_enabled = false;
491
492 taal_queue_ulps_work(dssdev);
493
494 return r;
495}
496
497static int taal_exit_ulps(struct omap_dss_device *dssdev)
498{
499 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
500 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
501 int r;
502
503 if (!td->ulps_enabled)
504 return 0;
505
506 r = omapdss_dsi_display_enable(dssdev);
507 if (r)
508 goto err;
509
510 omapdss_dsi_vc_enable_hs(td->channel, true);
511
512 r = _taal_enable_te(dssdev, true);
513 if (r)
514 goto err;
515
516 enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
517
518 taal_queue_ulps_work(dssdev);
519
520 td->ulps_enabled = false;
521
522 return 0;
523
524err:
525 dev_err(&dssdev->dev, "exit ULPS failed");
526 r = taal_panel_reset(dssdev);
527
528 enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
529 td->ulps_enabled = false;
530
531 taal_queue_ulps_work(dssdev);
532
533 return r;
534}
535
536static int taal_wake_up(struct omap_dss_device *dssdev)
537{
538 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
539
540 if (td->ulps_enabled)
541 return taal_exit_ulps(dssdev);
542
543 taal_cancel_ulps_work(dssdev);
544 taal_queue_ulps_work(dssdev);
545 return 0;
546}
547
440static int taal_bl_update_status(struct backlight_device *dev) 548static int taal_bl_update_status(struct backlight_device *dev)
441{ 549{
442 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 550 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
@@ -458,7 +566,11 @@ static int taal_bl_update_status(struct backlight_device *dev)
458 if (td->use_dsi_bl) { 566 if (td->use_dsi_bl) {
459 if (td->enabled) { 567 if (td->enabled) {
460 dsi_bus_lock(); 568 dsi_bus_lock();
461 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); 569
570 r = taal_wake_up(dssdev);
571 if (!r)
572 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
573
462 dsi_bus_unlock(); 574 dsi_bus_unlock();
463 } else { 575 } else {
464 r = 0; 576 r = 0;
@@ -521,7 +633,11 @@ static ssize_t taal_num_errors_show(struct device *dev,
521 633
522 if (td->enabled) { 634 if (td->enabled) {
523 dsi_bus_lock(); 635 dsi_bus_lock();
524 r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); 636
637 r = taal_wake_up(dssdev);
638 if (!r)
639 r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
640
525 dsi_bus_unlock(); 641 dsi_bus_unlock();
526 } else { 642 } else {
527 r = -ENODEV; 643 r = -ENODEV;
@@ -547,7 +663,11 @@ static ssize_t taal_hw_revision_show(struct device *dev,
547 663
548 if (td->enabled) { 664 if (td->enabled) {
549 dsi_bus_lock(); 665 dsi_bus_lock();
550 r = taal_get_id(td, &id1, &id2, &id3); 666
667 r = taal_wake_up(dssdev);
668 if (!r)
669 r = taal_get_id(td, &id1, &id2, &id3);
670
551 dsi_bus_unlock(); 671 dsi_bus_unlock();
552 } else { 672 } else {
553 r = -ENODEV; 673 r = -ENODEV;
@@ -595,6 +715,7 @@ static ssize_t store_cabc_mode(struct device *dev,
595 struct omap_dss_device *dssdev = to_dss_device(dev); 715 struct omap_dss_device *dssdev = to_dss_device(dev);
596 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 716 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
597 int i; 717 int i;
718 int r;
598 719
599 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { 720 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
600 if (sysfs_streq(cabc_modes[i], buf)) 721 if (sysfs_streq(cabc_modes[i], buf))
@@ -608,8 +729,17 @@ static ssize_t store_cabc_mode(struct device *dev,
608 729
609 if (td->enabled) { 730 if (td->enabled) {
610 dsi_bus_lock(); 731 dsi_bus_lock();
611 if (!td->cabc_broken) 732
612 taal_dcs_write_1(td, DCS_WRITE_CABC, i); 733 if (!td->cabc_broken) {
734 r = taal_wake_up(dssdev);
735 if (r)
736 goto err;
737
738 r = taal_dcs_write_1(td, DCS_WRITE_CABC, i);
739 if (r)
740 goto err;
741 }
742
613 dsi_bus_unlock(); 743 dsi_bus_unlock();
614 } 744 }
615 745
@@ -618,6 +748,10 @@ static ssize_t store_cabc_mode(struct device *dev,
618 mutex_unlock(&td->lock); 748 mutex_unlock(&td->lock);
619 749
620 return count; 750 return count;
751err:
752 dsi_bus_unlock();
753 mutex_unlock(&td->lock);
754 return r;
621} 755}
622 756
623static ssize_t show_cabc_available_modes(struct device *dev, 757static ssize_t show_cabc_available_modes(struct device *dev,
@@ -675,6 +809,101 @@ static ssize_t taal_show_esd_interval(struct device *dev,
675 return snprintf(buf, PAGE_SIZE, "%u\n", t); 809 return snprintf(buf, PAGE_SIZE, "%u\n", t);
676} 810}
677 811
812static ssize_t taal_store_ulps(struct device *dev,
813 struct device_attribute *attr,
814 const char *buf, size_t count)
815{
816 struct omap_dss_device *dssdev = to_dss_device(dev);
817 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
818 unsigned long t;
819 int r;
820
821 r = strict_strtoul(buf, 10, &t);
822 if (r)
823 return r;
824
825 mutex_lock(&td->lock);
826
827 if (td->enabled) {
828 dsi_bus_lock();
829
830 if (t)
831 r = taal_enter_ulps(dssdev);
832 else
833 r = taal_wake_up(dssdev);
834
835 dsi_bus_unlock();
836 }
837
838 mutex_unlock(&td->lock);
839
840 if (r)
841 return r;
842
843 return count;
844}
845
846static ssize_t taal_show_ulps(struct device *dev,
847 struct device_attribute *attr,
848 char *buf)
849{
850 struct omap_dss_device *dssdev = to_dss_device(dev);
851 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
852 unsigned t;
853
854 mutex_lock(&td->lock);
855 t = td->ulps_enabled;
856 mutex_unlock(&td->lock);
857
858 return snprintf(buf, PAGE_SIZE, "%u\n", t);
859}
860
861static ssize_t taal_store_ulps_timeout(struct device *dev,
862 struct device_attribute *attr,
863 const char *buf, size_t count)
864{
865 struct omap_dss_device *dssdev = to_dss_device(dev);
866 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
867 unsigned long t;
868 int r;
869
870 r = strict_strtoul(buf, 10, &t);
871 if (r)
872 return r;
873
874 mutex_lock(&td->lock);
875 td->ulps_timeout = t;
876
877 if (td->enabled) {
878 /* taal_wake_up will restart the timer */
879 dsi_bus_lock();
880 r = taal_wake_up(dssdev);
881 dsi_bus_unlock();
882 }
883
884 mutex_unlock(&td->lock);
885
886 if (r)
887 return r;
888
889 return count;
890}
891
892static ssize_t taal_show_ulps_timeout(struct device *dev,
893 struct device_attribute *attr,
894 char *buf)
895{
896 struct omap_dss_device *dssdev = to_dss_device(dev);
897 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
898 unsigned t;
899
900 mutex_lock(&td->lock);
901 t = td->ulps_timeout;
902 mutex_unlock(&td->lock);
903
904 return snprintf(buf, PAGE_SIZE, "%u\n", t);
905}
906
678static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); 907static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
679static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); 908static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
680static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, 909static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
@@ -683,6 +912,10 @@ static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
683 show_cabc_available_modes, NULL); 912 show_cabc_available_modes, NULL);
684static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR, 913static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR,
685 taal_show_esd_interval, taal_store_esd_interval); 914 taal_show_esd_interval, taal_store_esd_interval);
915static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
916 taal_show_ulps, taal_store_ulps);
917static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
918 taal_show_ulps_timeout, taal_store_ulps_timeout);
686 919
687static struct attribute *taal_attrs[] = { 920static struct attribute *taal_attrs[] = {
688 &dev_attr_num_dsi_errors.attr, 921 &dev_attr_num_dsi_errors.attr,
@@ -690,6 +923,8 @@ static struct attribute *taal_attrs[] = {
690 &dev_attr_cabc_mode.attr, 923 &dev_attr_cabc_mode.attr,
691 &dev_attr_cabc_available_modes.attr, 924 &dev_attr_cabc_available_modes.attr,
692 &dev_attr_esd_interval.attr, 925 &dev_attr_esd_interval.attr,
926 &dev_attr_ulps.attr,
927 &dev_attr_ulps_timeout.attr,
693 NULL, 928 NULL,
694}; 929};
695 930
@@ -759,6 +994,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
759 td->dssdev = dssdev; 994 td->dssdev = dssdev;
760 td->panel_config = panel_config; 995 td->panel_config = panel_config;
761 td->esd_interval = panel_data->esd_interval; 996 td->esd_interval = panel_data->esd_interval;
997 td->ulps_enabled = false;
998 td->ulps_timeout = panel_data->ulps_timeout;
762 999
763 mutex_init(&td->lock); 1000 mutex_init(&td->lock);
764 1001
@@ -776,6 +1013,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
776 goto err_wq; 1013 goto err_wq;
777 } 1014 }
778 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); 1015 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
1016 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
779 1017
780 dev_set_drvdata(&dssdev->dev, td); 1018 dev_set_drvdata(&dssdev->dev, td);
781 1019
@@ -900,6 +1138,7 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
900 taal_bl_update_status(bldev); 1138 taal_bl_update_status(bldev);
901 backlight_device_unregister(bldev); 1139 backlight_device_unregister(bldev);
902 1140
1141 taal_cancel_ulps_work(dssdev);
903 taal_cancel_esd_work(dssdev); 1142 taal_cancel_esd_work(dssdev);
904 destroy_workqueue(td->workqueue); 1143 destroy_workqueue(td->workqueue);
905 1144
@@ -1072,12 +1311,15 @@ static void taal_disable(struct omap_dss_device *dssdev)
1072 1311
1073 mutex_lock(&td->lock); 1312 mutex_lock(&td->lock);
1074 1313
1314 taal_cancel_ulps_work(dssdev);
1075 taal_cancel_esd_work(dssdev); 1315 taal_cancel_esd_work(dssdev);
1076 1316
1077 dsi_bus_lock(); 1317 dsi_bus_lock();
1078 1318
1079 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 1319 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
1320 taal_wake_up(dssdev);
1080 taal_power_off(dssdev); 1321 taal_power_off(dssdev);
1322 }
1081 1323
1082 dsi_bus_unlock(); 1324 dsi_bus_unlock();
1083 1325
@@ -1100,11 +1342,14 @@ static int taal_suspend(struct omap_dss_device *dssdev)
1100 goto err; 1342 goto err;
1101 } 1343 }
1102 1344
1345 taal_cancel_ulps_work(dssdev);
1103 taal_cancel_esd_work(dssdev); 1346 taal_cancel_esd_work(dssdev);
1104 1347
1105 dsi_bus_lock(); 1348 dsi_bus_lock();
1106 1349
1107 taal_power_off(dssdev); 1350 r = taal_wake_up(dssdev);
1351 if (!r)
1352 taal_power_off(dssdev);
1108 1353
1109 dsi_bus_unlock(); 1354 dsi_bus_unlock();
1110 1355
@@ -1213,6 +1458,10 @@ static int taal_update(struct omap_dss_device *dssdev,
1213 mutex_lock(&td->lock); 1458 mutex_lock(&td->lock);
1214 dsi_bus_lock(); 1459 dsi_bus_lock();
1215 1460
1461 r = taal_wake_up(dssdev);
1462 if (r)
1463 goto err;
1464
1216 if (!td->enabled) { 1465 if (!td->enabled) {
1217 r = 0; 1466 r = 0;
1218 goto err; 1467 goto err;
@@ -1300,6 +1549,10 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1300 dsi_bus_lock(); 1549 dsi_bus_lock();
1301 1550
1302 if (td->enabled) { 1551 if (td->enabled) {
1552 r = taal_wake_up(dssdev);
1553 if (r)
1554 goto err;
1555
1303 r = _taal_enable_te(dssdev, enable); 1556 r = _taal_enable_te(dssdev, enable);
1304 if (r) 1557 if (r)
1305 goto err; 1558 goto err;
@@ -1346,6 +1599,10 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1346 dsi_bus_lock(); 1599 dsi_bus_lock();
1347 1600
1348 if (td->enabled) { 1601 if (td->enabled) {
1602 r = taal_wake_up(dssdev);
1603 if (r)
1604 goto err;
1605
1349 r = taal_set_addr_mode(td, rotate, td->mirror); 1606 r = taal_set_addr_mode(td, rotate, td->mirror);
1350 if (r) 1607 if (r)
1351 goto err; 1608 goto err;
@@ -1389,6 +1646,10 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
1389 1646
1390 dsi_bus_lock(); 1647 dsi_bus_lock();
1391 if (td->enabled) { 1648 if (td->enabled) {
1649 r = taal_wake_up(dssdev);
1650 if (r)
1651 goto err;
1652
1392 r = taal_set_addr_mode(td, td->rotate, enable); 1653 r = taal_set_addr_mode(td, td->rotate, enable);
1393 if (r) 1654 if (r)
1394 goto err; 1655 goto err;
@@ -1433,6 +1694,10 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
1433 1694
1434 dsi_bus_lock(); 1695 dsi_bus_lock();
1435 1696
1697 r = taal_wake_up(dssdev);
1698 if (r)
1699 goto err2;
1700
1436 r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); 1701 r = taal_dcs_read_1(td, DCS_GET_ID1, &id1);
1437 if (r) 1702 if (r)
1438 goto err2; 1703 goto err2;
@@ -1479,6 +1744,10 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1479 1744
1480 dsi_bus_lock(); 1745 dsi_bus_lock();
1481 1746
1747 r = taal_wake_up(dssdev);
1748 if (r)
1749 goto err2;
1750
1482 /* plen 1 or 2 goes into short packet. until checksum error is fixed, 1751 /* plen 1 or 2 goes into short packet. until checksum error is fixed,
1483 * use short packets. plen 32 works, but bigger packets seem to cause 1752 * use short packets. plen 32 works, but bigger packets seem to cause
1484 * an error. */ 1753 * an error. */
@@ -1531,6 +1800,27 @@ err1:
1531 return r; 1800 return r;
1532} 1801}
1533 1802
1803static void taal_ulps_work(struct work_struct *work)
1804{
1805 struct taal_data *td = container_of(work, struct taal_data,
1806 ulps_work.work);
1807 struct omap_dss_device *dssdev = td->dssdev;
1808
1809 mutex_lock(&td->lock);
1810
1811 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) {
1812 mutex_unlock(&td->lock);
1813 return;
1814 }
1815
1816 dsi_bus_lock();
1817
1818 taal_enter_ulps(dssdev);
1819
1820 dsi_bus_unlock();
1821 mutex_unlock(&td->lock);
1822}
1823
1534static void taal_esd_work(struct work_struct *work) 1824static void taal_esd_work(struct work_struct *work)
1535{ 1825{
1536 struct taal_data *td = container_of(work, struct taal_data, 1826 struct taal_data *td = container_of(work, struct taal_data,
@@ -1549,6 +1839,12 @@ static void taal_esd_work(struct work_struct *work)
1549 1839
1550 dsi_bus_lock(); 1840 dsi_bus_lock();
1551 1841
1842 r = taal_wake_up(dssdev);
1843 if (r) {
1844 dev_err(&dssdev->dev, "failed to exit ULPS\n");
1845 goto err;
1846 }
1847
1552 r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); 1848 r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
1553 if (r) { 1849 if (r) {
1554 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1850 dev_err(&dssdev->dev, "failed to read Taal status\n");