diff options
author | Jani Nikula <ext-jani.1.nikula@nokia.com> | 2010-04-13 03:57:52 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@nokia.com> | 2010-08-03 08:18:48 -0400 |
commit | 7ae2fb1192f0510991a833ca1dd4baace9bd8977 (patch) | |
tree | cbc7ea2cf4595a54456688487f21c2cec1033ac1 /drivers | |
parent | d2b657873839fd401798ba277868fc8442997443 (diff) |
OMAP: DSS2: Taal: Add proper external TE support
Add gpio irq based external TE support with timeout.
Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 93 |
1 files changed, 75 insertions, 18 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 2f8967874680..e52631efe7e2 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/fb.h> | 28 | #include <linux/fb.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
31 | #include <linux/completion.h> | ||
32 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
@@ -65,6 +64,8 @@ | |||
65 | /* #define TAAL_USE_ESD_CHECK */ | 64 | /* #define TAAL_USE_ESD_CHECK */ |
66 | #define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) | 65 | #define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) |
67 | 66 | ||
67 | static irqreturn_t taal_te_isr(int irq, void *data); | ||
68 | static void taal_te_timeout_work_callback(struct work_struct *work); | ||
68 | 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); |
69 | 70 | ||
70 | struct taal_data { | 71 | struct taal_data { |
@@ -85,7 +86,15 @@ struct taal_data { | |||
85 | 86 | ||
86 | bool te_enabled; | 87 | bool te_enabled; |
87 | bool use_ext_te; | 88 | bool use_ext_te; |
88 | struct completion te_completion; | 89 | |
90 | atomic_t do_update; | ||
91 | struct { | ||
92 | u16 x; | ||
93 | u16 y; | ||
94 | u16 w; | ||
95 | u16 h; | ||
96 | } update_region; | ||
97 | struct delayed_work te_timeout_work; | ||
89 | 98 | ||
90 | bool use_dsi_bl; | 99 | bool use_dsi_bl; |
91 | 100 | ||
@@ -346,16 +355,6 @@ static void taal_get_resolution(struct omap_dss_device *dssdev, | |||
346 | } | 355 | } |
347 | } | 356 | } |
348 | 357 | ||
349 | static irqreturn_t taal_te_isr(int irq, void *data) | ||
350 | { | ||
351 | struct omap_dss_device *dssdev = data; | ||
352 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
353 | |||
354 | complete_all(&td->te_completion); | ||
355 | |||
356 | return IRQ_HANDLED; | ||
357 | } | ||
358 | |||
359 | static ssize_t taal_num_errors_show(struct device *dev, | 358 | static ssize_t taal_num_errors_show(struct device *dev, |
360 | struct device_attribute *attr, char *buf) | 359 | struct device_attribute *attr, char *buf) |
361 | { | 360 | { |
@@ -545,6 +544,8 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
545 | 544 | ||
546 | mutex_init(&td->lock); | 545 | mutex_init(&td->lock); |
547 | 546 | ||
547 | atomic_set(&td->do_update, 0); | ||
548 | |||
548 | td->esd_wq = create_singlethread_workqueue("taal_esd"); | 549 | td->esd_wq = create_singlethread_workqueue("taal_esd"); |
549 | if (td->esd_wq == NULL) { | 550 | if (td->esd_wq == NULL) { |
550 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 551 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); |
@@ -606,9 +607,12 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
606 | goto err_irq; | 607 | goto err_irq; |
607 | } | 608 | } |
608 | 609 | ||
609 | init_completion(&td->te_completion); | 610 | INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work, |
611 | taal_te_timeout_work_callback); | ||
610 | 612 | ||
611 | td->use_ext_te = true; | 613 | td->use_ext_te = true; |
614 | |||
615 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); | ||
612 | } | 616 | } |
613 | 617 | ||
614 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); | 618 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); |
@@ -909,6 +913,47 @@ static void taal_framedone_cb(int err, void *data) | |||
909 | dsi_bus_unlock(); | 913 | dsi_bus_unlock(); |
910 | } | 914 | } |
911 | 915 | ||
916 | static irqreturn_t taal_te_isr(int irq, void *data) | ||
917 | { | ||
918 | struct omap_dss_device *dssdev = data; | ||
919 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
920 | int old; | ||
921 | int r; | ||
922 | |||
923 | old = atomic_cmpxchg(&td->do_update, 1, 0); | ||
924 | |||
925 | if (old) { | ||
926 | cancel_delayed_work(&td->te_timeout_work); | ||
927 | |||
928 | r = omap_dsi_update(dssdev, TCH, | ||
929 | td->update_region.x, | ||
930 | td->update_region.y, | ||
931 | td->update_region.w, | ||
932 | td->update_region.h, | ||
933 | taal_framedone_cb, dssdev); | ||
934 | if (r) | ||
935 | goto err; | ||
936 | } | ||
937 | |||
938 | return IRQ_HANDLED; | ||
939 | err: | ||
940 | dev_err(&dssdev->dev, "start update failed\n"); | ||
941 | dsi_bus_unlock(); | ||
942 | return IRQ_HANDLED; | ||
943 | } | ||
944 | |||
945 | static void taal_te_timeout_work_callback(struct work_struct *work) | ||
946 | { | ||
947 | struct taal_data *td = container_of(work, struct taal_data, | ||
948 | te_timeout_work.work); | ||
949 | struct omap_dss_device *dssdev = td->dssdev; | ||
950 | |||
951 | dev_err(&dssdev->dev, "TE not received for 250ms!\n"); | ||
952 | |||
953 | atomic_set(&td->do_update, 0); | ||
954 | dsi_bus_unlock(); | ||
955 | } | ||
956 | |||
912 | static int taal_update(struct omap_dss_device *dssdev, | 957 | static int taal_update(struct omap_dss_device *dssdev, |
913 | u16 x, u16 y, u16 w, u16 h) | 958 | u16 x, u16 y, u16 w, u16 h) |
914 | { | 959 | { |
@@ -933,10 +978,21 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
933 | if (r) | 978 | if (r) |
934 | goto err; | 979 | goto err; |
935 | 980 | ||
936 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | 981 | if (td->te_enabled && td->use_ext_te) { |
937 | taal_framedone_cb, dssdev); | 982 | td->update_region.x = x; |
938 | if (r) | 983 | td->update_region.y = y; |
939 | goto err; | 984 | td->update_region.w = w; |
985 | td->update_region.h = h; | ||
986 | barrier(); | ||
987 | schedule_delayed_work(&td->te_timeout_work, | ||
988 | msecs_to_jiffies(250)); | ||
989 | atomic_set(&td->do_update, 1); | ||
990 | } else { | ||
991 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | ||
992 | taal_framedone_cb, dssdev); | ||
993 | if (r) | ||
994 | goto err; | ||
995 | } | ||
940 | 996 | ||
941 | /* note: no bus_unlock here. unlock is in framedone_cb */ | 997 | /* note: no bus_unlock here. unlock is in framedone_cb */ |
942 | mutex_unlock(&td->lock); | 998 | mutex_unlock(&td->lock); |
@@ -972,7 +1028,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
972 | else | 1028 | else |
973 | r = taal_dcs_write_0(DCS_TEAR_OFF); | 1029 | r = taal_dcs_write_0(DCS_TEAR_OFF); |
974 | 1030 | ||
975 | omapdss_dsi_enable_te(dssdev, enable); | 1031 | if (!td->use_ext_te) |
1032 | omapdss_dsi_enable_te(dssdev, enable); | ||
976 | 1033 | ||
977 | /* XXX for some reason, DSI TE breaks if we don't wait here. | 1034 | /* XXX for some reason, DSI TE breaks if we don't wait here. |
978 | * Panel bug? Needs more studying */ | 1035 | * Panel bug? Needs more studying */ |