[PATCH] touchscreen: tps6507x-ts: only poll while touch event is occurring

2014-03-04 Thread Jon Ringle
We only need to poll for touch events after an interrupt occurs due to the
user touching the screen. We continue to poll until the user stops touching
the screen

Signed-off-by: Jon Ringle 
---
 drivers/input/touchscreen/tps6507x-ts.c | 191 +---
 include/linux/mfd/tps6507x.h|   1 +
 2 files changed, 153 insertions(+), 39 deletions(-)

diff --git a/drivers/input/touchscreen/tps6507x-ts.c 
b/drivers/input/touchscreen/tps6507x-ts.c
index 94cde2c..fa1fb24 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -17,11 +17,14 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 

 #define TSC_DEFAULT_POLL_PERIOD 30 /* ms */
 #define TPS_DEFAULT_MIN_PRESSURE 0x30
@@ -39,13 +42,17 @@ struct ts_event {
 };

 struct tps6507x_ts {
+   struct input_dev*input_dev;
struct device   *dev;
-   struct input_polled_dev *poll_dev;
struct tps6507x_dev *mfd;
charphys[32];
+   struct delayed_work work;
struct ts_event tc;
+   int irq;
+   unsigned long   poll_period;/* ms */
u16 min_pressure;
boolpendown;
+   int open_count;
 };

 static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
@@ -155,13 +162,20 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
return ret;
 }

-static void tps6507x_ts_poll(struct input_polled_dev *poll_dev)
+static void tps6507x_ts_handler(struct work_struct *work)
 {
-   struct tps6507x_ts *tsc = poll_dev->private;
-   struct input_dev *input_dev = poll_dev->input;
+   struct tps6507x_ts *tsc =  container_of(work, struct tps6507x_ts, 
work.work);
+   struct input_dev *input_dev = tsc->input_dev;
bool pendown;
+   int schd;
+   int poll = 0;
s32 ret;

+   if (tsc->irq) {
+   // Disable the touch interrupt
+   tps6507x_write_u8(tsc, TPS6507X_REG_INT, 0);
+   }
+
ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
  >tc.pressure);
if (ret)
@@ -178,9 +192,11 @@ static void tps6507x_ts_poll(struct input_polled_dev 
*poll_dev)
}

if (pendown) {
+   int report_pendown = 0;

if (!tsc->pendown) {
dev_dbg(tsc->dev, "DOWN\n");
+   report_pendown = 1;
input_report_key(input_dev, BTN_TOUCH, 1);
} else
dev_dbg(tsc->dev, "still down\n");
@@ -195,15 +211,89 @@ static void tps6507x_ts_poll(struct input_polled_dev 
*poll_dev)
if (ret)
goto done;

-   input_report_abs(input_dev, ABS_X, tsc->tc.x);
-   input_report_abs(input_dev, ABS_Y, tsc->tc.y);
-   input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure);
-   input_sync(input_dev);
-   tsc->pendown = true;
+   if (tsc->tc.x && tsc->tc.y) {
+   if (report_pendown)
+   input_report_key(input_dev, BTN_TOUCH, 1);
+
+   input_report_abs(input_dev, ABS_X, tsc->tc.x);
+   input_report_abs(input_dev, ABS_Y, tsc->tc.y);
+   input_report_abs(input_dev, ABS_PRESSURE, 
tsc->tc.pressure);
+   input_sync(input_dev);
+   tsc->pendown = true;
+   } else {
+   dev_dbg(tsc->dev, "discarding bogus read x=%d, y=%d, 
pressure=%d\n", tsc->tc.x, tsc->tc.y, tsc->tc.pressure);
+   }
+   poll = 1;
}

 done:
tps6507x_adc_standby(tsc);
+   if (tsc->irq && !poll) {
+   // Re-enable the interrupt
+   tps6507x_write_u8(tsc, TPS6507X_REG_INT, TPS6507X_REG_MASK_TSC);
+   } else {
+   /* always poll if not using interrupts */
+   schd = schedule_delayed_work(>work,
+
msecs_to_jiffies(tsc->poll_period));
+   }
+}
+
+static irqreturn_t tps6507x_ts_irq(int irq, void * dev_id)
+{
+   struct tps6507x_ts * tsc = (struct tps6507x_ts *)dev_id;
+
+   schedule_delayed_work(>work, 0);
+
+   return IRQ_HANDLED;
+}
+
+static int tps6507x_ts_open(struct input_dev *input_dev)
+{
+   int ret;
+   struct tps6507x_ts *tsc = input_get_drvdata(input_dev);
+
+   tsc->open_count++;
+
+// printk("%s: %s\n", __func__, comm);
+   dump_stack();
+
+   if (tsc->irq) {
+
+   tps6507x_write_u8(tsc, TPS6507X_REG_INT, 0);
+   tps6507x_adc_standby(tsc);
+
+   ret = request_irq(tsc->irq,tps6507x_ts_irq, 0, "TPS6507x",tsc);
+
+   

[PATCH] touchscreen: tps6507x-ts: only poll while touch event is occurring

2014-03-04 Thread Jon Ringle
We only need to poll for touch events after an interrupt occurs due to the
user touching the screen. We continue to poll until the user stops touching
the screen

Signed-off-by: Jon Ringle jrin...@gridpoint.com
---
 drivers/input/touchscreen/tps6507x-ts.c | 191 +---
 include/linux/mfd/tps6507x.h|   1 +
 2 files changed, 153 insertions(+), 39 deletions(-)

diff --git a/drivers/input/touchscreen/tps6507x-ts.c 
b/drivers/input/touchscreen/tps6507x-ts.c
index 94cde2c..fa1fb24 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -17,11 +17,14 @@
 #include linux/workqueue.h
 #include linux/slab.h
 #include linux/input.h
-#include linux/input-polldev.h
 #include linux/platform_device.h
 #include linux/mfd/tps6507x.h
 #include linux/input/tps6507x-ts.h
 #include linux/delay.h
+#include linux/gpio.h
+#include linux/i2c.h
+#include linux/irq.h
+#include linux/interrupt.h

 #define TSC_DEFAULT_POLL_PERIOD 30 /* ms */
 #define TPS_DEFAULT_MIN_PRESSURE 0x30
@@ -39,13 +42,17 @@ struct ts_event {
 };

 struct tps6507x_ts {
+   struct input_dev*input_dev;
struct device   *dev;
-   struct input_polled_dev *poll_dev;
struct tps6507x_dev *mfd;
charphys[32];
+   struct delayed_work work;
struct ts_event tc;
+   int irq;
+   unsigned long   poll_period;/* ms */
u16 min_pressure;
boolpendown;
+   int open_count;
 };

 static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
@@ -155,13 +162,20 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
return ret;
 }

-static void tps6507x_ts_poll(struct input_polled_dev *poll_dev)
+static void tps6507x_ts_handler(struct work_struct *work)
 {
-   struct tps6507x_ts *tsc = poll_dev-private;
-   struct input_dev *input_dev = poll_dev-input;
+   struct tps6507x_ts *tsc =  container_of(work, struct tps6507x_ts, 
work.work);
+   struct input_dev *input_dev = tsc-input_dev;
bool pendown;
+   int schd;
+   int poll = 0;
s32 ret;

+   if (tsc-irq) {
+   // Disable the touch interrupt
+   tps6507x_write_u8(tsc, TPS6507X_REG_INT, 0);
+   }
+
ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
  tsc-tc.pressure);
if (ret)
@@ -178,9 +192,11 @@ static void tps6507x_ts_poll(struct input_polled_dev 
*poll_dev)
}

if (pendown) {
+   int report_pendown = 0;

if (!tsc-pendown) {
dev_dbg(tsc-dev, DOWN\n);
+   report_pendown = 1;
input_report_key(input_dev, BTN_TOUCH, 1);
} else
dev_dbg(tsc-dev, still down\n);
@@ -195,15 +211,89 @@ static void tps6507x_ts_poll(struct input_polled_dev 
*poll_dev)
if (ret)
goto done;

-   input_report_abs(input_dev, ABS_X, tsc-tc.x);
-   input_report_abs(input_dev, ABS_Y, tsc-tc.y);
-   input_report_abs(input_dev, ABS_PRESSURE, tsc-tc.pressure);
-   input_sync(input_dev);
-   tsc-pendown = true;
+   if (tsc-tc.x  tsc-tc.y) {
+   if (report_pendown)
+   input_report_key(input_dev, BTN_TOUCH, 1);
+
+   input_report_abs(input_dev, ABS_X, tsc-tc.x);
+   input_report_abs(input_dev, ABS_Y, tsc-tc.y);
+   input_report_abs(input_dev, ABS_PRESSURE, 
tsc-tc.pressure);
+   input_sync(input_dev);
+   tsc-pendown = true;
+   } else {
+   dev_dbg(tsc-dev, discarding bogus read x=%d, y=%d, 
pressure=%d\n, tsc-tc.x, tsc-tc.y, tsc-tc.pressure);
+   }
+   poll = 1;
}

 done:
tps6507x_adc_standby(tsc);
+   if (tsc-irq  !poll) {
+   // Re-enable the interrupt
+   tps6507x_write_u8(tsc, TPS6507X_REG_INT, TPS6507X_REG_MASK_TSC);
+   } else {
+   /* always poll if not using interrupts */
+   schd = schedule_delayed_work(tsc-work,
+
msecs_to_jiffies(tsc-poll_period));
+   }
+}
+
+static irqreturn_t tps6507x_ts_irq(int irq, void * dev_id)
+{
+   struct tps6507x_ts * tsc = (struct tps6507x_ts *)dev_id;
+
+   schedule_delayed_work(tsc-work, 0);
+
+   return IRQ_HANDLED;
+}
+
+static int tps6507x_ts_open(struct input_dev *input_dev)
+{
+   int ret;
+   struct tps6507x_ts *tsc = input_get_drvdata(input_dev);
+
+   tsc-open_count++;
+
+// printk(%s: %s\n, __func__, comm);
+   dump_stack();
+
+   if (tsc-irq) {
+
+