Add support to the reMarkable2 (rM2) for the Wacom I2C device.
This is based on the reMarkable Linux fork and with this series I am
able to use the Wacom digitiser on the rM2.
v9:
- Add two new patches
- Fixup the device tree interrupt line
v7:
- Fx the compatible name and documentation
Alistair Francis (11):
dt-bindings: Add Wacom to vendor bindings
dt-bindings: touchscreen: Initial commit of wacom,i2c
Input: wacom_i2c - Add device tree support to wacom_i2c
Input: wacom_i2c - Add touchscren properties
Input: wacom_i2c - Add support for distance and tilt x/y
Input: wacom_i2c - Clean up the query device fields
Input: wacom_i2c - Add support for vdd regulator
Input: wacom_i2c - Use macros for the bit masks
Input: wacom_i2c - Allow flipping the values from the DT
ARM: imx_v6_v7_defconfig: Enable Wacom I2C
ARM: dts: imx7d: remarkable2: add wacom digitizer device
.../input/touchscreen/wacom,generic.yaml | 66 ++++++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
arch/arm/boot/dts/imx7d-remarkable2.dts | 61 ++++++
arch/arm/configs/imx_v6_v7_defconfig | 1 +
drivers/input/touchscreen/wacom_i2c.c | 203 ++++++++++++++----
5 files changed, 297 insertions(+), 36 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
--
2.31.1
Signed-off-by: Alistair Francis <[email protected]>
Acked-by: Rob Herring <[email protected]>
Cc: [email protected]
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 4dfaae537daf..31745c45dd92 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1252,6 +1252,8 @@ patternProperties:
description: Vision Optical Technology Co., Ltd.
"^vxt,.*":
description: VXT Ltd
+ "^wacom,.*":
+ description: Wacom Co., Ltd
"^wand,.*":
description: Wandbord (Technexion)
"^waveshare,.*":
--
2.31.1
Signed-off-by: Alistair Francis <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Cc: [email protected]
---
.../input/touchscreen/wacom,generic.yaml | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml b/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
new file mode 100644
index 000000000000..a8a7f362b0ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/wacom,generic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Wacom I2C Controller
+
+maintainers:
+ - Alistair Francis <[email protected]>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ const: wacom,i2c-30
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vdd-supply:
+ description: Power Supply
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include "dt-bindings/interrupt-controller/irq.h"
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ digitiser@9 {
+ compatible = "wacom,i2c-30";
+ reg = <0x9>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <®_touch>;
+ };
+ };
--
2.31.1
Allow the wacom-i2c device to be exposed via device tree.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/input/touchscreen/wacom_i2c.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 22826c387da5..6053595f2b30 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/of.h>
#include <asm/unaligned.h>
#define WACOM_CMD_QUERY0 0x04
@@ -241,10 +242,17 @@ static const struct i2c_device_id wacom_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, wacom_i2c_id);
+static const struct of_device_id wacom_i2c_of_match_table[] = {
+ { .compatible = "wacom,i2c-30" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, wacom_i2c_of_match_table);
+
static struct i2c_driver wacom_i2c_driver = {
.driver = {
.name = "wacom_i2c",
.pm = &wacom_i2c_pm,
+ .of_match_table = wacom_i2c_of_match_table,
},
.probe = wacom_i2c_probe,
--
2.31.1
Connect touchscreen properties to the wacom_i2c.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/input/touchscreen/wacom_i2c.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 6053595f2b30..28255c77d426 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -11,6 +11,7 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
+#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <asm/unaligned.h>
@@ -33,6 +34,8 @@ struct wacom_features {
struct wacom_i2c {
struct i2c_client *client;
struct input_dev *input;
+ struct touchscreen_properties props;
+ struct wacom_features features;
u8 data[WACOM_QUERY_SIZE];
bool prox;
int tool;
@@ -90,6 +93,7 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
{
struct wacom_i2c *wac_i2c = dev_id;
struct input_dev *input = wac_i2c->input;
+ struct wacom_features *features = &wac_i2c->features;
u8 *data = wac_i2c->data;
unsigned int x, y, pressure;
unsigned char tsw, f1, f2, ers;
@@ -114,6 +118,8 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
wac_i2c->prox = data[3] & 0x20;
+ touchscreen_report_pos(input, &wac_i2c->props, features->x_max,
+ features->y_max, true);
input_report_key(input, BTN_TOUCH, tsw || ers);
input_report_key(input, wac_i2c->tool, wac_i2c->prox);
input_report_key(input, BTN_STYLUS, f1);
@@ -151,7 +157,7 @@ static int wacom_i2c_probe(struct i2c_client *client,
struct device *dev = &client->dev;
struct wacom_i2c *wac_i2c;
struct input_dev *input;
- struct wacom_features features = { 0 };
+ struct wacom_features *features;
int error;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
@@ -159,14 +165,15 @@ static int wacom_i2c_probe(struct i2c_client *client,
return -EIO;
}
- error = wacom_query_device(client, &features);
- if (error)
- return error;
-
wac_i2c = devm_kzalloc(dev, sizeof(*wac_i2c), GFP_KERNEL);
if (!wac_i2c)
return -ENOMEM;
+ features = &wac_i2c->features;
+ error = wacom_query_device(client, features);
+ if (error)
+ return error;
+
wac_i2c->client = client;
input = devm_input_allocate_device(dev);
@@ -178,7 +185,7 @@ static int wacom_i2c_probe(struct i2c_client *client,
input->name = "Wacom I2C Digitizer";
input->id.bustype = BUS_I2C;
input->id.vendor = 0x56a;
- input->id.version = features.fw_version;
+ input->id.version = features->fw_version;
input->open = wacom_i2c_open;
input->close = wacom_i2c_close;
@@ -190,10 +197,11 @@ static int wacom_i2c_probe(struct i2c_client *client,
__set_bit(BTN_STYLUS2, input->keybit);
__set_bit(BTN_TOUCH, input->keybit);
- input_set_abs_params(input, ABS_X, 0, features.x_max, 0, 0);
- input_set_abs_params(input, ABS_Y, 0, features.y_max, 0, 0);
+ touchscreen_parse_properties(input, true, &wac_i2c->props);
+ input_set_abs_params(input, ABS_X, 0, features->x_max, 0, 0);
+ input_set_abs_params(input, ABS_Y, 0, features->y_max, 0, 0);
input_set_abs_params(input, ABS_PRESSURE,
- 0, features.pressure_max, 0, 0);
+ 0, features->pressure_max, 0, 0);
input_set_drvdata(input, wac_i2c);
--
2.31.1
Add support for the distance and tilt x/y.
This is based on the out of tree rM2 driver.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/input/touchscreen/wacom_i2c.c | 35 +++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 28255c77d426..4d0c19fbada4 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -22,12 +22,18 @@
#define WACOM_CMD_QUERY3 0x02
#define WACOM_CMD_THROW0 0x05
#define WACOM_CMD_THROW1 0x00
-#define WACOM_QUERY_SIZE 19
+#define WACOM_QUERY_SIZE 22
+
+#define WACOM_DISTANCE_TILT_VERSION 0x30
struct wacom_features {
int x_max;
int y_max;
int pressure_max;
+ int distance_max;
+ int distance_physical_max;
+ int tilt_x_max;
+ int tilt_y_max;
char fw_version;
};
@@ -80,6 +86,17 @@ static int wacom_query_device(struct i2c_client *client,
features->y_max = get_unaligned_le16(&data[5]);
features->pressure_max = get_unaligned_le16(&data[11]);
features->fw_version = get_unaligned_le16(&data[13]);
+ if (features->fw_version >= WACOM_DISTANCE_TILT_VERSION) {
+ features->distance_max = data[15];
+ features->distance_physical_max = data[16];
+ features->tilt_x_max = get_unaligned_le16(&data[17]);
+ features->tilt_y_max = get_unaligned_le16(&data[19]);
+ } else {
+ features->distance_max = -1;
+ features->distance_physical_max = -1;
+ features->tilt_x_max = -1;
+ features->tilt_y_max = -1;
+ }
dev_dbg(&client->dev,
"x_max:%d, y_max:%d, pressure:%d, fw:%d\n",
@@ -97,6 +114,7 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
u8 *data = wac_i2c->data;
unsigned int x, y, pressure;
unsigned char tsw, f1, f2, ers;
+ short tilt_x, tilt_y, distance;
int error;
error = i2c_master_recv(wac_i2c->client,
@@ -112,6 +130,12 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
y = le16_to_cpup((__le16 *)&data[6]);
pressure = le16_to_cpup((__le16 *)&data[8]);
+ /* Signed */
+ tilt_x = le16_to_cpup((__le16 *)&data[11]);
+ tilt_y = le16_to_cpup((__le16 *)&data[13]);
+
+ distance = le16_to_cpup((__le16 *)&data[15]);
+
if (!wac_i2c->prox)
wac_i2c->tool = (data[3] & 0x0c) ?
BTN_TOOL_RUBBER : BTN_TOOL_PEN;
@@ -127,6 +151,9 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, pressure);
+ input_report_abs(input, ABS_DISTANCE, distance);
+ input_report_abs(input, ABS_TILT_X, tilt_x);
+ input_report_abs(input, ABS_TILT_Y, tilt_y);
input_sync(input);
out:
@@ -202,7 +229,11 @@ static int wacom_i2c_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_Y, 0, features->y_max, 0, 0);
input_set_abs_params(input, ABS_PRESSURE,
0, features->pressure_max, 0, 0);
-
+ input_set_abs_params(input, ABS_DISTANCE, 0, features->distance_max, 0, 0);
+ input_set_abs_params(input, ABS_TILT_X, -features->tilt_x_max,
+ features->tilt_x_max, 0, 0);
+ input_set_abs_params(input, ABS_TILT_Y, -features->tilt_y_max,
+ features->tilt_y_max, 0, 0);
input_set_drvdata(input, wac_i2c);
error = devm_request_threaded_irq(dev, client->irq, NULL, wacom_i2c_irq,
--
2.31.1
Add support for a VDD regulator. This allows the kernel to probe the
Wacom-I2C device on the rM2.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/input/touchscreen/wacom_i2c.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 33a3ba110171..fd486b8ef2cc 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
+#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/of.h>
#include <asm/unaligned.h>
@@ -59,6 +60,7 @@ struct wacom_i2c {
struct input_dev *input;
struct touchscreen_properties props;
struct wacom_features features;
+ struct regulator *vdd;
u8 data[WACOM_QUERY_SIZE];
bool prox;
int tool;
@@ -220,6 +222,16 @@ static int wacom_i2c_probe(struct i2c_client *client,
if (!wac_i2c)
return -ENOMEM;
+ wac_i2c->vdd = regulator_get(&client->dev, "vdd");
+ if (IS_ERR(wac_i2c->vdd))
+ return PTR_ERR(wac_i2c->vdd);
+
+ error = regulator_enable(wac_i2c->vdd);
+ if (error) {
+ regulator_put(wac_i2c->vdd);
+ return error;
+ }
+
features = &wac_i2c->features;
error = wacom_query_device(client, features);
if (error)
@@ -228,8 +240,11 @@ static int wacom_i2c_probe(struct i2c_client *client,
wac_i2c->client = client;
input = devm_input_allocate_device(dev);
- if (!input)
+ if (!input) {
+ regulator_disable(wac_i2c->vdd);
+ regulator_put(wac_i2c->vdd);
return -ENOMEM;
+ }
wac_i2c->input = input;
@@ -264,6 +279,8 @@ static int wacom_i2c_probe(struct i2c_client *client,
IRQF_ONESHOT, "wacom_i2c", wac_i2c);
if (error) {
dev_err(dev, "Failed to request IRQ: %d\n", error);
+ regulator_disable(wac_i2c->vdd);
+ regulator_put(wac_i2c->vdd);
return error;
}
@@ -273,6 +290,8 @@ static int wacom_i2c_probe(struct i2c_client *client,
error = input_register_device(wac_i2c->input);
if (error) {
dev_err(dev, "Failed to register input device: %d\n", error);
+ regulator_disable(wac_i2c->vdd);
+ regulator_put(wac_i2c->vdd);
return error;
}
--
2.31.1
Allow the device tree properties to flip the tilx, position or distance
values.
This is required for the stylus to work correctly on the reMarkable 2.
Signed-off-by: Alistair Francis <[email protected]>
---
.../input/touchscreen/wacom,generic.yaml | 18 ++++++++++
drivers/input/touchscreen/wacom_i2c.c | 33 +++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml b/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
index a8a7f362b0ce..0da63fd92ea1 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
@@ -25,6 +25,24 @@ properties:
vdd-supply:
description: Power Supply
+ flip-tilt-x:
+ type: boolean
+
+ flip-tilt-y:
+ type: boolean
+
+ flip-pos-x:
+ type: boolean
+
+ flip-pos-y:
+ type: boolean
+
+ flip-distance:
+ type: boolean
+
+ flip-pressure:
+ type: boolean
+
required:
- compatible
- reg
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index c6579a1a8d04..82b62a768451 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -72,6 +72,13 @@ struct wacom_i2c {
u8 data[WACOM_QUERY_SIZE];
bool prox;
int tool;
+
+ bool flip_tilt_x;
+ bool flip_tilt_y;
+ bool flip_pos_x;
+ bool flip_pos_y;
+ bool flip_distance;
+ bool flip_pressure;
};
static int wacom_query_device(struct i2c_client *client,
@@ -140,6 +147,20 @@ static int wacom_query_device(struct i2c_client *client,
return 0;
}
+#ifdef CONFIG_OF
+static void wacom_of_read(struct wacom_i2c *wac_i2c)
+{
+ struct i2c_client *client = wac_i2c->client;
+
+ wac_i2c->flip_tilt_x = of_property_read_bool(client->dev.of_node, "flip-tilt-x");
+ wac_i2c->flip_tilt_y = of_property_read_bool(client->dev.of_node, "flip-tilt-y");
+ wac_i2c->flip_pos_x = of_property_read_bool(client->dev.of_node, "flip-pos-x");
+ wac_i2c->flip_pos_y = of_property_read_bool(client->dev.of_node, "flip-pos-y");
+ wac_i2c->flip_distance = of_property_read_bool(client->dev.of_node, "flip-distance");
+ wac_i2c->flip_pressure = of_property_read_bool(client->dev.of_node, "flip-pressure");
+}
+#endif
+
static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
{
struct wacom_i2c *wac_i2c = dev_id;
@@ -176,6 +197,14 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
wac_i2c->prox = data[3] & 0x20;
+ // Flip the values based on properties from the device tree
+ pressure = wac_i2c->flip_pressure ? (features->pressure_max - pressure) : pressure;
+ distance = wac_i2c->flip_distance ? -distance : distance;
+ x = wac_i2c->flip_pos_x ? (features->x_max - x) : x;
+ y = wac_i2c->flip_pos_y ? (features->y_max - y) : y;
+ tilt_x = wac_i2c->flip_tilt_x ? -tilt_x : tilt_x;
+ tilt_y = wac_i2c->flip_tilt_y ? -tilt_y : tilt_y;
+
touchscreen_report_pos(input, &wac_i2c->props, features->x_max,
features->y_max, true);
input_report_key(input, BTN_TOUCH, tsw || ers);
@@ -303,6 +332,10 @@ static int wacom_i2c_probe(struct i2c_client *client,
return error;
}
+#ifdef CONFIG_OF
+ wacom_of_read(wac_i2c);
+#endif
+
return 0;
}
--
2.31.1
Enable the wacom_i2c touchscreen for the reMarkable2.
Signed-off-by: Alistair Francis <[email protected]>
---
arch/arm/boot/dts/imx7d-remarkable2.dts | 61 +++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/arch/arm/boot/dts/imx7d-remarkable2.dts b/arch/arm/boot/dts/imx7d-remarkable2.dts
index 89cbf13097a4..052f9da32398 100644
--- a/arch/arm/boot/dts/imx7d-remarkable2.dts
+++ b/arch/arm/boot/dts/imx7d-remarkable2.dts
@@ -34,6 +34,19 @@ reg_brcm: regulator-brcm {
startup-delay-us = <150>;
};
+ reg_digitizer: regulator-digitizer {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_3V3_DIGITIZER";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_digitizer_reg>;
+ pinctrl-1 = <&pinctrl_digitizer_reg>;
+ gpio = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100000>; /* 100 ms */
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
pinctrl-names = "default";
@@ -51,6 +64,28 @@ &clks {
assigned-clock-rates = <0>, <32768>;
};
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ wacom_digitizer: digitizer@9 {
+ compatible = "wacom,i2c-30";
+ reg = <0x09>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wacom>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+ flip-tilt-x;
+ flip-tilt-y;
+ flip-pos-x;
+ flip-pos-y;
+ flip-distance;
+ vdd-supply = <®_digitizer>;
+ };
+};
+
&snvs_pwrkey {
status = "okay";
};
@@ -117,6 +152,25 @@ &wdog1 {
fsl,ext-reset-output;
};
+&iomuxc_lpsr {
+ pinctrl_digitizer_reg: digitizerreggrp {
+ fsl,pins = <
+ /* DIGITIZER_PWR_EN */
+ MX7D_PAD_LPSR_GPIO1_IO06__GPIO1_IO6 0x14
+ >;
+ };
+
+ pinctrl_wacom: wacomgrp {
+ fsl,pins = <
+ /*MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5 0x00000014 /* FWE */
+ MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x00000074 /* PDCTB */
+ MX7D_PAD_LPSR_GPIO1_IO01__GPIO1_IO1 0x00000034 /* WACOM INT */
+ /*MX7D_PAD_LPSR_GPIO1_IO06__GPIO1_IO6 0x00000014 /* WACOM PWR ENABLE */
+ /*MX7D_PAD_LPSR_GPIO1_IO00__GPIO1_IO0 0x00000074 /* WACOM RESET */
+ >;
+ };
+};
+
&iomuxc {
pinctrl_brcm_reg: brcmreggrp {
fsl,pins = <
@@ -125,6 +179,13 @@ MX7D_PAD_SAI1_TX_BCLK__GPIO6_IO13 0x14
>;
};
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f
+ MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79
--
2.31.1
Improve the query device fields to be more verbose.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/input/touchscreen/wacom_i2c.c | 64 ++++++++++++++++++---------
1 file changed, 44 insertions(+), 20 deletions(-)
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 4d0c19fbada4..33a3ba110171 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -13,15 +13,32 @@
#include <linux/irq.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
+#include <linux/reset.h>
#include <linux/of.h>
#include <asm/unaligned.h>
-#define WACOM_CMD_QUERY0 0x04
-#define WACOM_CMD_QUERY1 0x00
-#define WACOM_CMD_QUERY2 0x33
-#define WACOM_CMD_QUERY3 0x02
-#define WACOM_CMD_THROW0 0x05
-#define WACOM_CMD_THROW1 0x00
+// Registers
+#define WACOM_COMMAND_LSB 0x04
+#define WACOM_COMMAND_MSB 0x00
+
+#define WACOM_DATA_LSB 0x05
+#define WACOM_DATA_MSB 0x00
+
+// Report types
+#define REPORT_FEATURE 0x30
+
+// Requests / operations
+#define OPCODE_GET_REPORT 0x02
+
+// Power settings
+#define POWER_ON 0x00
+#define POWER_SLEEP 0x01
+
+// Input report ids
+#define WACOM_PEN_DATA_REPORT 2
+#define WACOM_SHINONOME_REPORT 26
+
+#define WACOM_QUERY_REPORT 3
#define WACOM_QUERY_SIZE 22
#define WACOM_DISTANCE_TILT_VERSION 0x30
@@ -51,27 +68,30 @@ static int wacom_query_device(struct i2c_client *client,
struct wacom_features *features)
{
int ret;
- u8 cmd1[] = { WACOM_CMD_QUERY0, WACOM_CMD_QUERY1,
- WACOM_CMD_QUERY2, WACOM_CMD_QUERY3 };
- u8 cmd2[] = { WACOM_CMD_THROW0, WACOM_CMD_THROW1 };
u8 data[WACOM_QUERY_SIZE];
+
+ u8 get_query_data_cmd[] = {
+ WACOM_COMMAND_LSB,
+ WACOM_COMMAND_MSB,
+ REPORT_FEATURE | WACOM_QUERY_REPORT,
+ OPCODE_GET_REPORT,
+ WACOM_DATA_LSB,
+ WACOM_DATA_MSB,
+ };
+
struct i2c_msg msgs[] = {
+ // Request reading of feature ReportID: 3 (Pen Query Data)
{
.addr = client->addr,
.flags = 0,
- .len = sizeof(cmd1),
- .buf = cmd1,
- },
- {
- .addr = client->addr,
- .flags = 0,
- .len = sizeof(cmd2),
- .buf = cmd2,
+ .len = sizeof(get_query_data_cmd),
+ .buf = get_query_data_cmd,
},
+ // Read 21 bytes
{
.addr = client->addr,
.flags = I2C_M_RD,
- .len = sizeof(data),
+ .len = WACOM_QUERY_SIZE - 1,
.buf = data,
},
};
@@ -99,9 +119,13 @@ static int wacom_query_device(struct i2c_client *client,
}
dev_dbg(&client->dev,
- "x_max:%d, y_max:%d, pressure:%d, fw:%d\n",
+ "x_max:%d, y_max:%d, pressure:%d, fw:%d, "
+ "distance: %d, phys distance: %d, "
+ "tilt_x_max: %d, tilt_y_max: %d\n",
features->x_max, features->y_max,
- features->pressure_max, features->fw_version);
+ features->pressure_max, features->fw_version,
+ features->distance_max, features->distance_physical_max,
+ features->tilt_x_max, features->tilt_y_max);
return 0;
}
--
2.31.1
Enable the Wacom I2C in the imx defconfig as it is used by the
reMarkable2 tablet.
Signed-off-by: Alistair Francis <[email protected]>
---
arch/arm/configs/imx_v6_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 079fcd8d1d11..477dac1edc75 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -176,6 +176,7 @@ CONFIG_TOUCHSCREEN_DA9052=y
CONFIG_TOUCHSCREEN_EGALAX=y
CONFIG_TOUCHSCREEN_GOODIX=y
CONFIG_TOUCHSCREEN_ILI210X=y
+CONFIG_TOUCHSCREEN_WACOM_I2C=y
CONFIG_TOUCHSCREEN_MAX11801=y
CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
CONFIG_TOUCHSCREEN_EDT_FT5X06=y
--
2.31.1
To make the code easier to read use macros for the bit masks.
Signed-off-by: Alistair Francis <[email protected]>
---
drivers/input/touchscreen/wacom_i2c.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index fd486b8ef2cc..c6579a1a8d04 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -18,6 +18,14 @@
#include <linux/of.h>
#include <asm/unaligned.h>
+// Bitmasks (for data[3])
+#define WACOM_TIP_SWITCH_bm (1 << 0)
+#define WACOM_BARREL_SWITCH_bm (1 << 1)
+#define WACOM_ERASER_bm (1 << 2)
+#define WACOM_INVERT_bm (1 << 3)
+#define WACOM_BARREL_SWITCH_2_bm (1 << 4)
+#define WACOM_IN_RANGE_bm (1 << 5)
+
// Registers
#define WACOM_COMMAND_LSB 0x04
#define WACOM_COMMAND_MSB 0x00
@@ -148,10 +156,10 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
if (error < 0)
goto out;
- tsw = data[3] & 0x01;
- ers = data[3] & 0x04;
- f1 = data[3] & 0x02;
- f2 = data[3] & 0x10;
+ tsw = data[3] & WACOM_TIP_SWITCH_bm;
+ ers = data[3] & WACOM_ERASER_bm;
+ f1 = data[3] & WACOM_BARREL_SWITCH_bm;
+ f2 = data[3] & WACOM_BARREL_SWITCH_2_bm;
x = le16_to_cpup((__le16 *)&data[4]);
y = le16_to_cpup((__le16 *)&data[6]);
pressure = le16_to_cpup((__le16 *)&data[8]);
--
2.31.1
On 18.08.21 17:49, Alistair Francis wrote:
> Add support for the distance and tilt x/y.
>
> This is based on the out of tree rM2 driver.
>
> Signed-off-by: Alistair Francis <[email protected]>
> ---
> drivers/input/touchscreen/wacom_i2c.c | 35 +++++++++++++++++++++++++--
> 1 file changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
> index 28255c77d426..4d0c19fbada4 100644
> --- a/drivers/input/touchscreen/wacom_i2c.c
> +++ b/drivers/input/touchscreen/wacom_i2c.c
> + /* Signed */
> + tilt_x = le16_to_cpup((__le16 *)&data[11]);
> + tilt_y = le16_to_cpup((__le16 *)&data[13]);
> +
> + distance = le16_to_cpup((__le16 *)&data[15]);
Use get_unaligned_u16 for all three. The existing code doesn't need to do this,
because with the current struct layout, the array is suitable aligned
for 2 byte accesses. You are accessing data at odd indices though, so you
need to use an unaligned accessor.
Cheers,
Ahmad
> +
> if (!wac_i2c->prox)
> wac_i2c->tool = (data[3] & 0x0c) ?
> BTN_TOOL_RUBBER : BTN_TOOL_PEN;
> @@ -127,6 +151,9 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
> input_report_abs(input, ABS_X, x);
> input_report_abs(input, ABS_Y, y);
> input_report_abs(input, ABS_PRESSURE, pressure);
> + input_report_abs(input, ABS_DISTANCE, distance);
> + input_report_abs(input, ABS_TILT_X, tilt_x);
> + input_report_abs(input, ABS_TILT_Y, tilt_y);
> input_sync(input);
>
> out:
> @@ -202,7 +229,11 @@ static int wacom_i2c_probe(struct i2c_client *client,
> input_set_abs_params(input, ABS_Y, 0, features->y_max, 0, 0);
> input_set_abs_params(input, ABS_PRESSURE,
> 0, features->pressure_max, 0, 0);
> -
> + input_set_abs_params(input, ABS_DISTANCE, 0, features->distance_max, 0, 0);
> + input_set_abs_params(input, ABS_TILT_X, -features->tilt_x_max,
> + features->tilt_x_max, 0, 0);
> + input_set_abs_params(input, ABS_TILT_Y, -features->tilt_y_max,
> + features->tilt_y_max, 0, 0);
> input_set_drvdata(input, wac_i2c);
>
> error = devm_request_threaded_irq(dev, client->irq, NULL, wacom_i2c_irq,
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Thu, Aug 19, 2021 at 01:49:33AM +1000, Alistair Francis wrote:
> Allow the device tree properties to flip the tilx, position or distance
> values.
>
> This is required for the stylus to work correctly on the reMarkable 2.
>
> Signed-off-by: Alistair Francis <[email protected]>
> ---
> .../input/touchscreen/wacom,generic.yaml | 18 ++++++++++
> drivers/input/touchscreen/wacom_i2c.c | 33 +++++++++++++++++++
> 2 files changed, 51 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml b/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
> index a8a7f362b0ce..0da63fd92ea1 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
> +++ b/Documentation/devicetree/bindings/input/touchscreen/wacom,generic.yaml
> @@ -25,6 +25,24 @@ properties:
> vdd-supply:
> description: Power Supply
>
> + flip-tilt-x:
> + type: boolean
These all need descriptions.
> +
> + flip-tilt-y:
> + type: boolean
> +
> + flip-pos-x:
> + type: boolean
> +
> + flip-pos-y:
> + type: boolean
> +
> + flip-distance:
> + type: boolean
> +
> + flip-pressure:
> + type: boolean
I don't understand how you flip pressure?
> +
> required:
> - compatible
> - reg
> diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
> index c6579a1a8d04..82b62a768451 100644
> --- a/drivers/input/touchscreen/wacom_i2c.c
> +++ b/drivers/input/touchscreen/wacom_i2c.c
> @@ -72,6 +72,13 @@ struct wacom_i2c {
> u8 data[WACOM_QUERY_SIZE];
> bool prox;
> int tool;
> +
> + bool flip_tilt_x;
> + bool flip_tilt_y;
> + bool flip_pos_x;
> + bool flip_pos_y;
> + bool flip_distance;
> + bool flip_pressure;
> };
>
> static int wacom_query_device(struct i2c_client *client,
> @@ -140,6 +147,20 @@ static int wacom_query_device(struct i2c_client *client,
> return 0;
> }
>
> +#ifdef CONFIG_OF
Use 'if (!IS_ENABLED(CONFIG_OF))' in the function and drop all the
ifdefs.
> +static void wacom_of_read(struct wacom_i2c *wac_i2c)
> +{
> + struct i2c_client *client = wac_i2c->client;
> +
> + wac_i2c->flip_tilt_x = of_property_read_bool(client->dev.of_node, "flip-tilt-x");
> + wac_i2c->flip_tilt_y = of_property_read_bool(client->dev.of_node, "flip-tilt-y");
> + wac_i2c->flip_pos_x = of_property_read_bool(client->dev.of_node, "flip-pos-x");
> + wac_i2c->flip_pos_y = of_property_read_bool(client->dev.of_node, "flip-pos-y");
> + wac_i2c->flip_distance = of_property_read_bool(client->dev.of_node, "flip-distance");
> + wac_i2c->flip_pressure = of_property_read_bool(client->dev.of_node, "flip-pressure");
> +}
> +#endif
> +
> static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
> {
> struct wacom_i2c *wac_i2c = dev_id;
> @@ -176,6 +197,14 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
>
> wac_i2c->prox = data[3] & 0x20;
>
> + // Flip the values based on properties from the device tree
> + pressure = wac_i2c->flip_pressure ? (features->pressure_max - pressure) : pressure;
> + distance = wac_i2c->flip_distance ? -distance : distance;
> + x = wac_i2c->flip_pos_x ? (features->x_max - x) : x;
> + y = wac_i2c->flip_pos_y ? (features->y_max - y) : y;
> + tilt_x = wac_i2c->flip_tilt_x ? -tilt_x : tilt_x;
> + tilt_y = wac_i2c->flip_tilt_y ? -tilt_y : tilt_y;
> +
> touchscreen_report_pos(input, &wac_i2c->props, features->x_max,
> features->y_max, true);
> input_report_key(input, BTN_TOUCH, tsw || ers);
> @@ -303,6 +332,10 @@ static int wacom_i2c_probe(struct i2c_client *client,
> return error;
> }
>
> +#ifdef CONFIG_OF
> + wacom_of_read(wac_i2c);
> +#endif
> +
> return 0;
> }
>
> --
> 2.31.1
>
>