Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH] input: goodix: Add option to power off the controller during suspend
From: Jan Jasper de Kroon @ 2023-03-10 17:00 UTC (permalink / raw)
  To: linux-input; +Cc: Ondřej Jirman, Jan Jasper de Kroon

From: Ondřej Jirman <megi@xff.cz>

For whatever reason the controller is not suspended on Pinephone
by the default procedure. It consumes quite a bit of power (~40mW)
during system sleep, and more when the screen is touched.

Let's power off the controller during system sleep instead.

Signed-off-by: Ondrej Jirman <megi@xff.cz>

input: goodix: Don't disable regulators during suspend

It does no harm to disable them, but on Pinephone we have other
peripherals attached to the same power supplies, whose drivers
will not reference the regulator, so powering down the regulators
from Goodix driver will break those other devices.

Until those drivers gain the regulator support, don't disable
the regulators in Goodix driver.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
Signed-off-by: Jan Jasper de Kroon <jajadekroon@gmail.com>
---
 drivers/input/touchscreen/goodix.c | 23 +++++++++++++++++++++++
 drivers/input/touchscreen/goodix.h |  1 +
 2 files changed, 24 insertions(+)

diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index b348172f19c3..e6d054ede960 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1284,6 +1284,7 @@ static void goodix_disable_regulators(void *arg)
 
 static int goodix_ts_probe(struct i2c_client *client)
 {
+	struct device_node *np = client->dev.of_node;
 	struct goodix_ts_data *ts;
 	const char *cfg_name;
 	int error;
@@ -1303,6 +1304,7 @@ static int goodix_ts_probe(struct i2c_client *client)
 	i2c_set_clientdata(client, ts);
 	init_completion(&ts->firmware_loading_complete);
 	ts->contact_size = GOODIX_CONTACT_SIZE;
+	ts->poweroff_in_suspend = of_property_read_bool(np, "poweroff-in-suspend");
 
 	error = goodix_get_gpio_config(ts);
 	if (error)
@@ -1410,6 +1412,13 @@ static int goodix_suspend(struct device *dev)
 	if (ts->load_cfg_from_disk)
 		wait_for_completion(&ts->firmware_loading_complete);
 
+	if (ts->poweroff_in_suspend) {
+		goodix_free_irq(ts);
+		goodix_irq_direction_output(ts, 0);
+		gpiod_direction_output(ts->gpiod_rst, 0);
+		return 0;
+	}
+
 	/* We need gpio pins to suspend/resume */
 	if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
 		disable_irq(client->irq);
@@ -1455,6 +1464,20 @@ static int goodix_resume(struct device *dev)
 	u8 config_ver;
 	int error;
 
+	if (ts->poweroff_in_suspend) {
+		error = goodix_reset(ts);
+		if (error) {
+			dev_err(dev, "Controller reset failed.\n");
+			return error;
+		}
+
+		error = goodix_request_irq(ts);
+		if (error)
+			return error;
+
+		return 0;
+	}
+
 	if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
 		enable_irq(client->irq);
 		return 0;
diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
index 87797cc88b32..dc358bcda698 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -104,6 +104,7 @@ struct goodix_ts_data {
 	u8 main_clk[GOODIX_MAIN_CLK_LEN];
 	int bak_ref_len;
 	u8 *bak_ref;
+	bool poweroff_in_suspend;
 };
 
 int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);
-- 
2.34.3


^ permalink raw reply related

* Re: [PATCH] input: goodix: Add option to power off the controller during suspend
From: Ondřej Jirman @ 2023-03-10 21:19 UTC (permalink / raw)
  To: Jan Jasper de Kroon; +Cc: linux-input
In-Reply-To: <20230310170026.415739-1-jajadekroon@gmail.com>

Hi Jan,

On Fri, Mar 10, 2023 at 06:00:26PM +0100, Jan Jasper de Kroon wrote:
> From: Ondřej Jirman <megi@xff.cz>
> 
> For whatever reason the controller is not suspended on Pinephone
> by the default procedure. It consumes quite a bit of power (~40mW)
> during system sleep, and more when the screen is touched.
> 
> Let's power off the controller during system sleep instead.
> 
> Signed-off-by: Ondrej Jirman <megi@xff.cz>
> 
> input: goodix: Don't disable regulators during suspend

I don't think you should concatenate commit messages like this.
Also what the change actually does is that it holds the controller
in reset during sleep, and doesn't try to power it off.

> It does no harm to disable them, but on Pinephone we have other
> peripherals attached to the same power supplies, whose drivers
> will not reference the regulator, so powering down the regulators
> from Goodix driver will break those other devices.
> 
> Until those drivers gain the regulator support, don't disable
> the regulators in Goodix driver.
> 
> Signed-off-by: Ondrej Jirman <megi@xff.cz>
> Signed-off-by: Jan Jasper de Kroon <jajadekroon@gmail.com>
> ---
>  drivers/input/touchscreen/goodix.c | 23 +++++++++++++++++++++++
>  drivers/input/touchscreen/goodix.h |  1 +
>  2 files changed, 24 insertions(+)
> 
> diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
> index b348172f19c3..e6d054ede960 100644
> --- a/drivers/input/touchscreen/goodix.c
> +++ b/drivers/input/touchscreen/goodix.c
> @@ -1284,6 +1284,7 @@ static void goodix_disable_regulators(void *arg)
>  
>  static int goodix_ts_probe(struct i2c_client *client)
>  {
> +	struct device_node *np = client->dev.of_node;
>  	struct goodix_ts_data *ts;
>  	const char *cfg_name;
>  	int error;
> @@ -1303,6 +1304,7 @@ static int goodix_ts_probe(struct i2c_client *client)
>  	i2c_set_clientdata(client, ts);
>  	init_completion(&ts->firmware_loading_complete);
>  	ts->contact_size = GOODIX_CONTACT_SIZE;
> +	ts->poweroff_in_suspend = of_property_read_bool(np, "poweroff-in-suspend");

If you're adding a new DT property, you need to document it in the device tree
bindings of the driver.

>  	error = goodix_get_gpio_config(ts);
>  	if (error)
> @@ -1410,6 +1412,13 @@ static int goodix_suspend(struct device *dev)
>  	if (ts->load_cfg_from_disk)
>  		wait_for_completion(&ts->firmware_loading_complete);
>  
> +	if (ts->poweroff_in_suspend) {
> +		goodix_free_irq(ts);
> +		goodix_irq_direction_output(ts, 0);
> +		gpiod_direction_output(ts->gpiod_rst, 0);
> +		return 0;
> +	}
> +
>  	/* We need gpio pins to suspend/resume */
>  	if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
>  		disable_irq(client->irq);
> @@ -1455,6 +1464,20 @@ static int goodix_resume(struct device *dev)
>  	u8 config_ver;
>  	int error;
>  
> +	if (ts->poweroff_in_suspend) {
> +		error = goodix_reset(ts);
> +		if (error) {
> +			dev_err(dev, "Controller reset failed.\n");
> +			return error;
> +		}
> +
> +		error = goodix_request_irq(ts);
> +		if (error)
> +			return error;
> +
> +		return 0;
> +	}
> +
>  	if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
>  		enable_irq(client->irq);
>  		return 0;
> diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
> index 87797cc88b32..dc358bcda698 100644
> --- a/drivers/input/touchscreen/goodix.h
> +++ b/drivers/input/touchscreen/goodix.h
> @@ -104,6 +104,7 @@ struct goodix_ts_data {
>  	u8 main_clk[GOODIX_MAIN_CLK_LEN];
>  	int bak_ref_len;
>  	u8 *bak_ref;
> +	bool poweroff_in_suspend;

Hold reset in suspend?

kind regards,
	o.

>  };
>  
>  int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);
> -- 
> 2.34.3
> 

^ permalink raw reply

* Re: BUG: hid-sensor-ids code includes binary data in device name
From: Todd Brandt @ 2023-03-10 23:35 UTC (permalink / raw)
  To: Philipp Jungkamp, srinivas pandruvada, linux-input, linux-kernel,
	Even Xu
  Cc: Jonathan.Cameron, jkosina, todd.e.brandt
In-Reply-To: <424882ed2a79a641f88b5f2d1ed5a5d3d4fe98d9.camel@gmx.net>

On Fri, 2023-03-10 at 15:35 +0100, Philipp Jungkamp wrote:
> Hello,
> 
> on v3 of the patchset I had this comment on the 'real_usage'
> initialization:
> 
> > > -	char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
> > > +	char real_usage[HID_SENSOR_USAGE_LENGTH];
> > >  	struct platform_device *custom_pdev;
> > >  	const char *dev_name;
> > >  	char *c;
> > > 
> > > -	/* copy real usage id */
> > > -	memcpy(real_usage, known_sensor_luid[index], 4);
> > > +	memcpy(real_usage, match->luid, 4);
> > > +	real_usage[4] = '\0';
> > 
> > Why the change in approach for setting the NULL character?
> > Doesn't seem relevant to main purpose of this patch.
> 
> Based on the comment, I changed that in the final v4 revision to:
> 
> > -       char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
> > +       char real_usage[HID_SENSOR_USAGE_LENGTH];
> >         struct platform_device *custom_pdev;
> >         const char *dev_name;
> >         char *c;
> >  
> > -       /* copy real usage id */
> > -       memcpy(real_usage, known_sensor_luid[index], 4);
> > +       memcpy(real_usage, match->luid, 4);
> 
> I ommitted the line adding the null terminator to the string but kept
> that I didn't initialize the 'real_usage' as { 0 } anymore. The
> string
> now misses the null terminator which leads to the broken utf-8.
> 
> The simple fix is to reintroduce the 0 initialization in
> hid_sensor_register_platform_device. E.g.
> 
> -	char real_usage[HID_SENSOR_USAGE_LENGTH];
> +	char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
> 

I didn't realize that the issue was a buffer overrun. I tested the
kernel built with this simple fix and it works ok now. i.e. this patch
is is all that's needed:

diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-
custom.c
index 3e3f89e01d81..d85398721659 100644
--- a/drivers/hid/hid-sensor-custom.c
+++ b/drivers/hid/hid-sensor-custom.c
@@ -940,7 +940,7 @@ hid_sensor_register_platform_device(struct
platform_device *pdev,
                                    struct hid_sensor_hub_device
*hsdev,
                                    const struct
hid_sensor_custom_match *match)
 {
-       char real_usage[HID_SENSOR_USAGE_LENGTH];
+       char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
        struct platform_device *custom_pdev;
        const char *dev_name;
        char *c;

> Where do I need to submit a patch for this? And on which tree should
> I
> base the patch?
> 

The change is so small it shouldn't require any rebasing. Just send the
patch to these emails (from MAINTAINERS):

HID SENSOR HUB DRIVERS
M:  Jiri Kosina <jikos@kernel.org>
M:  Jonathan Cameron <jic23@kernel.org>
M:  Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L:  linux-input@vger.kernel.org
L:  linux-iio@vger.kernel.org

> I'm sorry for the problems my patch caused.
> 

No problem. It actually made sleepgraph better because it exposed a bug
in the ftrace processing code. I wasn't properly handling the corner
case where ftrace had binary data in it.

> Regards,
> Philipp Jungkamp
> 
> On Fri, 2023-03-10 at 01:51 -0800, srinivas pandruvada wrote:
> > +Even
> > 
> > On Thu, 2023-03-09 at 15:33 -0800, Todd Brandt wrote:
> > > Hi all, I've run into an issue in 6.3.0-rc1 that causes problems
> > > with
> > > ftrace and I've bisected it to this commit:
> > > 
> > > commit 98c062e8245199fa9121141a0bf1035dc45ae90e (HEAD,
> > > refs/bisect/bad)
> > > Author: Philipp Jungkamp p.jungkamp@gmx.net
> > > Date:   Fri Nov 25 00:38:38 2022 +0100
> > > 
> > >     HID: hid-sensor-custom: Allow more custom iio sensors
> > > 
> > >     The known LUID table for established/known custom HID sensors
> > > was
> > >     limited to sensors with "INTEL" as manufacturer. But some
> > > vendors
> > > such
> > >     as Lenovo also include fairly standard iio sensors (e.g.
> > > ambient
> > > light)
> > >     in their custom sensors.
> > > 
> > >     Expand the known custom sensors table by a tag used for the
> > > platform
> > >     device name and match sensors based on the LUID as well as
> > > optionally
> > >     on model and manufacturer properties.
> > > 
> > >     Signed-off-by: Philipp Jungkamp p.jungkamp@gmx.net
> > >     Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com
> > >     Acked-by: Srinivas Pandruvada
> > > srinivas.pandruvada@linux.intel.com
> > >     Signed-off-by: Jiri Kosina jkosina@suse.cz
> > > 
> > > You're using raw data as part of the devname in the "real_usage"
> > > string, but it includes chars other than ASCII, and those chars
> > > end
> > > up being printed out in the ftrace log which is meant to be ASCII
> > > only.
> > > 
> > > -       /* HID-SENSOR-INT-REAL_USAGE_ID */
> > > -       dev_name = kasprintf(GFP_KERNEL, "HID-SENSOR-INT-%s",
> > > real_usage);
> > > +       /* HID-SENSOR-TAG-REAL_USAGE_ID */
> > > +       dev_name = kasprintf(GFP_KERNEL, "HID-SENSOR-%s-%s",
> > > +                            match->tag, real_usage);
> > > 
> > > My sleepgraph tool started to crash because it read these lines
> > > from
> > > ftrace:
> > > 
> > > device_pm_callback_start: platform HID-SENSOR-INT-020b?.39.auto,
> > > parent: 001F:8087:0AC2.0003, [suspend]
> > > device_pm_callback_end: platform HID-SENSOR-INT-020b?.39.auto,
> > > err=0
> > > 
> > 
> > Here tag is:
> > .tag = "INT",
> > .luid = "020B000000000000",
> > 
> > 
> > The LUID is still a string. Probably too long for a dev_name.
> > 
> > Even,
> > 
> > Please check.
> > 
> > Thanks.
> > Srinivas
> > 
> > 
> > > The "HID-SENSOR-INT-020b?.39.auto" string includes a binary char
> > > that
> > > kills
> > > python3 code that loops through an ascii file as such:
> > > 
> > >   File "/usr/bin/sleepgraph", line 5579, in executeSuspend
> > >     for line in fp:
> > >   File "/usr/lib/python3.10/codecs.py", line 322, in decode
> > >     (result, consumed) = self._buffer_decode(data, self.errors,
> > > final)
> > > UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in
> > > position
> > > 1568: invalid start byte
> > > 
> > > I've updated sleepgraph to handle random non-ascii chars, but
> > > other
> > > tools
> > > may suffer the same fate. Can you rewrite this to ensure that no
> > > binary
> > > chars make it into the devname?
> > > 
> 
> 


^ permalink raw reply related

* [PATCH] Fix buffer overrun in HID-SENSOR name.
From: Todd Brandt @ 2023-03-10 23:54 UTC (permalink / raw)
  To: linux-input, linux-iio, linux-kernel
  Cc: todd.e.brandt, todd.e.brandt, srinivas.pandruvada, jic23, jikos,
	p.jungkamp

Philipp Jungkamp created this fix, I'm simply submitting it. I've
verified it fixes bugzilla issue 217169.

Reported-and-tested-by: Todd Brandt <todd.e.brandt@linux.intel.com>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217169
Signed-off-by: Todd Brandt <todd.e.brandt@intel.com>
---
 drivers/hid/hid-sensor-custom.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
index 3e3f89e01d81..d85398721659 100644
--- a/drivers/hid/hid-sensor-custom.c
+++ b/drivers/hid/hid-sensor-custom.c
@@ -940,7 +940,7 @@ hid_sensor_register_platform_device(struct platform_device *pdev,
 				    struct hid_sensor_hub_device *hsdev,
 				    const struct hid_sensor_custom_match *match)
 {
-	char real_usage[HID_SENSOR_USAGE_LENGTH];
+	char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
 	struct platform_device *custom_pdev;
 	const char *dev_name;
 	char *c;
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH] Fix buffer overrun in HID-SENSOR name.
From: Philipp Jungkamp @ 2023-03-11  0:53 UTC (permalink / raw)
  To: Todd Brandt, linux-input, linux-iio, linux-kernel
  Cc: todd.e.brandt, srinivas.pandruvada, jic23, jikos
In-Reply-To: <20230310235414.12467-1-todd.e.brandt@intel.com>

This is exactly the fix I proposed. Thank you for testing and properly
submitting it.

Regards,
Philipp Jungkamp

On Fri, 2023-03-10 at 15:54 -0800, Todd Brandt wrote:
> Philipp Jungkamp created this fix, I'm simply submitting it. I've
> verified it fixes bugzilla issue 217169.
> 
> Reported-and-tested-by: Todd Brandt <todd.e.brandt@linux.intel.com>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=217169
> Signed-off-by: Todd Brandt <todd.e.brandt@intel.com>
> ---
>  drivers/hid/hid-sensor-custom.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-
> sensor-custom.c
> index 3e3f89e01d81..d85398721659 100644
> --- a/drivers/hid/hid-sensor-custom.c
> +++ b/drivers/hid/hid-sensor-custom.c
> @@ -940,7 +940,7 @@ hid_sensor_register_platform_device(struct
> platform_device *pdev,
>                                     struct hid_sensor_hub_device
> *hsdev,
>                                     const struct
> hid_sensor_custom_match *match)
>  {
> -       char real_usage[HID_SENSOR_USAGE_LENGTH];
> +       char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
>         struct platform_device *custom_pdev;
>         const char *dev_name;
>         char *c;


^ permalink raw reply

* [PATCH HID for-next v1 0/1] HID: shield
From: Rahul Rameshbabu @ 2023-03-11  1:09 UTC (permalink / raw)
  To: linux-input; +Cc: Jiri Kosina, Benjamin Tissoires, Rahul Rameshbabu

Hi.

This is an initial driver implementation for supporting NVIDIA SHIELD
peripherals. Currently supports the following functionality for the
THUNDERSTRIKE (SHIELD 2017) controller.

  - Haptics (ff_memless)
  - Serial number query (sysfs)
  - Hardware information query (sysfs)
  - Firmware version query (sysfs)

Rahul Rameshbabu (1):
  HID: shield: Initial driver implementation with Thunderstrike support

 MAINTAINERS              |   6 +
 drivers/hid/Kconfig      |  18 ++
 drivers/hid/Makefile     |   1 +
 drivers/hid/hid-ids.h    |   3 +
 drivers/hid/hid-shield.c | 587 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 615 insertions(+)
 create mode 100644 drivers/hid/hid-shield.c

-- 
2.38.3


^ permalink raw reply

* [PATCH HID for-next v1 1/1] HID: shield: Initial driver implementation with Thunderstrike support
From: Rahul Rameshbabu @ 2023-03-11  1:09 UTC (permalink / raw)
  To: linux-input; +Cc: Jiri Kosina, Benjamin Tissoires, Rahul Rameshbabu
In-Reply-To: <20230311010940.57585-1-rrameshbabu@nvidia.com>

Supports the Thunderstrike (SHIELD 2017) controller. Implements support for
the Thunderstrike HOSTCMD firmware interface. Adds sysfs attributes about a
SHIELD device and introduces haptics support for controllers.

Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
---
 MAINTAINERS              |   6 +
 drivers/hid/Kconfig      |  18 ++
 drivers/hid/Makefile     |   1 +
 drivers/hid/hid-ids.h    |   3 +
 drivers/hid/hid-shield.c | 587 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 615 insertions(+)
 create mode 100644 drivers/hid/hid-shield.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a36df9ed283d..e8064131466d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9234,6 +9234,12 @@ F:	drivers/hid/hid-sensor-*
 F:	drivers/iio/*/hid-*
 F:	include/linux/hid-sensor-*
 
+HID SHIELD DRIVER
+M:	Rahul Rameshbabu <rrameshbabu@nvidia.com>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	drivers/hid/hid-shield.c
+
 HID VRC-2 CAR CONTROLLER DRIVER
 M:	Marcus Folkesson <marcus.folkesson@gmail.com>
 L:	linux-input@vger.kernel.org
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index e2a5d30c8895..a886e620a214 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -976,6 +976,24 @@ config HID_SEMITEK
 	- Woo-dy
 	- X-Bows Nature/Knight
 
+config HID_SHIELD
+	tristate "SHIELD HID Driver"
+	depends on USB_HID
+	depends on BT_HIDP
+	help
+	Support for NVIDIA SHIELD accessories.
+
+	Supported devices:
+	- Thunderstrike (NVIDIA SHIELD Controller 2017)
+
+config SHIELD_FF
+	bool "SHIELD force feedback support"
+	depends on HID_SHIELD
+	select INPUT_FF_MEMLESS
+	help
+	Say Y here if you would like to enable force feedback support for
+	NVIDIA SHIELD accessories with haptics capabilities.
+
 config HID_SIGMAMICRO
 	tristate "SiGma Micro-based keyboards"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e8014c1a2f8b..7d79c91f2503 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_HID_RMI)		+= hid-rmi.o
 obj-$(CONFIG_HID_SAITEK)	+= hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SEMITEK)	+= hid-semitek.o
+obj-$(CONFIG_HID_SHIELD)	+= hid-shield.o
 obj-$(CONFIG_HID_SIGMAMICRO)	+= hid-sigmamicro.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 82713ef3aaa6..1cfec6bd542d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -987,6 +987,9 @@
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18   0x0014
 #define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500
 
+#define USB_VENDOR_ID_NVIDIA				0x0955
+#define USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER	0x7214
+
 #define USB_VENDOR_ID_ONTRAK		0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
diff --git a/drivers/hid/hid-shield.c b/drivers/hid/hid-shield.c
new file mode 100644
index 000000000000..b29af579868f
--- /dev/null
+++ b/drivers/hid/hid-shield.c
@@ -0,0 +1,587 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.  All rights reserved.
+ *
+ *  HID driver for NVIDIA SHIELD peripherals.
+ */
+
+#include <linux/hid.h>
+#include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include "hid-ids.h"
+
+#define NOT_INIT_STR "NOT INITIALIZED"
+
+enum {
+	SHIELD_FW_VERSION_INITIALIZED = 0,
+	SHIELD_BOARD_INFO_INITIALIZED,
+};
+
+enum {
+	THUNDERSTRIKE_FW_VERSION_UPDATE = 0,
+	THUNDERSTRIKE_BOARD_INFO_UPDATE,
+	THUNDERSTRIKE_HAPTICS_UPDATE,
+};
+
+enum {
+	THUNDERSTRIKE_HOSTCMD_REPORT_SIZE = 33,
+	THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID = 0x4,
+	THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID = 0x3,
+};
+
+enum {
+	THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION = 1,
+	THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO = 16,
+	THUNDERSTRIKE_HOSTCMD_ID_USB_INIT = 53,
+	THUNDERSTRIKE_HOSTCMD_ID_HAPTICS = 57,
+	THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT = 58,
+};
+
+struct thunderstrike_hostcmd_board_info {
+	__le16 revision;
+	__le16 serial[7];
+};
+
+struct thunderstrike_hostcmd_haptics {
+	u8 motor_left;
+	u8 motor_right;
+};
+
+struct thunderstrike_hostcmd_resp_report {
+	u8 report_id; /* THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID */
+	u8 cmd_id;
+	u8 reserved_at_10;
+
+	union {
+		struct thunderstrike_hostcmd_board_info board_info;
+		struct thunderstrike_hostcmd_haptics motors;
+		__le16 fw_version;
+		u8 payload[30];
+	};
+} __packed;
+static_assert(sizeof(struct thunderstrike_hostcmd_resp_report) ==
+	      THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);
+
+struct thunderstrike_hostcmd_req_report {
+	u8 report_id; /* THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID */
+	u8 cmd_id;
+	u8 reserved_at_10;
+
+	struct {
+		u8 update;
+		struct thunderstrike_hostcmd_haptics motors;
+	} haptics;
+	u8 reserved_at_30[27];
+} __packed;
+static_assert(sizeof(struct thunderstrike_hostcmd_req_report) ==
+	      THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);
+
+/* Common struct for shield accessories. */
+struct shield_device {
+	struct hid_device *hdev;
+
+	unsigned long initialized_flags;
+	const char *codename;
+	u16 fw_version;
+	struct {
+		u16 revision;
+		char serial_number[15];
+	} board_info;
+};
+
+struct thunderstrike {
+	struct shield_device base;
+
+	/* Sub-devices */
+	struct input_dev *haptics_dev;
+
+	/* Resources */
+	void *req_report_dmabuf;
+	unsigned long update_flags;
+	struct thunderstrike_hostcmd_haptics haptics_val;
+	spinlock_t haptics_update_lock;
+	struct work_struct hostcmd_req_work;
+};
+
+static inline void thunderstrike_hostcmd_req_report_init(
+	struct thunderstrike_hostcmd_req_report *report, u8 cmd_id)
+{
+	memset(report, 0, sizeof(*report));
+	report->report_id = THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID;
+	report->cmd_id = cmd_id;
+}
+
+static inline void shield_strrev(char *dest, size_t len, u16 rev)
+{
+	dest[0] = ('A' - 1) + (rev >> 8);
+	snprintf(&dest[1], len - 1, "%02X", 0xff & rev);
+}
+
+static struct input_dev *shield_allocate_input_dev(struct hid_device *hdev,
+						   const char *name_suffix)
+{
+	struct input_dev *idev;
+
+	idev = input_allocate_device();
+	if (!idev)
+		goto err_device;
+
+	idev->id.bustype = hdev->bus;
+	idev->id.vendor = hdev->vendor;
+	idev->id.product = hdev->product;
+	idev->id.version = hdev->version;
+	idev->uniq = hdev->uniq;
+	idev->name = devm_kasprintf(&idev->dev, GFP_KERNEL, "%s %s", hdev->name,
+				    name_suffix);
+	if (!idev->name)
+		goto err_name;
+
+	input_set_drvdata(idev, hdev);
+
+	return idev;
+
+err_name:
+	input_free_device(idev);
+err_device:
+	return ERR_PTR(-ENOMEM);
+}
+
+static struct input_dev *shield_haptics_create(
+	struct shield_device *dev,
+	int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
+{
+	struct input_dev *haptics;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_SHIELD_FF))
+		return NULL;
+
+	haptics = shield_allocate_input_dev(dev->hdev, "Haptics");
+	if (IS_ERR(haptics))
+		return haptics;
+
+	input_set_capability(haptics, EV_FF, FF_RUMBLE);
+	input_ff_create_memless(haptics, NULL, play_effect);
+
+	ret = input_register_device(haptics);
+	if (ret)
+		goto err;
+
+	return haptics;
+
+ err:
+	input_free_device(haptics);
+	return ERR_PTR(ret);
+}
+
+static inline void thunderstrike_send_hostcmd_request(struct thunderstrike *ts)
+{
+	struct thunderstrike_hostcmd_req_report *report = ts->req_report_dmabuf;
+	struct shield_device *shield_dev = &ts->base;
+	int ret;
+
+	ret = hid_hw_raw_request(shield_dev->hdev, report->report_id,
+				 ts->req_report_dmabuf,
+				 THUNDERSTRIKE_HOSTCMD_REPORT_SIZE,
+				 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+
+	if (ret < 0) {
+		hid_err(shield_dev->hdev,
+			"Failed to output Thunderstrike HOSTCMD request HID report due to %pe\n",
+			ERR_PTR(ret));
+	}
+}
+
+void thunderstrike_hostcmd_req_work_handler(struct work_struct *work)
+{
+	struct thunderstrike *ts =
+		container_of(work, struct thunderstrike, hostcmd_req_work);
+	struct thunderstrike_hostcmd_req_report *report;
+	unsigned long flags;
+
+	report = ts->req_report_dmabuf;
+
+	if (test_and_clear_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags)) {
+		thunderstrike_hostcmd_req_report_init(
+			report, THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION);
+		thunderstrike_send_hostcmd_request(ts);
+	}
+
+	if (test_and_clear_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags)) {
+		thunderstrike_hostcmd_req_report_init(
+			report, THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO);
+		thunderstrike_send_hostcmd_request(ts);
+	}
+
+	if (test_and_clear_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags)) {
+		thunderstrike_hostcmd_req_report_init(
+			report, THUNDERSTRIKE_HOSTCMD_ID_HAPTICS);
+
+		report->haptics.update = 1;
+		spin_lock_irqsave(&ts->haptics_update_lock, flags);
+		report->haptics.motors = ts->haptics_val;
+		spin_unlock_irqrestore(&ts->haptics_update_lock, flags);
+
+		thunderstrike_send_hostcmd_request(ts);
+	}
+}
+
+static inline void thunderstrike_request_firmware_version(struct thunderstrike *ts)
+{
+	set_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags);
+	schedule_work(&ts->hostcmd_req_work);
+}
+
+static inline void thunderstrike_request_board_info(struct thunderstrike *ts)
+{
+	set_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags);
+	schedule_work(&ts->hostcmd_req_work);
+}
+
+static inline int
+thunderstrike_update_haptics(struct thunderstrike *ts,
+			     struct thunderstrike_hostcmd_haptics *motors)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ts->haptics_update_lock, flags);
+	ts->haptics_val = *motors;
+	spin_unlock_irqrestore(&ts->haptics_update_lock, flags);
+
+	set_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags);
+	schedule_work(&ts->hostcmd_req_work);
+
+	return 0;
+}
+
+static int thunderstrike_play_effect(struct input_dev *idev, void *data,
+				     struct ff_effect *effect)
+{
+	struct hid_device *hdev = input_get_drvdata(idev);
+	struct thunderstrike_hostcmd_haptics motors;
+	struct shield_device *shield_dev;
+	struct thunderstrike *ts;
+
+	if (effect->type != FF_RUMBLE)
+		return 0;
+
+	shield_dev = hid_get_drvdata(hdev);
+	ts = container_of(shield_dev, struct thunderstrike, base);
+
+	/* Thunderstrike motor values range from 0 to 32 inclusively */
+	motors.motor_left = effect->u.rumble.strong_magnitude / 2047;
+	motors.motor_right = effect->u.rumble.weak_magnitude / 2047;
+
+	hid_dbg(hdev, "Thunderstrike FF_RUMBLE request, left: %u right: %u\n",
+		motors.motor_left, motors.motor_right);
+
+	return thunderstrike_update_haptics(ts, &motors);
+}
+
+static void
+thunderstrike_parse_fw_version_payload(struct shield_device *shield_dev,
+				       __le16 fw_version)
+{
+	shield_dev->fw_version = le16_to_cpu(fw_version);
+
+	set_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags);
+
+	hid_dbg(shield_dev->hdev, "Thunderstrike firmware version 0x%04X\n",
+		shield_dev->fw_version);
+}
+
+static void
+thunderstrike_parse_board_info_payload(struct shield_device *shield_dev,
+				       struct thunderstrike_hostcmd_board_info *board_info)
+{
+	char board_revision_str[4];
+	int i;
+
+	shield_dev->board_info.revision = le16_to_cpu(board_info->revision);
+	for (i = 0; i < 7; ++i) {
+		u16 val = le16_to_cpu(board_info->serial[i]);
+
+		shield_dev->board_info.serial_number[2 * i] = val & 0xFF;
+		shield_dev->board_info.serial_number[2 * i + 1] = val >> 8;
+	}
+	shield_dev->board_info.serial_number[14] = '\0';
+
+	set_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags);
+
+	shield_strrev(board_revision_str, 4, shield_dev->board_info.revision);
+	hid_dbg(shield_dev->hdev,
+		"Thunderstrike BOARD_REVISION_%s (0x%04X) S/N: %s\n",
+		board_revision_str, shield_dev->board_info.revision,
+		shield_dev->board_info.serial_number);
+}
+
+static inline void
+thunderstrike_parse_haptics_payload(struct shield_device *shield_dev,
+				    struct thunderstrike_hostcmd_haptics *haptics)
+{
+	hid_dbg(shield_dev->hdev,
+		"Thunderstrike haptics HOSTCMD response, left: %u right: %u\n",
+		haptics->motor_left, haptics->motor_right);
+}
+
+static int thunderstrike_parse_report(struct shield_device *shield_dev,
+				      struct hid_report *report, u8 *data,
+				      int size)
+{
+	struct thunderstrike_hostcmd_resp_report *hostcmd_resp_report;
+	struct thunderstrike *ts =
+		container_of(shield_dev, struct thunderstrike, base);
+	struct hid_device *hdev = shield_dev->hdev;
+
+	switch (report->id) {
+	case THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID:
+		if (size != THUNDERSTRIKE_HOSTCMD_REPORT_SIZE) {
+			hid_err(hdev,
+				"Encountered Thunderstrike HOSTCMD HID report with unexpected size %d\n",
+				size);
+			return -EINVAL;
+		}
+
+		hostcmd_resp_report =
+			(struct thunderstrike_hostcmd_resp_report *)data;
+
+		switch (hostcmd_resp_report->cmd_id) {
+		case THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION:
+			thunderstrike_parse_fw_version_payload(
+				shield_dev, hostcmd_resp_report->fw_version);
+			break;
+		case THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO:
+			thunderstrike_parse_board_info_payload(
+				shield_dev, &hostcmd_resp_report->board_info);
+			break;
+		case THUNDERSTRIKE_HOSTCMD_ID_HAPTICS:
+			thunderstrike_parse_haptics_payload(
+				shield_dev, &hostcmd_resp_report->motors);
+			break;
+
+		case THUNDERSTRIKE_HOSTCMD_ID_USB_INIT:
+		case THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT:
+			/* May block HOSTCMD requests till received initially */
+			thunderstrike_request_firmware_version(ts);
+			thunderstrike_request_board_info(ts);
+			/* Only HOSTCMD that can be triggered without a request */
+			return 0;
+		default:
+			hid_warn(hdev,
+				 "Unhandled Thunderstrike HOSTCMD id %d\n",
+				 hostcmd_resp_report->cmd_id);
+			return -ENOENT;
+		}
+
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static struct shield_device *thunderstrike_create(struct hid_device *hdev)
+{
+	struct shield_device *shield_dev;
+	struct thunderstrike *ts;
+
+	ts = devm_kzalloc(&hdev->dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return ERR_PTR(-ENOMEM);
+
+	ts->req_report_dmabuf = devm_kzalloc(
+		&hdev->dev, THUNDERSTRIKE_HOSTCMD_REPORT_SIZE, GFP_KERNEL);
+	if (!ts->req_report_dmabuf)
+		return ERR_PTR(-ENOMEM);
+
+	shield_dev = &ts->base;
+	shield_dev->hdev = hdev;
+	shield_dev->codename = "Thunderstrike";
+
+	spin_lock_init(&ts->haptics_update_lock);
+	INIT_WORK(&ts->hostcmd_req_work, thunderstrike_hostcmd_req_work_handler);
+
+	hid_set_drvdata(hdev, shield_dev);
+
+	ts->haptics_dev = shield_haptics_create(shield_dev, thunderstrike_play_effect);
+	if (IS_ERR(ts->haptics_dev))
+		return ERR_CAST(ts->haptics_dev);
+
+	hid_info(hdev, "Registered Thunderstrike controller\n");
+	return shield_dev;
+}
+
+static ssize_t firmware_version_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct hid_device *hdev = to_hid_device(dev);
+	struct shield_device *shield_dev;
+	int ret;
+
+	shield_dev = hid_get_drvdata(hdev);
+
+	if (test_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags))
+		ret = sysfs_emit(buf, "0x%04X\n", shield_dev->fw_version);
+	else
+		ret = sysfs_emit(buf, NOT_INIT_STR "\n");
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(firmware_version);
+
+static ssize_t hardware_version_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct hid_device *hdev = to_hid_device(dev);
+	struct shield_device *shield_dev;
+	char board_revision_str[4];
+	int ret;
+
+	shield_dev = hid_get_drvdata(hdev);
+
+	if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags)) {
+		shield_strrev(board_revision_str, 4, shield_dev->board_info.revision);
+		ret = sysfs_emit(buf, "%s BOARD_REVISION_%s (0x%04X)\n",
+				 shield_dev->codename, board_revision_str,
+				 shield_dev->board_info.revision);
+	} else
+		ret = sysfs_emit(buf, NOT_INIT_STR "\n");
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(hardware_version);
+
+static ssize_t serial_number_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct hid_device *hdev = to_hid_device(dev);
+	struct shield_device *shield_dev;
+	int ret;
+
+	shield_dev = hid_get_drvdata(hdev);
+
+	if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags))
+		ret = sysfs_emit(buf, "%s\n", shield_dev->board_info.serial_number);
+	else
+		ret = sysfs_emit(buf, NOT_INIT_STR "\n");
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(serial_number);
+
+static struct attribute *shield_device_attrs[] = {
+	&dev_attr_firmware_version.attr,
+	&dev_attr_hardware_version.attr,
+	&dev_attr_serial_number.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(shield_device);
+
+static int shield_raw_event(struct hid_device *hdev, struct hid_report *report,
+			    u8 *data, int size)
+{
+	struct shield_device *dev = hid_get_drvdata(hdev);
+
+	return thunderstrike_parse_report(dev, report, data, size);
+}
+
+static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	struct shield_device *shield_dev = NULL;
+	struct thunderstrike *ts;
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "Parse failed\n");
+		return ret;
+	}
+
+	switch (id->product) {
+	case USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER:
+		shield_dev = thunderstrike_create(hdev);
+		break;
+	}
+
+	if (unlikely(!shield_dev)) {
+		hid_err(hdev, "Failed to identify SHIELD device\n");
+		return -ENODEV;
+	}
+	if (IS_ERR(shield_dev)) {
+		hid_err(hdev, "Failed to create SHIELD device\n");
+		return PTR_ERR(shield_dev);
+	}
+
+	ts = container_of(shield_dev, struct thunderstrike, base);
+
+	ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT);
+	if (ret) {
+		hid_err(hdev, "Failed to start HID device\n");
+		goto err_haptics;
+	}
+
+	ret = hid_hw_open(hdev);
+	if (ret) {
+		hid_err(hdev, "Failed to open HID device\n");
+		goto err_stop;
+	}
+
+	thunderstrike_request_firmware_version(ts);
+	thunderstrike_request_board_info(ts);
+
+	return ret;
+
+err_stop:
+	hid_hw_stop(hdev);
+err_haptics:
+	if (ts->haptics_dev)
+		input_unregister_device(ts->haptics_dev);
+	return ret;
+}
+
+static void shield_remove(struct hid_device *hdev)
+{
+	struct shield_device *dev = hid_get_drvdata(hdev);
+	struct thunderstrike *ts;
+
+	ts = container_of(dev, struct thunderstrike, base);
+
+	hid_hw_close(hdev);
+	if (ts->haptics_dev)
+		input_unregister_device(ts->haptics_dev);
+	cancel_work_sync(&ts->hostcmd_req_work);
+	hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id shield_devices[] = {
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NVIDIA,
+			       USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NVIDIA,
+			 USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) },
+	{}
+};
+MODULE_DEVICE_TABLE(hid, shield_devices);
+
+static struct hid_driver shield_driver = {
+	.name         = "shield",
+	.id_table     = shield_devices,
+	.probe        = shield_probe,
+	.remove       = shield_remove,
+	.raw_event    = shield_raw_event,
+	.driver = {
+		.dev_groups = shield_device_groups,
+	},
+};
+module_hid_driver(shield_driver);
+
+MODULE_AUTHOR("Rahul Rameshbabu <rrameshbabu@nvidia.com>");
+MODULE_DESCRIPTION("HID Driver for NVIDIA SHIELD peripherals.");
+MODULE_LICENSE("GPL");
-- 
2.38.3


^ permalink raw reply related

* Re: [PATCH v2 2/2] Input: hideep - Optionally reset controller work mode to native HiDeep protocol
From: Dmitry Torokhov @ 2023-03-11  4:48 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Krzysztof Kozlowski, devicetree, linux-input
In-Reply-To: <857e6fc3-65f6-5b71-073f-b518ab3c814e@redhat.com>

On Sun, Mar 05, 2023 at 04:04:30PM +0100, Hans de Goede wrote:
> Hi,
> 
> On 3/5/23 14:34, Krzysztof Kozlowski wrote:
> > On 03/03/2023 23:21, Hans de Goede wrote:
> >> The HiDeep IST940E touchscreen controller used on the Lenovo Yoga Book X90F
> >> convertible comes up in HID mode by default.
> >>
> >> This works well on the X91F Windows model where the touchscreen is
> >> correctly described in ACPI and ACPI takes care of controlling
> >> the reset GPIO and regulators.
> >>
> >> But the X90F ships with Android and the ACPI tables on this model don't
> >> describe the touchscreen. Instead this is hardcoded in the vendor kernel.
> >>
> >> The vendor kernel uses the touchscreen in native HiDeep 20 (2.0?) protocol
> >> mode and switches the controller to this mode by writing 0 to reg 0x081e.
> >>
> >> Adjusting the i2c-hid code to deal with the reset-gpio and regulators on
> >> this non devicetree (but rather broken ACPI) convertible is somewhat tricky
> >> and the native protocol reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR
> >> which are not reported in HID mode, so it is preferable to use the native
> >> mode.
> >>
> >> Add support to the hideep driver to reset the work-mode to the native
> >> HiDeep protocol to allow using it on the Lenovo Yoga Book X90F.
> >> This is guarded behind a new "hideep,reset-work-mode" boolean property,
> >> to avoid changing behavior on other devices.
> >>
> >> For the record: I did test using the i2c-hid driver with some quick hacks
> >> and it does work. The I2C-HID descriptor is available from address 0x0020,
> >> just like on the X91F Windows model.
> >>
> >> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> > 
> > Please use scripts/get_maintainers.pl to get a list of necessary people
> > and lists to CC.  It might happen, that command when run on an older
> > kernel, gives you outdated entries.  Therefore please be sure you base
> > your patches on recent Linux kernel.
> > 
> >> ---
> >>  .../bindings/input/touchscreen/hideep.txt        |  1 +
> >>  drivers/input/touchscreen/hideep.c               | 16 ++++++++++++++++
> >>  2 files changed, 17 insertions(+)
> >>
> >> diff --git a/Documentation/devicetree/bindings/input/touchscreen/hideep.txt b/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
> >> index a47c36190b01..68bb9f8dcc30 100644
> >> --- a/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
> >> +++ b/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
> >> @@ -17,6 +17,7 @@ Optional properties:
> >>  - linux,keycodes	: Specifies an array of numeric keycode values to
> >>  			be used for reporting button presses. The array can
> >>  			contain up to 3 entries.
> >> +- hideep,reset-work-mode: bool, reset touch report format to the native HiDeep protocol
> > 
> > Bindings must be a separate patch.
> > 
> > Also, would be nice to convert first the TXT to DT schema (YAML).
> > 
> > "-mode" suggests it's some enum, not bool. Otherwise what exactly it is
> > choosing (which mode)?
> 
> As it says it is resetting the mode to the native HiDeep protocol,
> we have no docs on the controller, so I have no idea what other
> values may be written to 0x081e other then 0 and what modes those
> values will enable.

We could either have property specify desired register value, or call
the property something like "hideep,force-native-protocol" if we want to
keep it a bool.

> 
> Anyways I just realized I should have not included this at all,
> since atm this new property is only used on X86/ACPI platforms
> (through platform code setting a device-property), so it is not
> used on devicetree platforms at all.

Even if such properties are not documented I do not see how it will
prevent people from using them... I guess if they validate DT they will
be caught, but I am not sure that we can rely on this happening.


Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v4 0/4] HID: kye: Add support for all kye tablets
From: Yangfl @ 2023-03-11  5:47 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Benjamin Tissoires, linux-input, linux-kernel
In-Reply-To: <nycvar.YFH.7.76.2303101506030.1142@cbobk.fhfr.pm>

Jiri Kosina <jikos@kernel.org> 于2023年3月10日周五 22:06写道:
>
> On Tue, 7 Feb 2023, David Yang wrote:
>
> > This series refactor kye tablet descriptor fixup routine, by using a
> > template and filling parameters on the fly, and add support for all
> > possible kye tablets.
> > ---
> > v2: fix missing rsize assignment
> > v3: fix geometry
> > v4: split patches
> >
> > David Yang (4):
> >   HID: kye: Rewrite tablet descriptor fixup routine
> >   HID: kye: Generate tablet fixup descriptors on the fly
> >   HID: kye: Sort kye devices
> >   HID: kye: Add support for all kye tablets
> >
> >  drivers/hid/hid-ids.h    |   9 +-
> >  drivers/hid/hid-kye.c    | 917 +++++++++++++++++----------------------
> >  drivers/hid/hid-quirks.c |  14 +-
> >  3 files changed, 414 insertions(+), 526 deletions(-)
>
> Now queued in hid.git#for-6.4/kye, thanks David.
>
> --
> Jiri Kosina
> SUSE Labs
>

Thanks. But seems you missed the last patch.

^ permalink raw reply

* Re: [PATCH v5 0/2] Apple Magic Keyboard Backlight
From: Orlando Chamberlain @ 2023-03-11  6:33 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-doc, linux-input, Jonathan Corbet, Benjamin Tissoires,
	linux-kernel, Pavel Machek, Aditya Garg, Aun-Ali Zaidi,
	Kerem Karabay, Andy Shevchenko, Thomas Weißschuh
In-Reply-To: <nycvar.YFH.7.76.2303101535440.1142@cbobk.fhfr.pm>

On Fri, 10 Mar 2023 15:36:34 +0100 (CET)
Jiri Kosina <jikos@kernel.org> wrote:

> On Mon, 20 Feb 2023, Orlando Chamberlain wrote:
> 
> > This patchseries adds support for the internal keyboard backlight of
> > Macs with Apple's "Magic" keyboard (MacBookPro16,* and
> > MacBookAir9,1), and also documents what names should be used for
> > keyboard backlight leds in Documentation/leds/well-known-leds.txt.
> > 
> > v4->v5:
> > - use <tab><space><space> for help in Kconfig
> > - prepend "hid-" to filename in MAINTAINERS
> > 
> > v3->v4:
> > - collect reviews from Andy and Thomas
> > - remove now unused hdev member of apple_magic_backlight
> > 
> > v2->v3:
> > - remove unneeded header inclusion
> > - use s32 for report value type
> > - remove unneeded null check
> > - don't set drvdata as its never used
> > - prepend "hid-" to module name
> > 
> > v1->v2:
> > - drop unneeded remove function
> > - combine set functions
> > - add missing header inclusions
> > - avoid char as argument in favour of u8
> > - handful of style/formatting fixes
> > - use standard led name ":white:kbd_backlight"
> > - rename USAGE_MAGIC_BL to HID_USAGE_MAGIC_BL
> > - New patch documenting preferred keyboard backlight names
> > 
> > v1:
> > https://lore.kernel.org/linux-input/7D70F1FE-7F54-4D0A-8922-5466AA2AD364@live.com/
> > v2:
> > https://lore.kernel.org/linux-input/20230216041224.4731-1-orlandoch.dev@gmail.com/
> > v3:
> > https://lore.kernel.org/linux-input/20230217102319.3419-1-orlandoch.dev@gmail.com/
> > v4:
> > https://lore.kernel.org/linux-input/20230218090709.7467-1-orlandoch.dev@gmail.com/
> > 
> > Orlando Chamberlain (2):
> >   Documentation: leds: standardise keyboard backlight led names
> >   HID: hid-apple-magic-backlight: Add driver for keyboard backlight
> > on internal Magic Keyboards
> > 
> >  Documentation/leds/well-known-leds.txt  |   8 ++
> >  MAINTAINERS                             |   6 ++
> >  drivers/hid/Kconfig                     |  13 +++
> >  drivers/hid/Makefile                    |   1 +
> >  drivers/hid/hid-apple-magic-backlight.c | 120
> > ++++++++++++++++++++++++ 5 files changed, 148 insertions(+)
> >  create mode 100644 drivers/hid/hid-apple-magic-backlight.c  
> 
> Hi,
> 
> thanks for creating the support for backlight.
> 
> Is there any reason why not to fold all this into existing hid-apple?
> I don't think we need separate driver for the backlist, separated
> from the rest of hid-apple support.

Hi Jiri,

I think we can do that if we modify hid-apple to support usb endpoints
with only the keyboard backlight and no keyboard, assuming it doesn't
prevent the (not upstream) touchbar driver from using the touchbar
backlight interface (and I don't think it will, given hid-apple lets a
different driver bind to the trackpad interface of the
keyboard/trackpad usb device).

> 
> Thanks,
> 


^ permalink raw reply

* [PATCH] Use HID descriptor for razer devices
From: Dick Marinus @ 2023-03-11  6:51 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-kernel, linux-input; +Cc: Dick Marinus

hid-razer currently makes some guesses which device should be used to
send control messages and the size of it.

This patch derives this information from the HID descriptors, the
Windows Drivers from Razer also do this.

The crc in the blackwidow_init packet is now calculated (copied from
openrazer GPL code).

Signed-off-by: Dick Marinus <dick@mrns.nl>
---
 drivers/hid/hid-razer.c | 141 ++++++++++++++++++++++++++++++----------
 drivers/hid/hid-razer.h |   7 ++
 2 files changed, 115 insertions(+), 33 deletions(-)
 create mode 100644 drivers/hid/hid-razer.h

diff --git a/drivers/hid/hid-razer.c b/drivers/hid/hid-razer.c
index 740df148b0..0c83269d66 100644
--- a/drivers/hid/hid-razer.c
+++ b/drivers/hid/hid-razer.c
@@ -15,31 +15,15 @@
 #include <linux/wait.h>
 
 #include "hid-ids.h"
+#include "hid-razer.h"
 
 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
 
-#define RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE	91
-
 static bool macro_key_remapping = 1;
 module_param(macro_key_remapping, bool, 0644);
 MODULE_PARM_DESC(macro_key_remapping, " on (Y) off (N)");
 
