All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] Input: pixcir_i2c_ts: Add Type-B Multi-touch and DT support
@ 2014-04-30 12:36 ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Hi Dmitry,

This series does the following

- use devres managed resource allocations
- convert to Type-B multi touch protocol
- support upto 5 fingers with hardware supplied tracking IDs
- device tree support

Please queue this for -next (3.16). Thanks.

cheers,
-roger

Changelog:

v3:
- Rebased to 3.15-rc3
- Fixed suspend while touchscreen in use
- Fixed module removal while touchscreen in use

v2:
- Addressed review comments and re-arranged patch order

v1:
- http://article.gmane.org/gmane.linux.kernel/1616417

---
Roger Quadros (7):
  Input: pixcir_i2c_ts: Use devres managed resource allocations
  Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
  Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
  Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol
  Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided
    tracking IDs
  Input: pixcir_i2c_ts: Implement wakeup from suspend
  Input: pixcir_i2c_ts: Add device tree support

 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   |  26 +
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 525 ++++++++++++++++++---
 include/linux/input/pixcir_ts.h                    |  56 ++-
 4 files changed, 548 insertions(+), 60 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt

-- 
1.8.3.2


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 0/7] Input: pixcir_i2c_ts: Add Type-B Multi-touch and DT support
@ 2014-04-30 12:36 ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Hi Dmitry,

This series does the following

- use devres managed resource allocations
- convert to Type-B multi touch protocol
- support upto 5 fingers with hardware supplied tracking IDs
- device tree support

Please queue this for -next (3.16). Thanks.

cheers,
-roger

Changelog:

v3:
- Rebased to 3.15-rc3
- Fixed suspend while touchscreen in use
- Fixed module removal while touchscreen in use

v2:
- Addressed review comments and re-arranged patch order

v1:
- http://article.gmane.org/gmane.linux.kernel/1616417

---
Roger Quadros (7):
  Input: pixcir_i2c_ts: Use devres managed resource allocations
  Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
  Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
  Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol
  Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided
    tracking IDs
  Input: pixcir_i2c_ts: Implement wakeup from suspend
  Input: pixcir_i2c_ts: Add device tree support

 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   |  26 +
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 525 ++++++++++++++++++---
 include/linux/input/pixcir_ts.h                    |  56 ++-
 4 files changed, 548 insertions(+), 60 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt

-- 
1.8.3.2


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Use devm_() and friends for allocating memory, input device
and IRQ.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 36 +++++++++++++------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 02392d2..45bc2d1 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -130,6 +130,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 {
 	const struct pixcir_ts_platform_data *pdata =
 			dev_get_platdata(&client->dev);
+	struct device *dev = &client->dev;
 	struct pixcir_i2c_ts_data *tsdata;
 	struct input_dev *input;
 	int error;
@@ -139,12 +140,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
-	tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
-	input = input_allocate_device();
-	if (!tsdata || !input) {
-		dev_err(&client->dev, "Failed to allocate driver data!\n");
-		error = -ENOMEM;
-		goto err_free_mem;
+	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
+	if (!tsdata)
+		return -ENOMEM;
+
+	input = devm_input_allocate_device(dev);
+	if (!input) {
+		dev_err(&client->dev, "Failed to allocate input device\n");
+		return -ENOMEM;
 	}
 
 	tsdata->client = client;
@@ -165,29 +168,22 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 
 	input_set_drvdata(input, tsdata);
 
-	error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr,
-				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				     client->name, tsdata);
+	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
+					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					  client->name, tsdata);
 	if (error) {
-		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
-		goto err_free_mem;
+		dev_err(dev, "failed to request irq %d\n", client->irq);
+		return error;
 	}
 
 	error = input_register_device(input);
 	if (error)
-		goto err_free_irq;
+		return error;
 
 	i2c_set_clientdata(client, tsdata);
 	device_init_wakeup(&client->dev, 1);
 
 	return 0;
-
-err_free_irq:
-	free_irq(client->irq, tsdata);
-err_free_mem:
-	input_free_device(input);
-	kfree(tsdata);
-	return error;
 }
 
 static int pixcir_i2c_ts_remove(struct i2c_client *client)
@@ -198,10 +194,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
 
 	tsdata->exiting = true;
 	mb();
-	free_irq(client->irq, tsdata);
 
 	input_unregister_device(tsdata->input);
-	kfree(tsdata);
 
 	return 0;
 }
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Use devm_() and friends for allocating memory, input device
and IRQ.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 36 +++++++++++++------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 02392d2..45bc2d1 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -130,6 +130,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 {
 	const struct pixcir_ts_platform_data *pdata =
 			dev_get_platdata(&client->dev);
+	struct device *dev = &client->dev;
 	struct pixcir_i2c_ts_data *tsdata;
 	struct input_dev *input;
 	int error;
@@ -139,12 +140,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
-	tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
-	input = input_allocate_device();
-	if (!tsdata || !input) {
-		dev_err(&client->dev, "Failed to allocate driver data!\n");
-		error = -ENOMEM;
-		goto err_free_mem;
+	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
+	if (!tsdata)
+		return -ENOMEM;
+
+	input = devm_input_allocate_device(dev);
+	if (!input) {
+		dev_err(&client->dev, "Failed to allocate input device\n");
+		return -ENOMEM;
 	}
 
 	tsdata->client = client;
@@ -165,29 +168,22 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 
 	input_set_drvdata(input, tsdata);
 
-	error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr,
-				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				     client->name, tsdata);
+	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
+					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					  client->name, tsdata);
 	if (error) {
-		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
-		goto err_free_mem;
+		dev_err(dev, "failed to request irq %d\n", client->irq);
+		return error;
 	}
 
 	error = input_register_device(input);
 	if (error)
-		goto err_free_irq;
+		return error;
 
 	i2c_set_clientdata(client, tsdata);
 	device_init_wakeup(&client->dev, 1);
 
 	return 0;
-
-err_free_irq:
-	free_irq(client->irq, tsdata);
-err_free_mem:
-	input_free_device(input);
-	kfree(tsdata);
-	return error;
 }
 
 static int pixcir_i2c_ts_remove(struct i2c_client *client)
@@ -198,10 +194,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
 
 	tsdata->exiting = true;
 	mb();
-	free_irq(client->irq, tsdata);
 
 	input_unregister_device(tsdata->input);
-	kfree(tsdata);
 
 	return 0;
 }
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 2/7] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Introduce helper functions to configure power and interrupt
registers. Default to IDLE mode on probe as device supports
auto wakeup to ACVIE mode on detecting finger touch.

Configure interrupt mode and polarity on start up.
Power down on device closure or module removal.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 179 +++++++++++++++++++++++++++++-
 include/linux/input/pixcir_ts.h           |  42 +++++++
 2 files changed, 218 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 45bc2d1..670aa6e 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -100,6 +100,168 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
