linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc.
@ 2018-10-16  9:16 Richard Leitner
  2018-10-16  9:16 ` [PATCH 1/7] dt-bindings: input: touchscreen: sx8654: add reset-gpio property Richard Leitner
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:16 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

Add reset-gpio, sx8654[056] and common of_touchscreen functions support
for the sx8654 driver.

Richard Leitner (7):
  dt-bindings: input: touchscreen: sx8654: add reset-gpio property
  Input: sx8654 - add reset-gpio support
  dt-bindings: input: touchscreen: sx8654: add compatible models
  Input: sx8654 - add sx8655 and sx8656 to compatibles
  dt-bindings: input: touchscreen: sx8654: add sx8650 to comatibles
  Input: sx8654 - add sx8650 support
  Input: sx8654 - use common of_touchscreen functions

 .../bindings/input/touchscreen/sx8654.txt          |  10 +-
 drivers/input/touchscreen/sx8654.c                 | 267 ++++++++++++++++++---
 2 files changed, 245 insertions(+), 32 deletions(-)

-- 
2.11.0


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

* [PATCH 1/7] dt-bindings: input: touchscreen: sx8654: add reset-gpio property
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
@ 2018-10-16  9:16 ` Richard Leitner
  2018-10-16  9:16 ` [PATCH 2/7] Input: sx8654 - add reset-gpio support Richard Leitner
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:16 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

Document the reset-gpio property for the sx8654 touchscreen controller
driver.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 Documentation/devicetree/bindings/input/touchscreen/sx8654.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
index 4886c4aa2906..ca521d8f7d65 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
@@ -5,6 +5,9 @@ Required properties:
 - reg: i2c slave address
 - interrupts: touch controller interrupt
 
+Optional properties:
+ - reset-gpios: GPIO specification for the NRST input
+
 Example:
 
 	sx8654@48 {
@@ -12,4 +15,5 @@ Example:
 		reg = <0x48>;
 		interrupt-parent = <&gpio6>;
 		interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+		reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
 	};
-- 
2.11.0


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

* [PATCH 2/7] Input: sx8654 - add reset-gpio support
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
  2018-10-16  9:16 ` [PATCH 1/7] dt-bindings: input: touchscreen: sx8654: add reset-gpio property Richard Leitner
@ 2018-10-16  9:16 ` Richard Leitner
  2018-10-16 17:39   ` Dmitry Torokhov
  2018-10-16  9:16 ` [PATCH 3/7] dt-bindings: input: touchscreen: sx8654: add compatible models Richard Leitner
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:16 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

The sx8654 features a NRST input which may be connected to a GPIO.
Therefore add support for hard-resetting the sx8654 via this NRST.

If the reset-gpio property is provided the sx8654 is resetted via NRST
instead of the soft-reset via I2C.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/input/touchscreen/sx8654.c | 88 ++++++++++++++++++++++++++++++++------
 1 file changed, 74 insertions(+), 14 deletions(-)

diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
index ed29db3ec731..059127490c8d 100644
--- a/drivers/input/touchscreen/sx8654.c
+++ b/drivers/input/touchscreen/sx8654.c
@@ -33,6 +33,8 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
 
 /* register addresses */
 #define I2C_REG_TOUCH0			0x00
@@ -74,6 +76,7 @@
 struct sx8654 {
 	struct input_dev *input;
 	struct i2c_client *client;
+	struct gpio_desc *gpio_reset;
 };
 
 static irqreturn_t sx8654_irq(int irq, void *handle)
@@ -124,6 +127,27 @@ static irqreturn_t sx8654_irq(int irq, void *handle)
 	return IRQ_HANDLED;
 }
 
+static int sx8654_reset(struct sx8654 *ts)
+{
+	int err;
+
+	if (ts->gpio_reset) {
+		gpiod_set_value_cansleep(ts->gpio_reset, 1);
+		udelay(2); /* Tpulse > 1µs */
+		gpiod_set_value_cansleep(ts->gpio_reset, 0);
+
+		return 0;
+	}
+
+	dev_dbg(&ts->client->dev, "NRST unavailable, try softreset\n");
+	err = i2c_smbus_write_byte_data(ts->client, I2C_REG_SOFTRESET,
+					SOFTRESET_VALUE);
+	if (err)
+		return err;
+
+	return 0;
+}
+
 static int sx8654_open(struct input_dev *dev)
 {
 	struct sx8654 *sx8654 = input_get_drvdata(dev);
@@ -171,6 +195,44 @@ static void sx8654_close(struct input_dev *dev)
 	}
 }
 
+#ifdef CONFIG_OF
+static int sx8654_get_ofdata(struct sx8654 *ts)
+{
+	struct device *dev = &ts->client->dev;
+	struct device_node *node = dev->of_node;
+	int err;
+
+	if (!node) {
+		ts->gpio_reset = NULL;
+		return 0;
+	}
+
+	ts->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (PTR_ERR(ts->gpio_reset) == -EPROBE_DEFER) {
+		return -EPROBE_DEFER;
+	} else if (IS_ERR(ts->gpio_reset)) {
+		err = PTR_ERR(ts->gpio_reset);
+		dev_err(dev, "unable to request GPIO reset pin (%d)\n", err);
+		return err;
+	}
+	dev_dbg(dev, "got GPIO reset pin\n");
+
+	return 0;
+}
+
+static const struct of_device_id sx8654_of_match[] = {
+	{ .compatible = "semtech,sx8654", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sx8654_of_match);
+#else /* CONFIG_OF */
+static int sx8654_get_ofdata(struct sx8654 *ts)
+{
+	ts->gpio_reset = NULL;
+	return 0;
+}
+#endif /* CONFIG_OF */
+
 static int sx8654_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -186,10 +248,20 @@ static int sx8654_probe(struct i2c_client *client,
 	if (!sx8654)
 		return -ENOMEM;
 
+	sx8654->client = client;
+
+	error = sx8654_get_ofdata(sx8654);
+	if (error) {
+		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
+		return error;
+	}
+
 	input = devm_input_allocate_device(&client->dev);
 	if (!input)
 		return -ENOMEM;
 
+	sx8654->input = input;
+
 	input->name = "SX8654 I2C Touchscreen";
 	input->id.bustype = BUS_I2C;
 	input->dev.parent = &client->dev;
@@ -201,15 +273,11 @@ static int sx8654_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0);
 	input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0);
 
-	sx8654->client = client;
-	sx8654->input = input;
-
 	input_set_drvdata(sx8654->input, sx8654);
 
-	error = i2c_smbus_write_byte_data(client, I2C_REG_SOFTRESET,
-					  SOFTRESET_VALUE);
+	error = sx8654_reset(sx8654);
 	if (error) {
-		dev_err(&client->dev, "writing softreset value failed");
+		dev_err(&client->dev, "reset failed");
 		return error;
 	}
 
@@ -256,14 +324,6 @@ static int sx8654_probe(struct i2c_client *client,
 	return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id sx8654_of_match[] = {
-	{ .compatible = "semtech,sx8654", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, sx8654_of_match);
-#endif
-
 static const struct i2c_device_id sx8654_id_table[] = {
 	{ "semtech_sx8654", 0 },
 	{ },
-- 
2.11.0


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

* [PATCH 3/7] dt-bindings: input: touchscreen: sx8654: add compatible models
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
  2018-10-16  9:16 ` [PATCH 1/7] dt-bindings: input: touchscreen: sx8654: add reset-gpio property Richard Leitner
  2018-10-16  9:16 ` [PATCH 2/7] Input: sx8654 - add reset-gpio support Richard Leitner
@ 2018-10-16  9:16 ` Richard Leitner
  2018-10-16  9:16 ` [PATCH 4/7] Input: sx8654 - add sx8655 and sx8656 to compatibles Richard Leitner
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:16 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

As the sx865[456] share the same datasheet and differ only in the
presence of a "capacitive proximity detection circuit" and a "haptics
motor driver for LRA/ERM" add them to the compatbiles. As the driver
doesn't implement these features it should be no problem.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 Documentation/devicetree/bindings/input/touchscreen/sx8654.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
index ca521d8f7d65..a538678424dd 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
@@ -1,7 +1,10 @@
 * Semtech SX8654 I2C Touchscreen Controller
 
 Required properties:
-- compatible: must be "semtech,sx8654"
+- compatible: must be one of the following, depending on the model:
+	"semtech,sx8654"
+	"semtech,sx8655"
+	"semtech,sx8656"
 - reg: i2c slave address
 - interrupts: touch controller interrupt
 
-- 
2.11.0


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

* [PATCH 4/7] Input: sx8654 - add sx8655 and sx8656 to compatibles
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
                   ` (2 preceding siblings ...)
  2018-10-16  9:16 ` [PATCH 3/7] dt-bindings: input: touchscreen: sx8654: add compatible models Richard Leitner
@ 2018-10-16  9:16 ` Richard Leitner
  2018-10-16  9:22 ` [PATCH 5/7] dt-bindings: input: touchscreen: sx8654: add sx8650 to comatibles Richard Leitner
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:16 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

As the sx865[456] share the same datasheet and differ only in the
presence of a "capacitive proximity detection circuit" and a "haptics
motor driver for LRA/ERM" add them to the compatbiles. As the driver
doesn't implement these features it should be no problem.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/input/touchscreen/sx8654.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
index 059127490c8d..622283b49d7c 100644
--- a/drivers/input/touchscreen/sx8654.c
+++ b/drivers/input/touchscreen/sx8654.c
@@ -222,6 +222,8 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
 
 static const struct of_device_id sx8654_of_match[] = {
 	{ .compatible = "semtech,sx8654", },
+	{ .compatible = "semtech,sx8655", },
+	{ .compatible = "semtech,sx8656", },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, sx8654_of_match);
@@ -326,6 +328,8 @@ static int sx8654_probe(struct i2c_client *client,
 
 static const struct i2c_device_id sx8654_id_table[] = {
 	{ "semtech_sx8654", 0 },
+	{ "semtech_sx8655", 0 },
+	{ "semtech_sx8656", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, sx8654_id_table);
-- 
2.11.0


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

* [PATCH 5/7] dt-bindings: input: touchscreen: sx8654: add sx8650 to comatibles
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
                   ` (3 preceding siblings ...)
  2018-10-16  9:16 ` [PATCH 4/7] Input: sx8654 - add sx8655 and sx8656 to compatibles Richard Leitner
@ 2018-10-16  9:22 ` Richard Leitner
  2018-10-16  9:22 ` [PATCH 6/7] Input: sx8654 - add sx8650 support Richard Leitner
  2018-10-16  9:23 ` [PATCH 7/7] Input: sx8654 - use common of_touchscreen functions Richard Leitner
  6 siblings, 0 replies; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:22 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