-
-static unsigned char blackwidow_init[RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE] = {
-	0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04,
-	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x04, 0x00
-};
+static unsigned char set_device_mode[] = {0x00, 0x04, 0x02, 0x00};
 
 static int razer_input_mapping(struct hid_device *hdev,
 		struct hid_input *hi, struct hid_field *field,
@@ -73,35 +57,125 @@ static int razer_input_mapping(struct hid_device *hdev,
 	return 0;
 }
 
+static bool razer_check_control_interface(struct hid_device *hdev)
+{
+	int i;
+	unsigned int hid;
+	struct hid_report *report;
+	struct hid_razer *hid_razer_drvdata;
+
+	hid_razer_drvdata = hid_get_drvdata(hdev);
+
+	list_for_each_entry(report, &hdev->report_enum[HID_FEATURE_REPORT].report_list, list) {
+		for (i = 0; i < report->maxfield; i++) {
+			hid = report->field[i]->usage->hid;
+
+			if ((hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR && (hid & HID_USAGE) == 0x2) {
+				hid_razer_drvdata->report_count = report->field[i]->report_count;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static int razer_control_message(struct hid_device *hdev, unsigned char data_len,
+	unsigned char *data)
+{
+	struct hid_razer *hid_razer_drvdata;
+	unsigned char *full_control_message;
+	unsigned char crc = 0;
+	unsigned int i;
+	unsigned int report_count;
+	int ret;
+
+	if (data_len < 2) {
+		ret = -EINVAL;
+		goto cleanup_and_exit;
+	}
+
+	hid_razer_drvdata = hid_get_drvdata(hdev);
+
+	report_count = hid_razer_drvdata->report_count;
+
+	if (report_count < 2) {
+		ret = -EINVAL;
+		goto cleanup_and_exit;
+	}
+
+	full_control_message = kzalloc(report_count + 1, GFP_KERNEL);
+
+	if (full_control_message == NULL) {
+		ret = -ENOMEM;
+		goto cleanup_and_exit;
+	}
+
+	full_control_message[6] = data_len - 2;
+	memcpy(full_control_message + 7, data, data_len);
+
+	for (i = 2; i < report_count - 2; i++)
+		crc ^= full_control_message[i];
+
+	full_control_message[report_count - 1] = crc;
+
+	ret = hid_hw_raw_request(
+		hdev,
+		0,
+		full_control_message,
+		report_count + 1,
+		HID_FEATURE_REPORT,
+		HID_REQ_SET_REPORT
+	);
+
+	if (ret != report_count + 1) {
+		ret = -EIO;
+		goto cleanup_and_exit;
+	}
+
+cleanup_and_exit:
+	kfree(full_control_message);
+
+	return 0;
+}
+
+
 static int razer_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-	char *buf;
 	int ret = 0;
+	struct hid_razer *hid_razer_drvdata;
+
+	hid_razer_drvdata = kzalloc(sizeof(struct hid_razer), GFP_KERNEL);
+	if (hid_razer_drvdata == NULL)
+		return -ENOMEM;
+
+	hid_set_drvdata(hdev, hid_razer_drvdata);
 
 	ret = hid_parse(hdev);
+
 	if (ret)
 		return ret;
 
-	/*
-	 * Only send the enable macro keys command for the third device
-	 * identified as mouse input.
-	 */
-	if (hdev->type == HID_TYPE_USBMOUSE) {
-		buf = kmemdup(blackwidow_init, RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE, GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		ret = hid_hw_raw_request(hdev, 0, buf, RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE,
-				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-		if (ret != RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE)
+	if (razer_check_control_interface(hdev)) {
+		ret = razer_control_message(hdev, sizeof(set_device_mode), set_device_mode);
+		if (ret) {
 			hid_err(hdev, "failed to enable macro keys: %d\n", ret);
-
-		kfree(buf);
+			return ret;
+		}
 	}
 
 	return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 }
 
+static void razer_remove(struct hid_device *hdev)
+{
+	struct hid_razer *hid_razer_drvdata;
+
+	hid_razer_drvdata = hid_get_drvdata(hdev);
+
+	kfree(hid_razer_drvdata);
+}
+
 static const struct hid_device_id razer_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,
 		USB_DEVICE_ID_RAZER_BLACKWIDOW) },
@@ -118,6 +192,7 @@ static struct hid_driver razer_driver = {
 	.id_table = razer_devices,
 	.input_mapping = razer_input_mapping,
 	.probe = razer_probe,
+	.remove = razer_remove,
 };
 module_hid_driver(razer_driver);
 
diff --git a/drivers/hid/hid-razer.h b/drivers/hid/hid-razer.h
new file mode 100644
index 0000000000..d8214ca54b
--- /dev/null
+++ b/drivers/hid/hid-razer.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __HID_RAZER_H
+#define __HID_RAZER_H
+struct hid_razer {
+	unsigned int report_count;
+};
+#endif
-- 
2.39.2


^ permalink raw reply related

* [PATCH] Use HID descriptor for razer devices
From: Dick Marinus @ 2023-03-11  8:01 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-kernel, linux-input; +Cc: Dick Marinus

hid-razer currently makes some guesses which device should be used to
send control messages and the size of it.

This patch derives this information from the HID descriptors, the
Windows Drivers from Razer also do this.

The crc in the blackwidow_init packet is now calculated (copied from
openrazer GPL code).

Signed-off-by: Dick Marinus <dick@mrns.nl>
---
 drivers/hid/hid-razer.c | 141 ++++++++++++++++++++++++++++++----------
 drivers/hid/hid-razer.h |   7 ++
 2 files changed, 115 insertions(+), 33 deletions(-)
 create mode 100644 drivers/hid/hid-razer.h

diff --git a/drivers/hid/hid-razer.c b/drivers/hid/hid-razer.c
index 740df148b0..0c83269d66 100644
--- a/drivers/hid/hid-razer.c
+++ b/drivers/hid/hid-razer.c
@@ -15,31 +15,15 @@
 #include <linux/wait.h>
 
 #include "hid-ids.h"
+#include "hid-razer.h"
 
 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
 
-#define RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE	91
-
 static bool macro_key_remapping = 1;
 module_param(macro_key_remapping, bool, 0644);
 MODULE_PARM_DESC(macro_key_remapping, " on (Y) off (N)");
 
-
-static unsigned char blackwidow_init[RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE] = {
-	0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04,
-	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x04, 0x00
-};
+static unsigned char set_device_mode[] = {0x00, 0x04, 0x02, 0x00};
 
 static int razer_input_mapping(struct hid_device *hdev,
 		struct hid_input *hi, struct hid_field *field,
@@ -73,35 +57,125 @@ static int razer_input_mapping(struct hid_device *hdev,
 	return 0;
 }
 
+static bool razer_check_control_interface(struct hid_device *hdev)
+{
+	int i;
+	unsigned int hid;
+	struct hid_report *report;
+	struct hid_razer *hid_razer_drvdata;
+
+	hid_razer_drvdata = hid_get_drvdata(hdev);
+
+	list_for_each_entry(report, &hdev->report_enum[HID_FEATURE_REPORT].report_list, list) {
+		for (i = 0; i < report->maxfield; i++) {
+			hid = report->field[i]->usage->hid;
+
+			if ((hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR && (hid & HID_USAGE) == 0x2) {
+				hid_razer_drvdata->report_count = report->field[i]->report_count;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static int razer_control_message(struct hid_device *hdev, unsigned char data_len,
+	unsigned char *data)
+{
+	struct hid_razer *hid_razer_drvdata;
+	unsigned char *full_control_message;
+	unsigned char crc = 0;
+	unsigned int i;
+	unsigned int report_count;
+	int ret;
+
+	if (data_len < 2) {
+		ret = -EINVAL;
+		goto cleanup_and_exit;
+	}
+
+	hid_razer_drvdata = hid_get_drvdata(hdev);
+
+	report_count = hid_razer_drvdata->report_count;
+
+	if (report_count < 2) {
+		ret = -EINVAL;
+		goto cleanup_and_exit;
+	}
+
+	full_control_message = kzalloc(report_count + 1, GFP_KERNEL);
+
+	if (full_control_message == NULL) {
+		ret = -ENOMEM;
+		goto cleanup_and_exit;
+	}
+
+	full_control_message[6] = data_len - 2;
+	memcpy(full_control_message + 7, data, data_len);
+
+	for (i = 2; i < report_count - 2; i++)
+		crc ^= full_control_message[i];
+
+	full_control_message[report_count - 1] = crc;
+
+	ret = hid_hw_raw_request(
+		hdev,
+		0,
+		full_control_message,
+		report_count + 1,
+		HID_FEATURE_REPORT,
+		HID_REQ_SET_REPORT
+	);
+
+	if (ret != report_count + 1) {
+		ret = -EIO;
+		goto cleanup_and_exit;
+	}
+
+cleanup_and_exit:
+	kfree(full_control_message);
+
+	return 0;
+}
+
+
 static int razer_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-	char *buf;
 	int ret = 0;
+	struct hid_razer *hid_razer_drvdata;
+
+	hid_razer_drvdata = kzalloc(sizeof(struct hid_razer), GFP_KERNEL);
+	if (hid_razer_drvdata == NULL)
+		return -ENOMEM;
+
+	hid_set_drvdata(hdev, hid_razer_drvdata);
 
 	ret = hid_parse(hdev);
+
 	if (ret)
 		return ret;
 
-	/*
-	 * Only send the enable macro keys command for the third device
-	 * identified as mouse input.
-	 */
-	if (hdev->type == HID_TYPE_USBMOUSE) {
-		buf = kmemdup(blackwidow_init, RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE, GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		ret = hid_hw_raw_request(hdev, 0, buf, RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE,
-				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-		if (ret != RAZER_BLACKWIDOW_TRANSFER_BUF_SIZE)
+	if (razer_check_control_interface(hdev)) {
+		ret = razer_control_message(hdev, sizeof(set_device_mode), set_device_mode);
+		if (ret) {
 			hid_err(hdev, "failed to enable macro keys: %d\n", ret);
-
-		kfree(buf);
+			return ret;
+		}
 	}
 
 	return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 }
 
+static void razer_remove(struct hid_device *hdev)
+{
+	struct hid_razer *hid_razer_drvdata;
+
+	hid_razer_drvdata = hid_get_drvdata(hdev);
+
+	kfree(hid_razer_drvdata);
+}
+
 static const struct hid_device_id razer_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER,
 		USB_DEVICE_ID_RAZER_BLACKWIDOW) },
@@ -118,6 +192,7 @@ static struct hid_driver razer_driver = {
 	.id_table = razer_devices,
 	.input_mapping = razer_input_mapping,
 	.probe = razer_probe,
+	.remove = razer_remove,
 };
 module_hid_driver(razer_driver);
 
diff --git a/drivers/hid/hid-razer.h b/drivers/hid/hid-razer.h
new file mode 100644
index 0000000000..d8214ca54b
--- /dev/null
+++ b/drivers/hid/hid-razer.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __HID_RAZER_H
+#define __HID_RAZER_H
+struct hid_razer {
+	unsigned int report_count;
+};
+#endif
-- 
2.39.2


^ permalink raw reply related

* Re: [PATCH v2 2/2] Input: hideep - Optionally reset controller work mode to native HiDeep protocol
From: Hans de Goede @ 2023-03-11 11:16 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Krzysztof Kozlowski, devicetree, linux-input
In-Reply-To: <ZAwIIypDOjkNLRLk@google.com>

Hi,

On 3/11/23 05:48, Dmitry Torokhov wrote:
> On Sun, Mar 05, 2023 at 04:04:30PM +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 3/5/23 14:34, Krzysztof Kozlowski wrote:
>>> On 03/03/2023 23:21, Hans de Goede wrote:
>>>> The HiDeep IST940E touchscreen controller used on the Lenovo Yoga Book X90F
>>>> convertible comes up in HID mode by default.
>>>>
>>>> This works well on the X91F Windows model where the touchscreen is
>>>> correctly described in ACPI and ACPI takes care of controlling
>>>> the reset GPIO and regulators.
>>>>
>>>> But the X90F ships with Android and the ACPI tables on this model don't
>>>> describe the touchscreen. Instead this is hardcoded in the vendor kernel.
>>>>
>>>> The vendor kernel uses the touchscreen in native HiDeep 20 (2.0?) protocol
>>>> mode and switches the controller to this mode by writing 0 to reg 0x081e.
>>>>
>>>> Adjusting the i2c-hid code to deal with the reset-gpio and regulators on
>>>> this non devicetree (but rather broken ACPI) convertible is somewhat tricky
>>>> and the native protocol reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR
>>>> which are not reported in HID mode, so it is preferable to use the native
>>>> mode.
>>>>
>>>> Add support to the hideep driver to reset the work-mode to the native
>>>> HiDeep protocol to allow using it on the Lenovo Yoga Book X90F.
>>>> This is guarded behind a new "hideep,reset-work-mode" boolean property,
>>>> to avoid changing behavior on other devices.
>>>>
>>>> For the record: I did test using the i2c-hid driver with some quick hacks
>>>> and it does work. The I2C-HID descriptor is available from address 0x0020,
>>>> just like on the X91F Windows model.
>>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>
>>> Please use scripts/get_maintainers.pl to get a list of necessary people
>>> and lists to CC.  It might happen, that command when run on an older
>>> kernel, gives you outdated entries.  Therefore please be sure you base
>>> your patches on recent Linux kernel.
>>>
>>>> ---
>>>>  .../bindings/input/touchscreen/hideep.txt        |  1 +
>>>>  drivers/input/touchscreen/hideep.c               | 16 ++++++++++++++++
>>>>  2 files changed, 17 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/input/touchscreen/hideep.txt b/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
>>>> index a47c36190b01..68bb9f8dcc30 100644
>>>> --- a/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
>>>> +++ b/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
>>>> @@ -17,6 +17,7 @@ Optional properties:
>>>>  - linux,keycodes	: Specifies an array of numeric keycode values to
>>>>  			be used for reporting button presses. The array can
>>>>  			contain up to 3 entries.
>>>> +- hideep,reset-work-mode: bool, reset touch report format to the native HiDeep protocol
>>>
>>> Bindings must be a separate patch.
>>>
>>> Also, would be nice to convert first the TXT to DT schema (YAML).
>>>
>>> "-mode" suggests it's some enum, not bool. Otherwise what exactly it is
>>> choosing (which mode)?
>>
>> As it says it is resetting the mode to the native HiDeep protocol,
>> we have no docs on the controller, so I have no idea what other
>> values may be written to 0x081e other then 0 and what modes those
>> values will enable.
> 
> We could either have property specify desired register value, or call
> the property something like "hideep,force-native-protocol" if we want to
> keep it a bool.

"hideep,force-native-protocol" is a good suggestion I'll prepare a new
version with that.

>> Anyways I just realized I should have not included this at all,
>> since atm this new property is only used on X86/ACPI platforms
>> (through platform code setting a device-property), so it is not
>> used on devicetree platforms at all.
> 
> Even if such properties are not documented I do not see how it will
> prevent people from using them... I guess if they validate DT they will
> be caught, but I am not sure that we can rely on this happening.

Right, but I have beene explicitly told multiple times (1) to not document
device-properties when they are only used between x86 platform code and
drivers consuming them (and thus not actually used in any DT files
at that point in time).

Regards,

Hans


1) By the DT bindings maintainers


^ permalink raw reply

* Re: [PATCH v2 2/2] Input: hideep - Optionally reset controller work mode to native HiDeep protocol
From: Krzysztof Kozlowski @ 2023-03-11 11:36 UTC (permalink / raw)
  To: Hans de Goede, Dmitry Torokhov; +Cc: devicetree, linux-input
In-Reply-To: <4a273927-fa03-8503-e1c8-94b0223e80d1@redhat.com>

On 11/03/2023 12:16, Hans de Goede wrote:
> 
> "hideep,force-native-protocol" is a good suggestion I'll prepare a new
> version with that.
> 
>>> Anyways I just realized I should have not included this at all,
>>> since atm this new property is only used on X86/ACPI platforms
>>> (through platform code setting a device-property), so it is not
>>> used on devicetree platforms at all.
>>
>> Even if such properties are not documented I do not see how it will
>> prevent people from using them... I guess if they validate DT they will
>> be caught, but I am not sure that we can rely on this happening.
> 
> Right, but I have beene explicitly told multiple times (1) to not document
> device-properties when they are only used between x86 platform code and
> drivers consuming them (and thus not actually used in any DT files
> at that point in time).

Comment in the code that this is not a DT property, is the most we can
do now (so people won't use it later as argument to add to the binding)...

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH v5 2/2] Input: hideep - Optionally reset controller work mode to native HiDeep protocol
From: Hans de Goede @ 2023-03-11 11:47 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Hans de Goede, Krzysztof Kozlowski, linux-input
In-Reply-To: <20230311114726.182789-1-hdegoede@redhat.com>

The HiDeep IST940E touchscreen controller used on the Lenovo Yoga Book X90F
convertible comes up in HID mode by default.

This works well on the X91F Windows model where the touchscreen is
correctly described in ACPI and ACPI takes care of controlling
the reset GPIO and regulators.

But the X90F ships with Android and the ACPI tables on this model don't
describe the touchscreen. Instead this is hardcoded in the vendor kernel.

The vendor kernel uses the touchscreen in native HiDeep 20 (2.0?) protocol
mode and switches the controller to this mode by writing 0 to reg 0x081e.

Adjusting the i2c-hid code to deal with the reset-gpio and regulators on
this non devicetree (but rather broken ACPI) convertible is somewhat tricky
and the native protocol reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR
which are not reported in HID mode, so it is preferable to use the native
mode.

Add support to the hideep driver to reset the work-mode to the native
HiDeep protocol to allow using it on the Lenovo Yoga Book X90F.
This is guarded behind a new "hideep,force-native-protocol" boolean
property, to avoid changing behavior on other devices.

For the record: I did test using the i2c-hid driver with some quick hacks
and it does work. The I2C-HID descriptor is available from address 0x0020,
just like on the X91F Windows model.

So far the new "hideep,force-native-protocol" property is only used on
x86/ACPI (non devicetree) devs. IOW it is not used in actual devicetree
files. The devicetree-bindings maintainers have requested properties like
these to not be added to the devicetree-bindings, so the new property is
deliberately not added to the existing devicetree-bindings.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v5:
- Rename the property to "hideep,force-native-protocol"
- Add a comment to the property checking code that this property
  should not be used in devicetree without first adding it to
  the devicetree-bindings.

Changes in v3:
- Do not add the x86/acpi only property to the dt-bindings doc

Changes in v2:
- New patch in v2 of this patch-set
---
 drivers/input/touchscreen/hideep.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index 5e6e43d56448..74673db06ed0 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -35,6 +35,7 @@
 #define HIDEEP_EVENT_ADDR		0x240
 
 /* command list */
+#define HIDEEP_WORK_MODE		0x081e
 #define HIDEEP_RESET_CMD		0x9800
 
 /* event bit */
@@ -964,6 +965,21 @@ static const struct attribute_group hideep_ts_attr_group = {
 	.attrs = hideep_ts_sysfs_entries,
 };
 
+static void hideep_set_work_mode(struct hideep_ts *ts)
+{
+	/*
+	 * Reset touch report format to the native HiDeep 20 protocol if requested.
+	 * This is necessary to make touchscreens which come up in I2C-HID mode
+	 * work with this driver.
+	 *
+	 * Note this is a kernel internal device-property set by x86 platform code,
+	 * this MUST not be used in devicetree files without first adding it to
+	 * the DT bindings.
+	 */
+	if (device_property_read_bool(&ts->client->dev, "hideep,force-native-protocol"))
+		regmap_write(ts->reg, HIDEEP_WORK_MODE, 0x00);
+}
+
 static int hideep_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -987,6 +1003,8 @@ static int hideep_resume(struct device *dev)
 		return error;
 	}
 
+	hideep_set_work_mode(ts);
+
 	enable_irq(client->irq);
 
 	return 0;
@@ -1063,6 +1081,8 @@ static int hideep_probe(struct i2c_client *client)
 		return error;
 	}
 
+	hideep_set_work_mode(ts);
+
 	error = hideep_init_input(ts);
 	if (error)
 		return error;
-- 
2.39.1


^ permalink raw reply related

* [PATCH v5 1/2] Input: hideep - Silence error in SW_RESET()
From: Hans de Goede @ 2023-03-11 11:47 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Hans de Goede, Krzysztof Kozlowski, linux-input
In-Reply-To: <20230311114726.182789-1-hdegoede@redhat.com>

On some models the first HIDEEP_SYSCON_WDT_CON write alone is enough to
cause the controller to reset, causing the second write to fail:

i2c-hideep_ts: write to register 0x52000014 (0x000001) failed: -121

Switch this write to a raw hideep_pgm_w_mem() to avoid an error getting
logged in this case.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/input/touchscreen/hideep.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index bd454d93f1f7..5e6e43d56448 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -271,9 +271,14 @@ static int hideep_pgm_w_reg(struct hideep_ts *ts, u32 addr, u32 val)
 
 #define SW_RESET_IN_PGM(clk)					\
 {								\
+	__be32 data = cpu_to_be32(0x01);			\
 	hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CNT, (clk));	\
 	hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, 0x03);	\
-	hideep_pgm_w_reg(ts, HIDEEP_SYSCON_WDT_CON, 0x01);	\
+	/*							\
+	 * The first write may already cause a reset, use a raw	\
+	 * write for the second write to avoid error logging.	\
+	 */							\
+	hideep_pgm_w_mem(ts, HIDEEP_SYSCON_WDT_CON, &data, 1);	\
 }
 
 #define SET_FLASH_PIO(ce)					\
-- 
2.39.1


^ permalink raw reply related

* [PATCH v5 0/2] Input: hideep - 2 HiDeep touchscreen patches
From: Hans de Goede @ 2023-03-11 11:47 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Hans de Goede, Krzysztof Kozlowski, linux-input

Hi Dmitry,

Here are 2 patches for the HiDeep touchscreen driver.

Changes in v5:
- Rename the property to "hideep,force-native-protocol"
- Add a comment to the property checking code that this property
  should not be used in devicetree without first adding it to
  the devicetree-bindings.

Changes in v4:
- Rebase on v6.3-rc1

Changes in v3:
- Do not add the x86/acpi only "hideep,reset-work-mode" property to
  the dt-bindings doc

Changes in v2:
- Add "Optionally reset controller work mode to native HiDeep protocol"
  patch

Regards,

Hans


Hans de Goede (2):
  Input: hideep - Silence error in SW_RESET()
  Input: hideep - Optionally reset controller work mode to native HiDeep
    protocol

 drivers/input/touchscreen/hideep.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

-- 
2.39.1


^ permalink raw reply

* Re: [PATCH] Fix buffer overrun in HID-SENSOR name.
From: Jonathan Cameron @ 2023-03-11 12:31 UTC (permalink / raw)
  To: Philipp Jungkamp
  Cc: Todd Brandt, linux-input, linux-iio, linux-kernel, todd.e.brandt,
	srinivas.pandruvada, jikos
In-Reply-To: <b9dab02783e5eeaa74b291d4394150689e7c7b8a.camel@gmx.net>

On Sat, 11 Mar 2023 01:53:22 +0100
Philipp Jungkamp <p.jungkamp@gmx.net> wrote:

> This is exactly the fix I proposed. Thank you for testing and properly
> submitting it.
> 
> Regards,
> Philipp Jungkamp

Looks good to me as well.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

> 
> On Fri, 2023-03-10 at 15:54 -0800, Todd Brandt wrote:
> > Philipp Jungkamp created this fix, I'm simply submitting it. I've
> > verified it fixes bugzilla issue 217169.
> > 
> > Reported-and-tested-by: Todd Brandt <todd.e.brandt@linux.intel.com>
> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217169
> > Signed-off-by: Todd Brandt <todd.e.brandt@intel.com>
> > ---
> >  drivers/hid/hid-sensor-custom.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-
> > sensor-custom.c
> > index 3e3f89e01d81..d85398721659 100644
> > --- a/drivers/hid/hid-sensor-custom.c
> > +++ b/drivers/hid/hid-sensor-custom.c
> > @@ -940,7 +940,7 @@ hid_sensor_register_platform_device(struct
> > platform_device *pdev,
> >                                     struct hid_sensor_hub_device
> > *hsdev,
> >                                     const struct
> > hid_sensor_custom_match *match)
> >  {
> > -       char real_usage[HID_SENSOR_USAGE_LENGTH];
> > +       char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
> >         struct platform_device *custom_pdev;
> >         const char *dev_name;
> >         char *c;  
> 


^ permalink raw reply

* [PATCH v2] input: touchscreen: goodix: Hold controller in reset during suspend
From: Jan Jasper de Kroon @ 2023-03-11 13:15 UTC (permalink / raw)
  To: jajadekroon; +Cc: linux-input, megi
In-Reply-To: <20230310170026.415739-1-jajadekroon@gmail.com>

From: Ondřej Jirman <megi@xff.cz>

The Goodix touchscreen controller used in PinePhone is not properly
suspended during system sleep, leading to high power consumption. This
commit modifies the driver to hold the controller in reset during
system sleep, reducing power consumption by around 40mW.

The original patch also disabled the regulators during system sleep, but
this could cause issues with other peripherals attached to the same power
supplies. Hence, this commit only holds the controller in reset during
system sleep and does not attempt to power it off.

A separate commit adds a new device tree property "hold-in-reset-in-suspend"
to control the hold-in-reset behavior of the controller during system sleep.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
Signed-off-by: Jan Jasper de Kroon <jajadekroon@gmail.com>
---
V1 -> V2: Rewrote the commit message and function name to better reflect it's behavior.

 drivers/input/touchscreen/goodix.c | 23 +++++++++++++++++++++++
 drivers/input/touchscreen/goodix.h |  1 +
 2 files changed, 24 insertions(+)

diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index b348172f19c3..a35a203e04bf 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1284,6 +1284,7 @@ static void goodix_disable_regulators(void *arg)
 
 static int goodix_ts_probe(struct i2c_client *client)
 {
+	struct device_node *np = client->dev.of_node;
 	struct goodix_ts_data *ts;
 	const char *cfg_name;
 	int error;
@@ -1303,6 +1304,7 @@ static int goodix_ts_probe(struct i2c_client *client)
 	i2c_set_clientdata(client, ts);
 	init_completion(&ts->firmware_loading_complete);
 	ts->contact_size = GOODIX_CONTACT_SIZE;
+	ts->hold_in_reset_in_suspend = of_property_read_bool(np, "hold-in-reset-in-suspend");
 
 	error = goodix_get_gpio_config(ts);
 	if (error)
@@ -1410,6 +1412,13 @@ static int goodix_suspend(struct device *dev)
 	if (ts->load_cfg_from_disk)
 		wait_for_completion(&ts->firmware_loading_complete);
 
+	if (ts->hold_in_reset_in_suspend) {
+		goodix_free_irq(ts);
+		goodix_irq_direction_output(ts, 0);
+		gpiod_direction_output(ts->gpiod_rst, 0);
+		return 0;
+	}
+
 	/* We need gpio pins to suspend/resume */
 	if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
 		disable_irq(client->irq);
@@ -1455,6 +1464,20 @@ static int goodix_resume(struct device *dev)
 	u8 config_ver;
 	int error;
 
+	if (ts->hold_in_reset_in_suspend) {
+		error = goodix_reset(ts);
+		if (error) {
+			dev_err(dev, "Controller reset failed.\n");
+			return error;
+		}
+
+		error = goodix_request_irq(ts);
+		if (error)
+			return error;
+
+		return 0;
+	}
+
 	if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
 		enable_irq(client->irq);
 		return 0;
diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
index 87797cc88b32..c515d03b742c 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -104,6 +104,7 @@ struct goodix_ts_data {
 	u8 main_clk[GOODIX_MAIN_CLK_LEN];
 	int bak_ref_len;
 	u8 *bak_ref;
+	bool hold_in_reset_in_suspend;
 };
 
 int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);
-- 
2.34.3


^ permalink raw reply related

* [PATCH 0/5] Add support for Focaltech FTS Touchscreen
From: Joel Selvaraj @ 2023-03-12  9:32 UTC (permalink / raw)
  To: Caleb Connolly, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Andy Gross, Bjorn Andersson, Konrad Dybcio, Henrik Rydberg,
	Arnd Bergmann, Robert Jarzmik, Jeff LaBundy, Neil Armstrong,
	Markuss Broks, Jean Delvare, Max Krummenacher, Job Noorman,
	Alistair Francis, Chris Morgan
  Cc: linux-input, devicetree, linux-kernel, linux-arm-msm,
	~postmarketos/upstreaming, phone-devel, Joel Selvaraj

The Focaltech FTS driver supports several variants of focaltech
touchscreens found in ~2018 era smartphones including variants found on
the PocoPhone F1 and the SHIFT6mq which are already present in mainline.
This driver is loosely based on the original driver from Focaltech and
the patches submitted by Caleb Connolly previously[1] but has been
simplified and largely reworked.

Kindly let me know if any improvements are needed. Thanks.

[1] https://patchwork.kernel.org/project/linux-input/patch/20220123173650.290349-3-caleb@connolly.tech/

Joel Selvaraj (5):
  dt-bindings: input: touchscreen: add bindings for focaltech,fts
  Input: add driver for Focaltech FTS touchscreen
  arm64: dts: qcom: sdm845-xiaomi-beryllium-common: add touchscreen
    related nodes
  arm64: dts: qcom: sdm845-xiaomi-beryllium-ebbg: introduce support for
    fts touchscreen
  arm64: dts: qcom: sdm845-shift-axolotl: update focaltech touchscreen
    properties

 .../input/touchscreen/focaltech,fts.yaml      |  81 ++++
 MAINTAINERS                                   |   8 +
 .../boot/dts/qcom/sdm845-shift-axolotl.dts    |  17 +-
 .../qcom/sdm845-xiaomi-beryllium-common.dtsi  |  39 ++
 .../dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts |  27 ++
 drivers/input/touchscreen/Kconfig             |  12 +
 drivers/input/touchscreen/Makefile            |   1 +
 drivers/input/touchscreen/focaltech_fts.c     | 448 ++++++++++++++++++
 8 files changed, 625 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/focaltech,fts.yaml
 create mode 100644 drivers/input/touchscreen/focaltech_fts.c

-- 
2.39.2


^ permalink raw reply

* [PATCH 1/5] dt-bindings: input: touchscreen: add bindings for focaltech,fts
From: Joel Selvaraj @ 2023-03-12  9:32 UTC (permalink / raw)
  To: Caleb Connolly, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Andy Gross, Bjorn Andersson, Konrad Dybcio, Henrik Rydberg,
	Arnd Bergmann, Robert Jarzmik, Jeff LaBundy, Neil Armstrong,
	Markuss Broks, Jean Delvare, Max Krummenacher, Job Noorman,
	Alistair Francis, Chris Morgan
  Cc: linux-input, devicetree, linux-kernel, linux-arm-msm,
	~postmarketos/upstreaming, phone-devel, Joel Selvaraj
In-Reply-To: <20230312093249.1846993-1-joelselvaraj.oss@gmail.com>

Add devicetree bindings for the Focaltech FTS touchscreen drivers.

Signed-off-by: Joel Selvaraj <joelselvaraj.oss@gmail.com>
Signed-off-by: Caleb Connolly <caleb@connolly.tech>
---
 .../input/touchscreen/focaltech,fts.yaml      | 81 +++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/focaltech,fts.yaml

diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech,fts.yaml b/Documentation/devicetree/bindings/input/touchscreen/focaltech,fts.yaml
new file mode 100644
index 000000000000..07fe595cc9ed
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/focaltech,fts.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/focaltech,fts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Focaltech FTS I2C Touchscreen Controller
+
+maintainers:
+  - Joel Selvaraj <joelselvaraj.oss@gmail.com>
+  - Caleb Connolly <caleb@connolly.tech>
+
+allOf:
+  - $ref: touchscreen.yaml#
+
+properties:
+  compatible:
+    enum:
+      - focaltech,fts5452
+      - focaltech,fts8719
+  reg:
+    const: 0x38
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    maxItems: 1
+
+  avdd-supply:
+    description: a phandle for the regulator supplying analog power (2.6V to 3.3V).
+
+  vddio-supply:
+    description: a phandle for the regulator supplying IO power (1.8V).
+
+  focaltech,max-touch-number:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: max number of fingers supported
+    minimum: 2
+    maximum: 10
+
+  touchscreen-size-x: true
+  touchscreen-size-y: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - reset-gpios
+  - focaltech,max-touch-number
+  - touchscreen-size-x
+  - touchscreen-size-y
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    &i2c5 {
+      status="okay";
+
+      touchscreen: focaltech@38 {
+        compatible = "focaltech,fts8719";
+        reg = <0x38>;
+        interrupt-parent = <&tlmm>;
+        interrupts = <31 IRQ_TYPE_EDGE_RISING>;
+
+        avdd-supply = <&vreg_l28a_3p0>;
+        vddio-supply = <&vreg_l14a_1p8>;
+
+        pinctrl-names = "default", "sleep";
+        pinctrl-0 = <&ts_int_default &ts_reset_default>;
+        pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+
+        reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+
+        touchscreen-size-x = <1080>;
+        touchscreen-size-y = <2246>;
+        focaltech,max-touch-number = <10>;
+      };
+    };
-- 
2.39.2


^ permalink raw reply related

* [PATCH 2/5] Input: add driver for Focaltech FTS touchscreen
From: Joel Selvaraj @ 2023-03-12  9:32 UTC (permalink / raw)
  To: Caleb Connolly, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Andy Gross, Bjorn Andersson, Konrad Dybcio, Henrik Rydberg,
	Arnd Bergmann, Robert Jarzmik, Jeff LaBundy, Neil Armstrong,
	Markuss Broks, Jean Delvare, Max Krummenacher, Job Noorman,
	Alistair Francis, Chris Morgan
  Cc: linux-input, devicetree, linux-kernel, linux-arm-msm,
	~postmarketos/upstreaming, phone-devel, Joel Selvaraj
In-Reply-To: <20230312093249.1846993-1-joelselvaraj.oss@gmail.com>

The Focaltech FTS driver supports several variants of focaltech
touchscreens found in ~2018 era smartphones including variants found on
the PocoPhone F1 and the SHIFT6mq which are already present in mainline.
This driver is loosely based on the original driver from Focaltech
but has been simplified and largely reworked.

Co-developed-by: Caleb Connolly <caleb@connolly.tech>
Signed-off-by: Caleb Connolly <caleb@connolly.tech>
Signed-off-by: Joel Selvaraj <joelselvaraj.oss@gmail.com>
---
 MAINTAINERS                               |   8 +
 drivers/input/touchscreen/Kconfig         |  12 +
 drivers/input/touchscreen/Makefile        |   1 +
 drivers/input/touchscreen/focaltech_fts.c | 448 ++++++++++++++++++++++
 4 files changed, 469 insertions(+)
 create mode 100644 drivers/input/touchscreen/focaltech_fts.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2892858cb040..deb561c356f2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7993,6 +7993,14 @@ L:	linux-input@vger.kernel.org
 S:	Maintained
 F:	drivers/input/joystick/fsia6b.c
 
+FOCALTECH FTS TOUCHSCREEN DRIVER
+M:	Joel Selvaraj <joelselvaraj.oss@gmail.com>
+M:	Caleb Connolly <caleb@connolly.tech>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/input/touchscreen/focaltech,fts.yaml
+F:	drivers/input/touchscreen/focaltech_fts.c
+
 FOCUSRITE SCARLETT GEN 2/3 MIXER DRIVER
 M:	Geoffrey D. Bennett <g@b4.vu>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1a2049b336a6..320925bac3a1 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -388,6 +388,18 @@ config TOUCHSCREEN_EXC3000
 	  To compile this driver as a module, choose M here: the
 	  module will be called exc3000.
 
+config TOUCHSCREEN_FOCALTECH_FTS
+	tristate "Focaltech FTS Touchscreen"
+	depends on I2C
+	help
+	  Say Y here to enable support for I2C connected Focaltech FTS
+	  based touch panels, including the 5452 and 8917 panels.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called focaltech_fts.
+
 config TOUCHSCREEN_FUJITSU
 	tristate "Fujitsu serial touchscreen"
 	select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f2fd28cc34a6..83ea2e3ce754 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)	+= egalax_ts_serial.o
 obj-$(CONFIG_TOUCHSCREEN_EXC3000)	+= exc3000.o
+obj-$(CONFIG_TOUCHSCREEN_FOCALTECH_FTS)	+= focaltech_fts.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HIDEEP)	+= hideep.o
diff --git a/drivers/input/touchscreen/focaltech_fts.c b/drivers/input/touchscreen/focaltech_fts.c
new file mode 100644
index 000000000000..d389c8b88944
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_fts.c
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *
+ * FocalTech touchscreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ * Copyright (C) 2018 XiaoMi, Inc.
+ * Copyright (c) 2021 Caleb Connolly <caleb@connolly.tech>
+ * Copyright (c) 2023 Joel Selvaraj <joelselvaraj.oss@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/mutex.h>
+
+#define FTS_REG_CHIP_ID_H 0xA3
+#define FTS_REG_CHIP_ID_L 0x9F
+
+#define FTS_MAX_POINTS_SUPPORT 10
+#define FTS_ONE_TOUCH_LEN 6
+
+#define FTS_TOUCH_X_H_OFFSET 3
+#define FTS_TOUCH_X_L_OFFSET 4
+#define FTS_TOUCH_Y_H_OFFSET 5
+#define FTS_TOUCH_Y_L_OFFSET 6
+#define FTS_TOUCH_PRESSURE_OFFSET 7
+#define FTS_TOUCH_AREA_OFFSET 8
+#define FTS_TOUCH_TYPE_OFFSET 3
+#define FTS_TOUCH_ID_OFFSET 5
+
+#define FTS_TOUCH_DOWN 0
+#define FTS_TOUCH_UP 1
+#define FTS_TOUCH_CONTACT 2
+
+#define FTS_DRIVER_NAME "fts-i2c"
+#define INTERVAL_READ_REG 100 /* unit:ms */
+#define TIMEOUT_READ_REG 2000 /* unit:ms */
+
+#define CHIP_TYPE_5452 0x5452
+#define CHIP_TYPE_8719 0x8719
+
+struct fts_ts_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct touchscreen_properties prop;
+
+	struct regmap *regmap;
+	int irq;
+
+	struct regulator_bulk_data regulators[2];
+
+	/* Touch data */
+	u8 max_touch_number;
+	u8 *point_buf;
+	int point_buf_size;
+
+	/* DT data */
+	struct gpio_desc *reset_gpio;
+};
+
+static const struct regmap_config fts_ts_i2c_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static bool fts_chip_is_valid(struct fts_ts_data *data, u16 id)
+{
+	if (id != CHIP_TYPE_5452 && id != CHIP_TYPE_8719)
+		return false;
+
+	return true;
+}
+
+int fts_check_status(struct fts_ts_data *data)
+{
+	int count = 0;
+	unsigned int val, id;
+
+	do {
+		regmap_read(data->regmap, FTS_REG_CHIP_ID_H, &val);
+		id = val << 8;
+		regmap_read(data->regmap, FTS_REG_CHIP_ID_L, &val);
+		id |= val;
+
+		if (fts_chip_is_valid(data, id)) {
+			dev_dbg(&data->client->dev, "TS Ready: Chip ID = 0x%x", id);
+			return 0;
+		}
+
+		count++;
+		msleep(INTERVAL_READ_REG);
+	} while ((count * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
+
+	return -EIO;
+}
+
+static void fts_report_touch(struct fts_ts_data *data)
+{
+	struct input_dev *input_dev = data->input_dev;
+	int base;
+	unsigned int x, y, z, maj;
+	u8 slot, type;
+	int error, i = 0;
+
+	u8 *buf = data->point_buf;
+
+	memset(buf, 0, data->point_buf_size);
+
+	error = regmap_bulk_read(data->regmap, 0, buf, data->point_buf_size);
+	if (error) {
+		dev_err_ratelimited(&data->client->dev, "I2C read failed: %d\n",
+				    error);
+		return;
+	}
+
+	for (i = 0; i < data->max_touch_number; i++) {
+		base = FTS_ONE_TOUCH_LEN * i;
+
+		slot = (buf[base + FTS_TOUCH_ID_OFFSET]) >> 4;
+		if (slot >= data->max_touch_number)
+			break;
+
+		x = ((buf[base + FTS_TOUCH_X_H_OFFSET] & 0x0F) << 8) +
+			 (buf[base + FTS_TOUCH_X_L_OFFSET] & 0xFF);
+		y = ((buf[base + FTS_TOUCH_Y_H_OFFSET] & 0x0F) << 8) +
+			 (buf[base + FTS_TOUCH_Y_L_OFFSET] & 0xFF);
+
+		z = buf[base + FTS_TOUCH_PRESSURE_OFFSET];
+		if (z <= 0)
+			z = 0x3f;
+
+		maj = buf[base + FTS_TOUCH_AREA_OFFSET] >> 4;
+		if (maj <= 0)
+			maj = 0x09;
+
+		type = buf[base + FTS_TOUCH_TYPE_OFFSET] >> 6;
+
+		input_mt_slot(input_dev, slot);
+		if (type == FTS_TOUCH_DOWN || type == FTS_TOUCH_CONTACT) {
+			input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);
+			touchscreen_report_pos(data->input_dev, &data->prop, x, y, true);
+			input_report_abs(input_dev, ABS_MT_PRESSURE, z);
+			input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, maj);
+			input_report_key(data->input_dev, BTN_TOUCH, 1);
+		} else {
+			input_report_key(data->input_dev, BTN_TOUCH, 0);
+			input_mt_report_slot_inactive(input_dev);
+		}
+	}
+	input_sync(input_dev);
+}
+
+static irqreturn_t fts_ts_interrupt(int irq, void *dev_id)
+{
+	struct fts_ts_data *data = dev_id;
+
+	fts_report_touch(data);
+
+	return IRQ_HANDLED;
+}
+
+static void fts_power_off(void *d)
+{
+	struct fts_ts_data *data = d;
+
+	regulator_bulk_disable(ARRAY_SIZE(data->regulators),
+			       data->regulators);
+}
+
+static int fts_start(struct fts_ts_data *data)
+{
+	int error;
+
+	error = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
+				      data->regulators);
+	if (error) {
+		dev_err(&data->client->dev, "failed to enable regulators\n");
+		return error;
+	}
+
+	gpiod_set_value_cansleep(data->reset_gpio, 0);
+	msleep(200);
+
+	enable_irq(data->irq);
+
+	return 0;
+}
+
+static int fts_stop(struct fts_ts_data *data)
+{
+	disable_irq(data->irq);
+	gpiod_set_value_cansleep(data->reset_gpio, 1);
+	fts_power_off(data);
+
+	return 0;
+}
+
+static int fts_input_open(struct input_dev *dev)
+{
+	struct fts_ts_data *data = input_get_drvdata(dev);
+	int error;
+
+	error = fts_start(data);
+	if (error)
+		return error;
+
+	error = fts_check_status(data);
+	if (error) {
+		dev_err(&data->client->dev, "Failed to start or unsupported chip");
+		return error;
+	}
+
+	return 0;
+}
+
+static void fts_input_close(struct input_dev *dev)
+{
+	struct fts_ts_data *data = input_get_drvdata(dev);
+
+	fts_stop(data);
+}
+
+static int fts_input_init(struct fts_ts_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct input_dev *input_dev;
+	int error = 0;
+
+	input_dev = devm_input_allocate_device(dev);
+	if (!input_dev)
+		return -ENOMEM;
+
+	data->input_dev = input_dev;
+
+	/* Init and register Input device */
+	input_dev->name = FTS_DRIVER_NAME;
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = dev;
+	input_dev->open = fts_input_open;
+	input_dev->close = fts_input_close;
+
+	input_set_drvdata(input_dev, data);
+
+	__set_bit(EV_SYN, input_dev->evbit);
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+	input_mt_init_slots(input_dev, data->max_touch_number,
+			    INPUT_MT_DIRECT);
+	input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
+	input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+	touchscreen_parse_properties(input_dev, true, &data->prop);
+	if (!data->prop.max_x || !data->prop.max_y) {
+		dev_err(dev,
+			"touchscreen-size-x and/or touchscreen-size-y not set in dts\n");
+		return -EINVAL;
+	}
+
+	data->point_buf_size = (data->max_touch_number * FTS_ONE_TOUCH_LEN) + 3;
+	data->point_buf = devm_kzalloc(dev, data->point_buf_size, GFP_KERNEL);
+	if (!data->point_buf) {
+		dev_err(dev, "Failed to alloc memory for point buffer\n");
+		return -ENOMEM;
+	}
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(dev, "Failed to register input device\n");
+		return error;
+	}
+
+	return 0;
+}
+
+static int fts_parse_dt(struct fts_ts_data *data)
+{
+	int error = 0;
+	struct device *dev = &data->client->dev;
+	struct device_node *np = dev->of_node;
+	u32 val;
+
+	error = of_property_read_u32(np, "focaltech,max-touch-number", &val);
+	if (error) {
+		dev_err(dev, "Unable to read property 'focaltech,max-touch-number'");
+		return -EINVAL;
+	}
+	if (val < 2 || val > FTS_MAX_POINTS_SUPPORT) {
+		dev_err(dev, "'focaltech,max-touch-number' out of range [2, %d]",
+			FTS_MAX_POINTS_SUPPORT);
+		return -EINVAL;
+	}
+	data->max_touch_number = val;
+
+	data->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(data->reset_gpio)) {
+		error = PTR_ERR(data->reset_gpio);
+		dev_err(dev, "Failed to request reset gpio, error %d\n", error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int fts_ts_probe(struct i2c_client *client)
+{
+	int error = 0;
+	struct fts_ts_data *data;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "I2C not supported");
+		return -ENODEV;
+	}
+
+	if (!client->irq) {
+		dev_err(&client->dev, "No irq specified\n");
+		return -EINVAL;
+	}
+
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->client = client;
+
+	error = fts_parse_dt(data);
+	if (error)
+		return error;
+
+	i2c_set_clientdata(client, data);
+
+	data->regmap = devm_regmap_init_i2c(client, &fts_ts_i2c_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&client->dev, "regmap allocation failed\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	/*
+	 * AVDD is the analog voltage supply (2.6V to 3.3V)
+	 * VDDIO is the digital voltage supply (1.8V)
+	 */
+	data->regulators[0].supply = "avdd";
+	data->regulators[1].supply = "vddio";
+	error = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(data->regulators),
+				      data->regulators);
+	if (error) {
+		dev_err(&client->dev, "Failed to get regulators %d\n", error);
+		return error;
+	}
+
+	error = devm_add_action_or_reset(&client->dev, fts_power_off, data);
+	if (error) {
+		dev_err(&client->dev, "failed to install power off handler\n");
+		return error;
+	}
+
+	error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+					fts_ts_interrupt, IRQF_ONESHOT,
+					client->name, data);
+	if (error) {
+		dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
+		return error;
+	}
+
+	error = fts_input_init(data);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static int fts_pm_suspend(struct device *dev)
+{
+	struct fts_ts_data *data = dev_get_drvdata(dev);
+
+	mutex_lock(&data->input_dev->mutex);
+
+	if (input_device_enabled(data->input_dev))
+		fts_stop(data);
+
+	mutex_unlock(&data->input_dev->mutex);
+
+	return 0;
+}
+
+static int fts_pm_resume(struct device *dev)
+{
+	struct fts_ts_data *data = dev_get_drvdata(dev);
+	int error = 0;
+
+	mutex_lock(&data->input_dev->mutex);
+
+	if (input_device_enabled(data->input_dev))
+		error = fts_start(data);
+
+	mutex_unlock(&data->input_dev->mutex);
+
+	return error;
+}
+
+static const struct dev_pm_ops fts_dev_pm_ops = {
+	.suspend = fts_pm_suspend,
+	.resume = fts_pm_resume,
+};
+
+static const struct of_device_id fts_match_table[] = {
+	{ .compatible = "focaltech,fts5452", },
+	{ .compatible = "focaltech,fts8719", },
+	{ /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, fts_match_table);
+
+static struct i2c_driver fts_ts_driver = {
+	.probe_new = fts_ts_probe,
+	.driver = {
+		.name = FTS_DRIVER_NAME,
+		.pm = &fts_dev_pm_ops,
+		.of_match_table = fts_match_table,
+	},
+};
+module_i2c_driver(fts_ts_driver);
+
+MODULE_AUTHOR("Joel Selvaraj <joelselvaraj.oss@gmail.com>");
+MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
+MODULE_DESCRIPTION("FocalTech touchscreen Driver");
+MODULE_LICENSE("GPL");
-- 
2.39.2


^ permalink raw reply related

* [PATCH 3/5] arm64: dts: qcom: sdm845-xiaomi-beryllium-common: add touchscreen related nodes
From: Joel Selvaraj @ 2023-03-12  9:32 UTC (permalink / raw)
  To: Caleb Connolly, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Andy Gross, Bjorn Andersson, Konrad Dybcio, Henrik Rydberg,
	Arnd Bergmann, Robert Jarzmik, Jeff LaBundy, Neil Armstrong,
	Markuss Broks, Jean Delvare, Max Krummenacher, Job Noorman,
	Alistair Francis, Chris Morgan
  Cc: linux-input, devicetree, linux-kernel, linux-arm-msm,
	~postmarketos/upstreaming, phone-devel, Joel Selvaraj
In-Reply-To: <20230312093249.1846993-1-joelselvaraj.oss@gmail.com>

Enable qupv3_id_1 and gpi_dma1 as they are required for configuring
touchscreen. Also add pinctrl configurations needed for touchscreen.
These are common for both the tianma and ebbg touchscreen variant.
In the subsequent patch, we will initially enable support for the focaltech
touchscreen used in the EBBG variant. This is done in preparation for that.

Signed-off-by: Joel Selvaraj <joelselvaraj.oss@gmail.com>
---
 .../qcom/sdm845-xiaomi-beryllium-common.dtsi  | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index e0fda4d754fe..ecfd85bde966 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -270,6 +270,10 @@ &gmu {
 	status = "okay";
 };
 
+&gpi_dma1 {
+	status = "okay";
+};
+
 &gpu {
 	status = "okay";
 
@@ -368,6 +372,10 @@ &qupv3_id_0 {
 	status = "okay";
 };
 
+&qupv3_id_1 {
+	status = "okay";
+};
+
 &sdhc_2 {
 	status = "okay";
 
@@ -473,6 +481,37 @@ sdc2_card_det_n: sd-card-det-n-state {
 		function = "gpio";
 		bias-pull-up;
 	};
+
+	ts_int_default: ts-int-default-state {
+		pins = "gpio31";
+		function = "gpio";
+		drive-strength = <16>;
+		bias-pull-down;
+		input-enable;
+	};
+
+	ts_reset_default: ts-reset-default-state {
+		pins = "gpio32";
+		function = "gpio";
+		drive-strength = <16>;
+		output-high;
+	};
+
+	ts_int_sleep: ts-int-sleep-state {
+		pins = "gpio31";
+		function = "gpio";
+		drive-strength = <2>;
+		bias-pull-down;
+		input-enable;
+	};
+
+	ts_reset_sleep: ts-reset-sleep-state {
+		pins = "gpio32";
+		function = "gpio";
+		drive-strength = <2>;
+		bias-disable;
+		output-low;
+	};
 };
 
 &uart6 {
-- 
2.39.2


^ permalink raw reply related

* [PATCH 4/5] arm64: dts: qcom: sdm845-xiaomi-beryllium-ebbg: introduce support for fts touchscreen
From: Joel Selvaraj @ 2023-03-12  9:32 UTC (permalink / raw)
  To: Caleb Connolly, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Andy Gross, Bjorn Andersson, Konrad Dybcio, Henrik Rydberg,
	Arnd Bergmann, Robert Jarzmik, Jeff LaBundy, Neil Armstrong,
	Markuss Broks, Jean Delvare, Max Krummenacher, Job Noorman,
	Alistair Francis, Chris Morgan
  Cc: linux-input, devicetree, linux-kernel, linux-arm-msm,
	~postmarketos/upstreaming, phone-devel, Joel Selvaraj
In-Reply-To: <20230312093249.1846993-1-joelselvaraj.oss@gmail.com>

The Poco F1 EBBG variant uses Focaltech FTS touchscreen. Introduce
support for it.

Signed-off-by: Joel Selvaraj <joelselvaraj.oss@gmail.com>
---
 .../dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
index 76931ebad065..a23be4c8e1bb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
@@ -13,3 +13,30 @@ &display_panel {
 	compatible = "ebbg,ft8719";
 	status = "okay";
 };
+
+&i2c14 {
+	status = "okay";
+
+	dmas =  <&gpi_dma1 0 6 QCOM_GPI_I2C>,
+		<&gpi_dma1 1 6 QCOM_GPI_I2C>;
+	dma-names = "tx", "rx";
+
+	touchscreen: focaltech@38 {
+		compatible = "focaltech,fts8719";
+		reg = <0x38>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <31 IRQ_TYPE_EDGE_RISING>;
+
+		vddio-supply = <&vreg_l14a_1p8>;
+
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&ts_int_default &ts_reset_default>;
+		pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+
+		reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+
+		touchscreen-size-x = <1080>;
+		touchscreen-size-y = <2246>;
+		focaltech,max-touch-number = <10>;
+	};
+};
-- 
2.39.2


^ permalink raw reply related

* [PATCH 5/5] arm64: dts: qcom: sdm845-shift-axolotl: update focaltech touchscreen properties
From: Joel Selvaraj @ 2023-03-12  9:32 UTC (permalink / raw)
  To: Caleb Connolly, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Andy Gross, Bjorn Andersson, Konrad Dybcio, Henrik Rydberg,
	Arnd Bergmann, Robert Jarzmik, Jeff LaBundy, Neil Armstrong,
	Markuss Broks, Jean Delvare, Max Krummenacher, Job Noorman,
	Alistair Francis, Chris Morgan
  Cc: linux-input, devicetree, linux-kernel, linux-arm-msm,
	~postmarketos/upstreaming, phone-devel, Joel Selvaraj
In-Reply-To: <20230312093249.1846993-1-joelselvaraj.oss@gmail.com>

The touchscreen nodes were added before the driver patches were merged.
Update the focaltech touchscreen properties to match with the upstreamed
focaltech driver. Also, the touchscreen used is in axolotl is fts5452
and not fts8719.

Signed-off-by: Joel Selvaraj <joelselvaraj.oss@gmail.com>
---
 .../boot/dts/qcom/sdm845-shift-axolotl.dts      | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
index b54e304abf71..39f59ee3612a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
@@ -473,21 +473,22 @@ zap-shader {
 &i2c5 {
 	status = "okay";
 
-	touchscreen@38 {
-		compatible = "focaltech,fts8719";
+	touchscreen: focaltech@38 {
+		compatible = "focaltech,fts5452";
 		reg = <0x38>;
-		wakeup-source;
+
 		interrupt-parent = <&tlmm>;
-		interrupts = <125 0x2>;
-		vdd-supply = <&vreg_l28a_3p0>;
-		vcc-i2c-supply = <&vreg_l14a_1p88>;
+		interrupts = <125 IRQ_TYPE_EDGE_FALLING>;
+
+		avdd-supply = <&vreg_l28a_3p0>;
+		vddio-supply = <&vreg_l14a_1p88>;
 
 		pinctrl-names = "default", "suspend";
 		pinctrl-0 = <&ts_int_active &ts_reset_active>;
 		pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
 
-		reset-gpio = <&tlmm 99 GPIO_ACTIVE_HIGH>;
-		irq-gpio = <&tlmm 125 GPIO_TRANSITORY>;
+		reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
+
 		touchscreen-size-x = <1080>;
 		touchscreen-size-y = <2160>;
 		focaltech,max-touch-number = <5>;
-- 
2.39.2


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox