Skip to contentSkip to conversation

Various touchscreens: Support axis inversion / swapping / extra gpios

PATCH Superseded Hans de Goede 3 participants 12 messages Nov 20, 2015 – Nov 24, 2015

Subsystems (5)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover Various touchscreens: Support axis inversion / swapping / extra gpios

Hi Dimtry and Maxime,

Brown paper-bag release of this series fixing 2 issues which I missed during initial testing. First the original coverletter again:

This patch-set extends the of_touchscreen.c helpers to (optionally) also deal with axis inversion / swapping, and patches a bunch of drivers to use this new functionality.

One of the modified drivers is the pixcir_i2c_ts driver. Sander Vermin has been helping me with getting this driver to work on a tablet I own. This patch-set includes a v2 of Sander's "Input: pixcir_i2c_ts: add wake and enable gpios" patch. v1 also included axis inversion / swapping support, which I've redone using the new helpers in a separate patch in this set.

Dmitry can you pickup patches 1-5 please ?
Maxime can you pickup patches 6-7 please ? Merging them seperately should not be an issue without patches 1-5 the touchscreen will not work but there will be no other breakage, so no regressions.

Changes in v2:
-[touchscreen: icn8318: Use parse_properties and apply_prop_to_x_y helpers]
Call input_set_capability() before calling touchscreen_parse_properties()
-[touchscreen: pixcir_ts: Add support for axis inversion / swapping]
Add a fix which actually makes this patch compile, which accidentally ended up in a later commit in my tree

Thanks & Regards,

Hans

#1 lore raw

PATCH v2 1/7 of_touchscreen-helpers: Add support for inverted / swapped axis

Extend touchscreen_parse_properties() with support for the touchscreen-inverted-x/y and touchscreen-swapped-x-y properties and add a touchscreen_apply_prop_to_x_y() helper function for adjusting x and y coordinates to take these properties into account.

This commit also modifies the existing callers of touchscreen_parse_properties() to pass in NULL for the new third argument, keeping the existing behavior.

---
 drivers/input/touchscreen/edt-ft5x06.c     |  2 +-
 drivers/input/touchscreen/of_touchscreen.c | 56 +++++++++++++++++++++++++++++-
 drivers/input/touchscreen/pixcir_i2c_ts.c  |  2 +-
 drivers/input/touchscreen/tsc200x-core.c   |  2 +-
 include/linux/input/touchscreen.h          | 16 ++++++++-
 5 files changed, 73 insertions(+), 5 deletions(-)
drivers/input/touchscreen/edt-ft5x06.c +1 -1
index 0b0f8c1..a97b54a 100644
@@ -966,7 +966,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_MT_POSITION_Y,
 			     0, tsdata->num_y * 64 - 1, 0, 0);
 
-	touchscreen_parse_properties(input, true);
+	touchscreen_parse_properties(input, true, NULL);
 
 	error = input_mt_init_slots(input, tsdata->max_support_points,
 				INPUT_MT_DIRECT);
drivers/input/touchscreen/of_touchscreen.c +55 -1

72 lines not on this page · raw message

drivers/input/touchscreen/pixcir_i2c_ts.c +1 -1
index 4b961ad..211408c 100644
@@ -495,7 +495,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	} else {
 		input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
 		input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
-		touchscreen_parse_properties(input, true);
+		touchscreen_parse_properties(input, true, NULL);
 		if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
 		    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
 			dev_err(dev, "Touchscreen size is not specified\n");
drivers/input/touchscreen/tsc200x-core.c +1 -1
index 15240c1..26e81d1 100644
@@ -559,7 +559,7 @@ int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
 
 	if (np)
-		touchscreen_parse_properties(input_dev, false);
+		touchscreen_parse_properties(input_dev, false, NULL);
 
 	input_dev->open = tsc200x_open;
 	input_dev->close = tsc200x_close;
include/linux/input/touchscreen.h +15 -1
index c91e137..9e6ba20 100644
@@ -9,8 +9,22 @@
 #ifndef _TOUCHSCREEN_H
 #define _TOUCHSCREEN_H
 
+#include <asm/types.h>
+
 struct input_dev;
 
-void touchscreen_parse_properties(struct input_dev *dev, bool multitouch);
+struct touchscreen_properties {
+	s32 max_x;
+	s32 max_y;
+	bool invert_x;
+	bool invert_y;
+	bool swap_x_y;
+};
+
+void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
+				  struct touchscreen_properties *prop);
+
+void touchscreen_apply_prop_to_x_y(struct touchscreen_properties *prop,
+				   s16 *x, s16 *y);
 
 #endif
Signature · 1 line
2.5.0
#2 lore raw

PATCH v2 2/7 touchscreen: ft5x06: Add support for axis inversion / swapping

In reply to Hans de Goede

Add support for axis inversion / swapping using the new touchscreen_parse_properties and touchscreen_apply_prop_to_x_y functionality.

---
 drivers/input/touchscreen/edt-ft5x06.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/input/touchscreen/edt-ft5x06.c +5 -2
index a97b54a..6fe8d51 100644
@@ -86,6 +86,7 @@ struct edt_reg_addr {
 struct edt_ft5x06_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input;
+	struct touchscreen_properties prop;
 	u16 num_x;
 	u16 num_y;
 
@@ -173,7 +174,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 	struct device *dev = &tsdata->client->dev;
 	u8 cmd;
 	u8 rdbuf[63];
-	int i, type, x, y, id;
+	s16 x, y;
+	int i, type, id;
 	int offset, tplen, datalen, crclen;
 	int error;
 
@@ -246,6 +248,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 		if (!down)
 			continue;
 
+		touchscreen_apply_prop_to_x_y(&tsdata->prop, &x, &y);
 		input_report_abs(tsdata->input, ABS_MT_POSITION_X, x);
 		input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y);
 	}
@@ -966,7 +969,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_MT_POSITION_Y,
 			     0, tsdata->num_y * 64 - 1, 0, 0);
 
-	touchscreen_parse_properties(input, true, NULL);
+	touchscreen_parse_properties(input, true, &tsdata->prop);
 
 	error = input_mt_init_slots(input, tsdata->max_support_points,
 				INPUT_MT_DIRECT);
Signature · 1 line
2.5.0
#3 lore raw

PATCH v2 3/7 touchscreen: icn8318: Use parse_properties and apply_prop_to_x_y helpers

In reply to Hans de Goede

Use the touchscreen_parse_properties and touchscreen_apply_prop_to_x_y functions, instead of DIY code, this results in a nice cleanup.

---
Changes in v2:
-Call input_set_capability() before calling touchscreen_parse_properties()

---
 drivers/input/touchscreen/chipone_icn8318.c | 58 +++++++----------------------
 1 file changed, 14 insertions(+), 44 deletions(-)
drivers/input/touchscreen/chipone_icn8318.c +14 -44
index 22a6fea..92151f9 100644
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
 #include <linux/module.h>
 #include <linux/of.h>
 
@@ -52,11 +53,7 @@ struct icn8318_data {
 	struct i2c_client *client;
 	struct input_dev *input;
 	struct gpio_desc *wake_gpio;
-	u32 max_x;
-	u32 max_y;
-	bool invert_x;
-	bool invert_y;
-	bool swap_x_y;
+	struct touchscreen_properties prop;
 };
 
 static int icn8318_read_touch_data(struct i2c_client *client,
@@ -91,7 +88,8 @@ static irqreturn_t icn8318_irq(int irq, void *dev_id)
 	struct icn8318_data *data = dev_id;
 	struct device *dev = &data->client->dev;
 	struct icn8318_touch_data touch_data;
-	int i, ret, x, y;
+	int i, ret;
+	s16 x, y;
 
 	ret = icn8318_read_touch_data(data->client, &touch_data);
 	if (ret < 0) {
@@ -127,19 +125,9 @@ static irqreturn_t icn8318_irq(int irq, void *dev_id)
 		x = be16_to_cpu(touch->x);
 		y = be16_to_cpu(touch->y);
 
-		if (data->invert_x)
-			x = data->max_x - x;
-
-		if (data->invert_y)
-			y = data->max_y - y;
-
-		if (!data->swap_x_y) {
-			input_event(data->input, EV_ABS, ABS_MT_POSITION_X, x);
-			input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, y);
-		} else {
-			input_event(data->input, EV_ABS, ABS_MT_POSITION_X, y);
-			input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, x);
-		}
+		touchscreen_apply_prop_to_x_y(&data->prop, &x, &y);
+		input_event(data->input, EV_ABS, ABS_MT_POSITION_X, x);
+		input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, y);
 	}
 
 	input_mt_sync_frame(data->input);