+				 enum pixcir_power_mode mode)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_POWER_MODE, ret);
+		return ret;
+	}
+
+	ret &= ~PIXCIR_POWER_MODE_MASK;
+	ret |= mode;
+
+	/* Always AUTO_IDLE */
+	ret |= PIXCIR_POWER_ALLOW_IDLE;
+
+	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_POWER_MODE, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Set the interrupt mode for the device i.e. ATTB line behaviour
+ *
+ * @polarity : 1 for active high, 0 for active low.
+ */
+static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
+			       enum pixcir_int_mode mode,
+					bool polarity)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	ret &= ~PIXCIR_INT_MODE_MASK;
+	ret |= mode;
+
+	if (polarity)
+		ret |= PIXCIR_INT_POL_HIGH;
+	else
+		ret &= ~PIXCIR_INT_POL_HIGH;
+
+	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Enable/disable interrupt generation
+ */
+static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	if (enable)
+		ret |= PIXCIR_INT_ENABLE;
+	else
+		ret &= ~PIXCIR_INT_ENABLE;
+
+	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pixcir_start(struct pixcir_i2c_ts_data *ts)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	/* LEVEL_TOUCH interrupt with active low polarity */
+	ret = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
+	if (ret) {
+		dev_err(dev, "Failed to set interrupt mode\n");
+		return ret;
+	}
+
+	ts->exiting = false;
+	mb();	/* Update status before IRQ can fire */
+
+	/* enable interrupt generation */
+	ret = pixcir_int_enable(ts, 1);
+	if (ret) {
+		dev_err(dev, "Failed to enable interrupt generation\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	/* exit ISR if running, no more report parsing */
+	ts->exiting = true;
+	mb();	/* update status before we synchronize irq */
+
+	/* disable ISR from running again */
+	disable_irq(ts->client->irq);
+
+	/* wait till running ISR complete */
+	synchronize_irq(ts->client->irq);
+
+	/* disable interrupt generation */
+	ret = pixcir_int_enable(ts, 0);
+	if (ret)
+		dev_err(dev, "Failed to disable interrupt generation\n");
+
+	/* restore IRQ */
+	enable_irq(ts->client->irq);
+
+	return ret;
+}
+
+static int pixcir_input_open(struct input_dev *dev)
+{
+	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
+
+	return pixcir_start(ts);
+}
+
+static void pixcir_input_close(struct input_dev *dev)
+{
+	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
+
+	pixcir_stop(ts);
+}
+
+
 #ifdef CONFIG_PM_SLEEP
 static int pixcir_i2c_ts_suspend(struct device *dev)
 {
@@ -157,6 +319,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	input->name = client->name;
 	input->id.bustype = BUS_I2C;
 	input->dev.parent = &client->dev;
+	input->open = pixcir_input_open;
+	input->close = pixcir_input_close;
 
 	__set_bit(EV_KEY, input->evbit);
 	__set_bit(EV_ABS, input->evbit);
@@ -176,6 +340,18 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	/* Always be in IDLE mode to save power, device supports auto wake */
+	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
+	if (error) {
+		dev_err(dev, "Failed to set IDLE mode\n");
+		return error;
+	}
+
+	/* Stop device till opened */
+	error = pixcir_stop(tsdata);
+	if (error)
+		return error;
+
 	error = input_register_device(input);
 	if (error)
 		return error;
@@ -192,9 +368,6 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
 
 	device_init_wakeup(&client->dev, 0);
 
-	tsdata->exiting = true;
-	mb();
-
 	input_unregister_device(tsdata->input);
 
 	return 0;
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 7163d91..7942804 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -1,6 +1,48 @@
 #ifndef	_PIXCIR_I2C_TS_H
 #define	_PIXCIR_I2C_TS_H
 
+/*
+ * Register map
+ */
+#define PIXCIR_REG_POWER_MODE	51
+#define PIXCIR_REG_INT_MODE	52
+
+/*
+ * Power modes:
+ * active: max scan speed
+ * idle: lower scan speed with automatic transition to active on touch
+ * halt: datasheet says sleep but this is more like halt as the chip
+ *       clocks are cut and it can only be brought out of this mode
+ *	 using the RESET pin.
+ */
+enum pixcir_power_mode {
+	PIXCIR_POWER_ACTIVE,
+	PIXCIR_POWER_IDLE,
+	PIXCIR_POWER_HALT,
+};
+
+#define PIXCIR_POWER_MODE_MASK	0x03
+#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
+
+/*
+ * Interrupt modes:
+ * periodical: interrupt is asserted periodicaly
+ * diff coordinates: interrupt is asserted when coordinates change
+ * level on touch: interrupt level asserted during touch
+ * pulse on touch: interrupt pulse asserted druing touch
+ *
+ */
+enum pixcir_int_mode {
+	PIXCIR_INT_PERIODICAL,
+	PIXCIR_INT_DIFF_COORD,
+	PIXCIR_INT_LEVEL_TOUCH,
+	PIXCIR_INT_PULSE_TOUCH,
+};
+
+#define PIXCIR_INT_MODE_MASK	0x03
+#define PIXCIR_INT_ENABLE	(1UL << 3)
+#define PIXCIR_INT_POL_HIGH	(1UL << 2)
+
 struct pixcir_ts_platform_data {
 	int (*attb_read_val)(void);
 	int x_max;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 2/7] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Introduce helper functions to configure power and interrupt
registers. Default to IDLE mode on probe as device supports
auto wakeup to ACVIE mode on detecting finger touch.

Configure interrupt mode and polarity on start up.
Power down on device closure or module removal.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 179 +++++++++++++++++++++++++++++-
 include/linux/input/pixcir_ts.h           |  42 +++++++
 2 files changed, 218 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 45bc2d1..670aa6e 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -100,6 +100,168 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
+				 enum pixcir_power_mode mode)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_POWER_MODE, ret);
+		return ret;
+	}
+
+	ret &= ~PIXCIR_POWER_MODE_MASK;
+	ret |= mode;
+
+	/* Always AUTO_IDLE */
+	ret |= PIXCIR_POWER_ALLOW_IDLE;
+
+	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_POWER_MODE, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Set the interrupt mode for the device i.e. ATTB line behaviour
+ *
+ * @polarity : 1 for active high, 0 for active low.
+ */
+static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
+			       enum pixcir_int_mode mode,
+					bool polarity)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	ret &= ~PIXCIR_INT_MODE_MASK;
+	ret |= mode;
+
+	if (polarity)
+		ret |= PIXCIR_INT_POL_HIGH;
+	else
+		ret &= ~PIXCIR_INT_POL_HIGH;
+
+	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Enable/disable interrupt generation
+ */
+static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	if (enable)
+		ret |= PIXCIR_INT_ENABLE;
+	else
+		ret &= ~PIXCIR_INT_ENABLE;
+
+	ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
+	if (ret < 0) {
+		dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+			__func__, PIXCIR_REG_INT_MODE, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pixcir_start(struct pixcir_i2c_ts_data *ts)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	/* LEVEL_TOUCH interrupt with active low polarity */
+	ret = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
+	if (ret) {
+		dev_err(dev, "Failed to set interrupt mode\n");
+		return ret;
+	}
+
+	ts->exiting = false;
+	mb();	/* Update status before IRQ can fire */
+
+	/* enable interrupt generation */
+	ret = pixcir_int_enable(ts, 1);
+	if (ret) {
+		dev_err(dev, "Failed to enable interrupt generation\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
+{
+	struct device *dev = &ts->client->dev;
+	int ret;
+
+	/* exit ISR if running, no more report parsing */
+	ts->exiting = true;
+	mb();	/* update status before we synchronize irq */
+
+	/* disable ISR from running again */
+	disable_irq(ts->client->irq);
+
+	/* wait till running ISR complete */
+	synchronize_irq(ts->client->irq);
+
+	/* disable interrupt generation */
+	ret = pixcir_int_enable(ts, 0);
+	if (ret)
+		dev_err(dev, "Failed to disable interrupt generation\n");
+
+	/* restore IRQ */
+	enable_irq(ts->client->irq);
+
+	return ret;
+}
+
+static int pixcir_input_open(struct input_dev *dev)
+{
+	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
+
+	return pixcir_start(ts);
+}
+
+static void pixcir_input_close(struct input_dev *dev)
+{
+	struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
+
+	pixcir_stop(ts);
+}
+
+
 #ifdef CONFIG_PM_SLEEP
 static int pixcir_i2c_ts_suspend(struct device *dev)
 {
@@ -157,6 +319,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	input->name = client->name;
 	input->id.bustype = BUS_I2C;
 	input->dev.parent = &client->dev;
+	input->open = pixcir_input_open;
+	input->close = pixcir_input_close;
 
 	__set_bit(EV_KEY, input->evbit);
 	__set_bit(EV_ABS, input->evbit);
@@ -176,6 +340,18 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	/* Always be in IDLE mode to save power, device supports auto wake */
+	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
+	if (error) {
+		dev_err(dev, "Failed to set IDLE mode\n");
+		return error;
+	}
+
+	/* Stop device till opened */
+	error = pixcir_stop(tsdata);
+	if (error)
+		return error;
+
 	error = input_register_device(input);
 	if (error)
 		return error;
@@ -192,9 +368,6 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
 
 	device_init_wakeup(&client->dev, 0);
 
-	tsdata->exiting = true;
-	mb();
-
 	input_unregister_device(tsdata->input);
 
 	return 0;
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 7163d91..7942804 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -1,6 +1,48 @@
 #ifndef	_PIXCIR_I2C_TS_H
 #define	_PIXCIR_I2C_TS_H
 
+/*
+ * Register map
+ */
+#define PIXCIR_REG_POWER_MODE	51
+#define PIXCIR_REG_INT_MODE	52
+
+/*
+ * Power modes:
+ * active: max scan speed
+ * idle: lower scan speed with automatic transition to active on touch
+ * halt: datasheet says sleep but this is more like halt as the chip
+ *       clocks are cut and it can only be brought out of this mode
+ *	 using the RESET pin.
+ */
+enum pixcir_power_mode {
+	PIXCIR_POWER_ACTIVE,
+	PIXCIR_POWER_IDLE,
+	PIXCIR_POWER_HALT,
+};
+
+#define PIXCIR_POWER_MODE_MASK	0x03
+#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
+
+/*
+ * Interrupt modes:
+ * periodical: interrupt is asserted periodicaly
+ * diff coordinates: interrupt is asserted when coordinates change
+ * level on touch: interrupt level asserted during touch
+ * pulse on touch: interrupt pulse asserted druing touch
+ *
+ */
+enum pixcir_int_mode {
+	PIXCIR_INT_PERIODICAL,
+	PIXCIR_INT_DIFF_COORD,
+	PIXCIR_INT_LEVEL_TOUCH,
+	PIXCIR_INT_PULSE_TOUCH,
+};
+
+#define PIXCIR_INT_MODE_MASK	0x03
+#define PIXCIR_INT_ENABLE	(1UL << 3)
+#define PIXCIR_INT_POL_HIGH	(1UL << 2)
+
 struct pixcir_ts_platform_data {
 	int (*attb_read_val)(void);
 	int x_max;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 3/7] Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Get rid of the attb_read_val() platform hook. Instead,
read the ATTB gpio directly from the driver.

Fail if valid ATTB gpio is not provided by patform data.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 16 +++++++++++++++-
 include/linux/input/pixcir_ts.h           |  2 +-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 670aa6e..106096f 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/input/pixcir_ts.h>
+#include <linux/gpio.h>
 
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
@@ -87,11 +88,12 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
+	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
 
 	while (!tsdata->exiting) {
 		pixcir_ts_poscheck(tsdata);
 
-		if (tsdata->chip->attb_read_val())
+		if (gpio_get_value(pdata->gpio_attb))
 			break;
 
 		msleep(20);
@@ -300,6 +302,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	if (!pdata) {
 		dev_err(&client->dev, "platform data not defined\n");
 		return -EINVAL;
+	} else {
+		if (!gpio_is_valid(pdata->gpio_attb)) {
+			dev_err(dev, "Invalid gpio_attb in pdata\n");
+			return -EINVAL;
+		}
 	}
 
 	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
@@ -332,6 +339,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 
 	input_set_drvdata(input, tsdata);
 
+	error = devm_gpio_request_one(dev, pdata->gpio_attb,
+				      GPIOF_DIR_IN, "pixcir_i2c_attb");
+	if (error) {
+		dev_err(dev, "Failed to request ATTB gpio\n");
+		return error;
+	}
+
 	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					  client->name, tsdata);
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 7942804..160cf35 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -44,9 +44,9 @@ enum pixcir_int_mode {
 #define PIXCIR_INT_POL_HIGH	(1UL << 2)
 
 struct pixcir_ts_platform_data {
-	int (*attb_read_val)(void);
 	int x_max;
 	int y_max;
+	int gpio_attb;		/* GPIO connected to ATTB line */
 };
 
 #endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 3/7] Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val()
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Get rid of the attb_read_val() platform hook. Instead,
read the ATTB gpio directly from the driver.

Fail if valid ATTB gpio is not provided by patform data.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 16 +++++++++++++++-
 include/linux/input/pixcir_ts.h           |  2 +-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 670aa6e..106096f 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/input/pixcir_ts.h>
+#include <linux/gpio.h>
 
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
@@ -87,11 +88,12 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
+	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
 
 	while (!tsdata->exiting) {
 		pixcir_ts_poscheck(tsdata);
 
-		if (tsdata->chip->attb_read_val())
+		if (gpio_get_value(pdata->gpio_attb))
 			break;
 
 		msleep(20);
@@ -300,6 +302,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	if (!pdata) {
 		dev_err(&client->dev, "platform data not defined\n");
 		return -EINVAL;
+	} else {
+		if (!gpio_is_valid(pdata->gpio_attb)) {
+			dev_err(dev, "Invalid gpio_attb in pdata\n");
+			return -EINVAL;
+		}
 	}
 
 	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
@@ -332,6 +339,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 
 	input_set_drvdata(input, tsdata);
 
+	error = devm_gpio_request_one(dev, pdata->gpio_attb,
+				      GPIOF_DIR_IN, "pixcir_i2c_attb");
+	if (error) {
+		dev_err(dev, "Failed to request ATTB gpio\n");
+		return error;
+	}
+
 	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					  client->name, tsdata);
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 7942804..160cf35 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -44,9 +44,9 @@ enum pixcir_int_mode {
 #define PIXCIR_INT_POL_HIGH	(1UL << 2)
 
 struct pixcir_ts_platform_data {
-	int (*attb_read_val)(void);
 	int x_max;
 	int y_max;
+	int gpio_attb;		/* GPIO connected to ATTB line */
 };
 
 #endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 4/7] Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Switch to using the Type-B Multi-Touch protocol.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 125 ++++++++++++++++++++++--------
 1 file changed, 94 insertions(+), 31 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 106096f..6127606 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -23,9 +23,12 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
 
+#define PIXCIR_MAX_SLOTS       2
+
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input;
@@ -33,12 +36,25 @@ struct pixcir_i2c_ts_data {
 	bool exiting;
 };
 
-static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
+struct pixcir_touch {
+	int x;
+	int y;
+};
+
+struct pixcir_report_data {
+	int num_touches;
+	struct pixcir_touch touches[PIXCIR_MAX_SLOTS];
+};
+
+static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
+			    struct pixcir_report_data *report)
 {
-	struct pixcir_i2c_ts_data *tsdata = data;
 	u8 rdbuf[10], wrbuf[1] = { 0 };
+	u8 *bufptr;
 	u8 touch;
-	int ret;
+	int ret, i;
+
+	memset(report, 0, sizeof(struct pixcir_report_data));
 
 	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
 	if (ret != sizeof(wrbuf)) {
@@ -56,45 +72,85 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
 		return;
 	}
 
-	touch = rdbuf[0];
-	if (touch) {
-		u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
-		u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
-		u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
-		u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
-
-		input_report_key(tsdata->input, BTN_TOUCH, 1);
-		input_report_abs(tsdata->input, ABS_X, posx1);
-		input_report_abs(tsdata->input, ABS_Y, posy1);
-
-		input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
-		input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
-		input_mt_sync(tsdata->input);
-
-		if (touch == 2) {
-			input_report_abs(tsdata->input,
-					 ABS_MT_POSITION_X, posx2);
-			input_report_abs(tsdata->input,
-					 ABS_MT_POSITION_Y, posy2);
-			input_mt_sync(tsdata->input);
-		}
-	} else {
-		input_report_key(tsdata->input, BTN_TOUCH, 0);
+	touch = rdbuf[0] & 0x7;
+	if (touch > PIXCIR_MAX_SLOTS)
+		touch = PIXCIR_MAX_SLOTS;
+
+	report->num_touches = touch;
+	bufptr = &rdbuf[2];
+
+	for (i = 0; i < touch; i++) {
+		report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
+		report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
+
+		bufptr = &bufptr[4];
 	}
+}
+
+static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
+			     struct pixcir_report_data *report)
+{
+	struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
+	int slots[PIXCIR_MAX_SLOTS];
+	struct pixcir_touch *touch;
+	int n, i, slot;
+	struct device *dev = &ts->client->dev;
 
-	input_sync(tsdata->input);
+	n = report->num_touches;
+	if (n > PIXCIR_MAX_SLOTS)
+		n = PIXCIR_MAX_SLOTS;
+
+	for (i = 0; i < n; i++) {
+		touch = &report->touches[i];
+		pos[i].x = touch->x;
+		pos[i].y = touch->y;
+	}
+
+	input_mt_assign_slots(ts->input, slots, pos, n);
+
+	for (i = 0; i < n; i++) {
+		touch = &report->touches[i];
+		slot = slots[i];
+
+		input_mt_slot(ts->input, slot);
+		input_mt_report_slot_state(ts->input,
+					   MT_TOOL_FINGER, true);
+
+		input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x);
+		input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y);
+
+		dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
+			i, slot, touch->x, touch->y);
+	}
+
+	input_mt_sync_frame(ts->input);
+	input_sync(ts->input);
 }
 
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
 	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+	struct pixcir_report_data report;
 
 	while (!tsdata->exiting) {
-		pixcir_ts_poscheck(tsdata);
-
-		if (gpio_get_value(pdata->gpio_attb))
+		/* parse packet */
+		pixcir_ts_parse(tsdata, &report);
+
+		/* report it */
+		pixcir_ts_report(tsdata, &report);
+
+		if (gpio_get_value(pdata->gpio_attb)) {
+			if (report.num_touches) {
+				/*
+				 * Last report with no finger up?
+				 * Do it now then.
+				 */
+				input_mt_sync_frame(tsdata->input);
+				input_sync(tsdata->input);
+			}
 			break;
+		}
 
 		msleep(20);
 	}
@@ -337,6 +393,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
 
+	error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS,
+				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+	if (error) {
+		dev_err(dev, "Error initializing Multi-Touch slots\n");
+		return error;
+	}
+
 	input_set_drvdata(input, tsdata);
 
 	error = devm_gpio_request_one(dev, pdata->gpio_attb,
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 4/7] Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Switch to using the Type-B Multi-Touch protocol.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 125 ++++++++++++++++++++++--------
 1 file changed, 94 insertions(+), 31 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 106096f..6127606 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -23,9 +23,12 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
 
+#define PIXCIR_MAX_SLOTS       2
+
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input;
@@ -33,12 +36,25 @@ struct pixcir_i2c_ts_data {
 	bool exiting;
 };
 
-static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
+struct pixcir_touch {
+	int x;
+	int y;
+};
+
+struct pixcir_report_data {
+	int num_touches;
+	struct pixcir_touch touches[PIXCIR_MAX_SLOTS];
+};
+
+static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
+			    struct pixcir_report_data *report)
 {
-	struct pixcir_i2c_ts_data *tsdata = data;
 	u8 rdbuf[10], wrbuf[1] = { 0 };
+	u8 *bufptr;
 	u8 touch;
-	int ret;
+	int ret, i;
+
+	memset(report, 0, sizeof(struct pixcir_report_data));
 
 	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
 	if (ret != sizeof(wrbuf)) {
@@ -56,45 +72,85 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
 		return;
 	}
 
-	touch = rdbuf[0];
-	if (touch) {
-		u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
-		u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
-		u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
-		u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
-
-		input_report_key(tsdata->input, BTN_TOUCH, 1);
-		input_report_abs(tsdata->input, ABS_X, posx1);
-		input_report_abs(tsdata->input, ABS_Y, posy1);
-
-		input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
-		input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
-		input_mt_sync(tsdata->input);
-
-		if (touch == 2) {
-			input_report_abs(tsdata->input,
-					 ABS_MT_POSITION_X, posx2);
-			input_report_abs(tsdata->input,
-					 ABS_MT_POSITION_Y, posy2);
-			input_mt_sync(tsdata->input);
-		}
-	} else {
-		input_report_key(tsdata->input, BTN_TOUCH, 0);
+	touch = rdbuf[0] & 0x7;
+	if (touch > PIXCIR_MAX_SLOTS)
+		touch = PIXCIR_MAX_SLOTS;
+
+	report->num_touches = touch;
+	bufptr = &rdbuf[2];
+
+	for (i = 0; i < touch; i++) {
+		report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
+		report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
+
+		bufptr = &bufptr[4];
 	}
+}
+
+static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
+			     struct pixcir_report_data *report)
+{
+	struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
+	int slots[PIXCIR_MAX_SLOTS];
+	struct pixcir_touch *touch;
+	int n, i, slot;
+	struct device *dev = &ts->client->dev;
 
-	input_sync(tsdata->input);
+	n = report->num_touches;
+	if (n > PIXCIR_MAX_SLOTS)
+		n = PIXCIR_MAX_SLOTS;
+
+	for (i = 0; i < n; i++) {
+		touch = &report->touches[i];
+		pos[i].x = touch->x;
+		pos[i].y = touch->y;
+	}
+
+	input_mt_assign_slots(ts->input, slots, pos, n);
+
+	for (i = 0; i < n; i++) {
+		touch = &report->touches[i];
+		slot = slots[i];
+
+		input_mt_slot(ts->input, slot);
+		input_mt_report_slot_state(ts->input,
+					   MT_TOOL_FINGER, true);
+
+		input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x);
+		input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y);
+
+		dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
+			i, slot, touch->x, touch->y);
+	}
+
+	input_mt_sync_frame(ts->input);
+	input_sync(ts->input);
 }
 
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
 	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+	struct pixcir_report_data report;
 
 	while (!tsdata->exiting) {
-		pixcir_ts_poscheck(tsdata);
-
-		if (gpio_get_value(pdata->gpio_attb))
+		/* parse packet */
+		pixcir_ts_parse(tsdata, &report);
+
+		/* report it */
+		pixcir_ts_report(tsdata, &report);
+
+		if (gpio_get_value(pdata->gpio_attb)) {
+			if (report.num_touches) {
+				/*
+				 * Last report with no finger up?
+				 * Do it now then.
+				 */
+				input_mt_sync_frame(tsdata->input);
+				input_sync(tsdata->input);
+			}
 			break;
+		}
 
 		msleep(20);
 	}