As the sx8650 is quite similar to the sx8654 support for it will be
added in the driver. Therefore add it to the compatibles.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 Documentation/devicetree/bindings/input/touchscreen/sx8654.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
index a538678424dd..0ebe6dd043c7 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
@@ -2,6 +2,7 @@
 
 Required properties:
 - compatible: must be one of the following, depending on the model:
+	"semtech,sx8650"
 	"semtech,sx8654"
 	"semtech,sx8655"
 	"semtech,sx8656"
-- 
2.11.0


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

* [PATCH 6/7] Input: sx8654 - add sx8650 support
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
                   ` (4 preceding siblings ...)
  2018-10-16  9:22 ` [PATCH 5/7] dt-bindings: input: touchscreen: sx8654: add sx8650 to comatibles Richard Leitner
@ 2018-10-16  9:22 ` Richard Leitner
  2018-10-16 17:48   ` Dmitry Torokhov
  2018-10-16  9:23 ` [PATCH 7/7] Input: sx8654 - use common of_touchscreen functions Richard Leitner
  6 siblings, 1 reply; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:22 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

The sx8654 and sx8650 are quite similar, therefore add support for the
sx8650 within the sx8654 driver.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/input/touchscreen/sx8654.c | 186 ++++++++++++++++++++++++++++++++-----
 1 file changed, 163 insertions(+), 23 deletions(-)

diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
index 622283b49d7c..33f7a0be4ef8 100644
--- a/drivers/input/touchscreen/sx8654.c
+++ b/drivers/input/touchscreen/sx8654.c
@@ -29,12 +29,13 @@
 
 #include <linux/input.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 #include <linux/delay.h>
+#include <linux/hrtimer.h>
 
 /* register addresses */
 #define I2C_REG_TOUCH0			0x00
@@ -44,9 +45,11 @@
 #define I2C_REG_IRQSRC			0x23
 #define I2C_REG_SOFTRESET		0x3f
 
+#define I2C_REG_SX8650_STAT		0x05
+#define SX8650_STAT_CONVIRQ		BIT(7)
+
 /* commands */
 #define CMD_READ_REGISTER		0x40
-#define CMD_MANUAL			0xc0
 #define CMD_PENTRG			0xe0
 
 /* value for I2C_REG_SOFTRESET */
@@ -58,11 +61,12 @@
 
 /* bits for RegTouch1 */
 #define CONDIRQ				0x20
+#define RPDNT_100K			0x00
 #define FILT_7SA			0x03
 
 /* bits for I2C_REG_CHANMASK */
-#define CONV_X				0x80
-#define CONV_Y				0x40
+#define CONV_X				BIT(7)
+#define CONV_Y				BIT(6)
 
 /* coordinates rate: higher nibble of CTRL0 register */
 #define RATE_MANUAL			0x00
@@ -71,14 +75,110 @@
 /* power delay: lower nibble of CTRL0 register */
 #define POWDLY_1_1MS			0x0b
 
+/* for sx8650, as we have no pen release IRQ there: timeout in ns following the
+ * last PENIRQ after which we assume the pen is lifted.
+ */
+#define SX8650_PENIRQ_TIMEOUT		(80 * 1100 * 1000)
+
 #define MAX_12BIT			((1 << 12) - 1)
+#define MAX_I2C_READ_LEN		10 /* see datasheet section 5.1.5 */
+
+/* channel definition */
+#define CH_X				0x00
+#define CH_Y				0x01
+
+struct sx865x_data {
+	u8 cmd_manual;
+	u8 chan_mask;
+	u8 has_irq_penrelease;
+	u8 has_reg_irqmask;
+	irq_handler_t irqh;
+};
 
 struct sx8654 {
 	struct input_dev *input;
 	struct i2c_client *client;
 	struct gpio_desc *gpio_reset;
+	struct hrtimer timer;
+
+	const struct sx865x_data *data;
 };
 
+static enum hrtimer_restart sx865x_penrelease_timer_handler(struct hrtimer *h)
+{
+	struct sx8654 *ts = container_of(h, struct sx8654, timer);
+
+	input_report_key(ts->input, BTN_TOUCH, 0);
+	input_sync(ts->input);
+	dev_dbg(&ts->client->dev, "penrelease by timer\n");
+
+	return HRTIMER_NORESTART;
+}
+
+static irqreturn_t sx8650_irq(int irq, void *handle)
+{
+	struct sx8654 *ts = handle;
+	struct device *dev = &ts->client->dev;
+	int len, i, ret;
+	u8 stat;
+	u16 x, y;
+	u8 data[MAX_I2C_READ_LEN];
+	u16 ch;
+	u16 chdata;
+	u8 readlen = hweight32(ts->data->chan_mask) * 2;
+
+	stat = i2c_smbus_read_byte_data(ts->client, CMD_READ_REGISTER
+						    | I2C_REG_SX8650_STAT);
+
+	if (!(stat & SX8650_STAT_CONVIRQ)) {
+		dev_dbg(dev, "%s ignore stat [0x%02x]", __func__, stat);
+		return IRQ_HANDLED;
+	}
+
+	len = i2c_master_recv(ts->client, data, readlen);
+	if (len != readlen) {
+		dev_dbg(dev, "ignore short recv (%d)\n", len);
+		return IRQ_HANDLED;
+	}
+
+	ret = hrtimer_try_to_cancel(&ts->timer);
+
+	x = 0;
+	y = 0;
+	for (i = 0; (i + 1) < len; i++) {
+		chdata = data[i] << 8;
+		i++;
+		chdata += data[i];
+
+		if (unlikely(chdata == 0xFFFF)) {
+			dev_dbg(dev, "invalid qualified data @ %d\n", i);
+			continue;
+		} else if (unlikely(chdata & 0x8000)) {
+			dev_warn(dev, "hibit @ %d [0x%04x]\n", i, chdata);
+			continue;
+		}
+
+		ch = chdata >> 12;
+		if      (ch == CH_X)
+			x = chdata & MAX_12BIT;
+		else if (ch == CH_Y)
+			y = chdata & MAX_12BIT;
+		else
+			dev_warn(dev, "unknown channel %d [0x%04x]\n", ch,
+				 chdata);
+	}
+
+	input_report_abs(ts->input, ABS_X, x);
+	input_report_abs(ts->input, ABS_Y, y);
+	input_report_key(ts->input, BTN_TOUCH, 1);
+	input_sync(ts->input);
+	dev_dbg(dev, "point(%4d,%4d)\n", x, y);
+
+	hrtimer_start(&ts->timer, ktime_set(0, SX8650_PENIRQ_TIMEOUT),
+		      HRTIMER_MODE_REL);
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t sx8654_irq(int irq, void *handle)
 {
 	struct sx8654 *sx8654 = handle;
@@ -127,6 +227,22 @@ static irqreturn_t sx8654_irq(int irq, void *handle)
 	return IRQ_HANDLED;
 }
 
+static const struct sx865x_data sx8650_data = {
+	.cmd_manual = 0xb0,
+	.has_irq_penrelease = 0,
+	.has_reg_irqmask = 0,
+	.chan_mask = (CONV_X | CONV_Y),
+	.irqh = sx8650_irq,
+};
+
+static const struct sx865x_data sx8654_data = {
+	.cmd_manual = 0xc0,
+	.has_irq_penrelease = 1,
+	.has_reg_irqmask = 1,
+	.chan_mask = (CONV_X | CONV_Y),
+	.irqh = sx8654_irq,
+};
+
 static int sx8654_reset(struct sx8654 *ts)
 {
 	int err;
@@ -182,13 +298,13 @@ static void sx8654_close(struct input_dev *dev)
 	disable_irq(client->irq);
 
 	/* enable manual mode mode */
-	error = i2c_smbus_write_byte(client, CMD_MANUAL);
+	error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual);
 	if (error) {
 		dev_err(&client->dev, "writing command CMD_MANUAL failed");
 		return;
 	}
 
-	error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 0);
+	error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, RATE_MANUAL);
 	if (error) {
 		dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed");
 		return;
@@ -196,10 +312,30 @@ static void sx8654_close(struct input_dev *dev)
 }
 
 #ifdef CONFIG_OF
+static const struct of_device_id sx8654_of_match[] = {
+	{
+		.compatible = "semtech,sx8650",
+		.data = &sx8650_data,
+	}, {
+		.compatible = "semtech,sx8654",
+		.data = &sx8654_data,
+	}, {
+		.compatible = "semtech,sx8655",
+		.data = &sx8654_data,
+	}, {
+		.compatible = "semtech,sx8656",
+		.data = &sx8654_data,
+	}, {},
+};
+MODULE_DEVICE_TABLE(of, sx8654_of_match);
+
 static int sx8654_get_ofdata(struct sx8654 *ts)
 {
 	struct device *dev = &ts->client->dev;
 	struct device_node *node = dev->of_node;
+	const struct of_device_id *of_id = of_match_device(sx8654_of_match,
+							   dev);
+	const struct sx865x_data *data = (struct sx865x_data *)of_id->data;
 	int err;
 
 	if (!node) {
@@ -207,6 +343,8 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
 		return 0;
 	}
 
+	ts->data = data;
+
 	ts->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 	if (PTR_ERR(ts->gpio_reset) == -EPROBE_DEFER) {
 		return -EPROBE_DEFER;
@@ -219,18 +357,11 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
 
 	return 0;
 }
-
-static const struct of_device_id sx8654_of_match[] = {
-	{ .compatible = "semtech,sx8654", },
-	{ .compatible = "semtech,sx8655", },
-	{ .compatible = "semtech,sx8656", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, sx8654_of_match);
 #else /* CONFIG_OF */
 static int sx8654_get_ofdata(struct sx8654 *ts)
 {
 	ts->gpio_reset = NULL;
+	ts->data = &sx8654_data;
 	return 0;
 }
 #endif /* CONFIG_OF */
@@ -258,6 +389,12 @@ static int sx8654_probe(struct i2c_client *client,
 		return error;
 	}
 
+	if (!sx8654->data->has_irq_penrelease) {
+		dev_dbg(&client->dev, "use timer for penrelease\n");
+		hrtimer_init(&sx8654->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		sx8654->timer.function = sx865x_penrelease_timer_handler;
+	}
+
 	input = devm_input_allocate_device(&client->dev);
 	if (!input)
 		return -ENOMEM;
@@ -284,29 +421,31 @@ static int sx8654_probe(struct i2c_client *client,
 	}
 
 	error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK,
-					  CONV_X | CONV_Y);
+					  sx8654->data->chan_mask);
 	if (error) {
 		dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed");
 		return error;
 	}
 
-	error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK,
-					  IRQ_PENTOUCH_TOUCHCONVDONE |
-						IRQ_PENRELEASE);
-	if (error) {
-		dev_err(&client->dev, "writing to I2C_REG_IRQMASK failed");
-		return error;
+	if (sx8654->data->has_reg_irqmask) {
+		error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK,
+						  IRQ_PENTOUCH_TOUCHCONVDONE |
+							IRQ_PENRELEASE);
+		if (error) {
+			dev_err(&client->dev, "writing I2C_REG_IRQMASK failed");
+			return error;
+		}
 	}
 
 	error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1,
-					  CONDIRQ | FILT_7SA);
+					  CONDIRQ | RPDNT_100K | FILT_7SA);
 	if (error) {
 		dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed");
 		return error;
 	}
 
 	error = devm_request_threaded_irq(&client->dev, client->irq,
-					  NULL, sx8654_irq,
+					  NULL, sx8654->data->irqh,
 					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					  client->name, sx8654);
 	if (error) {
@@ -327,6 +466,7 @@ static int sx8654_probe(struct i2c_client *client,
 }
 
 static const struct i2c_device_id sx8654_id_table[] = {
+	{ "semtech_sx8650", 0 },
 	{ "semtech_sx8654", 0 },
 	{ "semtech_sx8655", 0 },
 	{ "semtech_sx8656", 0 },
-- 
2.11.0


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

* [PATCH 7/7] Input: sx8654 - use common of_touchscreen functions
  2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
                   ` (5 preceding siblings ...)
  2018-10-16  9:22 ` [PATCH 6/7] Input: sx8654 - add sx8650 support Richard Leitner
@ 2018-10-16  9:23 ` Richard Leitner
  2018-10-16 17:52   ` Dmitry Torokhov
  6 siblings, 1 reply; 14+ messages in thread
From: Richard Leitner @ 2018-10-16  9:23 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, mark.rutland
  Cc: linux-input, devicetree, linux-kernel, Richard Leitner

of_touchscreen.c provides a common interface for a axis invertion and
swapping of touchscreens. Therefore use it in the sx8654 driver.

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/input/touchscreen/sx8654.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
index 33f7a0be4ef8..08b064f96b4e 100644
--- a/drivers/input/touchscreen/sx8654.c
+++ b/drivers/input/touchscreen/sx8654.c
@@ -36,6 +36,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/hrtimer.h>
+#include <linux/input/touchscreen.h>
 
 /* register addresses */
 #define I2C_REG_TOUCH0			0x00
@@ -100,6 +101,7 @@ struct sx8654 {
 	struct i2c_client *client;
 	struct gpio_desc *gpio_reset;
 	struct hrtimer timer;
+	struct touchscreen_properties props;
 
 	const struct sx865x_data *data;
 };
@@ -168,8 +170,7 @@ static irqreturn_t sx8650_irq(int irq, void *handle)
 				 chdata);
 	}
 
-	input_report_abs(ts->input, ABS_X, x);
-	input_report_abs(ts->input, ABS_Y, y);
+	touchscreen_report_pos(ts->input, &ts->props, x, y, false);
 	input_report_key(ts->input, BTN_TOUCH, 1);
 	input_sync(ts->input);
 	dev_dbg(dev, "point(%4d,%4d)\n", x, y);
@@ -215,8 +216,8 @@ static irqreturn_t sx8654_irq(int irq, void *handle)
 		x = ((data[0] & 0xf) << 8) | (data[1]);
 		y = ((data[2] & 0xf) << 8) | (data[3]);
 
-		input_report_abs(sx8654->input, ABS_X, x);
-		input_report_abs(sx8654->input, ABS_Y, y);
+		touchscreen_report_pos(sx8654->input, &sx8654->props, x, y,
+				       false);
 		input_report_key(sx8654->input, BTN_TOUCH, 1);
 		input_sync(sx8654->input);
 
@@ -355,6 +356,8 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
 	}
 	dev_dbg(dev, "got GPIO reset pin\n");
 
+	touchscreen_parse_properties(ts->input, false, &ts->props);
+
 	return 0;
 }
 #else /* CONFIG_OF */
@@ -380,25 +383,11 @@ static int sx8654_probe(struct i2c_client *client,
 	sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL);
 	if (!sx8654)
 		return -ENOMEM;
-
 	sx8654->client = client;
 
-	error = sx8654_get_ofdata(sx8654);
-	if (error) {
-		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
-		return error;
-	}
-
-	if (!sx8654->data->has_irq_penrelease) {
-		dev_dbg(&client->dev, "use timer for penrelease\n");
-		hrtimer_init(&sx8654->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-		sx8654->timer.function = sx865x_penrelease_timer_handler;
-	}
-
 	input = devm_input_allocate_device(&client->dev);
 	if (!input)
 		return -ENOMEM;
-
 	sx8654->input = input;
 
 	input->name = "SX8654 I2C Touchscreen";
@@ -414,6 +403,18 @@ static int sx8654_probe(struct i2c_client *client,
 
 	input_set_drvdata(sx8654->input, sx8654);
 
+	error = sx8654_get_ofdata(sx8654);
+	if (error) {
+		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
+		return error;
+	}
+
+	if (!sx8654->data->has_irq_penrelease) {
+		dev_dbg(&client->dev, "use timer for penrelease\n");
+		hrtimer_init(&sx8654->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		sx8654->timer.function = sx865x_penrelease_timer_handler;
+	}
+
 	error = sx8654_reset(sx8654);
 	if (error) {
 		dev_err(&client->dev, "reset failed");
-- 
2.11.0


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

* Re: [PATCH 2/7] Input: sx8654 - add reset-gpio support
  2018-10-16  9:16 ` [PATCH 2/7] Input: sx8654 - add reset-gpio support Richard Leitner
@ 2018-10-16 17:39   ` Dmitry Torokhov
  2018-10-16 19:32     ` Richard Leitner
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2018-10-16 17:39 UTC (permalink / raw)
  To: Richard Leitner
  Cc: robh+dt, mark.rutland, linux-input, devicetree, linux-kernel

Hi Richard,

On Tue, Oct 16, 2018 at 11:16:48AM +0200, Richard Leitner wrote:
> The sx8654 features a NRST input which may be connected to a GPIO.
> Therefore add support for hard-resetting the sx8654 via this NRST.
> 
> If the reset-gpio property is provided the sx8654 is resetted via NRST
> instead of the soft-reset via I2C.
> 
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
>  drivers/input/touchscreen/sx8654.c | 88 ++++++++++++++++++++++++++++++++------
>  1 file changed, 74 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
> index ed29db3ec731..059127490c8d 100644
> --- a/drivers/input/touchscreen/sx8654.c
> +++ b/drivers/input/touchscreen/sx8654.c
> @@ -33,6 +33,8 @@
>  #include <linux/i2c.h>
>  #include <linux/interrupt.h>
>  #include <linux/irq.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/delay.h>
>  
>  /* register addresses */
>  #define I2C_REG_TOUCH0			0x00
> @@ -74,6 +76,7 @@
>  struct sx8654 {
>  	struct input_dev *input;
>  	struct i2c_client *client;
> +	struct gpio_desc *gpio_reset;
>  };
>  
>  static irqreturn_t sx8654_irq(int irq, void *handle)
> @@ -124,6 +127,27 @@ static irqreturn_t sx8654_irq(int irq, void *handle)
>  	return IRQ_HANDLED;
>  }
>  
> +static int sx8654_reset(struct sx8654 *ts)
> +{
> +	int err;
> +
> +	if (ts->gpio_reset) {
> +		gpiod_set_value_cansleep(ts->gpio_reset, 1);
> +		udelay(2); /* Tpulse > 1µs */
> +		gpiod_set_value_cansleep(ts->gpio_reset, 0);
> +
> +		return 0;
> +	}
> +
> +	dev_dbg(&ts->client->dev, "NRST unavailable, try softreset\n");
> +	err = i2c_smbus_write_byte_data(ts->client, I2C_REG_SOFTRESET,
> +					SOFTRESET_VALUE);
> +	if (err)
> +		return err;

Have this in an "else" branch?

> +
> +	return 0;
> +}
> +
>  static int sx8654_open(struct input_dev *dev)
>  {
>  	struct sx8654 *sx8654 = input_get_drvdata(dev);
> @@ -171,6 +195,44 @@ static void sx8654_close(struct input_dev *dev)
>  	}
>  }
>  
> +#ifdef CONFIG_OF
> +static int sx8654_get_ofdata(struct sx8654 *ts)
> +{
> +	struct device *dev = &ts->client->dev;
> +	struct device_node *node = dev->of_node;
> +	int err;
> +
> +	if (!node) {
> +		ts->gpio_reset = NULL;
> +		return 0;
> +	}

There is no need to wrap this into CONFIG_OF or test "node". Just use
devm_gpiod_get_optional() and it will work equally well on DT, ACPI, and
static board systems.

> +
> +	ts->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> +	if (PTR_ERR(ts->gpio_reset) == -EPROBE_DEFER) {
> +		return -EPROBE_DEFER;
> +	} else if (IS_ERR(ts->gpio_reset)) {
> +		err = PTR_ERR(ts->gpio_reset);

I'd do:

		if (err != -EPROBE_DEFER)
			dev_err(...)

here instead of separate branch.

> +		dev_err(dev, "unable to request GPIO reset pin (%d)\n", err);
> +		return err;
> +	}
> +	dev_dbg(dev, "got GPIO reset pin\n");

Also, I'd move all this code directly into probe() since all this
#ifdefery is not needed.

> +
> +	return 0;
> +}
> +
> +static const struct of_device_id sx8654_of_match[] = {
> +	{ .compatible = "semtech,sx8654", },
> +	{ },
> +};