@@ -200,10 +188,8 @@ static int icn8318_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *np = dev->of_node;
 	struct icn8318_data *data;
 	struct input_dev *input;
-	u32 fuzz_x = 0, fuzz_y = 0;
 	int error;
 
 	if (!client->irq) {
@@ -223,19 +209,6 @@ static int icn8318_probe(struct i2c_client *client,
 		return error;
 	}
 
-	if (of_property_read_u32(np, "touchscreen-size-x", &data->max_x) ||
-	    of_property_read_u32(np, "touchscreen-size-y", &data->max_y)) {
-		dev_err(dev, "Error touchscreen-size-x and/or -y missing\n");
-		return -EINVAL;
-	}
-
-	/* Optional */
-	of_property_read_u32(np, "touchscreen-fuzz-x", &fuzz_x);
-	of_property_read_u32(np, "touchscreen-fuzz-y", &fuzz_y);
-	data->invert_x = of_property_read_bool(np, "touchscreen-inverted-x");
-	data->invert_y = of_property_read_bool(np, "touchscreen-inverted-y");
-	data->swap_x_y = of_property_read_bool(np, "touchscreen-swapped-x-y");
-
 	input = devm_input_allocate_device(dev);
 	if (!input)
 		return -ENOMEM;
@@ -246,16 +219,13 @@ static int icn8318_probe(struct i2c_client *client,
 	input->close = icn8318_stop;
 	input->dev.parent = dev;
 
-	if (!data->swap_x_y) {
-		input_set_abs_params(input, ABS_MT_POSITION_X, 0,
-				     data->max_x, fuzz_x, 0);
-		input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
-				     data->max_y, fuzz_y, 0);
-	} else {
-		input_set_abs_params(input, ABS_MT_POSITION_X, 0,
-				     data->max_y, fuzz_y, 0);
-		input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
-				     data->max_x, fuzz_x, 0);
+	input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
+	input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
+	touchscreen_parse_properties(input, true, &data->prop);
+	if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
+	    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
+		dev_err(dev, "Error touchscreen-size-x and/or -y missing\n");
+		return -EINVAL;
 	}
 
 	error = input_mt_init_slots(input, ICN8318_MAX_TOUCHES,
Signature · 1 line
2.5.0
#4 lore raw

PATCH v2 4/7 touchscreen: pixcir_i2c: Add support for wake and enable gpios

In reply to Hans de Goede

From: Sander Vermin <[email protected]>

On some devices the wake and enable pins of the pixcir touchscreen controller are connected to gpios and these must be controlled by the driver for the device to operate properly.

---
Changes in v2 (Hans de Goede):
-Split the changes for dealing with inverted / swapped axis out into a
separate patch
-Remove a bunch of dev_info calls to make the driver less chatty -Use devm_gpiod_get_optional as these new gpios are optional -Only msleep after setting enable high if we have an enable pin

---
 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   |  2 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 46 ++++++++++++++++++++++
 2 files changed, 48 insertions(+)
Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt +2 -0
index 8eb240a..72ca5ec 100644
@@ -10,6 +10,8 @@ Required properties:
 
 Optional properties:
 - reset-gpio: GPIO connected to the RESET line of the chip
+- enable-gpios: GPIO connected to the ENABLE line of the chip
+- wake-gpios: GPIO connected to the WAKE line of the chip
 
 Example:
 
drivers/input/touchscreen/pixcir_i2c_ts.c +46 -0

88 lines not on this page · raw message

Signature · 1 line
2.5.0
maintainer
#5 lore raw

PATCH v2 4/7 touchscreen: pixcir_i2c: Add support for wake and enable gpios

Quoted 118 lines · Hans de Goede

From: Sander Vermin <[email protected]>

On some devices the wake and enable pins of the pixcir touchscreen controller are connected to gpios and these must be controlled by the driver for the device to operate properly.

---
Changes in v2 (Hans de Goede):

(quoted diff) +0 -5
-Split the changes for dealing with inverted / swapped axis out into a
 separate patch
-Remove a bunch of dev_info calls to make the driver less chatty
-Use devm_gpiod_get_optional as these new gpios are optional
-Only msleep after setting enable high if we have an enable pin
---
 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   |  2 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 46 ++++++++++++++++++++++
 2 files changed, 48 insertions(+)
Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt +2 -0
index 8eb240a..72ca5ec 100644
@@ -10,6 +10,8 @@ Required properties:
 
 Optional properties:
 - reset-gpio: GPIO connected to the RESET line of the chip
+- enable-gpios: GPIO connected to the ENABLE line of the chip
+- wake-gpios: GPIO connected to the WAKE line of the chip
 
 Example:
 
drivers/input/touchscreen/pixcir_i2c_ts.c +38 -0
index 211408c..b75ef65 100644
@@ -38,6 +38,8 @@ struct pixcir_i2c_ts_data {
 	struct input_dev *input;
 	struct gpio_desc *gpio_attb;
 	struct gpio_desc *gpio_reset;
+	struct gpio_desc *gpio_enable;
+	struct gpio_desc *gpio_wake;
 	const struct pixcir_i2c_chip_data *chip;
 	int max_fingers;	/* Max fingers supported in this instance */
 	bool running;
@@ -208,6 +210,11 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
 	struct device *dev = &ts->client->dev;
 	int ret;
 
+	if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) {
+		if (!IS_ERR_OR_NULL(ts->gpio_wake))
+			gpiod_set_value_cansleep(ts->gpio_wake, 1);
+	}
+
 	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",
@@ -228,6 +235,11 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
 		return ret;
 	}
 
