* Re: [PATCH] Series-to: LKML <linux-kernel@vger.kernel.org>
From: Benjamin Tissoires @ 2023-04-03 16:47 UTC (permalink / raw)
To: Torsha Banerjee
Cc: u-boot, Jing, Sean, Jora Jacobi, Harry Cutts, Torsha Banerjee,
Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <20230331224536.1685149-1-torsha@google.com>
Hi Torsha,
Well, your commit title is just wrong, it should not start by
"Series-to: LKML ", which seems very much like a badly configured client
;)
On Mar 31 2023, Torsha Banerjee wrote:
> From: Jora Jacobi <jora@google.com>
This is much better than v1: we got the from and a matching S-o-B :)
So thanks for that.
>
> Restore missing cursor for digitizer devices
>
> A previously committed patch to remove cursors for HID Digitizer-Pen
> devices also removed the cursors for some tablets which have incorrect HID
> descriptors. These devices should enumerate with Usage ID "Digitizer"
> instead of Usage ID "Pen".
>
> Patch which introduced the issue: commit 8473a93d1ba5
> ("HID: input: Set INPUT_PROP_-property for HID_UP_DIGITIZERS")
>
> Changes-
> Add HID quirk HID_QUIRK_DEVICE_IS_DIGITIZER
> Quirk will force INPUT_PROP_POINTER for HID Digitizers
> Apply quirk to Huion tablets
> Apply quirk to UGEE/XP-Pen tablets based on device ID
>
> Tested with Huion H640P and H430P. Connected the digitizer to the
> Chromebook and confirmed with a drawing program that the cursor appears and
> moves when the digitizer's stylus is hovering over the surface of the
> digitizer.
Would you mind re-testing the issue against the branch for-6.4/core of
hid.git[0]
IIRC UCLogic tablets where having an issue after Commit f7d8e387d9ae
("HID: uclogic: Switch to Digitizer usage for styluses") and it was
manually fixed in 3405a4beaaa8 ("HID: uclogic: Add HID_QUIRK_HIDINPUT_FORCE
quirk")
One proposed solution was to use a0f5276716c8 ("HID: Recognize "Digitizer"
as a valid input application"), and given that it was slightly broader,
I was initially reluctant to take it.
Given that Huion tablets tend to use hid-uclogic, I hope that it's
already fixed, and we don't even need to do more work to have your problem
resolved.
Cheers,
Benjamin
[0] https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git/log/?h=for-6.4/core
>
> Signed-off-by: Jora Jacobi <jora@google.com>
> Reviewed-by: Harry Cutts <hcutts@chromium.org>
> Signed-off-by: Torsha Banerjee <torsha@google.com>
> ---
>
> drivers/hid/hid-input.c | 3 ++-
> drivers/hid/hid-quirks.c | 9 +++++++++
> include/linux/hid.h | 1 +
> 3 files changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 7fc967964dd8..f0c67baddc8d 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -927,7 +927,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
> break;
>
> case HID_UP_DIGITIZER:
> - if ((field->application & 0xff) == 0x01) /* Digitizer */
> + if (((field->application & 0xff) == 0x01) ||
> + (device->quirks & HID_QUIRK_DEVICE_IS_DIGITIZER)) /* Digitizer */
> __set_bit(INPUT_PROP_POINTER, input->propbit);
> else if ((field->application & 0xff) == 0x02) /* Pen */
> __set_bit(INPUT_PROP_DIRECT, input->propbit);
> diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
> index 66e64350f138..094fe4c4f3b3 100644
> --- a/drivers/hid/hid-quirks.c
> +++ b/drivers/hid/hid-quirks.c
> @@ -102,6 +102,8 @@ static const struct hid_device_id hid_quirks[] = {
> { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0941), HID_QUIRK_ALWAYS_POLL },
> { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
> { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a), HID_QUIRK_ALWAYS_POLL },
> + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_HS64), HID_QUIRK_DEVICE_IS_DIGITIZER },
> + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET), HID_QUIRK_DEVICE_IS_DIGITIZER },
> { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
> { HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
> { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
> @@ -1298,6 +1300,13 @@ unsigned long hid_lookup_quirk(const struct hid_device *hdev)
> quirks = hid_gets_squirk(hdev);
> mutex_unlock(&dquirks_lock);
>
> + /*
> + * UGEE/XP-Pen HID Pen devices which have 0x0-0x9 as the low nibble
> + * of the device ID are actually digitizers, not HID Pen devices
> + */
> + if (hdev->vendor == USB_VENDOR_ID_UGEE && (hdev->product & 0x0F) <= 0x09)
> + quirks |= HID_QUIRK_DEVICE_IS_DIGITIZER;
> +
> return quirks;
> }
> EXPORT_SYMBOL_GPL(hid_lookup_quirk);
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 1ea8c7a3570b..1653359002b3 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -354,6 +354,7 @@ struct hid_item {
> #define HID_QUIRK_INPUT_PER_APP BIT(11)
> #define HID_QUIRK_X_INVERT BIT(12)
> #define HID_QUIRK_Y_INVERT BIT(13)
> +#define HID_QUIRK_DEVICE_IS_DIGITIZER BIT(14)
> #define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16)
> #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17)
> #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18)
> --
> 2.40.0.348.gf938b09366-goog
>
^ permalink raw reply
* Re: [PATCH 00/11] selftests: hid: import the tests from hid-tools
From: Benjamin Tissoires @ 2023-04-03 16:20 UTC (permalink / raw)
To: Jiri Kosina, Shuah Khan
Cc: linux-input, linux-kselftest, linux-kernel, Peter Hutterer,
Candle Sun, Jose Torreguitar, Roderick Colenbrander, Silvan Jegen,
Kai-Heng Feng, наб, Blaž Hrastnik,
Jason Gerecke, Nicolas Saenz Julienne
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>
On Feb 17 2023, Benjamin Tissoires wrote:
> I have been running hid-tools for a while, but it was in its own
> separate repository for multiple reasons. And the past few weeks
> I finally managed to make the kernel tests in that repo in a
> state where we can merge them in the kernel tree directly:
>
> - the tests run in ~2 to 3 minutes
> - the tests are way more reliable than previously
> - the tests are mostly self-contained now (to the exception
> of the Sony ones)
>
> To be able to run the tests we need to use the latest release
> of hid-tools, as this project still keeps the HID parsing logic
> and is capable of generating the HID events.
>
> The series also ensures we can run the tests with vmtest.sh,
> allowing for a quick development and test in the tree itself.
>
> This should allow us to require tests to be added to a series
> when we see fit and keep them alive properly instead of having
> to deal with 2 repositories.
>
> In Cc are all of the people who participated in the elaboration
> of those tests, so please send back a signed-off-by for each
> commit you are part of.
>
> This series applies on top of the for-6.3/hid-bpf branch, which
> is the one that added the tools/testing/selftests/hid directory.
> Given that this is unlikely this series will make the cut for
> 6.3, we might just consider this series to be based on top of
> the future 6.3-rc1.
>
> Cheers,
> Benjamin
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
Jiri, do you mind if I push that code in the hid tree with the following
changes:
- Peter privately gave me his signed-off-by
- I included changes from https://gitlab.freedesktop.org/libevdev/hid-tools/-/merge_requests/143
to fix the failing sony tests in v6.3
I am not a big fan of sending a v2 because the ML are not happy with the
amount of changes...
Cheers,
Benjamin
> Benjamin Tissoires (11):
> selftests: hid: make vmtest rely on make
> selftests: hid: import hid-tools hid-core tests
> selftests: hid: import hid-tools hid-gamepad tests
> selftests: hid: import hid-tools hid-keyboards tests
> selftests: hid: import hid-tools hid-mouse tests
> selftests: hid: import hid-tools hid-multitouch and hid-tablets tests
> selftests: hid: import hid-tools wacom tests
> selftests: hid: import hid-tools hid-apple tests
> selftests: hid: import hid-tools hid-ite tests
> selftests: hid: import hid-tools hid-sony and hid-playstation tests
> selftests: hid: import hid-tools usb-crash tests
>
> tools/testing/selftests/hid/Makefile | 12 +
> tools/testing/selftests/hid/config | 11 +
> tools/testing/selftests/hid/hid-apple.sh | 7 +
> tools/testing/selftests/hid/hid-core.sh | 7 +
> tools/testing/selftests/hid/hid-gamepad.sh | 7 +
> tools/testing/selftests/hid/hid-ite.sh | 7 +
> tools/testing/selftests/hid/hid-keyboard.sh | 7 +
> tools/testing/selftests/hid/hid-mouse.sh | 7 +
> tools/testing/selftests/hid/hid-multitouch.sh | 7 +
> tools/testing/selftests/hid/hid-sony.sh | 7 +
> tools/testing/selftests/hid/hid-tablet.sh | 7 +
> tools/testing/selftests/hid/hid-usb_crash.sh | 7 +
> tools/testing/selftests/hid/hid-wacom.sh | 7 +
> tools/testing/selftests/hid/run-hid-tools-tests.sh | 28 +
> tools/testing/selftests/hid/settings | 3 +
> tools/testing/selftests/hid/tests/__init__.py | 2 +
> tools/testing/selftests/hid/tests/base.py | 345 ++++
> tools/testing/selftests/hid/tests/conftest.py | 81 +
> .../selftests/hid/tests/descriptors_wacom.py | 1360 +++++++++++++
> .../selftests/hid/tests/test_apple_keyboard.py | 440 +++++
> tools/testing/selftests/hid/tests/test_gamepad.py | 209 ++
> tools/testing/selftests/hid/tests/test_hid_core.py | 154 ++
> .../selftests/hid/tests/test_ite_keyboard.py | 166 ++
> tools/testing/selftests/hid/tests/test_keyboard.py | 485 +++++
> tools/testing/selftests/hid/tests/test_mouse.py | 977 +++++++++
> .../testing/selftests/hid/tests/test_multitouch.py | 2088 ++++++++++++++++++++
> tools/testing/selftests/hid/tests/test_sony.py | 282 +++
> tools/testing/selftests/hid/tests/test_tablet.py | 872 ++++++++
> .../testing/selftests/hid/tests/test_usb_crash.py | 103 +
> .../selftests/hid/tests/test_wacom_generic.py | 844 ++++++++
> tools/testing/selftests/hid/vmtest.sh | 25 +-
> 31 files changed, 8554 insertions(+), 10 deletions(-)
> ---
> base-commit: 2f7f4efb9411770b4ad99eb314d6418e980248b4
> change-id: 20230217-import-hid-tools-tests-dc0cd4f3c8a8
>
> Best regards,
> --
> Benjamin Tissoires <benjamin.tissoires@redhat.com>
>
^ permalink raw reply
* Re: [PATCH v3 1/6] HID: logitech-hidpp: Simplify array length check
From: Benjamin Tissoires @ 2023-04-03 13:33 UTC (permalink / raw)
To: linux-usb, linux-input, Bastien Nocera
Cc: Greg Kroah-Hartman, Alan Stern, Filipe Laíns,
Nestor Lopez Casado
In-Reply-To: <20230302105555.51417-1-hadess@hadess.net>
On Thu, 02 Mar 2023 11:55:50 +0100, Bastien Nocera wrote:
> Use the compiler to force a 100-length array, rather than check the
> length after the fact.
>
>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git (for-6.4/logitech-hidpp), thanks!
[1/6] HID: logitech-hidpp: Simplify array length check
https://git.kernel.org/hid/hid/c/e0138763be2d
[2/6] HID: logitech-hidpp: Add support for ADC measurement feature
https://git.kernel.org/hid/hid/c/c361982a13c9
[3/6] HID: logitech-hidpp: Add Logitech G935 headset
https://git.kernel.org/hid/hid/c/4a1529f44e32
[4/6] USB: core: Add wireless_status sysfs attribute
https://git.kernel.org/hid/hid/c/f98e0640c5c6
[5/6] USB: core: Add API to change the wireless_status
https://git.kernel.org/hid/hid/c/0a4db185f078
[6/6] HID: logitech-hidpp: Set wireless_status for G935 receiver
https://git.kernel.org/hid/hid/c/d9d5623f37c0
Cheers,
--
Benjamin Tissoires <benjamin.tissoires@redhat.com>
^ permalink raw reply
* Re: [PATCH 1/2] HID: logitech-hidpp: Don't use the USB serial for USB devices
From: Benjamin Tissoires @ 2023-04-03 13:33 UTC (permalink / raw)
To: linux-input, Bastien Nocera
Cc: linux-kernel, Jiri Kosina, Peter F . Patel-Schneider,
Filipe Laíns, Nestor Lopez Casado
In-Reply-To: <20230302130117.3975-1-hadess@hadess.net>
On Thu, 02 Mar 2023 14:01:16 +0100, Bastien Nocera wrote:
> For devices that support the 0x0003 feature (Device Information) version 4,
> set the serial based on the output of that feature, rather than relying
> on the usbhid code setting the USB serial.
>
> This should allow the serial when connected through USB to (nearly)
> match the one when connected through a unifying receiver.
>
> [...]
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git (for-6.4/logitech-hidpp), thanks!
[1/2] HID: logitech-hidpp: Don't use the USB serial for USB devices
https://git.kernel.org/hid/hid/c/7ad1fe0da0fa
[2/2] HID: logitech-hidpp: Reconcile USB and Unifying serials
https://git.kernel.org/hid/hid/c/5b3691d15e04
Cheers,
--
Benjamin Tissoires <benjamin.tissoires@redhat.com>
^ permalink raw reply
* Re: [PATCH V2] dt-bindings: input: pwm-beeper: convert to dt schema
From: Rob Herring @ 2023-04-03 13:10 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: robh+dt, s.hauer, linux-kernel, linux-input, Peng Fan,
krzysztof.kozlowski+dt, devicetree, dmitry.torokhov
In-Reply-To: <20230403090640.3237060-1-peng.fan@oss.nxp.com>
On Mon, 03 Apr 2023 17:06:40 +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Convert the binding doc to dt schema, and also fixed the
> example from fixed-regulator to regulator-fixed.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>
> V2:
> License update
> Don't need to show providers
> Make example complete
> Decrease beeper hz
> Misc update
>
> .../devicetree/bindings/input/pwm-beeper.txt | 24 -----------
> .../devicetree/bindings/input/pwm-beeper.yaml | 42 +++++++++++++++++++
> 2 files changed, 42 insertions(+), 24 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/input/pwm-beeper.txt
> create mode 100644 Documentation/devicetree/bindings/input/pwm-beeper.yaml
>
Running 'make dtbs_check' with the schema in this patch gives the
following warnings. Consider if they are expected or the schema is
incorrect. These may not be new warnings.
Note that it is not yet a requirement to have 0 warnings for dtbs_check.
This will change in the future.
Full log is available here: https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230403090640.3237060-1-peng.fan@oss.nxp.com
beeper: beeper-hz:0:0: 4000 is greater than the maximum of 4
arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dtb
arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dtb
arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dtb
beeper: Unevaluated properties are not allowed ('beeper-hz' was unexpected)
arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dtb
arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dtb
arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dtb
^ permalink raw reply
* [PATCH 2/2] Input: st1232 - add wake up event counting
From: Javier Carrasco @ 2023-04-03 12:47 UTC (permalink / raw)
To: linux-input, linux-kernel
Cc: Dmitry Torokhov, Jonathan Cameron, Linus Walleij, Uwe Kleine-g,
Michael Riesch, Javier Carrasco
In-Reply-To: <20230403124707.102986-1-javier.carrasco@wolfvision.net>
This device driver provides wakeup capabilities but the wakeup events
are not reflected in sysfs. Add pm_wakeup_event to the interrupt handler
in order to do so.
Signed-off-by: Javier Carrasco <javier.carrasco@wolfvision.net>
---
drivers/input/touchscreen/st1232.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index faa0be3993f4..f175bea464e1 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -59,6 +59,7 @@ struct st1232_ts_data {
const struct st_chip_info *chip_info;
int read_buf_len;
u8 *read_buf;
+ bool suspended;
};
static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg,
@@ -173,9 +174,13 @@ static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
{
struct st1232_ts_data *ts = dev_id;
+ struct i2c_client *client = ts->client;
int count;
int error;
+ if (ts->suspended && device_may_wakeup(&client->dev))
+ pm_wakeup_event(&client->dev, 0);
+
error = st1232_ts_read_data(ts, REG_XY_COORDINATES, ts->read_buf_len);
if (error)
goto out;
@@ -344,10 +349,16 @@ static int st1232_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
+ struct input_dev *input = ts->input_dev;
+
+ mutex_lock(&input->mutex);
+ ts->suspended = true;
if (!device_may_wakeup(&client->dev))
st1232_ts_power(ts, false);
+ mutex_unlock(&input->mutex);
+
return 0;
}
@@ -355,10 +366,16 @@ static int st1232_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
+ struct input_dev *input = ts->input_dev;
+
+ mutex_lock(&input->mutex);
+ ts->suspended = false;
if (!device_may_wakeup(&client->dev))
st1232_ts_power(ts, true);
+ mutex_unlock(&input->mutex);
+
return 0;
}
--
2.37.2
^ permalink raw reply related
* [PATCH 0/2] Input: st1232: wakeup in Suspend to idle
From: Javier Carrasco @ 2023-04-03 12:47 UTC (permalink / raw)
To: linux-input, linux-kernel
Cc: Dmitry Torokhov, Jonathan Cameron, Linus Walleij, Uwe Kleine-g,
Michael Riesch, Javier Carrasco
The st1232 touchscreen provides an interrupt line that can be configured
as a wakeup source, and currently it is possible to use this mechanism in
"Suspend to RAM" and "Hibernate" power states.
Unfortunately, that does not work in "Suspend to idle" (freeze) because
the device driver disables the interrupts in its suspend callback.
Given that the interrupt handling prior to entering the mentioned power
state modes is managed by the power subsystem, the irq enabling/disabling
can be removed from the touchscreen driver, allowing the device to work
as a wakeup source in "Suspend to idle".
Given that the st1232 device driver does not reflect its wakeup events
in sysfs, this series also adds pm_wakeup_event to the interrupt
handler.
These changes have been successfully tested with an ST1624-N32C and a
Rockchip-based platform.
Javier Carrasco (2):
Input: st1232 - remove enable/disable irq in resume/suspend callbacks
Input: st1232 - add wake up event counting
drivers/input/touchscreen/st1232.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
--
2.37.2
^ permalink raw reply
* [PATCH 1/2] Input: st1232 - remove enable/disable irq in resume/suspend callbacks
From: Javier Carrasco @ 2023-04-03 12:47 UTC (permalink / raw)
To: linux-input, linux-kernel
Cc: Dmitry Torokhov, Jonathan Cameron, Linus Walleij, Uwe Kleine-g,
Michael Riesch, Javier Carrasco
In-Reply-To: <20230403124707.102986-1-javier.carrasco@wolfvision.net>
Disabling the interrupts in the suspend callback leads to a loss of the
wakeup capability in suspend to idle (freeze) mode.
In commit 95dc58a9a02f ("Input: st1232 - rely on I2C core to configure
wakeup interrupt") redundancy was removed by letting the I2C core manage
the wake interrupt handling. On the other hand, the irq enabling/disabling
was generalized to all devices, regardless of their wakeup capabilities.
The interrupt enabling/disabling is carried out by the power subsystem in
the resume/suspend states and therefore there is no need to manage it
in the device driver. Remove the irq handling in the driver-specific
resume/suspend callbacks and rely on the power subsystem.
Fixes: 95dc58a9a02f ("Input: st1232 - rely on I2C core to configure wakeup interrupt")
Signed-off-by: Javier Carrasco <javier.carrasco@wolfvision.net>
---
drivers/input/touchscreen/st1232.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index f49566dc96f8..faa0be3993f4 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -345,8 +345,6 @@ static int st1232_ts_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
- disable_irq(client->irq);
-
if (!device_may_wakeup(&client->dev))
st1232_ts_power(ts, false);
@@ -361,8 +359,6 @@ static int st1232_ts_resume(struct device *dev)
if (!device_may_wakeup(&client->dev))
st1232_ts_power(ts, true);
- enable_irq(client->irq);
-
return 0;
}
--
2.37.2
^ permalink raw reply related
* [PATCH] HID: hid-stadiaff: add support for Stadia force feedback
From: Fabio Baltieri @ 2023-04-03 10:33 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: linux-input, linux-kernel, Fabio Baltieri
Add a hid-stadiaff module to support rumble based force feedback on the
Google Stadia controller. This works using the HID output endpoint
exposed on both the USB and BLE interface.
Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
Hi, this adds rumble support to the stadia controller using the input
interface. Up to now this has only been implemented at application level
using hidraw:
https://source.chromium.org/chromium/chromium/src/+/main:device/gamepad/hid_haptic_gamepad.cc
Tested with fftest, works both over USB and BLE.
drivers/hid/Kconfig | 7 ++
drivers/hid/Makefile | 1 +
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-stadiaff.c | 132 +++++++++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+)
create mode 100644 drivers/hid/hid-stadiaff.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 82f64fb31fda..934f73e9b800 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1031,6 +1031,13 @@ config HID_SPEEDLINK
help
Support for Speedlink Vicious and Divine Cezanne mouse.
+config HID_STADIA_FF
+ tristate "Google Stadia force feedback"
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you want to enable force feedback support for the Google
+ Stadia controller.
+
config HID_STEAM
tristate "Steam Controller/Deck support"
select POWER_SUPPLY
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 5d37cacbde33..1d900fa55890 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -120,6 +120,7 @@ obj-$(CONFIG_HID_SIGMAMICRO) += hid-sigmamicro.o
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
obj-$(CONFIG_HID_SONY) += hid-sony.o
obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o
+obj-$(CONFIG_HID_STADIA_FF) += hid-stadiaff.o
obj-$(CONFIG_HID_STEAM) += hid-steam.o
obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 63545cd307e5..cffd4ac609a0 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -525,6 +525,7 @@
#define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044
#define USB_DEVICE_ID_GOOGLE_DON 0x5050
#define USB_DEVICE_ID_GOOGLE_EEL 0x5057
+#define USB_DEVICE_ID_GOOGLE_STADIA 0x9400
#define USB_VENDOR_ID_GOTOP 0x08f2
#define USB_DEVICE_ID_SUPER_Q2 0x007f
diff --git a/drivers/hid/hid-stadiaff.c b/drivers/hid/hid-stadiaff.c
new file mode 100644
index 000000000000..f974b9e24d46
--- /dev/null
+++ b/drivers/hid/hid-stadiaff.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Stadia controller rumble support.
+ *
+ * Copyright 2023 Google LLC
+ */
+
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define STADIA_FF_REPORT_ID 5
+
+struct stadiaff_device {
+ struct hid_device *hid;
+ struct hid_report *report;
+ struct work_struct work;
+};
+
+static void stadiaff_work(struct work_struct *work)
+{
+ struct stadiaff_device *stadiaff =
+ container_of(work, struct stadiaff_device, work);
+
+ hid_hw_request(stadiaff->hid, stadiaff->report, HID_REQ_SET_REPORT);
+}
+
+static int stadiaff_play(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct stadiaff_device *stadiaff = hid_get_drvdata(hid);
+ struct hid_field *rumble_field = stadiaff->report->field[0];
+
+ rumble_field->value[0] = effect->u.rumble.strong_magnitude;
+ rumble_field->value[1] = effect->u.rumble.weak_magnitude;
+
+ schedule_work(&stadiaff->work);
+
+ return 0;
+}
+
+static int stadiaff_init(struct hid_device *hid)
+{
+ struct stadiaff_device *stadiaff;
+ struct hid_report *report;
+ struct hid_input *hidinput;
+ struct input_dev *dev;
+ int error;
+
+ if (list_empty(&hid->inputs)) {
+ hid_err(hid, "no inputs found\n");
+ return -ENODEV;
+ }
+ hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ dev = hidinput->input;
+
+ report = hid_validate_values(hid, HID_OUTPUT_REPORT,
+ STADIA_FF_REPORT_ID, 0, 2);
+ if (!report)
+ return -ENODEV;
+
+ stadiaff = devm_kzalloc(&hid->dev, sizeof(struct stadiaff_device),
+ GFP_KERNEL);
+ if (!stadiaff)
+ return -ENOMEM;
+
+ hid_set_drvdata(hid, stadiaff);
+
+ input_set_capability(dev, EV_FF, FF_RUMBLE);
+
+ error = input_ff_create_memless(dev, NULL, stadiaff_play);
+ if (error)
+ return error;
+
+ stadiaff->hid = hid;
+ stadiaff->report = report;
+ INIT_WORK(&stadiaff->work, stadiaff_work);
+
+ hid_info(hid, "Force Feedback for Google Stadia controller\n");
+
+ return 0;
+}
+
+static int stadia_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "parse failed\n");
+ return ret;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ hid_err(hdev, "hw start failed\n");
+ return ret;
+ }
+
+ stadiaff_init(hdev);
+
+ return 0;
+}
+
+static void stadia_remove(struct hid_device *hid)
+{
+ struct stadiaff_device *stadiaff = hid_get_drvdata(hid);
+
+ cancel_work_sync(&stadiaff->work);
+ hid_hw_stop(hid);
+}
+
+static const struct hid_device_id stadia_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STADIA) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STADIA) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, stadia_devices);
+
+static struct hid_driver stadia_driver = {
+ .name = "stadia",
+ .id_table = stadia_devices,
+ .probe = stadia_probe,
+ .remove = stadia_remove,
+};
+module_hid_driver(stadia_driver);
+
+MODULE_LICENSE("GPL");
--
2.40.0.348.gf938b09366-goog
^ permalink raw reply related
* [PATCH V2] dt-bindings: input: pwm-beeper: convert to dt schema
From: Peng Fan (OSS) @ 2023-04-03 9:06 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, s.hauer
Cc: linux-input, devicetree, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Convert the binding doc to dt schema, and also fixed the
example from fixed-regulator to regulator-fixed.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
V2:
License update
Don't need to show providers
Make example complete
Decrease beeper hz
Misc update
.../devicetree/bindings/input/pwm-beeper.txt | 24 -----------
.../devicetree/bindings/input/pwm-beeper.yaml | 42 +++++++++++++++++++
2 files changed, 42 insertions(+), 24 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/input/pwm-beeper.txt
create mode 100644 Documentation/devicetree/bindings/input/pwm-beeper.yaml
diff --git a/Documentation/devicetree/bindings/input/pwm-beeper.txt b/Documentation/devicetree/bindings/input/pwm-beeper.txt
deleted file mode 100644
index 8fc0e48c20db..000000000000
--- a/Documentation/devicetree/bindings/input/pwm-beeper.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-* PWM beeper device tree bindings
-
-Registers a PWM device as beeper.
-
-Required properties:
-- compatible: should be "pwm-beeper"
-- pwms: phandle to the physical PWM device
-
-Optional properties:
-- amp-supply: phandle to a regulator that acts as an amplifier for the beeper
-- beeper-hz: bell frequency in Hz
-
-Example:
-
-beeper_amp: amplifier {
- compatible = "fixed-regulator";
- gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
-};
-
-beeper {
- compatible = "pwm-beeper";
- pwms = <&pwm0>;
- amp-supply = <&beeper_amp>;
-};
diff --git a/Documentation/devicetree/bindings/input/pwm-beeper.yaml b/Documentation/devicetree/bindings/input/pwm-beeper.yaml
new file mode 100644
index 000000000000..a3797f338f46
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/pwm-beeper.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/pwm-beeper.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PWM beeper
+
+maintainers:
+ - Sascha Hauer <s.hauer@pengutronix.de>
+
+properties:
+ compatible:
+ const: pwm-beeper
+
+ pwms:
+ description: Phandle to the physical PWM device
+ maxItems: 1
+
+ amp-supply:
+ description: Phandle to a regulator that acts as an amplifier for the beeper
+
+ beeper-hz:
+ description: bell frequency in Hz
+ minimum: 1
+ maximum: 4
+
+required:
+ - compatible
+ - pwms
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ beeper {
+ compatible = "pwm-beeper";
+ pwms = <&pwm0>;
+ amp-supply = <&beeper_amp>;
+ beeper-hz = <1>;
+ };
--
2.37.1
^ permalink raw reply related
* Seeking directions: Workaround for failed keyboard initialization on some Lenovo laptops
From: Shang Ye @ 2023-04-03 7:42 UTC (permalink / raw)
To: linux-input
Hi,
There have been quite a few reports about failed keyboard initialization
on some 9 types of Lenovo Yoga / XiaoXinPro / IdeaPad (14", Intel)
laptops. A list of them can be found here:
https://github.com/yescallop/atkbd-nogetid#presumably-supported-machines
And a related kernel bug report can be found here:
https://bugzilla.kernel.org/show_bug.cgi?id=216994
I'd like to first provide a dmesg log (without patch) that illustrates
the problem on my Yoga 14sIHU 2021:
https://gist.github.com/yescallop/5a97d010f226172fafab0933ce8ea8af
At first the KBD port was successfully set up by `i8042`, but then the
first initialization attempt by `atkbd` failed:
[ 2.698474] i8042: [17] f2 -> i8042 (kbd-data)
[ 2.698678] i8042: [17] fa <- i8042 (interrupt, 0, 1)
[ 2.698746] i8042: [17] 83 <- i8042 (interrupt, 0, 1)
[ 2.698767] i8042: [17] 60 -> i8042 (command)
[ 2.698856] i8042: [17] 66 -> i8042 (parameter)
[ 2.698951] i8042: [17] 60 -> i8042 (command)
[ 2.699092] i8042: [17] 67 -> i8042 (parameter)
It seems that the i8042 implementation on the laptop omitted the `0xab`
byte from its response to the `GETID` command, thus making the
`atkbd_probe` function fail for receiving an invalid keyboard ID (should
normally be `0xab 0x83`).
This situation went on for a few rounds when I pressed and released the
space key (scan code: 0x39 when pressed, 0xb9 when released). The sixth
time I pressed the space key, something different happened:
[ 48.188540] i8042: [13664] 39 <- i8042 (interrupt, 0, 1)
[ 48.188658] i8042: [13664] f2 -> i8042 (kbd-data)
[ 48.188998] i8042: [13664] fa <- i8042 (interrupt, 0, 1)
[ 48.709743] i8042: [13821] ed -> i8042 (kbd-data)
[ 48.913069] i8042: [13882] 60 -> i8042 (command)
[ 48.913235] i8042: [13882] 66 -> i8042 (parameter)
[ 48.913446] i8042: [13882] 60 -> i8042 (command)
[ 48.913591] i8042: [13882] 67 -> i8042 (parameter)
[ 48.913672] i8042: [13882] fa <- i8042 (interrupt, 0, 0)
This time even the byte `0x83` was omitted, so the `GETID` command
failed and `atkbd_probe` tried to set the LEDs on the keyboard, but
failed again for not receiving an ACK to the command byte `0xed`.
However, when `i8042_port_close` was later called, an ACK was read from
the KBD port, which is an indication that the i8042 implementation might
have failed to raise an interrupt for this ACK.
And the next time I released the space key, the byte `0x83` was omitted
again, but `atkbd_probe` somehow succeeded in receiving an ACK to the
`SETLEDS` command, and the keyboard was finally initialized properly.
An easy workaround is to add a kernel parameter `i8042.dumbkbd` in the
boot loader, but as this makes the Caps Lock LED unusable, some other
solutions should be considered when it comes to patching the kernel.
Here I provide two possible solutions:
1. Add a module parameter in `atkbd`, say `assume_normal_kbd`, that,
when set to true, makes `atkbd_probe` skip sending the `GETID`
command and set the keyboard ID directly to `0xab83`. Then, add
quirks to make it a default for the affected machines.
2. In `atkbd_probe`: Call `i8042_flush` immediately after the `GETID`
command is finished, to get rid of any remaining byte in the
keyboard buffer that is not properly signaled by an interrupt. Then,
if the command failed or the keyboard ID is invalid, try to set the
LEDs on anything connected to the KBD port.
I have tried both solutions and both worked nicely on my laptop, but
there might be some problems with them:
* For the first solution: Do we add a module parameter, quirks, or
both? I find that `i8042.probe_defer` is an example for adding both
of them, and `atkbd_skip_deactivate` for adding only quirks.
* For the second solution: Is it okay to flush all data in the
keyboard/mouse buffer down the toilet from this particular call site
for all machines? I suspect some special handling is required for
not flushing the data in the mouse buffer but instead sending them
to the upper layers.
* For the second solution: Will it do any harm to persistently try to
set the LEDs on a mouse connected to the KBD port? A comment in
`atkbd_probe` says "If a mouse is connected, this should make sure
we don't try to set the LEDs on it." I'm not at all familiar to PS/2
devices, so can someone maybe explain this a bit?
The second solution is, indeed, a general one that may automatically fix
similar problems on other machines, without needing to manually add
quirks in `atkbd`. A example of a similar problem on HP Spectre x360
13-aw2xxx is described here:
https://patchwork.kernel.org/project/linux-input/patch/20210201160336.16008-1-anton@cpp.in/
But it can nevertheless cause regressions if not thoroughly considered.
Thus, I'm here seeking for your directions on a workaround for this
problem, as there can be some better solution that I'm not aware of.
Thanks,
Shang
^ permalink raw reply
* Re: [PATCH 0/9] Input: edt-ft5x06 - convert to use regmap API
From: Dmitry Torokhov @ 2023-04-03 4:40 UTC (permalink / raw)
To: Dario Binacchi
Cc: linux-kernel, michael, linux-amarula, Jonathan Cameron,
Oliver Graute, Uwe Kleine-König, Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
On Sun, Apr 02, 2023 at 10:09:42PM +0200, Dario Binacchi wrote:
>
> This series converts the driver to use the regmap API for accessing the
> registers of the different models it manages, making the driver code more
> generic.
> The series has been tested on the following touchscreen models:
> - M06
> - M09
> - M12
> - EP0430MLF0M
> - generic ft5x06 (05)
>
> The series also includes some code cleaning and optimization patches.
Applied the lot, thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v5] Input: tsc2007 - enable cansleep pendown GPIO
From: Dmitry Torokhov @ 2023-04-03 4:40 UTC (permalink / raw)
To: Benjamin Bara
Cc: hns, richard.leitner, christophe.jaillet, linux-input,
linux-kernel, Benjamin Bara
In-Reply-To: <20230328-tsc2007-sleep-v5-1-fc55e76d0ced@skidata.com>
On Sun, Apr 02, 2023 at 10:00:14AM +0200, Benjamin Bara wrote:
> From: Benjamin Bara <benjamin.bara@skidata.com>
>
> When a hard IRQ is triggered, the soft IRQ, which decides if an actual
> pen down happened, should always be triggered. This enables the usage of
> "can_sleep" GPIO chips as "pen down" GPIO, as the value is not read
> during the hard IRQ anymore. This might be the case if the GPIO chip is
> an expander behind i2c.
>
> Signed-off-by: Benjamin Bara <benjamin.bara@skidata.com>
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
Applied, thank you.
--
Dmitry
^ permalink raw reply
* [PATCH 9/9] Input: edt-ft5x06: Calculate points data length only once
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
It is pointless and expensive to calculate data in the interrupt that
depends on the type of touchscreen, which is detected on the driver
probe and cannot then be changed.
So calculate the size of the data buffer on the driver probe, as well as
the data retrieval command, and then use them in the ISR.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 56 +++++++++++++-------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index fdb32e3591be..24ab9e9f5b21 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -135,6 +135,10 @@ struct edt_ft5x06_ts_data {
int offset_y;
int report_rate;
int max_support_points;
+ int point_len;
+ u8 tdata_cmd;
+ int tdata_len;
+ int tdata_offset;
char name[EDT_NAME_LEN];
char fw_version[EDT_NAME_LEN];
@@ -296,38 +300,13 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
{
struct edt_ft5x06_ts_data *tsdata = dev_id;
struct device *dev = &tsdata->client->dev;
- u8 cmd;
u8 rdbuf[63];
int i, type, x, y, id;
- int offset, tplen, datalen, crclen;
int error;
- switch (tsdata->version) {
- case EDT_M06:
- cmd = 0xf9; /* tell the controller to send touch data */
- offset = 5; /* where the actual touch data starts */
- tplen = 4; /* data comes in so called frames */
- crclen = 1; /* length of the crc data */
- break;
-
- case EDT_M09:
- case EDT_M12:
- case EV_FT:
- case GENERIC_FT:
- cmd = 0x0;
- offset = 3;
- tplen = 6;
- crclen = 0;
- break;
-
- default:
- goto out;
- }
-
memset(rdbuf, 0, sizeof(rdbuf));
- datalen = tplen * tsdata->max_support_points + offset + crclen;
-
- error = regmap_bulk_read(tsdata->regmap, cmd, rdbuf, datalen);
+ error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf,
+ tsdata->tdata_len);
if (error) {
dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
error);
@@ -335,7 +314,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
}
for (i = 0; i < tsdata->max_support_points; i++) {
- u8 *buf = &rdbuf[i * tplen + offset];
+ u8 *buf = &rdbuf[i * tsdata->point_len + tsdata->tdata_offset];
type = buf[0] >> 6;
/* ignore Reserved events */
@@ -1071,6 +1050,26 @@ static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
}
}
+static void edt_ft5x06_ts_set_tdata_parameters(struct edt_ft5x06_ts_data *tsdata)
+{
+ int crclen;
+
+ if (tsdata->version == EDT_M06) {
+ tsdata->tdata_cmd = 0xf9;
+ tsdata->tdata_offset = 5;
+ tsdata->point_len = 4;
+ crclen = 1;
+ } else {
+ tsdata->tdata_cmd = 0x0;
+ tsdata->tdata_offset = 3;
+ tsdata->point_len = 6;
+ crclen = 0;
+ }
+
+ tsdata->tdata_len = tsdata->point_len * tsdata->max_support_points +
+ tsdata->tdata_offset + crclen;
+}
+
static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
{
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
@@ -1274,6 +1273,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
*/
regmap_read(tsdata->regmap, 0x00, &val);
+ edt_ft5x06_ts_set_tdata_parameters(tsdata);
edt_ft5x06_ts_set_regs(tsdata);
edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
edt_ft5x06_ts_get_parameters(tsdata);
--
2.32.0
^ permalink raw reply related
* [PATCH 8/9] Input: edt-ft5x06 - unify the crc check
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
With this patch, the CRC is always verified by the same function, even in
the case of accessing registers where the number of bytes is minimal.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 8aae4c1e6b73..fdb32e3591be 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -240,13 +240,10 @@ static int edt_M06_i2c_read(void *context, const void *reg_buf, size_t reg_size,
if (!edt_ft5x06_ts_check_crc(tsdata, val_buf, val_size))
return -EIO;
} else if (reg_read) {
- u8 crc = wbuf[0] ^ wbuf[1] ^ rbuf[0];
-
- if (crc != rbuf[1]) {
- dev_err(dev, "crc error: 0x%02x expected, got 0x%02x\n",
- crc, rbuf[1]);
+ wbuf[2] = rbuf[0];
+ wbuf[3] = rbuf[1];
+ if (!edt_ft5x06_ts_check_crc(tsdata, wbuf, 4))
return -EIO;
- }
*((u8 *)val_buf) = rbuf[0];
}
--
2.32.0
^ permalink raw reply related
* [PATCH 7/9] Input: edt-ft5x06 - convert to use regmap API
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
It replaces custom read/write functions with regmap API, making the
driver code more generic.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 424 +++++++++++++------------
1 file changed, 214 insertions(+), 210 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 89958881fca1..8aae4c1e6b73 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -3,6 +3,7 @@
* Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
* Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support)
* Lothar Waßmann <LW@KARO-electronics.de> (DT support)
+ * Dario Binacchi <dario.binacchi@amarulasolutions.com> (regmap support)
*/
/*
@@ -26,6 +27,7 @@
#include <linux/module.h>
#include <linux/property.h>
#include <linux/ratelimit.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
@@ -115,6 +117,8 @@ struct edt_ft5x06_ts_data {
struct gpio_desc *reset_gpio;
struct gpio_desc *wake_gpio;
+ struct regmap *regmap;
+
#if defined(CONFIG_DEBUG_FS)
struct dentry *debug_dir;
u8 *raw_buffer;
@@ -145,37 +149,10 @@ struct edt_i2c_chip_data {
int max_support_points;
};
-static int edt_ft5x06_ts_readwrite(struct i2c_client *client,
- u16 wr_len, u8 *wr_buf,
- u16 rd_len, u8 *rd_buf)
-{
- struct i2c_msg wrmsg[2];
- int i = 0;
- int ret;
-
- if (wr_len) {
- wrmsg[i].addr = client->addr;
- wrmsg[i].flags = 0;
- wrmsg[i].len = wr_len;
- wrmsg[i].buf = wr_buf;
- i++;
- }
- if (rd_len) {
- wrmsg[i].addr = client->addr;
- wrmsg[i].flags = I2C_M_RD;
- wrmsg[i].len = rd_len;
- wrmsg[i].buf = rd_buf;
- i++;
- }
-
- ret = i2c_transfer(client->adapter, wrmsg, i);
- if (ret < 0)
- return ret;
- if (ret != i)
- return -EIO;
-
- return 0;
-}
+static const struct regmap_config edt_ft5x06_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,
u8 *buf, int buflen)
@@ -197,6 +174,127 @@ static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,
return true;
}
+static int edt_M06_i2c_read(void *context, const void *reg_buf, size_t reg_size,
+ void *val_buf, size_t val_size)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(i2c);
+ struct i2c_msg xfer[2];
+ bool reg_read = false;
+ u8 addr;
+ u8 wlen;
+ u8 wbuf[4], rbuf[3];
+ int ret;
+
+ addr = *((u8 *)reg_buf);
+ wbuf[0] = addr;
+ switch (addr) {
+ case 0xf5:
+ wlen = 3;
+ wbuf[0] = 0xf5;
+ wbuf[1] = 0xe;
+ wbuf[2] = *((u8 *)val_buf);
+ break;
+ case 0xf9:
+ wlen = 1;
+ break;
+ default:
+ wlen = 2;
+ reg_read = true;
+ wbuf[0] = M06_REG_CMD(tsdata->factory_mode);
+ wbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr);
+ wbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
+ }
+
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = wlen;
+ xfer[0].buf = wbuf;
+
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = reg_read ? 2 : val_size;
+ xfer[1].buf = reg_read ? rbuf : val_buf;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret != 2) {
+ if (ret < 0)
+ return ret;
+
+ return -EIO;
+ }
+
+ if (addr == 0xf9) {
+ u8 *buf = (u8 *)val_buf;
+
+ if (buf[0] != 0xaa || buf[1] != 0xaa ||
+ buf[2] != val_size) {
+ tsdata->header_errors++;
+ dev_err_ratelimited(dev,
+ "Unexpected header: %02x%02x%02x\n",
+ buf[0], buf[1], buf[2]);
+ return -EIO;
+ }
+
+ if (!edt_ft5x06_ts_check_crc(tsdata, val_buf, val_size))
+ return -EIO;
+ } else if (reg_read) {
+ u8 crc = wbuf[0] ^ wbuf[1] ^ rbuf[0];
+
+ if (crc != rbuf[1]) {
+ dev_err(dev, "crc error: 0x%02x expected, got 0x%02x\n",
+ crc, rbuf[1]);
+ return -EIO;
+ }
+
+ *((u8 *)val_buf) = rbuf[0];
+ }
+
+ return 0;
+}
+
+static int edt_M06_i2c_write(void *context, const void *data, size_t count)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(i2c);
+ u8 addr, val;
+ u8 wbuf[4];
+ struct i2c_msg xfer;
+ int ret;
+
+ addr = *((u8 *)data);
+ val = *((u8 *)data + 1);
+
+ wbuf[0] = M06_REG_CMD(tsdata->factory_mode);
+ wbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr);
+ wbuf[2] = val;
+ wbuf[3] = wbuf[0] ^ wbuf[1] ^ wbuf[2];
+
+ xfer.addr = i2c->addr;
+ xfer.flags = 0;
+ xfer.len = 4;
+ xfer.buf = wbuf;
+
+ ret = i2c_transfer(i2c->adapter, &xfer, 1);
+ if (ret != 1) {
+ if (ret < 0)
+ return ret;
+
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const struct regmap_config edt_M06_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read = edt_M06_i2c_read,
+ .write = edt_M06_i2c_write,
+};
+
static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
{
struct edt_ft5x06_ts_data *tsdata = dev_id;
@@ -232,30 +330,13 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
memset(rdbuf, 0, sizeof(rdbuf));
datalen = tplen * tsdata->max_support_points + offset + crclen;
- error = edt_ft5x06_ts_readwrite(tsdata->client,
- sizeof(cmd), &cmd,
- datalen, rdbuf);
+ error = regmap_bulk_read(tsdata->regmap, cmd, rdbuf, datalen);
if (error) {
dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
error);
goto out;
}
- /* M09/M12 does not send header or CRC */
- if (tsdata->version == EDT_M06) {
- if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
- rdbuf[2] != datalen) {
- tsdata->header_errors++;
- dev_err_ratelimited(dev,
- "Unexpected header: %02x%02x%02x!\n",
- rdbuf[0], rdbuf[1], rdbuf[2]);
- goto out;
- }
-
- if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen))
- goto out;
- }
-
for (i = 0; i < tsdata->max_support_points; i++) {
u8 *buf = &rdbuf[i * tplen + offset];
@@ -290,79 +371,6 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
- u8 addr, u8 value)
-{
- u8 wrbuf[4];
-
- switch (tsdata->version) {
- case EDT_M06:
- wrbuf[0] = M06_REG_CMD(tsdata->factory_mode);
- wrbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr);
- wrbuf[2] = value;
- wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
- return edt_ft5x06_ts_readwrite(tsdata->client, 4,
- wrbuf, 0, NULL);
-
- case EDT_M09:
- case EDT_M12:
- case EV_FT:
- case GENERIC_FT:
- wrbuf[0] = addr;
- wrbuf[1] = value;
-
- return edt_ft5x06_ts_readwrite(tsdata->client, 2,
- wrbuf, 0, NULL);
-
- default:
- return -EINVAL;
- }
-}
-
-static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
- u8 addr)
-{
- u8 wrbuf[2], rdbuf[2], crc;
- int error;
-
- switch (tsdata->version) {
- case EDT_M06:
- wrbuf[0] = M06_REG_CMD(tsdata->factory_mode);
- wrbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr);
- wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
-
- error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2,
- rdbuf);
- if (error)
- return error;
-
- crc = wrbuf[0] ^ wrbuf[1] ^ rdbuf[0];
- if (crc != rdbuf[1]) {
- dev_err(&tsdata->client->dev,
- "crc error: 0x%02x expected, got 0x%02x\n",
- crc, rdbuf[1]);
- return -EIO;
- }
- break;
-
- case EDT_M09:
- case EDT_M12:
- case EV_FT:
- case GENERIC_FT:
- wrbuf[0] = addr;
- error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
- wrbuf, 1, rdbuf);
- if (error)
- return error;
- break;
-
- default:
- return -EINVAL;
- }
-
- return rdbuf[0];
-}
-
struct edt_ft5x06_attribute {
struct device_attribute dattr;
size_t field_offset;
@@ -396,7 +404,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
struct edt_ft5x06_attribute *attr =
container_of(dattr, struct edt_ft5x06_attribute, dattr);
u8 *field = (u8 *)tsdata + attr->field_offset;
- int val;
+ unsigned int val;
size_t count = 0;
int error = 0;
u8 addr;
@@ -429,9 +437,8 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
}
if (addr != NO_REGISTER) {
- val = edt_ft5x06_register_read(tsdata, addr);
- if (val < 0) {
- error = val;
+ error = regmap_read(tsdata->regmap, addr, &val);
+ if (error) {
dev_err(&tsdata->client->dev,
"Failed to fetch attribute %s, error %d\n",
dattr->attr.name, error);
@@ -504,7 +511,7 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
}
if (addr != NO_REGISTER) {
- error = edt_ft5x06_register_write(tsdata, addr, val);
+ error = regmap_write(tsdata->regmap, addr, val);
if (error) {
dev_err(&tsdata->client->dev,
"Failed to update attribute %s, error: %d\n",
@@ -605,23 +612,19 @@ static const struct attribute_group edt_ft5x06_attr_group = {
static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
{
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
+ struct regmap *regmap = tsdata->regmap;
- edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold,
- tsdata->threshold);
- edt_ft5x06_register_write(tsdata, reg_addr->reg_gain,
- tsdata->gain);
+ regmap_write(regmap, reg_addr->reg_threshold, tsdata->threshold);
+ regmap_write(regmap, reg_addr->reg_gain, tsdata->gain);
if (reg_addr->reg_offset != NO_REGISTER)
- edt_ft5x06_register_write(tsdata, reg_addr->reg_offset,
- tsdata->offset);
+ regmap_write(regmap, reg_addr->reg_offset, tsdata->offset);
if (reg_addr->reg_offset_x != NO_REGISTER)
- edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x,
- tsdata->offset_x);
+ regmap_write(regmap, reg_addr->reg_offset_x, tsdata->offset_x);
if (reg_addr->reg_offset_y != NO_REGISTER)
- edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y,
- tsdata->offset_y);
+ regmap_write(regmap, reg_addr->reg_offset_y, tsdata->offset_y);
if (reg_addr->reg_report_rate != NO_REGISTER)
- edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
- tsdata->report_rate);
+ regmap_write(regmap, reg_addr->reg_report_rate,
+ tsdata->report_rate);
}
#ifdef CONFIG_DEBUG_FS
@@ -629,7 +632,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
{
struct i2c_client *client = tsdata->client;
int retries = EDT_SWITCH_MODE_RETRIES;
- int ret;
+ unsigned int val;
int error;
if (tsdata->version != EDT_M06) {
@@ -651,7 +654,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
}
/* mode register is 0x3c when in the work mode */
- error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
+ error = regmap_write(tsdata->regmap, WORK_REGISTER_OPMODE, 0x03);
if (error) {
dev_err(&client->dev,
"failed to switch to factory mode, error %d\n", error);
@@ -662,8 +665,9 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
do {
mdelay(EDT_SWITCH_MODE_DELAY);
/* mode register is 0x01 when in factory mode */
- ret = edt_ft5x06_register_read(tsdata, FACTORY_REGISTER_OPMODE);
- if (ret == 0x03)
+ error = regmap_read(tsdata->regmap, FACTORY_REGISTER_OPMODE,
+ &val);
+ if (!error && val == 0x03)
break;
} while (--retries > 0);
@@ -689,11 +693,11 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
{
struct i2c_client *client = tsdata->client;
int retries = EDT_SWITCH_MODE_RETRIES;
- int ret;
+ unsigned int val;
int error;
/* mode register is 0x01 when in the factory mode */
- error = edt_ft5x06_register_write(tsdata, FACTORY_REGISTER_OPMODE, 0x1);
+ error = regmap_write(tsdata->regmap, FACTORY_REGISTER_OPMODE, 0x1);
if (error) {
dev_err(&client->dev,
"failed to switch to work mode, error: %d\n", error);
@@ -705,8 +709,8 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
do {
mdelay(EDT_SWITCH_MODE_DELAY);
/* mode register is 0x01 when in factory mode */
- ret = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OPMODE);
- if (ret == 0x01)
+ error = regmap_read(tsdata->regmap, WORK_REGISTER_OPMODE, &val);
+ if (!error && val == 0x01)
break;
} while (--retries > 0);
@@ -765,10 +769,10 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
struct edt_ft5x06_ts_data *tsdata = file->private_data;
struct i2c_client *client = tsdata->client;
int retries = EDT_RAW_DATA_RETRIES;
- int val, i, error;
+ unsigned int val;
+ int i, error;
size_t read = 0;
int colbytes;
- char wrbuf[3];
u8 *rdbuf;
if (*off < 0 || *off >= tsdata->raw_bufsize)
@@ -781,7 +785,7 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
goto out;
}
- error = edt_ft5x06_register_write(tsdata, 0x08, 0x01);
+ error = regmap_write(tsdata->regmap, 0x08, 0x01);
if (error) {
dev_err(&client->dev,
"failed to write 0x08 register, error %d\n", error);
@@ -790,18 +794,18 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
do {
usleep_range(EDT_RAW_DATA_DELAY, EDT_RAW_DATA_DELAY + 100);
- val = edt_ft5x06_register_read(tsdata, 0x08);
- if (val < 1)
+ error = regmap_read(tsdata->regmap, 0x08, &val);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to read 0x08 register, error %d\n",
+ error);
+ goto out;
+ }
+
+ if (val == 1)
break;
} while (--retries > 0);
- if (val < 0) {
- error = val;
- dev_err(&client->dev,
- "failed to read 0x08 register, error %d\n", error);
- goto out;
- }
-
if (retries == 0) {
dev_err(&client->dev,
"timed out waiting for register to settle\n");
@@ -812,13 +816,9 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
rdbuf = tsdata->raw_buffer;
colbytes = tsdata->num_y * sizeof(u16);
- wrbuf[0] = 0xf5;
- wrbuf[1] = 0x0e;
for (i = 0; i < tsdata->num_x; i++) {
- wrbuf[2] = i; /* column index */
- error = edt_ft5x06_ts_readwrite(tsdata->client,
- sizeof(wrbuf), wrbuf,
- colbytes, rdbuf);
+ rdbuf[0] = i; /* column index */
+ error = regmap_bulk_read(tsdata->regmap, 0xf5, rdbuf, colbytes);
if (error)
goto out;
@@ -894,8 +894,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
* to have garbage in there
*/
memset(rdbuf, 0, sizeof(rdbuf));
- error = edt_ft5x06_ts_readwrite(client, 1, "\xBB",
- EDT_NAME_LEN - 1, rdbuf);
+ error = regmap_bulk_read(tsdata->regmap, 0xBB, rdbuf, EDT_NAME_LEN - 1);
if (error)
return error;
@@ -917,6 +916,14 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
*p++ = '\0';
strscpy(model_name, rdbuf + 1, EDT_NAME_LEN);
strscpy(fw_version, p ? p : "", EDT_NAME_LEN);
+
+ regmap_exit(tsdata->regmap);
+ tsdata->regmap = regmap_init_i2c(client,
+ &edt_M06_i2c_regmap_config);
+ if (IS_ERR(tsdata->regmap)) {
+ dev_err(&client->dev, "regmap allocation failed\n");
+ return PTR_ERR(tsdata->regmap);
+ }
} else if (!strncasecmp(rdbuf, "EP0", 3)) {
tsdata->version = EDT_M12;
@@ -943,15 +950,13 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
*/
tsdata->version = GENERIC_FT;
- error = edt_ft5x06_ts_readwrite(client, 1, "\xA6",
- 2, rdbuf);
+ error = regmap_bulk_read(tsdata->regmap, 0xA6, rdbuf, 2);
if (error)
return error;
strscpy(fw_version, rdbuf, 2);
- error = edt_ft5x06_ts_readwrite(client, 1, "\xA8",
- 1, rdbuf);
+ error = regmap_bulk_read(tsdata->regmap, 0xA8, rdbuf, 1);
if (error)
return error;
@@ -980,8 +985,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
break;
case 0x59: /* Evervision Display with FT5xx6 TS */
tsdata->version = EV_FT;
- error = edt_ft5x06_ts_readwrite(client, 1, "\x53",
- 1, rdbuf);
+ error = regmap_bulk_read(tsdata->regmap, 0x53, rdbuf, 1);
if (error)
return error;
strscpy(fw_version, rdbuf, 1);
@@ -1003,42 +1007,40 @@ static void edt_ft5x06_ts_get_defaults(struct device *dev,
struct edt_ft5x06_ts_data *tsdata)
{
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
+ struct regmap *regmap = tsdata->regmap;
u32 val;
int error;
error = device_property_read_u32(dev, "threshold", &val);
if (!error) {
- edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, val);
+ regmap_write(regmap, reg_addr->reg_threshold, val);
tsdata->threshold = val;
}
error = device_property_read_u32(dev, "gain", &val);
if (!error) {
- edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, val);
+ regmap_write(regmap, reg_addr->reg_gain, val);
tsdata->gain = val;
}
error = device_property_read_u32(dev, "offset", &val);
if (!error) {
if (reg_addr->reg_offset != NO_REGISTER)
- edt_ft5x06_register_write(tsdata,
- reg_addr->reg_offset, val);
+ regmap_write(regmap, reg_addr->reg_offset, val);
tsdata->offset = val;
}
error = device_property_read_u32(dev, "offset-x", &val);
if (!error) {
if (reg_addr->reg_offset_x != NO_REGISTER)
- edt_ft5x06_register_write(tsdata,
- reg_addr->reg_offset_x, val);
+ regmap_write(regmap, reg_addr->reg_offset_x, val);
tsdata->offset_x = val;
}
error = device_property_read_u32(dev, "offset-y", &val);
if (!error) {
if (reg_addr->reg_offset_y != NO_REGISTER)
- edt_ft5x06_register_write(tsdata,
- reg_addr->reg_offset_y, val);
+ regmap_write(regmap, reg_addr->reg_offset_y, val);
tsdata->offset_y = val;
}
}
@@ -1046,33 +1048,30 @@ static void edt_ft5x06_ts_get_defaults(struct device *dev,
static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
{
struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
+ struct regmap *regmap = tsdata->regmap;
+ unsigned int val;
- tsdata->threshold = edt_ft5x06_register_read(tsdata,
- reg_addr->reg_threshold);
- tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain);
+ regmap_read(regmap, reg_addr->reg_threshold, &tsdata->threshold);
+ regmap_read(regmap, reg_addr->reg_gain, &tsdata->gain);
if (reg_addr->reg_offset != NO_REGISTER)
- tsdata->offset =
- edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
+ regmap_read(regmap, reg_addr->reg_offset, &tsdata->offset);
if (reg_addr->reg_offset_x != NO_REGISTER)
- tsdata->offset_x =
- edt_ft5x06_register_read(tsdata,
- reg_addr->reg_offset_x);
+ regmap_read(regmap, reg_addr->reg_offset_x, &tsdata->offset_x);
if (reg_addr->reg_offset_y != NO_REGISTER)
- tsdata->offset_y =
- edt_ft5x06_register_read(tsdata,
- reg_addr->reg_offset_y);
+ regmap_read(regmap, reg_addr->reg_offset_y, &tsdata->offset_y);
if (reg_addr->reg_report_rate != NO_REGISTER)
- tsdata->report_rate =
- edt_ft5x06_register_read(tsdata,
- reg_addr->reg_report_rate);
+ regmap_read(regmap, reg_addr->reg_report_rate,
+ &tsdata->report_rate);
tsdata->num_x = EDT_DEFAULT_NUM_X;
- if (reg_addr->reg_num_x != NO_REGISTER)
- tsdata->num_x = edt_ft5x06_register_read(tsdata,
- reg_addr->reg_num_x);
+ if (reg_addr->reg_num_x != NO_REGISTER) {
+ if (!regmap_read(regmap, reg_addr->reg_num_x, &val))
+ tsdata->num_x = val;
+ }
tsdata->num_y = EDT_DEFAULT_NUM_Y;
- if (reg_addr->reg_num_y != NO_REGISTER)
- tsdata->num_y = edt_ft5x06_register_read(tsdata,
- reg_addr->reg_num_y);
+ if (reg_addr->reg_num_y != NO_REGISTER) {
+ if (!regmap_read(regmap, reg_addr->reg_num_y, &val))
+ tsdata->num_y = val;
+ }
}
static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
@@ -1142,7 +1141,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct edt_i2c_chip_data *chip_data;
struct edt_ft5x06_ts_data *tsdata;
- u8 buf[2] = { 0xfc, 0x00 };
+ unsigned int val;
struct input_dev *input;
unsigned long irq_flags;
int error;
@@ -1156,6 +1155,12 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
return -ENOMEM;
}
+ tsdata->regmap = regmap_init_i2c(client, &edt_ft5x06_i2c_regmap_config);
+ if (IS_ERR(tsdata->regmap)) {
+ dev_err(&client->dev, "regmap allocation failed\n");
+ return PTR_ERR(tsdata->regmap);
+ }
+
chip_data = device_get_match_data(&client->dev);
if (!chip_data)
chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
@@ -1258,6 +1263,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
tsdata->client = client;
tsdata->input = input;
tsdata->factory_mode = false;
+ i2c_set_clientdata(client, tsdata);
error = edt_ft5x06_ts_identify(client, tsdata);
if (error) {
@@ -1269,7 +1275,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
* Dummy read access. EP0700MLP1 returns bogus data on the first
* register read access and ignores writes.
*/
- edt_ft5x06_ts_readwrite(tsdata->client, 2, buf, 2, buf);
+ regmap_read(tsdata->regmap, 0x00, &val);
edt_ft5x06_ts_set_regs(tsdata);
edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
@@ -1291,9 +1297,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
if (tsdata->version == EDT_M06)
tsdata->report_rate /= 10;
- edt_ft5x06_register_write(tsdata,
- tsdata->reg_addr.reg_report_rate,
- tsdata->report_rate);
+ regmap_write(tsdata->regmap, tsdata->reg_addr.reg_report_rate,
+ tsdata->report_rate);
}
dev_dbg(&client->dev,
@@ -1318,8 +1323,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
return error;
}
- i2c_set_clientdata(client, tsdata);
-
irq_flags = irq_get_trigger_type(client->irq);
if (irq_flags == IRQF_TRIGGER_NONE)
irq_flags = IRQF_TRIGGER_FALLING;
@@ -1357,6 +1360,7 @@ static void edt_ft5x06_ts_remove(struct i2c_client *client)
struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
edt_ft5x06_ts_teardown_debugfs(tsdata);
+ regmap_exit(tsdata->regmap);
}
static int edt_ft5x06_ts_suspend(struct device *dev)
@@ -1373,8 +1377,8 @@ static int edt_ft5x06_ts_suspend(struct device *dev)
return 0;
/* Enter hibernate mode. */
- ret = edt_ft5x06_register_write(tsdata, PMOD_REGISTER_OPMODE,
- PMOD_REGISTER_HIBERNATE);
+ ret = regmap_write(tsdata->regmap, PMOD_REGISTER_OPMODE,
+ PMOD_REGISTER_HIBERNATE);
if (ret)
dev_warn(dev, "Failed to set hibernate mode\n");
--
2.32.0
^ permalink raw reply related
* [PATCH 4/9] Input: edt-ft5x06 - don't recalculate the CRC
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
There is no need to recalculate the CRC when the data has not changed.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index c96fe6520578..d4f39724b259 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -319,7 +319,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
u8 addr)
{
- u8 wrbuf[2], rdbuf[2];
+ u8 wrbuf[2], rdbuf[2], crc;
int error;
switch (tsdata->version) {
@@ -333,11 +333,11 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
if (error)
return error;
- if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) {
+ crc = wrbuf[0] ^ wrbuf[1] ^ rdbuf[0];
+ if (crc != rdbuf[1]) {
dev_err(&tsdata->client->dev,
"crc error: 0x%02x expected, got 0x%02x\n",
- wrbuf[0] ^ wrbuf[1] ^ rdbuf[0],
- rdbuf[1]);
+ crc, rdbuf[1]);
return -EIO;
}
break;
--
2.32.0
^ permalink raw reply related
* [PATCH 5/9] Input: edt-ft5x06 - remove code duplication
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
The use of the macros M06_REG_ADDR and M06_REG_CMD avoids code
duplication without impacting the application load, and reduces the
chances of errors or mistakes.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index d4f39724b259..7d82f412ab15 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -75,6 +75,9 @@
#define EDT_DEFAULT_NUM_X 1024
#define EDT_DEFAULT_NUM_Y 1024
+#define M06_REG_CMD(factory) ((factory) ? 0xf3 : 0xfc)
+#define M06_REG_ADDR(factory, addr) ((factory) ? (addr) & 0x7f : (addr) & 0x3f)
+
enum edt_pmode {
EDT_PMODE_NOT_SUPPORTED,
EDT_PMODE_HIBERNATE,
@@ -294,8 +297,8 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
switch (tsdata->version) {
case EDT_M06:
- wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
- wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
+ wrbuf[0] = M06_REG_CMD(tsdata->factory_mode);
+ wrbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr);
wrbuf[2] = value;
wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
return edt_ft5x06_ts_readwrite(tsdata->client, 4,
@@ -324,8 +327,8 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
switch (tsdata->version) {
case EDT_M06:
- wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
- wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
+ wrbuf[0] = M06_REG_CMD(tsdata->factory_mode);
+ wrbuf[1] = M06_REG_ADDR(tsdata->factory_mode, addr);
wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2,
--
2.32.0
^ permalink raw reply related
* [PATCH 6/9] Input: edt-ft5x06 - don't print error messages with dev_dbg()
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
In some parts of the code, error messages were improperly printed with
dev_dbg() calls. In those cases, dev_dbg() has been replaced with
dev_err().
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 7d82f412ab15..89958881fca1 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -783,7 +783,7 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
error = edt_ft5x06_register_write(tsdata, 0x08, 0x01);
if (error) {
- dev_dbg(&client->dev,
+ dev_err(&client->dev,
"failed to write 0x08 register, error %d\n", error);
goto out;
}
@@ -797,13 +797,13 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
if (val < 0) {
error = val;
- dev_dbg(&client->dev,
+ dev_err(&client->dev,
"failed to read 0x08 register, error %d\n", error);
goto out;
}
if (retries == 0) {
- dev_dbg(&client->dev,
+ dev_err(&client->dev,
"timed out waiting for register to settle\n");
error = -ETIMEDOUT;
goto out;
--
2.32.0
^ permalink raw reply related
* [PATCH 3/9] Input: edt-ft5x06 - add spaces to ensure format specification
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
It adds spaces around '-' as recommended by the Linux coding style.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index c0ad3e4b6662..c96fe6520578 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -183,11 +183,11 @@ static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,
for (i = 0; i < buflen - 1; i++)
crc ^= buf[i];
- if (crc != buf[buflen-1]) {
+ if (crc != buf[buflen - 1]) {
tsdata->crc_errors++;
dev_err_ratelimited(&tsdata->client->dev,
"crc error: 0x%02x expected, got 0x%02x\n",
- crc, buf[buflen-1]);
+ crc, buf[buflen - 1]);
return false;
}
--
2.32.0
^ permalink raw reply related
* [PATCH 2/9] Input: edt-ft5x06 - remove unnecessary blank lines
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
It removes unnecessary blank lines so that checkpatch doesn't complain
anymore.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index daba6472fc65..c0ad3e4b6662 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -619,7 +619,6 @@ static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
if (reg_addr->reg_report_rate != NO_REGISTER)
edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
tsdata->report_rate);
-
}
#ifdef CONFIG_DEBUG_FS
@@ -1459,7 +1458,6 @@ static int edt_ft5x06_ts_resume(struct device *dev)
gpiod_set_value_cansleep(wake_gpio, 1);
}
-
return ret;
}
--
2.32.0
^ permalink raw reply related
* [PATCH 1/9] Input: edt-ft5x06 - fix indentation
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
In-Reply-To: <20230402200951.1032513-1-dario.binacchi@amarulasolutions.com>
Matches the alignment to the open parenthesis as suggested by
checkpatch.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/input/touchscreen/edt-ft5x06.c | 36 ++++++++++++++------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 2746649561c7..daba6472fc65 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -241,11 +241,11 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
/* M09/M12 does not send header or CRC */
if (tsdata->version == EDT_M06) {
if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
- rdbuf[2] != datalen) {
+ rdbuf[2] != datalen) {
tsdata->header_errors++;
dev_err_ratelimited(dev,
- "Unexpected header: %02x%02x%02x!\n",
- rdbuf[0], rdbuf[1], rdbuf[2]);
+ "Unexpected header: %02x%02x%02x!\n",
+ rdbuf[0], rdbuf[1], rdbuf[2]);
goto out;
}
@@ -618,7 +618,7 @@ static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
tsdata->offset_y);
if (reg_addr->reg_report_rate != NO_REGISTER)
edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
- tsdata->report_rate);
+ tsdata->report_rate);
}
@@ -757,7 +757,8 @@ DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get,
edt_ft5x06_debugfs_mode_set, "%llu\n");
static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
- char __user *buf, size_t count, loff_t *off)
+ char __user *buf, size_t count,
+ loff_t *off)
{
struct edt_ft5x06_ts_data *tsdata = file->private_data;
struct i2c_client *client = tsdata->client;
@@ -965,12 +966,12 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
case 0x70: /* EDT EP0700M09 */
tsdata->version = EDT_M09;
snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
- rdbuf[0] >> 4, rdbuf[0] & 0x0F);
+ rdbuf[0] >> 4, rdbuf[0] & 0x0F);
break;
case 0xa1: /* EDT EP1010ML00 */
tsdata->version = EDT_M09;
snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00",
- rdbuf[0] >> 4, rdbuf[0] & 0x0F);
+ rdbuf[0] >> 4, rdbuf[0] & 0x0F);
break;
case 0x5a: /* Solomon Goldentek Display */
snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
@@ -1051,14 +1052,17 @@ static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
tsdata->offset =
edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
if (reg_addr->reg_offset_x != NO_REGISTER)
- tsdata->offset_x = edt_ft5x06_register_read(tsdata,
- reg_addr->reg_offset_x);
+ tsdata->offset_x =
+ edt_ft5x06_register_read(tsdata,
+ reg_addr->reg_offset_x);
if (reg_addr->reg_offset_y != NO_REGISTER)
- tsdata->offset_y = edt_ft5x06_register_read(tsdata,
- reg_addr->reg_offset_y);
+ tsdata->offset_y =
+ edt_ft5x06_register_read(tsdata,
+ reg_addr->reg_offset_y);
if (reg_addr->reg_report_rate != NO_REGISTER)
- tsdata->report_rate = edt_ft5x06_register_read(tsdata,
- reg_addr->reg_report_rate);
+ tsdata->report_rate =
+ edt_ft5x06_register_read(tsdata,
+ reg_addr->reg_report_rate);
tsdata->num_x = EDT_DEFAULT_NUM_X;
if (reg_addr->reg_num_x != NO_REGISTER)
tsdata->num_x = edt_ft5x06_register_read(tsdata,
@@ -1306,7 +1310,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
touchscreen_parse_properties(input, true, &tsdata->prop);
error = input_mt_init_slots(input, tsdata->max_support_points,
- INPUT_MT_DIRECT);
+ INPUT_MT_DIRECT);
if (error) {
dev_err(&client->dev, "Unable to init MT slots.\n");
return error;
@@ -1320,8 +1324,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
irq_flags |= IRQF_ONESHOT;
error = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, edt_ft5x06_ts_isr, irq_flags,
- client->name, tsdata);
+ NULL, edt_ft5x06_ts_isr, irq_flags,
+ client->name, tsdata);
if (error) {
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
return error;
--
2.32.0
^ permalink raw reply related
* [PATCH 0/9] Input: edt-ft5x06 - convert to use regmap API
From: Dario Binacchi @ 2023-04-02 20:09 UTC (permalink / raw)
To: linux-kernel
Cc: michael, linux-amarula, Dario Binacchi, Dmitry Torokhov,
Jonathan Cameron, Oliver Graute, Uwe Kleine-König,
Wolfram Sang, linux-input
This series converts the driver to use the regmap API for accessing the
registers of the different models it manages, making the driver code more
generic.
The series has been tested on the following touchscreen models:
- M06
- M09
- M12
- EP0430MLF0M
- generic ft5x06 (05)
The series also includes some code cleaning and optimization patches.
Dario Binacchi (9):
Input: edt-ft5x06 - fix indentation
Input: edt-ft5x06 - remove unnecessary blank lines
Input: edt-ft5x06 - add spaces to ensure format specification
Input: edt-ft5x06 - don't recalculate the CRC
Input: edt-ft5x06 - remove code duplication
Input: edt-ft5x06 - don't print error messages with dev_dbg()
Input: edt-ft5x06 - convert to use regmap API
Input: edt-ft5x06 - unify the crc check
Input: edt-ft5x06: Calculate points data length only once
drivers/input/touchscreen/edt-ft5x06.c | 496 +++++++++++++------------
1 file changed, 251 insertions(+), 245 deletions(-)
--
2.32.0
^ permalink raw reply
* [PATCH v5] Input: tsc2007 - enable cansleep pendown GPIO
From: Benjamin Bara @ 2023-04-02 8:00 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: hns, richard.leitner, christophe.jaillet, linux-input,
linux-kernel, Benjamin Bara, Richard Leitner
From: Benjamin Bara <benjamin.bara@skidata.com>
When a hard IRQ is triggered, the soft IRQ, which decides if an actual
pen down happened, should always be triggered. This enables the usage of
"can_sleep" GPIO chips as "pen down" GPIO, as the value is not read
during the hard IRQ anymore. This might be the case if the GPIO chip is
an expander behind i2c.
Signed-off-by: Benjamin Bara <benjamin.bara@skidata.com>
Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
Hi!
Thanks for the feedback! The change unfortunately somehow got lost
during patch preparations - sorry for that. Here is the corrected
version with the missing part.
v4: https://lore.kernel.org/all/20230328-tsc2007-sleep-v4-1-2ede92ec9b71@skidata.com/
----
v5:
- actually use the can_sleep getter
v4:
- don't read value in hard IRQ
v3:
- extend commit message
v2:
- fix style mentioned by Christophe
---
drivers/input/touchscreen/tsc2007_core.c | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 3c793fb70a0e..21916a30fb76 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -172,19 +172,6 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
return IRQ_HANDLED;
}
-static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
-{
- struct tsc2007 *ts = handle;
-
- if (tsc2007_is_pen_down(ts))
- return IRQ_WAKE_THREAD;
-
- if (ts->clear_penirq)
- ts->clear_penirq();
-
- return IRQ_HANDLED;
-}
-
static void tsc2007_stop(struct tsc2007 *ts)
{
ts->stopped = true;
@@ -226,7 +213,7 @@ static int tsc2007_get_pendown_state_gpio(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct tsc2007 *ts = i2c_get_clientdata(client);
- return gpiod_get_value(ts->gpiod);
+ return gpiod_get_value_cansleep(ts->gpiod);
}
static int tsc2007_probe_properties(struct device *dev, struct tsc2007 *ts)
@@ -376,7 +363,7 @@ static int tsc2007_probe(struct i2c_client *client)
}
err = devm_request_threaded_irq(&client->dev, ts->irq,
- tsc2007_hard_irq, tsc2007_soft_irq,
+ NULL, tsc2007_soft_irq,
IRQF_ONESHOT,
client->dev.driver->name, ts);
if (err) {
---
base-commit: 197b6b60ae7bc51dd0814953c562833143b292aa
change-id: 20230328-tsc2007-sleep-f65953ae32d0
Best regards,
--
Benjamin Bara <benjamin.bara@skidata.com>
^ permalink raw reply related
* Re: [PATCH v4] Input: tsc2007 - enable cansleep pendown GPIO
From: Dmitry Torokhov @ 2023-04-02 5:51 UTC (permalink / raw)
To: Benjamin Bara
Cc: hns, richard.leitner, christophe.jaillet, linux-input,
linux-kernel, Benjamin Bara
In-Reply-To: <20230328-tsc2007-sleep-v4-1-2ede92ec9b71@skidata.com>
Hi Benjamin,
On Thu, Mar 30, 2023 at 09:10:37PM +0200, Benjamin Bara wrote:
> From: Benjamin Bara <benjamin.bara@skidata.com>
>
> When a hard IRQ is triggered, the soft IRQ, which decides if an actual
> pen down happened, should always be triggered. This enables the usage of
> "can_sleep" GPIO chips as "pen down" GPIO, as the value is not read
> during the hard IRQ anymore. This might be the case if the GPIO chip is
> an expander behind i2c.
>
> Signed-off-by: Benjamin Bara <benjamin.bara@skidata.com>
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
> Hi!
>
> I found a different approach to my problem:
> If the primary IRQ handler is set to NULL, the default primary IRQ
> handler simply triggers a soft IRQ handler wake up. As the hard IRQ is
> only triggered when a pen down is detected, the gpiod_get_value() inside
> tsc2007_is_pen_down() always returns true and therefore can be
> neglected.
Don't you need to switch to gpio_get_valued_cansleep() in
tsc2007_is_pen_down() to actually allow sleeping gpios?
Thanks.
--
Dmitry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox