aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/omap2/displays/panel-taal.c93
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
67static irqreturn_t taal_te_isr(int irq, void *data);
68static void taal_te_timeout_work_callback(struct work_struct *work);
68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 69static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
69 70
70struct taal_data { 71struct 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
349static 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
359static ssize_t taal_num_errors_show(struct device *dev, 358static 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
916static 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;
939err:
940 dev_err(&dssdev->dev, "start update failed\n");
941 dsi_bus_unlock();
942 return IRQ_HANDLED;
943}
944
945static 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
912static int taal_update(struct omap_dss_device *dssdev, 957static 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 */