+	if (mode == PIXCIR_POWER_HALT) {
+		if (!IS_ERR_OR_NULL(ts->gpio_wake))
+			gpiod_set_value_cansleep(ts->gpio_wake, 0);
+	}
+
 	return 0;
 }
 
@@ -302,6 +314,11 @@ static int pixcir_start(struct pixcir_i2c_ts_data *ts)
 	struct device *dev = &ts->client->dev;
 	int error;
 
+	if (!IS_ERR_OR_NULL(ts->gpio_enable)) {
+		gpiod_set_value_cansleep(ts->gpio_enable, 1);
+		msleep(100);
+	}
+
 	/* LEVEL_TOUCH interrupt with active low polarity */
 	error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
 	if (error) {
@@ -343,6 +360,9 @@ static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
 	/* Wait till running ISR is complete */
 	synchronize_irq(ts->client->irq);
 
+	if (!IS_ERR_OR_NULL(ts->gpio_enable))
+		gpiod_set_value_cansleep(ts->gpio_enable, 0);
+
 	return 0;
 }
 
@@ -534,6 +554,24 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(tsdata->gpio_wake)) {
+		error = PTR_ERR(tsdata->gpio_wake);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get wake gpio: %d\n", error);
+		return error;
+	}
+
+	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
+						      GPIOD_OUT_HIGH);
+	if (IS_ERR(tsdata->gpio_enable)) {
+		error = PTR_ERR(tsdata->gpio_enable);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get enable gpio: %d\n", error);
+		return error;
+	}
+
 	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					  client->name, tsdata);

drivers/input/touchscreen/pixcir_i2c_ts.c static int pixcir_i2c_ts_probe(struct i2c_client *client, · line 589

Quoted 10 lines
drivers/input/touchscreen/pixcir_i2c_ts.c +7 -0
@@ -542,6 +580,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	if (!IS_ERR_OR_NULL(tsdata->gpio_wake))
+		gpiod_set_value_cansleep(tsdata->gpio_wake, 1);
+
+	if (!IS_ERR_OR_NULL(tsdata->gpio_enable)) {
+		gpiod_set_value_cansleep(tsdata->gpio_enable, 1);
+		msleep(100);
+	}

Actually, another question: why do we need this calls to activate wake and enable gpios here if we request them as active?

Thanks.

Quoted 7 lines
drivers/input/touchscreen/pixcir_i2c_ts.c +1 -0
+
 	pixcir_reset(tsdata);
 
 	/* Always be in IDLE mode to save power, device supports auto wake */
Signature · 1 line
2.5.0
Signature · 1 line
Dmitry
#6 lore raw

PATCH v2 4/7 touchscreen: pixcir_i2c: Add support for wake and enable gpios

Hi,

Quoted 122 lines · Dmitry Torokhov
Quoted 121 lines · Hans de Goede

From: Sander Vermin <[email protected]>

On some devices the wake and enable pins of the pixcir touchscreen controller are connected to gpios and these must be controlled by the driver for the device to operate properly.

---
Changes in v2 (Hans de Goede):

(quoted diff) +0 -5
-Split the changes for dealing with inverted / swapped axis out into a
  separate patch
-Remove a bunch of dev_info calls to make the driver less chatty
-Use devm_gpiod_get_optional as these new gpios are optional
-Only msleep after setting enable high if we have an enable pin
---
  .../bindings/input/touchscreen/pixcir_i2c_ts.txt   |  2 +
  drivers/input/touchscreen/pixcir_i2c_ts.c          | 46 ++++++++++++++++++++++
  2 files changed, 48 insertions(+)
Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt +2 -0
index 8eb240a..72ca5ec 100644
@@ -10,6 +10,8 @@ Required properties:
 
  Optional properties:
  - reset-gpio: GPIO connected to the RESET line of the chip
+- enable-gpios: GPIO connected to the ENABLE line of the chip
+- wake-gpios: GPIO connected to the WAKE line of the chip
 
  Example:
 
drivers/input/touchscreen/pixcir_i2c_ts.c +38 -0
index 211408c..b75ef65 100644
@@ -38,6 +38,8 @@ struct pixcir_i2c_ts_data {
  	struct input_dev *input;
  	struct gpio_desc *gpio_attb;
  	struct gpio_desc *gpio_reset;
+	struct gpio_desc *gpio_enable;
+	struct gpio_desc *gpio_wake;
  	const struct pixcir_i2c_chip_data *chip;
  	int max_fingers;	/* Max fingers supported in this instance */
  	bool running;
@@ -208,6 +210,11 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
  	struct device *dev = &ts->client->dev;
  	int ret;
 
+	if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) {
+		if (!IS_ERR_OR_NULL(ts->gpio_wake))
+			gpiod_set_value_cansleep(ts->gpio_wake, 1);
+	}
+
  	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",
@@ -228,6 +235,11 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
  		return ret;
  	}
 
+	if (mode == PIXCIR_POWER_HALT) {
+		if (!IS_ERR_OR_NULL(ts->gpio_wake))
+			gpiod_set_value_cansleep(ts->gpio_wake, 0);
+	}
+
  	return 0;
  }
 
@@ -302,6 +314,11 @@ static int pixcir_start(struct pixcir_i2c_ts_data *ts)
  	struct device *dev = &ts->client->dev;
  	int error;
 
+	if (!IS_ERR_OR_NULL(ts->gpio_enable)) {
+		gpiod_set_value_cansleep(ts->gpio_enable, 1);
+		msleep(100);
+	}
+
  	/* LEVEL_TOUCH interrupt with active low polarity */
  	error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
  	if (error) {
@@ -343,6 +360,9 @@ static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
  	/* Wait till running ISR is complete */
  	synchronize_irq(ts->client->irq);
 
+	if (!IS_ERR_OR_NULL(ts->gpio_enable))
+		gpiod_set_value_cansleep(ts->gpio_enable, 0);
+
  	return 0;
  }
 