@@ -337,6 +393,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
 
+	error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS,
+				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+	if (error) {
+		dev_err(dev, "Error initializing Multi-Touch slots\n");
+		return error;
+	}
+
 	input_set_drvdata(input, tsdata);
 
 	error = devm_gpio_request_one(dev, pdata->gpio_attb,
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 5/7] Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided tracking IDs
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Some variants of the Pixcir touch controller support upto 5
simultaneous fingers and hardware tracking IDs. Prepare the driver
for that.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 74 ++++++++++++++++++++++++-------
 include/linux/input/pixcir_ts.h           | 12 +++++
 2 files changed, 69 insertions(+), 17 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 6127606..b3ff62c 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -27,18 +27,20 @@
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
 
-#define PIXCIR_MAX_SLOTS       2
+#define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
 
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input;
-	const struct pixcir_ts_platform_data *chip;
+	const struct pixcir_ts_platform_data *pdata;
 	bool exiting;
+	int max_fingers;	/* Max fingers supported in this instance */
 };
 
 struct pixcir_touch {
 	int x;
 	int y;
+	int id;
 };
 
 struct pixcir_report_data {
@@ -49,13 +51,21 @@ struct pixcir_report_data {
 static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 			    struct pixcir_report_data *report)
 {
-	u8 rdbuf[10], wrbuf[1] = { 0 };
+	u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
+	u8 wrbuf[1] = { 0 };
 	u8 *bufptr;
 	u8 touch;
 	int ret, i;
+	int readsize;
+	const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip;
 
 	memset(report, 0, sizeof(struct pixcir_report_data));
 
+	i = chip->has_hw_ids ? 1 : 0;
+	readsize = 2 + tsdata->max_fingers * (4 + i);
+	if (readsize > sizeof(rdbuf))
+		readsize = sizeof(rdbuf);
+
 	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
 	if (ret != sizeof(wrbuf)) {
 		dev_err(&tsdata->client->dev,
@@ -64,7 +74,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 		return;
 	}
 
-	ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
+	ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
 	if (ret != sizeof(rdbuf)) {
 		dev_err(&tsdata->client->dev,
 			"%s: i2c_master_recv failed(), ret=%d\n",
@@ -73,8 +83,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 	}
 
 	touch = rdbuf[0] & 0x7;
-	if (touch > PIXCIR_MAX_SLOTS)
-		touch = PIXCIR_MAX_SLOTS;
+	if (touch > tsdata->max_fingers)
+		touch = tsdata->max_fingers;
 
 	report->num_touches = touch;
 	bufptr = &rdbuf[2];
@@ -83,7 +93,12 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 		report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
 		report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
 
-		bufptr = &bufptr[4];
+		if (chip->has_hw_ids) {
+			report->touches[i].id = bufptr[4];
+			bufptr = &bufptr[5];
+		} else {
+			bufptr = &bufptr[4];
+		}
 	}
 }
 
@@ -95,22 +110,35 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
 	struct pixcir_touch *touch;
 	int n, i, slot;
 	struct device *dev = &ts->client->dev;
+	const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip;
 
 	n = report->num_touches;
 	if (n > PIXCIR_MAX_SLOTS)
 		n = PIXCIR_MAX_SLOTS;
 
-	for (i = 0; i < n; i++) {
-		touch = &report->touches[i];
-		pos[i].x = touch->x;
-		pos[i].y = touch->y;
-	}
+	if (!chip->has_hw_ids) {
+		for (i = 0; i < n; i++) {
+			touch = &report->touches[i];
+			pos[i].x = touch->x;
+			pos[i].y = touch->y;
+		}
 
-	input_mt_assign_slots(ts->input, slots, pos, n);
+		input_mt_assign_slots(ts->input, slots, pos, n);
+	}
 
 	for (i = 0; i < n; i++) {
 		touch = &report->touches[i];
-		slot = slots[i];
+
+		if (chip->has_hw_ids) {
+			slot = input_mt_get_slot_by_key(ts->input, touch->id);
+			if (slot < 0) {
+				dev_dbg(dev, "no free slot for id 0x%x\n",
+					touch->id);
+				continue;
+			}
+		} else {
+			slot = slots[i];
+		}
 
 		input_mt_slot(ts->input, slot);
 		input_mt_report_slot_state(ts->input,
@@ -130,7 +158,7 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
-	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+	const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
 	struct pixcir_report_data report;
 
 	while (!tsdata->exiting) {
@@ -363,6 +391,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 			dev_err(dev, "Invalid gpio_attb in pdata\n");
 			return -EINVAL;
 		}
+
+		if (pdata->chip.max_fingers <= 0) {
+			dev_err(dev, "Invalid max_fingers in pdata\n");
+			return -EINVAL;
+		}
 	}
 
 	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
@@ -377,7 +410,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 
 	tsdata->client = client;
 	tsdata->input = input;
-	tsdata->chip = pdata;
+	tsdata->pdata = pdata;
 
 	input->name = client->name;
 	input->id.bustype = BUS_I2C;
@@ -393,7 +426,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
 
-	error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS,
+	tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
+	if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
+		tsdata->max_fingers = PIXCIR_MAX_SLOTS;
+		dev_info(dev, "Limiting maximum fingers to %d\n",
+			 tsdata->max_fingers);
+	}
+
+	error = input_mt_init_slots(input, tsdata->max_fingers,
 				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
 	if (error) {
 		dev_err(dev, "Error initializing Multi-Touch slots\n");
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 160cf35..7bae83b 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -43,10 +43,22 @@ enum pixcir_int_mode {
 #define PIXCIR_INT_ENABLE	(1UL << 3)
 #define PIXCIR_INT_POL_HIGH	(1UL << 2)
 
+/**
+ * struct pixcir_irc_chip_data - chip related data
+ * @max_fingers:	Max number of fingers reported simultaneously by h/w
+ * @has_hw_ids:		Hardware supports finger tracking IDs
+ *
+ */
+struct pixcir_i2c_chip_data {
+	u8 max_fingers;
+	bool has_hw_ids;
+};
+
 struct pixcir_ts_platform_data {
 	int x_max;
 	int y_max;
 	int gpio_attb;		/* GPIO connected to ATTB line */
+	struct pixcir_i2c_chip_data chip;
 };
 
 #endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 5/7] Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided tracking IDs
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Some variants of the Pixcir touch controller support upto 5
simultaneous fingers and hardware tracking IDs. Prepare the driver
for that.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 74 ++++++++++++++++++++++++-------
 include/linux/input/pixcir_ts.h           | 12 +++++
 2 files changed, 69 insertions(+), 17 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 6127606..b3ff62c 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -27,18 +27,20 @@
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
 
-#define PIXCIR_MAX_SLOTS       2
+#define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
 
 struct pixcir_i2c_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input;
-	const struct pixcir_ts_platform_data *chip;
+	const struct pixcir_ts_platform_data *pdata;
 	bool exiting;
+	int max_fingers;	/* Max fingers supported in this instance */
 };
 
 struct pixcir_touch {
 	int x;
 	int y;
+	int id;
 };
 
 struct pixcir_report_data {
@@ -49,13 +51,21 @@ struct pixcir_report_data {
 static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 			    struct pixcir_report_data *report)
 {
-	u8 rdbuf[10], wrbuf[1] = { 0 };
+	u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
+	u8 wrbuf[1] = { 0 };
 	u8 *bufptr;
 	u8 touch;
 	int ret, i;
+	int readsize;
+	const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip;
 
 	memset(report, 0, sizeof(struct pixcir_report_data));
 
+	i = chip->has_hw_ids ? 1 : 0;
+	readsize = 2 + tsdata->max_fingers * (4 + i);
+	if (readsize > sizeof(rdbuf))
+		readsize = sizeof(rdbuf);
+
 	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
 	if (ret != sizeof(wrbuf)) {
 		dev_err(&tsdata->client->dev,
@@ -64,7 +74,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 		return;
 	}
 
-	ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
+	ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
 	if (ret != sizeof(rdbuf)) {
 		dev_err(&tsdata->client->dev,
 			"%s: i2c_master_recv failed(), ret=%d\n",
@@ -73,8 +83,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 	}
 
 	touch = rdbuf[0] & 0x7;
-	if (touch > PIXCIR_MAX_SLOTS)
-		touch = PIXCIR_MAX_SLOTS;
+	if (touch > tsdata->max_fingers)
+		touch = tsdata->max_fingers;
 
 	report->num_touches = touch;
 	bufptr = &rdbuf[2];
@@ -83,7 +93,12 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 		report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
 		report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
 
-		bufptr = &bufptr[4];
+		if (chip->has_hw_ids) {
+			report->touches[i].id = bufptr[4];
+			bufptr = &bufptr[5];
+		} else {
+			bufptr = &bufptr[4];
+		}
 	}
 }
 
@@ -95,22 +110,35 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
 	struct pixcir_touch *touch;
 	int n, i, slot;
 	struct device *dev = &ts->client->dev;
+	const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip;
 
 	n = report->num_touches;
 	if (n > PIXCIR_MAX_SLOTS)
 		n = PIXCIR_MAX_SLOTS;
 
-	for (i = 0; i < n; i++) {
-		touch = &report->touches[i];
-		pos[i].x = touch->x;
-		pos[i].y = touch->y;
-	}
+	if (!chip->has_hw_ids) {
+		for (i = 0; i < n; i++) {
+			touch = &report->touches[i];
+			pos[i].x = touch->x;
+			pos[i].y = touch->y;
+		}
 
-	input_mt_assign_slots(ts->input, slots, pos, n);
+		input_mt_assign_slots(ts->input, slots, pos, n);
+	}
 
 	for (i = 0; i < n; i++) {
 		touch = &report->touches[i];
-		slot = slots[i];
+
+		if (chip->has_hw_ids) {
+			slot = input_mt_get_slot_by_key(ts->input, touch->id);
+			if (slot < 0) {
+				dev_dbg(dev, "no free slot for id 0x%x\n",
+					touch->id);
+				continue;
+			}
+		} else {
+			slot = slots[i];
+		}
 
 		input_mt_slot(ts->input, slot);
 		input_mt_report_slot_state(ts->input,
@@ -130,7 +158,7 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
 {
 	struct pixcir_i2c_ts_data *tsdata = dev_id;
-	const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+	const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
 	struct pixcir_report_data report;
 
 	while (!tsdata->exiting) {
@@ -363,6 +391,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 			dev_err(dev, "Invalid gpio_attb in pdata\n");
 			return -EINVAL;
 		}
+
+		if (pdata->chip.max_fingers <= 0) {
+			dev_err(dev, "Invalid max_fingers in pdata\n");
+			return -EINVAL;
+		}
 	}
 
 	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
@@ -377,7 +410,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 
 	tsdata->client = client;
 	tsdata->input = input;
-	tsdata->chip = pdata;
+	tsdata->pdata = pdata;
 
 	input->name = client->name;
 	input->id.bustype = BUS_I2C;
@@ -393,7 +426,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
 
-	error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS,
+	tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
+	if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
+		tsdata->max_fingers = PIXCIR_MAX_SLOTS;
+		dev_info(dev, "Limiting maximum fingers to %d\n",
+			 tsdata->max_fingers);
+	}
+
+	error = input_mt_init_slots(input, tsdata->max_fingers,
 				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
 	if (error) {
 		dev_err(dev, "Error initializing Multi-Touch slots\n");
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
index 160cf35..7bae83b 100644
--- a/include/linux/input/pixcir_ts.h
+++ b/include/linux/input/pixcir_ts.h
@@ -43,10 +43,22 @@ enum pixcir_int_mode {
 #define PIXCIR_INT_ENABLE	(1UL << 3)
 #define PIXCIR_INT_POL_HIGH	(1UL << 2)
 
+/**
+ * struct pixcir_irc_chip_data - chip related data
+ * @max_fingers:	Max number of fingers reported simultaneously by h/w
+ * @has_hw_ids:		Hardware supports finger tracking IDs
+ *
+ */
+struct pixcir_i2c_chip_data {
+	u8 max_fingers;
+	bool has_hw_ids;
+};
+
 struct pixcir_ts_platform_data {
 	int x_max;
 	int y_max;
 	int gpio_attb;		/* GPIO connected to ATTB line */
+	struct pixcir_i2c_chip_data chip;
 };
 
 #endif
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 6/7] Input: pixcir_i2c_ts: Implement wakeup from suspend
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Improve the suspend and resume handlers to allow the device
to wakeup the system from suspend.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 53 ++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index b3ff62c..ea31e20 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -352,21 +352,66 @@ static void pixcir_input_close(struct input_dev *dev)
 static int pixcir_i2c_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
+	struct input_dev *input = ts->input;
+	int ret = 0;
+
+	mutex_lock(&input->mutex);
+
+	if (input->users) {
+		ret = pixcir_stop(ts);
+		if (ret)
+			goto unlock;
+	}
+
+	/*
+	 * If wakeup is enabled we need to enable interrupt generation
+	 * but don't need to process any reports i.e. ts->exiting must be true.
+	 */
+	if (device_may_wakeup(&client->dev)) {
+		/* enable wakeup interrupt generation */
+		ret = pixcir_int_enable(ts, 1);
+		if (ret) {
+			dev_err(dev, "Failed to enable interrupt generation\n");
+			goto unlock;
+		}
 
-	if (device_may_wakeup(&client->dev))
 		enable_irq_wake(client->irq);
+	}
 
-	return 0;
+unlock:
+	mutex_unlock(&input->mutex);
+
+	return ret;
 }
 
 static int pixcir_i2c_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
+	struct input_dev *input = ts->input;
+	int ret = 0;
 
-	if (device_may_wakeup(&client->dev))
+	mutex_lock(&input->mutex);
+
+	if (device_may_wakeup(&client->dev)) {
 		disable_irq_wake(client->irq);
 
-	return 0;
+		/* disable wakeup interrupt generation */
+		ret = pixcir_int_enable(ts, 0);
+		if (ret) {
+			dev_err(dev, "Failed to disable interrupt generation\n");
+			goto unlock;
+		}
+	}
+
+	if (input->users)
+		ret = pixcir_start(ts);
+
+unlock:
+	mutex_unlock(&input->mutex);
+
+	return ret;
 }
 #endif
 
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 6/7] Input: pixcir_i2c_ts: Implement wakeup from suspend
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Improve the suspend and resume handlers to allow the device
to wakeup the system from suspend.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 53 ++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index b3ff62c..ea31e20 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -352,21 +352,66 @@ static void pixcir_input_close(struct input_dev *dev)
 static int pixcir_i2c_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
+	struct input_dev *input = ts->input;
+	int ret = 0;
+
+	mutex_lock(&input->mutex);
+
+	if (input->users) {
+		ret = pixcir_stop(ts);
+		if (ret)
+			goto unlock;
+	}
+
+	/*
+	 * If wakeup is enabled we need to enable interrupt generation
+	 * but don't need to process any reports i.e. ts->exiting must be true.
+	 */
+	if (device_may_wakeup(&client->dev)) {
+		/* enable wakeup interrupt generation */
+		ret = pixcir_int_enable(ts, 1);
+		if (ret) {
+			dev_err(dev, "Failed to enable interrupt generation\n");
+			goto unlock;
+		}
 
-	if (device_may_wakeup(&client->dev))
 		enable_irq_wake(client->irq);
+	}
 
-	return 0;
+unlock:
+	mutex_unlock(&input->mutex);
+
+	return ret;
 }
 
 static int pixcir_i2c_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
+	struct input_dev *input = ts->input;
+	int ret = 0;
 
-	if (device_may_wakeup(&client->dev))
+	mutex_lock(&input->mutex);
+
+	if (device_may_wakeup(&client->dev)) {
 		disable_irq_wake(client->irq);
 
-	return 0;
+		/* disable wakeup interrupt generation */
+		ret = pixcir_int_enable(ts, 0);
+		if (ret) {
+			dev_err(dev, "Failed to disable interrupt generation\n");
+			goto unlock;
+		}
+	}
+
+	if (input->users)
+		ret = pixcir_start(ts);
+
+unlock:
+	mutex_unlock(&input->mutex);
+
+	return ret;
 }
 #endif
 
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 7/7] Input: pixcir_i2c_ts: Add device tree support
  2014-04-30 12:36 ` Roger Quadros
@ 2014-04-30 12:36   ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Provide device tree support and binding information.
Also provide support for a new chip "pixcir_tangoc".

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   | 26 ++++++++
 .../devicetree/bindings/vendor-prefixes.txt        |  1 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 78 ++++++++++++++++++++++
 3 files changed, 105 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt

diff --git a/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
new file mode 100644
index 0000000..0ab9505
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
@@ -0,0 +1,26 @@
+* Pixcir I2C touchscreen controllers
+
+Required properties:
+- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- attb-gpio: GPIO connected to the ATTB line of the chip
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Example:
+
+	i2c@00000000 {
+		/* ... */
+
+		pixcir_ts@5c {
+			compatible = "pixcir,pixcir_ts";
+			reg = <0x5c>;
+			interrupts = <2 0>;
+			attb-gpio = <&gpf 2 0 2>;
+			x-size = <800>;
+			y-size = <600>;
+		};
+
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index abc3080..2270ebe 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -94,6 +94,7 @@ panasonic	Panasonic Corporation
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
+pixcir  PIXCIR MICROELECTRONICS Co., Ltd
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index ea31e20..33f116c 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -26,6 +26,9 @@
 #include <linux/input/mt.h>
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
 
 #define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
 
@@ -418,16 +421,70 @@ unlock:
 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
 
+#ifdef CONFIG_OF
+static const struct of_device_id pixcir_of_match[];
+
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+	struct pixcir_ts_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(pixcir_of_match), dev);
+	if (!match)
+		return ERR_PTR(-EINVAL);
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data;
+
+	pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0);
+	/* gpio_attb validity is checked in probe */
+
+	if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
+		dev_err(dev, "Failed to get x-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	pdata->x_max -= 1;
+
+	if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
+		dev_err(dev, "Failed to get y-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	pdata->y_max -= 1;
+
+	dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__,
+		pdata->x_max + 1, pdata->y_max + 1, pdata->gpio_attb);
+
+	return pdata;
+}
+#else
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
 static int pixcir_i2c_ts_probe(struct i2c_client *client,
 					 const struct i2c_device_id *id)
 {
 	const struct pixcir_ts_platform_data *pdata =
 			dev_get_platdata(&client->dev);
 	struct device *dev = &client->dev;
+	struct device_node *np = dev->of_node;
 	struct pixcir_i2c_ts_data *tsdata;
 	struct input_dev *input;
 	int error;
 
+	if (np && !pdata) {
+		pdata = pixcir_parse_dt(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
+
 	if (!pdata) {
 		dev_err(&client->dev, "platform data not defined\n");
 		return -EINVAL;
@@ -537,15 +594,36 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
 
 static const struct i2c_device_id pixcir_i2c_ts_id[] = {
 	{ "pixcir_ts", 0 },
+	{ "pixcir_tangoc", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
 
+#ifdef CONFIG_OF
+static const struct pixcir_i2c_chip_data pixcir_ts_data = {
+	.max_fingers = 2,
+	/* no hw id support */
+};
+
+static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
+	.max_fingers = 5,
+	.has_hw_ids = true,
+};
+
+static const struct of_device_id pixcir_of_match[] = {
+	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
+	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pixcir_of_match);
+#endif
+
 static struct i2c_driver pixcir_i2c_ts_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "pixcir_ts",
 		.pm	= &pixcir_dev_pm_ops,
+		.of_match_table = of_match_ptr(pixcir_of_match),
 	},
 	.probe		= pixcir_i2c_ts_probe,
 	.remove		= pixcir_i2c_ts_remove,
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v3 7/7] Input: pixcir_i2c_ts: Add device tree support
@ 2014-04-30 12:36   ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-04-30 12:36 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree, Roger Quadros

Provide device tree support and binding information.
Also provide support for a new chip "pixcir_tangoc".

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   | 26 ++++++++
 .../devicetree/bindings/vendor-prefixes.txt        |  1 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 78 ++++++++++++++++++++++
 3 files changed, 105 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt

diff --git a/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
new file mode 100644
index 0000000..0ab9505
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
@@ -0,0 +1,26 @@
+* Pixcir I2C touchscreen controllers
+
+Required properties:
+- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- attb-gpio: GPIO connected to the ATTB line of the chip
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Example:
+
+	i2c@00000000 {
+		/* ... */
+
+		pixcir_ts@5c {
+			compatible = "pixcir,pixcir_ts";
+			reg = <0x5c>;
+			interrupts = <2 0>;
+			attb-gpio = <&gpf 2 0 2>;
+			x-size = <800>;
+			y-size = <600>;
+		};
+
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index abc3080..2270ebe 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -94,6 +94,7 @@ panasonic	Panasonic Corporation
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
+pixcir  PIXCIR MICROELECTRONICS Co., Ltd
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index ea31e20..33f116c 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -26,6 +26,9 @@
 #include <linux/input/mt.h>
 #include <linux/input/pixcir_ts.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
 
 #define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
 
@@ -418,16 +421,70 @@ unlock:
 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
 
+#ifdef CONFIG_OF
+static const struct of_device_id pixcir_of_match[];
+
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+	struct pixcir_ts_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(pixcir_of_match), dev);
+	if (!match)
+		return ERR_PTR(-EINVAL);
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data;
+
+	pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0);
+	/* gpio_attb validity is checked in probe */
+
+	if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
+		dev_err(dev, "Failed to get x-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	pdata->x_max -= 1;
+
+	if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
+		dev_err(dev, "Failed to get y-size property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	pdata->y_max -= 1;
+
+	dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__,
+		pdata->x_max + 1, pdata->y_max + 1, pdata->gpio_attb);
+
+	return pdata;
+}
+#else
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
 static int pixcir_i2c_ts_probe(struct i2c_client *client,
 					 const struct i2c_device_id *id)
 {
 	const struct pixcir_ts_platform_data *pdata =
 			dev_get_platdata(&client->dev);
 	struct device *dev = &client->dev;
+	struct device_node *np = dev->of_node;
 	struct pixcir_i2c_ts_data *tsdata;
 	struct input_dev *input;
 	int error;
 
+	if (np && !pdata) {
+		pdata = pixcir_parse_dt(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
+
 	if (!pdata) {
 		dev_err(&client->dev, "platform data not defined\n");
 		return -EINVAL;
@@ -537,15 +594,36 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
 
 static const struct i2c_device_id pixcir_i2c_ts_id[] = {
 	{ "pixcir_ts", 0 },
+	{ "pixcir_tangoc", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
 
+#ifdef CONFIG_OF
+static const struct pixcir_i2c_chip_data pixcir_ts_data = {
+	.max_fingers = 2,
+	/* no hw id support */
+};
+
+static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
+	.max_fingers = 5,
+	.has_hw_ids = true,
+};
+
+static const struct of_device_id pixcir_of_match[] = {
+	{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
+	{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pixcir_of_match);
+#endif
+
 static struct i2c_driver pixcir_i2c_ts_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "pixcir_ts",
 		.pm	= &pixcir_dev_pm_ops,
+		.of_match_table = of_match_ptr(pixcir_of_match),
 	},
 	.probe		= pixcir_i2c_ts_probe,
 	.remove		= pixcir_i2c_ts_remove,
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 2/7] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
  2014-04-30 12:36   ` Roger Quadros
  (?)
@ 2014-04-30 16:29   ` Dmitry Torokhov
  2014-05-05  8:42       ` Roger Quadros
  -1 siblings, 1 reply; 23+ messages in thread
From: Dmitry Torokhov @ 2014-04-30 16:29 UTC (permalink / raw)
  To: Roger Quadros
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree

Hi Roger,

On Wed, Apr 30, 2014 at 03:36:27PM +0300, Roger Quadros wrote:
> +static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
> +{
> +	struct device *dev = &ts->client->dev;
> +	int ret;
> +
> +	/* exit ISR if running, no more report parsing */
> +	ts->exiting = true;
> +	mb();	/* update status before we synchronize irq */
> +
> +	/* disable ISR from running again */
> +	disable_irq(ts->client->irq);
> +
> +	/* wait till running ISR complete */
> +	synchronize_irq(ts->client->irq);
> +
> +	/* disable interrupt generation */
> +	ret = pixcir_int_enable(ts, 0);
> +	if (ret)
> +		dev_err(dev, "Failed to disable interrupt generation\n");
> +
> +	/* restore IRQ */
> +	enable_irq(ts->client->irq);
> +
> +	return ret;

Should not this be:

	pixcir_int_enable(ts, 0);
	ts->exiting = true;
	mb();
	synchronize_irq(ts->client->irq);

Why do we also need to disable/enable irq?

By the way, disable_irq() implies synchronize_irq().

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations
@ 2014-04-30 16:30     ` Dmitry Torokhov
  0 siblings, 0 replies; 23+ messages in thread
From: Dmitry Torokhov @ 2014-04-30 16:30 UTC (permalink / raw)
  To: Roger Quadros
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree

Hi Roger,

On Wed, Apr 30, 2014 at 03:36:26PM +0300, Roger Quadros wrote:

>  static int pixcir_i2c_ts_remove(struct i2c_client *client)
> @@ -198,10 +194,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
>  
>  	tsdata->exiting = true;
>  	mb();
> -	free_irq(client->irq, tsdata);
>  
>  	input_unregister_device(tsdata->input);

There is no need to call input_unregister_device for managed input
devices.

> -	kfree(tsdata);
>  
>  	return 0;
>  }
> -- 
> 1.8.3.2
> 

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations
@ 2014-04-30 16:30     ` Dmitry Torokhov
  0 siblings, 0 replies; 23+ messages in thread
From: Dmitry Torokhov @ 2014-04-30 16:30 UTC (permalink / raw)
  To: Roger Quadros
  Cc: rydberg-Hk7bIW8heu4wFerOooGFRg, balbi-l0cyMroinI0,
	dmurphy-l0cyMroinI0, mugunthanvnm-l0cyMroinI0,
	nsekhar-l0cyMroinI0, linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Roger,

On Wed, Apr 30, 2014 at 03:36:26PM +0300, Roger Quadros wrote:

>  static int pixcir_i2c_ts_remove(struct i2c_client *client)
> @@ -198,10 +194,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
>  
>  	tsdata->exiting = true;
>  	mb();
> -	free_irq(client->irq, tsdata);
>  
>  	input_unregister_device(tsdata->input);

There is no need to call input_unregister_device for managed input
devices.

> -	kfree(tsdata);
>  
>  	return 0;
>  }
> -- 
> 1.8.3.2
> 

Thanks.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 2/7] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
  2014-04-30 16:29   ` Dmitry Torokhov
@ 2014-05-05  8:42       ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-05-05  8:42 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree

Hi Dmitry,

On 04/30/2014 07:29 PM, Dmitry Torokhov wrote:
> Hi Roger,
> 
> On Wed, Apr 30, 2014 at 03:36:27PM +0300, Roger Quadros wrote:
>> +static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
>> +{
>> +	struct device *dev = &ts->client->dev;
>> +	int ret;
>> +
>> +	/* exit ISR if running, no more report parsing */
>> +	ts->exiting = true;
>> +	mb();	/* update status before we synchronize irq */
>> +
>> +	/* disable ISR from running again */
>> +	disable_irq(ts->client->irq);
>> +
>> +	/* wait till running ISR complete */
>> +	synchronize_irq(ts->client->irq);
>> +
>> +	/* disable interrupt generation */
>> +	ret = pixcir_int_enable(ts, 0);
>> +	if (ret)
>> +		dev_err(dev, "Failed to disable interrupt generation\n");
>> +
>> +	/* restore IRQ */
>> +	enable_irq(ts->client->irq);
>> +
>> +	return ret;
> 
> Should not this be:
> 
> 	pixcir_int_enable(ts, 0);
> 	ts->exiting = true;
> 	mb();
> 	synchronize_irq(ts->client->irq);
> 
> Why do we also need to disable/enable irq?

Yes, you are right. It seems the problem with v2 was that order of mb() and synchronize_irq() were
reversed and thus causing the suspend/resume problem. I tried with your suggestion and it works.
I'll send a revised series.

> 
> By the way, disable_irq() implies synchronize_irq().

OK.

cheers,
-roger

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 2/7] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode
@ 2014-05-05  8:42       ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-05-05  8:42 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree

Hi Dmitry,

On 04/30/2014 07:29 PM, Dmitry Torokhov wrote:
> Hi Roger,
> 
> On Wed, Apr 30, 2014 at 03:36:27PM +0300, Roger Quadros wrote:
>> +static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
>> +{
>> +	struct device *dev = &ts->client->dev;
>> +	int ret;
>> +
>> +	/* exit ISR if running, no more report parsing */
>> +	ts->exiting = true;
>> +	mb();	/* update status before we synchronize irq */
>> +
>> +	/* disable ISR from running again */
>> +	disable_irq(ts->client->irq);
>> +
>> +	/* wait till running ISR complete */
>> +	synchronize_irq(ts->client->irq);
>> +
>> +	/* disable interrupt generation */
>> +	ret = pixcir_int_enable(ts, 0);
>> +	if (ret)
>> +		dev_err(dev, "Failed to disable interrupt generation\n");
>> +
>> +	/* restore IRQ */
>> +	enable_irq(ts->client->irq);
>> +
>> +	return ret;
> 
> Should not this be:
> 
> 	pixcir_int_enable(ts, 0);
> 	ts->exiting = true;
> 	mb();
> 	synchronize_irq(ts->client->irq);
> 
> Why do we also need to disable/enable irq?

Yes, you are right. It seems the problem with v2 was that order of mb() and synchronize_irq() were
reversed and thus causing the suspend/resume problem. I tried with your suggestion and it works.
I'll send a revised series.

> 
> By the way, disable_irq() implies synchronize_irq().

OK.

cheers,
-roger

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations
  2014-04-30 16:30     ` Dmitry Torokhov
@ 2014-05-05  8:44       ` Roger Quadros
  -1 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-05-05  8:44 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree

On 04/30/2014 07:30 PM, Dmitry Torokhov wrote:
> Hi Roger,
> 
> On Wed, Apr 30, 2014 at 03:36:26PM +0300, Roger Quadros wrote:
> 
>>  static int pixcir_i2c_ts_remove(struct i2c_client *client)
>> @@ -198,10 +194,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
>>  
>>  	tsdata->exiting = true;
>>  	mb();
>> -	free_irq(client->irq, tsdata);
>>  
>>  	input_unregister_device(tsdata->input);
> 
> There is no need to call input_unregister_device for managed input
> devices.

OK. I'll remove that.

> 
>> -	kfree(tsdata);
>>  
>>  	return 0;
>>  }

cheers,
-roger

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations
@ 2014-05-05  8:44       ` Roger Quadros
  0 siblings, 0 replies; 23+ messages in thread
From: Roger Quadros @ 2014-05-05  8:44 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: rydberg, balbi, dmurphy, mugunthanvnm, nsekhar, linux-input,
	linux-kernel, devicetree

On 04/30/2014 07:30 PM, Dmitry Torokhov wrote:
> Hi Roger,
> 
> On Wed, Apr 30, 2014 at 03:36:26PM +0300, Roger Quadros wrote:
> 
>>  static int pixcir_i2c_ts_remove(struct i2c_client *client)
>> @@ -198,10 +194,8 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
>>  
>>  	tsdata->exiting = true;
>>  	mb();
>> -	free_irq(client->irq, tsdata);
>>  
>>  	input_unregister_device(tsdata->input);
> 
> There is no need to call input_unregister_device for managed input
> devices.

OK. I'll remove that.

> 
>> -	kfree(tsdata);
>>  
>>  	return 0;
>>  }

cheers,
-roger

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2014-05-05  8:44 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-30 12:36 [PATCH v3 0/7] Input: pixcir_i2c_ts: Add Type-B Multi-touch and DT support Roger Quadros
2014-04-30 12:36 ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 1/7] Input: pixcir_i2c_ts: Use devres managed resource allocations Roger Quadros
2014-04-30 12:36   ` Roger Quadros
2014-04-30 16:30   ` Dmitry Torokhov
2014-04-30 16:30     ` Dmitry Torokhov
2014-05-05  8:44     ` Roger Quadros
2014-05-05  8:44       ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 2/7] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode Roger Quadros
2014-04-30 12:36   ` Roger Quadros
2014-04-30 16:29   ` Dmitry Torokhov
2014-05-05  8:42     ` Roger Quadros
2014-05-05  8:42       ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 3/7] Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val() Roger Quadros
2014-04-30 12:36   ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 4/7] Input: pixcir_i2c_ts: Use Type-B Multi-Touch protocol Roger Quadros
2014-04-30 12:36   ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 5/7] Input: pixcir_i2c_ts: support upto 5 fingers and hardware provided tracking IDs Roger Quadros
2014-04-30 12:36   ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 6/7] Input: pixcir_i2c_ts: Implement wakeup from suspend Roger Quadros
2014-04-30 12:36   ` Roger Quadros
2014-04-30 12:36 ` [PATCH v3 7/7] Input: pixcir_i2c_ts: Add device tree support Roger Quadros
2014-04-30 12:36   ` Roger Quadros

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.