Please keep the device table wehere it was.

> +MODULE_DEVICE_TABLE(of, sx8654_of_match);
> +#else /* CONFIG_OF */
> +static int sx8654_get_ofdata(struct sx8654 *ts)
> +{
> +	ts->gpio_reset = NULL;
> +	return 0;
> +}
> +#endif /* CONFIG_OF */
> +
>  static int sx8654_probe(struct i2c_client *client,
>  			const struct i2c_device_id *id)
>  {
> @@ -186,10 +248,20 @@ static int sx8654_probe(struct i2c_client *client,
>  	if (!sx8654)
>  		return -ENOMEM;
>  
> +	sx8654->client = client;
> +
> +	error = sx8654_get_ofdata(sx8654);
> +	if (error) {
> +		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
> +		return error;
> +	}
> +
>  	input = devm_input_allocate_device(&client->dev);
>  	if (!input)
>  		return -ENOMEM;
>  
> +	sx8654->input = input;
> +
>  	input->name = "SX8654 I2C Touchscreen";
>  	input->id.bustype = BUS_I2C;
>  	input->dev.parent = &client->dev;
> @@ -201,15 +273,11 @@ static int sx8654_probe(struct i2c_client *client,
>  	input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0);
>  	input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0);
>  
> -	sx8654->client = client;
> -	sx8654->input = input;
> -

Why do we need to move this?

>  	input_set_drvdata(sx8654->input, sx8654);
>  
> -	error = i2c_smbus_write_byte_data(client, I2C_REG_SOFTRESET,
> -					  SOFTRESET_VALUE);
> +	error = sx8654_reset(sx8654);
>  	if (error) {
> -		dev_err(&client->dev, "writing softreset value failed");
> +		dev_err(&client->dev, "reset failed");
>  		return error;
>  	}
>  
> @@ -256,14 +324,6 @@ static int sx8654_probe(struct i2c_client *client,
>  	return 0;
>  }
>  
> -#ifdef CONFIG_OF
> -static const struct of_device_id sx8654_of_match[] = {
> -	{ .compatible = "semtech,sx8654", },
> -	{ },
> -};
> -MODULE_DEVICE_TABLE(of, sx8654_of_match);
> -#endif
> -
>  static const struct i2c_device_id sx8654_id_table[] = {
>  	{ "semtech_sx8654", 0 },
>  	{ },
> -- 
> 2.11.0
> 

Thanks.

-- 
Dmitry

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

* Re: [PATCH 6/7] Input: sx8654 - add sx8650 support
  2018-10-16  9:22 ` [PATCH 6/7] Input: sx8654 - add sx8650 support Richard Leitner
@ 2018-10-16 17:48   ` Dmitry Torokhov
  2018-10-16 19:34     ` Richard Leitner
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2018-10-16 17:48 UTC (permalink / raw)
  To: Richard Leitner
  Cc: robh+dt, mark.rutland, linux-input, devicetree, linux-kernel

On Tue, Oct 16, 2018 at 11:22:48AM +0200, Richard Leitner wrote:
> The sx8654 and sx8650 are quite similar, therefore add support for the
> sx8650 within the sx8654 driver.
> 
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
>  drivers/input/touchscreen/sx8654.c | 186 ++++++++++++++++++++++++++++++++-----
>  1 file changed, 163 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
> index 622283b49d7c..33f7a0be4ef8 100644
> --- a/drivers/input/touchscreen/sx8654.c
> +++ b/drivers/input/touchscreen/sx8654.c
> @@ -29,12 +29,13 @@
>  
>  #include <linux/input.h>
>  #include <linux/module.h>
> -#include <linux/of.h>
> +#include <linux/of_device.h>
>  #include <linux/i2c.h>
>  #include <linux/interrupt.h>
>  #include <linux/irq.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/delay.h>
> +#include <linux/hrtimer.h>
>  
>  /* register addresses */
>  #define I2C_REG_TOUCH0			0x00
> @@ -44,9 +45,11 @@
>  #define I2C_REG_IRQSRC			0x23
>  #define I2C_REG_SOFTRESET		0x3f
>  
> +#define I2C_REG_SX8650_STAT		0x05
> +#define SX8650_STAT_CONVIRQ		BIT(7)
> +
>  /* commands */
>  #define CMD_READ_REGISTER		0x40
> -#define CMD_MANUAL			0xc0
>  #define CMD_PENTRG			0xe0
>  
>  /* value for I2C_REG_SOFTRESET */
> @@ -58,11 +61,12 @@
>  
>  /* bits for RegTouch1 */
>  #define CONDIRQ				0x20
> +#define RPDNT_100K			0x00
>  #define FILT_7SA			0x03
>  
>  /* bits for I2C_REG_CHANMASK */
> -#define CONV_X				0x80
> -#define CONV_Y				0x40
> +#define CONV_X				BIT(7)
> +#define CONV_Y				BIT(6)

If you are using BIT() you need to include include/linux/bitops.h

I also would prefer conversion to using BIT() as a separate patch.

>  
>  /* coordinates rate: higher nibble of CTRL0 register */
>  #define RATE_MANUAL			0x00
> @@ -71,14 +75,110 @@
>  /* power delay: lower nibble of CTRL0 register */
>  #define POWDLY_1_1MS			0x0b
>  
> +/* for sx8650, as we have no pen release IRQ there: timeout in ns following the
> + * last PENIRQ after which we assume the pen is lifted.
> + */
> +#define SX8650_PENIRQ_TIMEOUT		(80 * 1100 * 1000)
> +
>  #define MAX_12BIT			((1 << 12) - 1)
> +#define MAX_I2C_READ_LEN		10 /* see datasheet section 5.1.5 */
> +
> +/* channel definition */
> +#define CH_X				0x00
> +#define CH_Y				0x01
> +
> +struct sx865x_data {
> +	u8 cmd_manual;
> +	u8 chan_mask;
> +	u8 has_irq_penrelease;
> +	u8 has_reg_irqmask;
> +	irq_handler_t irqh;
> +};
>  
>  struct sx8654 {
>  	struct input_dev *input;
>  	struct i2c_client *client;
>  	struct gpio_desc *gpio_reset;
> +	struct hrtimer timer;

Does this have to be hrtimer? Can regular timer be used?

> +
> +	const struct sx865x_data *data;
>  };
>  
> +static enum hrtimer_restart sx865x_penrelease_timer_handler(struct hrtimer *h)
> +{
> +	struct sx8654 *ts = container_of(h, struct sx8654, timer);
> +
> +	input_report_key(ts->input, BTN_TOUCH, 0);
> +	input_sync(ts->input);
> +	dev_dbg(&ts->client->dev, "penrelease by timer\n");
> +
> +	return HRTIMER_NORESTART;
> +}
> +
> +static irqreturn_t sx8650_irq(int irq, void *handle)
> +{
> +	struct sx8654 *ts = handle;
> +	struct device *dev = &ts->client->dev;
> +	int len, i, ret;
> +	u8 stat;
> +	u16 x, y;
> +	u8 data[MAX_I2C_READ_LEN];
> +	u16 ch;
> +	u16 chdata;
> +	u8 readlen = hweight32(ts->data->chan_mask) * 2;
> +
> +	stat = i2c_smbus_read_byte_data(ts->client, CMD_READ_REGISTER
> +						    | I2C_REG_SX8650_STAT);
> +
> +	if (!(stat & SX8650_STAT_CONVIRQ)) {
> +		dev_dbg(dev, "%s ignore stat [0x%02x]", __func__, stat);
> +		return IRQ_HANDLED;
> +	}
> +
> +	len = i2c_master_recv(ts->client, data, readlen);
> +	if (len != readlen) {
> +		dev_dbg(dev, "ignore short recv (%d)\n", len);
> +		return IRQ_HANDLED;
> +	}
> +
> +	ret = hrtimer_try_to_cancel(&ts->timer);
> +
> +	x = 0;
> +	y = 0;
> +	for (i = 0; (i + 1) < len; i++) {
> +		chdata = data[i] << 8;
> +		i++;
> +		chdata += data[i];
> +
> +		if (unlikely(chdata == 0xFFFF)) {
> +			dev_dbg(dev, "invalid qualified data @ %d\n", i);
> +			continue;
> +		} else if (unlikely(chdata & 0x8000)) {
> +			dev_warn(dev, "hibit @ %d [0x%04x]\n", i, chdata);
> +			continue;
> +		}
> +
> +		ch = chdata >> 12;
> +		if      (ch == CH_X)
> +			x = chdata & MAX_12BIT;
> +		else if (ch == CH_Y)
> +			y = chdata & MAX_12BIT;
> +		else
> +			dev_warn(dev, "unknown channel %d [0x%04x]\n", ch,
> +				 chdata);
> +	}
> +
> +	input_report_abs(ts->input, ABS_X, x);
> +	input_report_abs(ts->input, ABS_Y, y);
> +	input_report_key(ts->input, BTN_TOUCH, 1);
> +	input_sync(ts->input);
> +	dev_dbg(dev, "point(%4d,%4d)\n", x, y);
> +
> +	hrtimer_start(&ts->timer, ktime_set(0, SX8650_PENIRQ_TIMEOUT),
> +		      HRTIMER_MODE_REL);
> +	return IRQ_HANDLED;
> +}
> +
>  static irqreturn_t sx8654_irq(int irq, void *handle)
>  {
>  	struct sx8654 *sx8654 = handle;
> @@ -127,6 +227,22 @@ static irqreturn_t sx8654_irq(int irq, void *handle)
>  	return IRQ_HANDLED;
>  }
>  
> +static const struct sx865x_data sx8650_data = {
> +	.cmd_manual = 0xb0,
> +	.has_irq_penrelease = 0,
> +	.has_reg_irqmask = 0,
> +	.chan_mask = (CONV_X | CONV_Y),
> +	.irqh = sx8650_irq,
> +};
> +
> +static const struct sx865x_data sx8654_data = {
> +	.cmd_manual = 0xc0,
> +	.has_irq_penrelease = 1,
> +	.has_reg_irqmask = 1,
> +	.chan_mask = (CONV_X | CONV_Y),
> +	.irqh = sx8654_irq,
> +};
> +
>  static int sx8654_reset(struct sx8654 *ts)
>  {
>  	int err;
> @@ -182,13 +298,13 @@ static void sx8654_close(struct input_dev *dev)
>  	disable_irq(client->irq);
>  
>  	/* enable manual mode mode */
> -	error = i2c_smbus_write_byte(client, CMD_MANUAL);
> +	error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual);
>  	if (error) {
>  		dev_err(&client->dev, "writing command CMD_MANUAL failed");
>  		return;
>  	}
>  
> -	error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 0);
> +	error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, RATE_MANUAL);
>  	if (error) {
>  		dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed");
>  		return;
> @@ -196,10 +312,30 @@ static void sx8654_close(struct input_dev *dev)
>  }
>  
>  #ifdef CONFIG_OF
> +static const struct of_device_id sx8654_of_match[] = {
> +	{
> +		.compatible = "semtech,sx8650",
> +		.data = &sx8650_data,
> +	}, {
> +		.compatible = "semtech,sx8654",
> +		.data = &sx8654_data,
> +	}, {
> +		.compatible = "semtech,sx8655",
> +		.data = &sx8654_data,
> +	}, {
> +		.compatible = "semtech,sx8656",
> +		.data = &sx8654_data,
> +	}, {},
> +};
> +MODULE_DEVICE_TABLE(of, sx8654_of_match);
> +
>  static int sx8654_get_ofdata(struct sx8654 *ts)
>  {
>  	struct device *dev = &ts->client->dev;
>  	struct device_node *node = dev->of_node;
> +	const struct of_device_id *of_id = of_match_device(sx8654_of_match,
> +							   dev);

If you use of_device_get_match_data() you do not need to move device
table around.

> +	const struct sx865x_data *data = (struct sx865x_data *)of_id->data;
>  	int err;
>  
>  	if (!node) {
> @@ -207,6 +343,8 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
>  		return 0;
>  	}
>  
> +	ts->data = data;
> +
>  	ts->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>  	if (PTR_ERR(ts->gpio_reset) == -EPROBE_DEFER) {
>  		return -EPROBE_DEFER;
> @@ -219,18 +357,11 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
>  
>  	return 0;
>  }
> -
> -static const struct of_device_id sx8654_of_match[] = {
> -	{ .compatible = "semtech,sx8654", },
> -	{ .compatible = "semtech,sx8655", },
> -	{ .compatible = "semtech,sx8656", },
> -	{ },
> -};
> -MODULE_DEVICE_TABLE(of, sx8654_of_match);
>  #else /* CONFIG_OF */
>  static int sx8654_get_ofdata(struct sx8654 *ts)
>  {
>  	ts->gpio_reset = NULL;
> +	ts->data = &sx8654_data;
>  	return 0;
>  }
>  #endif /* CONFIG_OF */
> @@ -258,6 +389,12 @@ static int sx8654_probe(struct i2c_client *client,
>  		return error;
>  	}
>  
> +	if (!sx8654->data->has_irq_penrelease) {
> +		dev_dbg(&client->dev, "use timer for penrelease\n");
> +		hrtimer_init(&sx8654->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +		sx8654->timer.function = sx865x_penrelease_timer_handler;
> +	}
> +
>  	input = devm_input_allocate_device(&client->dev);
>  	if (!input)
>  		return -ENOMEM;
> @@ -284,29 +421,31 @@ static int sx8654_probe(struct i2c_client *client,
>  	}
>  
>  	error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK,
> -					  CONV_X | CONV_Y);
> +					  sx8654->data->chan_mask);
>  	if (error) {
>  		dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed");
>  		return error;
>  	}
>  
> -	error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK,
> -					  IRQ_PENTOUCH_TOUCHCONVDONE |
> -						IRQ_PENRELEASE);
> -	if (error) {
> -		dev_err(&client->dev, "writing to I2C_REG_IRQMASK failed");
> -		return error;
> +	if (sx8654->data->has_reg_irqmask) {
> +		error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK,
> +						  IRQ_PENTOUCH_TOUCHCONVDONE |
> +							IRQ_PENRELEASE);
> +		if (error) {
> +			dev_err(&client->dev, "writing I2C_REG_IRQMASK failed");
> +			return error;
> +		}
>  	}
>  
>  	error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1,
> -					  CONDIRQ | FILT_7SA);
> +					  CONDIRQ | RPDNT_100K | FILT_7SA);
>  	if (error) {
>  		dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed");
>  		return error;
>  	}
>  
>  	error = devm_request_threaded_irq(&client->dev, client->irq,
> -					  NULL, sx8654_irq,
> +					  NULL, sx8654->data->irqh,
>  					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>  					  client->name, sx8654);
>  	if (error) {
> @@ -327,6 +466,7 @@ static int sx8654_probe(struct i2c_client *client,
>  }
>  
>  static const struct i2c_device_id sx8654_id_table[] = {
> +	{ "semtech_sx8650", 0 },

Can we add the data here as well?

>  	{ "semtech_sx8654", 0 },
>  	{ "semtech_sx8655", 0 },
>  	{ "semtech_sx8656", 0 },
> -- 
> 2.11.0
> 

Thanks.

-- 
Dmitry

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

* Re: [PATCH 7/7] Input: sx8654 - use common of_touchscreen functions
  2018-10-16  9:23 ` [PATCH 7/7] Input: sx8654 - use common of_touchscreen functions Richard Leitner
@ 2018-10-16 17:52   ` Dmitry Torokhov
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2018-10-16 17:52 UTC (permalink / raw)
  To: Richard Leitner
  Cc: robh+dt, mark.rutland, linux-input, devicetree, linux-kernel

On Tue, Oct 16, 2018 at 11:23:10AM +0200, Richard Leitner wrote:
> of_touchscreen.c provides a common interface for a axis invertion and
> swapping of touchscreens. Therefore use it in the sx8654 driver.
> 
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
>  drivers/input/touchscreen/sx8654.c | 37 +++++++++++++++++++------------------
>  1 file changed, 19 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
> index 33f7a0be4ef8..08b064f96b4e 100644
> --- a/drivers/input/touchscreen/sx8654.c
> +++ b/drivers/input/touchscreen/sx8654.c
> @@ -36,6 +36,7 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/delay.h>
>  #include <linux/hrtimer.h>
> +#include <linux/input/touchscreen.h>
>  
>  /* register addresses */
>  #define I2C_REG_TOUCH0			0x00
> @@ -100,6 +101,7 @@ struct sx8654 {
>  	struct i2c_client *client;
>  	struct gpio_desc *gpio_reset;
>  	struct hrtimer timer;
> +	struct touchscreen_properties props;
>  
>  	const struct sx865x_data *data;
>  };
> @@ -168,8 +170,7 @@ static irqreturn_t sx8650_irq(int irq, void *handle)
>  				 chdata);
>  	}
>  
> -	input_report_abs(ts->input, ABS_X, x);
> -	input_report_abs(ts->input, ABS_Y, y);
> +	touchscreen_report_pos(ts->input, &ts->props, x, y, false);
>  	input_report_key(ts->input, BTN_TOUCH, 1);
>  	input_sync(ts->input);
>  	dev_dbg(dev, "point(%4d,%4d)\n", x, y);
> @@ -215,8 +216,8 @@ static irqreturn_t sx8654_irq(int irq, void *handle)
>  		x = ((data[0] & 0xf) << 8) | (data[1]);
>  		y = ((data[2] & 0xf) << 8) | (data[3]);
>  
> -		input_report_abs(sx8654->input, ABS_X, x);
> -		input_report_abs(sx8654->input, ABS_Y, y);
> +		touchscreen_report_pos(sx8654->input, &sx8654->props, x, y,
> +				       false);
>  		input_report_key(sx8654->input, BTN_TOUCH, 1);
>  		input_sync(sx8654->input);
>  
> @@ -355,6 +356,8 @@ static int sx8654_get_ofdata(struct sx8654 *ts)
>  	}
>  	dev_dbg(dev, "got GPIO reset pin\n");
>  

You need to mark axes used by the device before calling
touchscreen_parse_properties(), otherwise you'll get warnings if
corresponding property is present in DT.

> +	touchscreen_parse_properties(ts->input, false, &ts->props);
> +
>  	return 0;
>  }
>  #else /* CONFIG_OF */
> @@ -380,25 +383,11 @@ static int sx8654_probe(struct i2c_client *client,
>  	sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL);
>  	if (!sx8654)
>  		return -ENOMEM;
> -
>  	sx8654->client = client;
>  
> -	error = sx8654_get_ofdata(sx8654);
> -	if (error) {
> -		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
> -		return error;
> -	}
> -
> -	if (!sx8654->data->has_irq_penrelease) {
> -		dev_dbg(&client->dev, "use timer for penrelease\n");
> -		hrtimer_init(&sx8654->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> -		sx8654->timer.function = sx865x_penrelease_timer_handler;
> -	}
> -
>  	input = devm_input_allocate_device(&client->dev);
>  	if (!input)
>  		return -ENOMEM;
> -
>  	sx8654->input = input;
>  
>  	input->name = "SX8654 I2C Touchscreen";
> @@ -414,6 +403,18 @@ static int sx8654_probe(struct i2c_client *client,
>  
>  	input_set_drvdata(sx8654->input, sx8654);
>  
> +	error = sx8654_get_ofdata(sx8654);
> +	if (error) {
> +		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
> +		return error;
> +	}
> +
> +	if (!sx8654->data->has_irq_penrelease) {
> +		dev_dbg(&client->dev, "use timer for penrelease\n");
> +		hrtimer_init(&sx8654->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +		sx8654->timer.function = sx865x_penrelease_timer_handler;
> +	}
> +
>  	error = sx8654_reset(sx8654);
>  	if (error) {
>  		dev_err(&client->dev, "reset failed");
> -- 
> 2.11.0
> 

-- 
Dmitry

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

* Re: [PATCH 2/7] Input: sx8654 - add reset-gpio support
  2018-10-16 17:39   ` Dmitry Torokhov
@ 2018-10-16 19:32     ` Richard Leitner
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Leitner @ 2018-10-16 19:32 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: robh+dt, mark.rutland, linux-input, devicetree, linux-kernel,
	Richard Leitner

Hi Dimitry,
thanks for the quick reply!

On 10/16/18 7:39 PM, Dmitry Torokhov wrote:
> Hi Richard,
> 
> On Tue, Oct 16, 2018 at 11:16:48AM +0200, Richard Leitner wrote:
>> The sx8654 features a NRST input which may be connected to a GPIO.
>> Therefore add support for hard-resetting the sx8654 via this NRST.
>>
>> If the reset-gpio property is provided the sx8654 is resetted via NRST
>> instead of the soft-reset via I2C.
>>

...

>> +
>> +	dev_dbg(&ts->client->dev, "NRST unavailable, try softreset\n");
>> +	err = i2c_smbus_write_byte_data(ts->client, I2C_REG_SOFTRESET,
>> +					SOFTRESET_VALUE);
>> +	if (err)
>> +		return err;
> 
> Have this in an "else" branch?

If that's the preferred way... of course.

> 
>> +
>> +	return 0;
>> +}
>> +
>>   static int sx8654_open(struct input_dev *dev)
>>   {
>>   	struct sx8654 *sx8654 = input_get_drvdata(dev);
>> @@ -171,6 +195,44 @@ static void sx8654_close(struct input_dev *dev)
>>   	}
>>   }
>>   
>> +#ifdef CONFIG_OF
>> +static int sx8654_get_ofdata(struct sx8654 *ts)
>> +{
>> +	struct device *dev = &ts->client->dev;
>> +	struct device_node *node = dev->of_node;
>> +	int err;
>> +
>> +	if (!node) {
>> +		ts->gpio_reset = NULL;
>> +		return 0;
>> +	}
> 
> There is no need to wrap this into CONFIG_OF or test "node". Just use
> devm_gpiod_get_optional() and it will work equally well on DT, ACPI, and
> static board systems.

Ok. Thank you for that information!
I haven't been aware of this before :-)

> 
>> +
>> +	ts->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
>> +	if (PTR_ERR(ts->gpio_reset) == -EPROBE_DEFER) {
>> +		return -EPROBE_DEFER;
>> +	} else if (IS_ERR(ts->gpio_reset)) {
>> +		err = PTR_ERR(ts->gpio_reset);
> 
> I'd do:
> 
> 		if (err != -EPROBE_DEFER)
> 			dev_err(...)
> 
> here instead of separate branch.

Indeed... Looks like a more sexy solution. Thanks.

> 
>> +		dev_err(dev, "unable to request GPIO reset pin (%d)\n", err);
>> +		return err;
>> +	}
>> +	dev_dbg(dev, "got GPIO reset pin\n");
> 
> Also, I'd move all this code directly into probe() since all this
> #ifdefery is not needed.

Without the #ifdef'ery and node checking this sounds reasonable.

> 
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id sx8654_of_match[] = {
>> +	{ .compatible = "semtech,sx8654", },
>> +	{ },
>> +};
> 
> Please keep the device table wehere it was.

OK.

>> @@ -186,10 +248,20 @@ static int sx8654_probe(struct i2c_client *client,
>>   	if (!sx8654)
>>   		return -ENOMEM;
>>   
>> +	sx8654->client = client;
>> +
>> +	error = sx8654_get_ofdata(sx8654);
>> +	if (error) {
>> +		dev_err(&client->dev, "get_ofdata failed: %d\n", error);
>> +		return error;
>> +	}
>> +
>>   	input = devm_input_allocate_device(&client->dev);
>>   	if (!input)
>>   		return -ENOMEM;
>>   
>> +	sx8654->input = input;
>> +
>>   	input->name = "SX8654 I2C Touchscreen";
>>   	input->id.bustype = BUS_I2C;
>>   	input->dev.parent = &client->dev;
>> @@ -201,15 +273,11 @@ static int sx8654_probe(struct i2c_client *client,
>>   	input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0);
>>   	input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0);
>>   
>> -	sx8654->client = client;
>> -	sx8654->input = input;
>> -
> 
> Why do we need to move this?

This was because sx8654_get_ofdata needed ts->client->dev.
But as I will integrate the reset gpio getting in the probe function 
I'll move it back.

...

> 
> Thanks.
> 

I'll send a v2 of the series as soon as I have fixed the other patches.

regards;Richard.L

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

* Re: [PATCH 6/7] Input: sx8654 - add sx8650 support
  2018-10-16 17:48   ` Dmitry Torokhov
@ 2018-10-16 19:34     ` Richard Leitner
  2018-10-16 20:18       ` Dmitry Torokhov
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Leitner @ 2018-10-16 19:34 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: robh+dt, mark.rutland, linux-input, devicetree, linux-kernel,
	Richard Leitner


On 10/16/18 7:48 PM, Dmitry Torokhov wrote:
> On Tue, Oct 16, 2018 at 11:22:48AM +0200, Richard Leitner wrote:
>> The sx8654 and sx8650 are quite similar, therefore add support for the
>> sx8650 within the sx8654 driver.
>>

...

>>   
>>   /* bits for I2C_REG_CHANMASK */
>> -#define CONV_X				0x80
>> -#define CONV_Y				0x40
>> +#define CONV_X				BIT(7)
>> +#define CONV_Y				BIT(6)
> 
> If you are using BIT() you need to include include/linux/bitops.h
> 
> I also would prefer conversion to using BIT() as a separate patch.

OK. I'll take it out of this patch.

Should I convert them (and the other #defines where it makes sense) to 
BIT() at all?

> 
>>   
>>   /* coordinates rate: higher nibble of CTRL0 register */
>>   #define RATE_MANUAL			0x00
>> @@ -71,14 +75,110 @@
>>   /* power delay: lower nibble of CTRL0 register */
>>   #define POWDLY_1_1MS			0x0b
>>   
>> +/* for sx8650, as we have no pen release IRQ there: timeout in ns following the
>> + * last PENIRQ after which we assume the pen is lifted.
>> + */
>> +#define SX8650_PENIRQ_TIMEOUT		(80 * 1100 * 1000)
>> +
>>   #define MAX_12BIT			((1 << 12) - 1)
>> +#define MAX_I2C_READ_LEN		10 /* see datasheet section 5.1.5 */
>> +
>> +/* channel definition */
>> +#define CH_X				0x00
>> +#define CH_Y				0x01
>> +
>> +struct sx865x_data {
>> +	u8 cmd_manual;
>> +	u8 chan_mask;
>> +	u8 has_irq_penrelease;
>> +	u8 has_reg_irqmask;
>> +	irq_handler_t irqh;
>> +};
>>   
>>   struct sx8654 {
>>   	struct input_dev *input;
>>   	struct i2c_client *client;
>>   	struct gpio_desc *gpio_reset;
>> +	struct hrtimer timer;
> 
> Does this have to be hrtimer? Can regular timer be used?

I'll check again if it's feasible to reduce the timer delay to something 
below the "normal" jiffy. If not I'll replace the hrtimer with a timer.

> 
>> +
>> +	const struct sx865x_data *data;
>>   };
>>   
>> +static enum hrtimer_restart sx865x_penrelease_timer_handler(struct hrtimer *h)
>> +{
>> +	struct sx8654 *ts = container_of(h, struct sx8654, timer);
>> +
>> +	input_report_key(ts->input, BTN_TOUCH, 0);
>> +	input_sync(ts->input);
>> +	dev_dbg(&ts->client->dev, "penrelease by timer\n");
>> +
>> +	return HRTIMER_NORESTART;
>> +}
>> +

...

>> @@ -196,10 +312,30 @@ static void sx8654_close(struct input_dev *dev)
>>   }
>>   
>>   #ifdef CONFIG_OF
>> +static const struct of_device_id sx8654_of_match[] = {
>> +	{
>> +		.compatible = "semtech,sx8650",
>> +		.data = &sx8650_data,
>> +	}, {
>> +		.compatible = "semtech,sx8654",
>> +		.data = &sx8654_data,
>> +	}, {
>> +		.compatible = "semtech,sx8655",
>> +		.data = &sx8654_data,
>> +	}, {
>> +		.compatible = "semtech,sx8656",
>> +		.data = &sx8654_data,
>> +	}, {},
>> +};
>> +MODULE_DEVICE_TABLE(of, sx8654_of_match);
>> +
>>   static int sx8654_get_ofdata(struct sx8654 *ts)
>>   {
>>   	struct device *dev = &ts->client->dev;
>>   	struct device_node *node = dev->of_node;
>> +	const struct of_device_id *of_id = of_match_device(sx8654_of_match,
>> +							   dev);
> 
> If you use of_device_get_match_data() you do not need to move device
> table around.

Thanks for that hint. I haven't known there's something like this ;-)

> 
>> +	const struct sx865x_data *data = (struct sx865x_data *)of_id->data;
>>   	int err;
>>   
>>   	if (!node) {

...

>> @@ -327,6 +466,7 @@ static int sx8654_probe(struct i2c_client *client,
>>   }
>>   
>>   static const struct i2c_device_id sx8654_id_table[] = {
>> +	{ "semtech_sx8650", 0 },
> 
> Can we add the data here as well?

Does it generate any benefit if we add it? Who should be using it?

I found in other drivers that it's used as a fallback when 
of_device_get_match_data() returns NULL... Should I also implement it 
that way?

> 
>>   	{ "semtech_sx8654", 0 },
>>   	{ "semtech_sx8655", 0 },
>>   	{ "semtech_sx8656", 0 },
>> -- 
>> 2.11.0
>>
> 
> Thanks.
> 

thanks&regards;Richard.L

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

* Re: [PATCH 6/7] Input: sx8654 - add sx8650 support
  2018-10-16 19:34     ` Richard Leitner
@ 2018-10-16 20:18       ` Dmitry Torokhov
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2018-10-16 20:18 UTC (permalink / raw)
  To: Richard Leitner
  Cc: robh+dt, mark.rutland, linux-input, devicetree, linux-kernel

On Tue, Oct 16, 2018 at 09:34:26PM +0200, Richard Leitner wrote:
> 
> On 10/16/18 7:48 PM, Dmitry Torokhov wrote:
> > On Tue, Oct 16, 2018 at 11:22:48AM +0200, Richard Leitner wrote:
> > > The sx8654 and sx8650 are quite similar, therefore add support for the
> > > sx8650 within the sx8654 driver.
> > > 
> 
> ...
> 
> > >   /* bits for I2C_REG_CHANMASK */
> > > -#define CONV_X				0x80
> > > -#define CONV_Y				0x40
> > > +#define CONV_X				BIT(7)
> > > +#define CONV_Y				BIT(6)
> > 
> > If you are using BIT() you need to include include/linux/bitops.h
> > 
> > I also would prefer conversion to using BIT() as a separate patch.
> 
> OK. I'll take it out of this patch.
> 
> Should I convert them (and the other #defines where it makes sense) to BIT()
> at all?

Sure as it documents the intent better, I just asked it to be split out
since each patch should solve one particular problem.

> 
> > 
> > >   /* coordinates rate: higher nibble of CTRL0 register */
> > >   #define RATE_MANUAL			0x00
> > > @@ -71,14 +75,110 @@
> > >   /* power delay: lower nibble of CTRL0 register */
> > >   #define POWDLY_1_1MS			0x0b
> > > +/* for sx8650, as we have no pen release IRQ there: timeout in ns following the
> > > + * last PENIRQ after which we assume the pen is lifted.
> > > + */
> > > +#define SX8650_PENIRQ_TIMEOUT		(80 * 1100 * 1000)
> > > +
> > >   #define MAX_12BIT			((1 << 12) - 1)
> > > +#define MAX_I2C_READ_LEN		10 /* see datasheet section 5.1.5 */
> > > +
> > > +/* channel definition */
> > > +#define CH_X				0x00
> > > +#define CH_Y				0x01
> > > +
> > > +struct sx865x_data {
> > > +	u8 cmd_manual;
> > > +	u8 chan_mask;
> > > +	u8 has_irq_penrelease;
> > > +	u8 has_reg_irqmask;
> > > +	irq_handler_t irqh;
> > > +};
> > >   struct sx8654 {
> > >   	struct input_dev *input;
> > >   	struct i2c_client *client;
> > >   	struct gpio_desc *gpio_reset;
> > > +	struct hrtimer timer;
> > 
> > Does this have to be hrtimer? Can regular timer be used?
> 
> I'll check again if it's feasible to reduce the timer delay to something
> below the "normal" jiffy. If not I'll replace the hrtimer with a timer.

That means polling faster than 200HZ in the best case. I think it is too
much.

> 
> > 
> > > +
> > > +	const struct sx865x_data *data;
> > >   };
> > > +static enum hrtimer_restart sx865x_penrelease_timer_handler(struct hrtimer *h)
> > > +{
> > > +	struct sx8654 *ts = container_of(h, struct sx8654, timer);
> > > +
> > > +	input_report_key(ts->input, BTN_TOUCH, 0);
> > > +	input_sync(ts->input);
> > > +	dev_dbg(&ts->client->dev, "penrelease by timer\n");
> > > +
> > > +	return HRTIMER_NORESTART;
> > > +}
> > > +
> 
> ...
> 
> > > @@ -196,10 +312,30 @@ static void sx8654_close(struct input_dev *dev)
> > >   }
> > >   #ifdef CONFIG_OF
> > > +static const struct of_device_id sx8654_of_match[] = {
> > > +	{
> > > +		.compatible = "semtech,sx8650",
> > > +		.data = &sx8650_data,
> > > +	}, {
> > > +		.compatible = "semtech,sx8654",
> > > +		.data = &sx8654_data,
> > > +	}, {
> > > +		.compatible = "semtech,sx8655",
> > > +		.data = &sx8654_data,
> > > +	}, {
> > > +		.compatible = "semtech,sx8656",
> > > +		.data = &sx8654_data,
> > > +	}, {},
> > > +};
> > > +MODULE_DEVICE_TABLE(of, sx8654_of_match);
> > > +
> > >   static int sx8654_get_ofdata(struct sx8654 *ts)
> > >   {
> > >   	struct device *dev = &ts->client->dev;
> > >   	struct device_node *node = dev->of_node;
> > > +	const struct of_device_id *of_id = of_match_device(sx8654_of_match,
> > > +							   dev);
> > 
> > If you use of_device_get_match_data() you do not need to move device
> > table around.
> 
> Thanks for that hint. I haven't known there's something like this ;-)
> 
> > 
> > > +	const struct sx865x_data *data = (struct sx865x_data *)of_id->data;
> > >   	int err;
> > >   	if (!node) {
> 
> ...
> 
> > > @@ -327,6 +466,7 @@ static int sx8654_probe(struct i2c_client *client,
> > >   }
> > >   static const struct i2c_device_id sx8654_id_table[] = {
> > > +	{ "semtech_sx8650", 0 },
> > 
> > Can we add the data here as well?
> 
> Does it generate any benefit if we add it? Who should be using it?

If someone decides to use driver in non-DT environment.

> 
> I found in other drivers that it's used as a fallback when
> of_device_get_match_data() returns NULL... Should I also implement it that
> way?

Yes, that would be good.

Thanks.

-- 
Dmitry

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

end of thread, other threads:[~2018-10-16 20:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-16  9:16 [PATCH 0/7] Input: sx8654 - reset-gpio, sx865[056] support, etc Richard Leitner
2018-10-16  9:16 ` [PATCH 1/7] dt-bindings: input: touchscreen: sx8654: add reset-gpio property Richard Leitner
2018-10-16  9:16 ` [PATCH 2/7] Input: sx8654 - add reset-gpio support Richard Leitner
2018-10-16 17:39   ` Dmitry Torokhov
2018-10-16 19:32     ` Richard Leitner
2018-10-16  9:16 ` [PATCH 3/7] dt-bindings: input: touchscreen: sx8654: add compatible models Richard Leitner
2018-10-16  9:16 ` [PATCH 4/7] Input: sx8654 - add sx8655 and sx8656 to compatibles Richard Leitner
2018-10-16  9:22 ` [PATCH 5/7] dt-bindings: input: touchscreen: sx8654: add sx8650 to comatibles Richard Leitner
2018-10-16  9:22 ` [PATCH 6/7] Input: sx8654 - add sx8650 support Richard Leitner
2018-10-16 17:48   ` Dmitry Torokhov
2018-10-16 19:34     ` Richard Leitner
2018-10-16 20:18       ` Dmitry Torokhov
2018-10-16  9:23 ` [PATCH 7/7] Input: sx8654 - use common of_touchscreen functions Richard Leitner
2018-10-16 17:52   ` Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).