@@ -534,6 +554,24 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
  		return error;
  	}
 
+	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(tsdata->gpio_wake)) {
+		error = PTR_ERR(tsdata->gpio_wake);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get wake gpio: %d\n", error);
+		return error;
+	}
+
+	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
+						      GPIOD_OUT_HIGH);
+	if (IS_ERR(tsdata->gpio_enable)) {
+		error = PTR_ERR(tsdata->gpio_enable);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get enable gpio: %d\n", error);
+		return error;
+	}
+
  	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
  					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  					  client->name, tsdata);
@@ -542,6 +580,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
  		return error;
  	}
 
Quoted 10 lines

drivers/input/touchscreen/pixcir_i2c_ts.c static int pixcir_i2c_ts_probe(struct i2c_client *client, · line 589

Quoted 7 lines
drivers/input/touchscreen/pixcir_i2c_ts.c +7 -0
+	if (!IS_ERR_OR_NULL(tsdata->gpio_wake))
+		gpiod_set_value_cansleep(tsdata->gpio_wake, 1);
+
+	if (!IS_ERR_OR_NULL(tsdata->gpio_enable)) {
+		gpiod_set_value_cansleep(tsdata->gpio_enable, 1);
+		msleep(100);
+	}

Actually, another question: why do we need this calls to activate wake and enable gpios here if we request them as active?

Hmm, interesting point. I will re-test with just the msleep there. For v2 what do you want to do with the if tests, keep as "if (!IS_ERR_OR_NULL(...))" or change them to just "if (...)" ?

Regards,

Hans

Quoted 11 lines

Thanks.

Quoted 7 lines
drivers/input/touchscreen/pixcir_i2c_ts.c +1 -1
+
  	pixcir_reset(tsdata);
 
  	/* Always be in IDLE mode to save power, device supports auto wake */
--

2.5.0

maintainer
#7 lore raw

PATCH v2 4/7 touchscreen: pixcir_i2c: Add support for wake and enable gpios

Quoted 136 lines · Hans de Goede

Hi,

Quoted 122 lines · Dmitry Torokhov
Quoted 121 lines · Hans de Goede

From: Sander Vermin <[email protected]>

On some devices the wake and enable pins of the pixcir touchscreen controller are connected to gpios and these must be controlled by the driver for the device to operate properly.

---
Changes in v2 (Hans de Goede):

(quoted diff) +0 -5
-Split the changes for dealing with inverted / swapped axis out into a
 separate patch
-Remove a bunch of dev_info calls to make the driver less chatty
-Use devm_gpiod_get_optional as these new gpios are optional
-Only msleep after setting enable high if we have an enable pin
---
 .../bindings/input/touchscreen/pixcir_i2c_ts.txt   |  2 +
 drivers/input/touchscreen/pixcir_i2c_ts.c          | 46 ++++++++++++++++++++++
 2 files changed, 48 insertions(+)
Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt +2 -0
index 8eb240a..72ca5ec 100644
@@ -10,6 +10,8 @@ Required properties:
 
 Optional properties:
 - reset-gpio: GPIO connected to the RESET line of the chip
+- enable-gpios: GPIO connected to the ENABLE line of the chip
+- wake-gpios: GPIO connected to the WAKE line of the chip
 
 Example:
 
drivers/input/touchscreen/pixcir_i2c_ts.c +38 -0
index 211408c..b75ef65 100644
@@ -38,6 +38,8 @@ struct pixcir_i2c_ts_data {
 	struct input_dev *input;
 	struct gpio_desc *gpio_attb;
 	struct gpio_desc *gpio_reset;
+	struct gpio_desc *gpio_enable;
+	struct gpio_desc *gpio_wake;
 	const struct pixcir_i2c_chip_data *chip;
 	int max_fingers;	/* Max fingers supported in this instance */
 	bool running;
@@ -208,6 +210,11 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
 	struct device *dev = &ts->client->dev;
 	int ret;
 
+	if (mode == PIXCIR_POWER_ACTIVE || mode == PIXCIR_POWER_IDLE) {
+		if (!IS_ERR_OR_NULL(ts->gpio_wake))
+			gpiod_set_value_cansleep(ts->gpio_wake, 1);
+	}
+
 	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",
@@ -228,6 +235,11 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
 		return ret;
 	}
 
+	if (mode == PIXCIR_POWER_HALT) {
+		if (!IS_ERR_OR_NULL(ts->gpio_wake))
+			gpiod_set_value_cansleep(ts->gpio_wake, 0);
+	}
+
 	return 0;
 }
 
@@ -302,6 +314,11 @@ static int pixcir_start(struct pixcir_i2c_ts_data *ts)
 	struct device *dev = &ts->client->dev;
 	int error;
 
+	if (!IS_ERR_OR_NULL(ts->gpio_enable)) {
+		gpiod_set_value_cansleep(ts->gpio_enable, 1);
+		msleep(100);
+	}
+
 	/* LEVEL_TOUCH interrupt with active low polarity */
 	error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
 	if (error) {
@@ -343,6 +360,9 @@ static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
 	/* Wait till running ISR is complete */
 	synchronize_irq(ts->client->irq);
 
+	if (!IS_ERR_OR_NULL(ts->gpio_enable))
+		gpiod_set_value_cansleep(ts->gpio_enable, 0);
+
 	return 0;
 }
 
@@ -534,6 +554,24 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(tsdata->gpio_wake)) {
+		error = PTR_ERR(tsdata->gpio_wake);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get wake gpio: %d\n", error);
+		return error;
+	}
+
+	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
+						      GPIOD_OUT_HIGH);
+	if (IS_ERR(tsdata->gpio_enable)) {
+		error = PTR_ERR(tsdata->gpio_enable);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get enable gpio: %d\n", error);
+		return error;
+	}
+
 	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					  client->name, tsdata);
@@ -542,6 +580,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
Quoted 10 lines

drivers/input/touchscreen/pixcir_i2c_ts.c static int pixcir_i2c_ts_probe(struct i2c_client *client, · line 589

Quoted 7 lines
drivers/input/touchscreen/pixcir_i2c_ts.c +7 -0
+	if (!IS_ERR_OR_NULL(tsdata->gpio_wake))
+		gpiod_set_value_cansleep(tsdata->gpio_wake, 1);
+
+	if (!IS_ERR_OR_NULL(tsdata->gpio_enable)) {
+		gpiod_set_value_cansleep(tsdata->gpio_enable, 1);
+		msleep(100);
+	}

Actually, another question: why do we need this calls to activate wake and enable gpios here if we request them as active?

Quoted 3 lines

Hmm, interesting point. I will re-test with just the msleep there. For v2 what do you want to do with the if tests, keep as "if (!IS_ERR_OR_NULL(...))" or change them to just "if (...)" ?

Would prefer plain "if (gpio)" where makes sense.

Thanks!

Signature · 1 line
Dmitry
#8 lore raw

PATCH v2 5/7 touchscreen: pixcir_ts: Add support for axis inversion / swapping

In reply to Hans de Goede

Add support for axis inversion / swapping using the new touchscreen_parse_properties and touchscreen_apply_prop_to_x_y functionality.

---
Changes in v2:
-Add a fix which actually makes this patch compile, which accidentally ended
up in a later commit in my tree

---
 drivers/input/touchscreen/pixcir_i2c_ts.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/input/touchscreen/pixcir_i2c_ts.c +7 -3
index b75ef65..c553c68 100644
@@ -41,13 +41,14 @@ struct pixcir_i2c_ts_data {
 	struct gpio_desc *gpio_enable;
 	struct gpio_desc *gpio_wake;
 	const struct pixcir_i2c_chip_data *chip;
+	struct touchscreen_properties prop;
 	int max_fingers;	/* Max fingers supported in this instance */
 	bool running;
 };
 
 struct pixcir_touch {
-	int x;
-	int y;
+	s16 x;
+	s16 y;
 	int id;
 };
 
@@ -100,6 +101,9 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
 	for (i = 0; i < touch; i++) {
 		report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
 		report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
+		touchscreen_apply_prop_to_x_y(&tsdata->prop,
+					      &report->touches[i].x,
+					      &report->touches[i].y);
 
 		if (chip->has_hw_ids) {
 			report->touches[i].id = bufptr[4];
@@ -515,7 +519,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
 	} else {
 		input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
 		input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
-		touchscreen_parse_properties(input, true, NULL);
+		touchscreen_parse_properties(input, true, &tsdata->prop);
 		if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
 		    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
 			dev_err(dev, "Touchscreen size is not specified\n");
Signature · 1 line
2.5.0
#9 lore raw

PATCH v2 6/7 ARM: dts: sun4i: Add touchscreen node to iNet1 tablet

In reply to Hans de Goede

Add a node describing the touchscreen controller used on the iNet1 tablet.

---
 arch/arm/boot/dts/sun4i-a10-inet1.dts | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
arch/arm/boot/dts/sun4i-a10-inet1.dts +20 -0
index 487ce63..703d756 100644
@@ -104,6 +104,19 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c2_pins_a>;
 	status = "okay";
+
+	ft5x: touchscreen at 38 {
+		compatible = "edt,edt-ft5406";
+		reg = <0x38>;
+		interrupt-parent = <&pio>;
+		interrupts = <7 21 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&touchscreen_wake_pin>;
+		wake-gpios = <&pio 1 13 GPIO_ACTIVE_HIGH>; /* PB13 */
+		touchscreen-size-x = <600>;
+		touchscreen-size-y = <1024>;
+		touchscreen-swapped-x-y;
+	};
 };
 
 &lradc {
@@ -151,6 +164,13 @@
 };
 
 &pio {
+	touchscreen_wake_pin: touchscreen_wake_pin at 0 {
+		allwinner,pins = "PB13";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	usb0_id_detect_pin: usb0_id_detect_pin at 0 {
 		allwinner,pins = "PH4";
 		allwinner,function = "gpio_in";
Signature · 1 line
2.5.0
#10 lore raw

PATCH v2 7/7 ARM: dts: sun4i: Add touchscreen node to pov protab2-ips9 tablet

In reply to Hans de Goede

Add a node describing the touchscreen found on the pov protab2-ips9 tablet.

---
 arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts +23 -0
index 82e69c3..0e5124f 100644
@@ -93,6 +93,22 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c2_pins_a>;
 	status = "okay";
+
+	pixcir_ts at 5c {
+		pinctrl-names = "default";
+		pinctrl-0 = <&touchscreen_pins>;
+		compatible = "pixcir,pixcir_tangoc";
+		reg = <0x5c>;
+		interrupt-parent = <&pio>;
+		interrupts = <7 21 IRQ_TYPE_EDGE_FALLING>; /* EINT21 (PH21) */
+		attb-gpio = <&pio 7 21 GPIO_ACTIVE_HIGH>; /* PH21 */
+		enable-gpios = <&pio 0 5 GPIO_ACTIVE_LOW>;
+		wake-gpios = <&pio 1 13 GPIO_ACTIVE_LOW>;
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <768>;
+		touchscreen-inverted-x;
+		touchscreen-inverted-y;
+	};
 };
 
 &lradc {
@@ -129,6 +145,13 @@
 };
 
 &pio {
+	touchscreen_pins: touchscreen_pins at 0 {
+		allwinner,pins = "PA5", "PB13";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	usb0_id_detect_pin: usb0_id_detect_pin at 0 {
 		allwinner,pins = "PH4";
 		allwinner,function = "gpio_in";
Signature · 1 line
2.5.0
#11 lore raw

PATCH v2 7/7 ARM: dts: sun4i: Add touchscreen node to pov protab2-ips9 tablet

Quoted 4 lines · Hans de Goede

Add a node describing the touchscreen found on the pov protab2-ips9 tablet.

Applied 6 and 7, thanks!
Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151124/6f2dac37/attachment-0001.sig>