* [PATCH v3 0/4] Add support for slider gestures and OTP variants
@ 2024-01-01 20:00 Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 1/4] dt-bindings: input: iqs269a: Add bindings for slider gestures Jeff LaBundy
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Jeff LaBundy @ 2024-01-01 20:00 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt
Cc: linux-input, devicetree, jeff
This series introduces support for some additional features offered by the
Azoteq IQS269A capacitive touch controller.
Patches 1 and 2 add support for slider gestures (e.g. tap or swipe). Gestures
are recognized by the hardware itself based on touch activity across the chan-
nels associated with the slider. This feature is useful for lightweight systems
that do not post-process absolute coordinates to determine gestures expressed
by the user.
Gestures are presented to user space as keycodes. An example use-case is an
array of multimedia keys as seen in the following demo:
https://youtu.be/k_vMRQiHLgA
Patches 3 and 4 add support for the device's available OTP variants, which
trade features or exhibit errata that require workarounds.
Jeff LaBundy (4):
dt-bindings: input: iqs269a: Add bindings for slider gestures
Input: iqs269a - add support for slider gestures
dt-bindings: input: iqs269a: Add bindings for OTP variants
Input: iqs269a - add support for OTP variants
.../devicetree/bindings/input/iqs269a.yaml | 98 +++++-
drivers/input/misc/iqs269a.c | 312 ++++++++++++++++--
2 files changed, 377 insertions(+), 33 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 1/4] dt-bindings: input: iqs269a: Add bindings for slider gestures
2024-01-01 20:00 [PATCH v3 0/4] Add support for slider gestures and OTP variants Jeff LaBundy
@ 2024-01-01 20:02 ` Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 2/4] Input: iqs269a - add support " Jeff LaBundy
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jeff LaBundy @ 2024-01-01 20:02 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt
Cc: linux-input, devicetree, jeff
This patch adds bindings for slider gestures that can be expressed
by the device.
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v3:
- None
Changes in v2:
- Renamed 'azoteq,slider-swipe' to 'azoteq,gesture-swipe' to match IQS626A and
noted it as depending upon 'linux,keycodes'
- Dropped the $ref declaration for 'linux,keycodes' and referenced input.yaml,
which has since been updated to define this property
.../devicetree/bindings/input/iqs269a.yaml | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/iqs269a.yaml b/Documentation/devicetree/bindings/input/iqs269a.yaml
index 3c430d38594f..b42f07542d27 100644
--- a/Documentation/devicetree/bindings/input/iqs269a.yaml
+++ b/Documentation/devicetree/bindings/input/iqs269a.yaml
@@ -9,6 +9,9 @@ title: Azoteq IQS269A Capacitive Touch Controller
maintainers:
- Jeff LaBundy <jeff@labundy.com>
+allOf:
+ - $ref: input.yaml#
+
description: |
The Azoteq IQS269A is an 8-channel capacitive touch controller that features
additional Hall-effect and inductive sensing capabilities.
@@ -204,6 +207,63 @@ properties:
default: 1
description: Specifies the slider coordinate filter strength.
+ linux,keycodes:
+ minItems: 1
+ maxItems: 8
+ description: |
+ Specifies the numeric keycodes associated with each available gesture in
+ the following order (enter 0 for unused gestures):
+ 0: Slider 0 tap
+ 1: Slider 0 hold
+ 2: Slider 0 positive flick or swipe
+ 3: Slider 0 negative flick or swipe
+ 4: Slider 1 tap
+ 5: Slider 1 hold
+ 6: Slider 1 positive flick or swipe
+ 7: Slider 1 negative flick or swipe
+
+ azoteq,gesture-swipe:
+ type: boolean
+ description:
+ Directs the device to interpret axial gestures as a swipe (finger remains
+ on slider) instead of a flick (finger leaves slider).
+
+ azoteq,timeout-tap-ms:
+ multipleOf: 16
+ minimum: 0
+ maximum: 4080
+ default: 400
+ description:
+ Specifies the length of time (in ms) within which a slider touch must be
+ released in order to be interpreted as a tap. Default and maximum values
+ as well as step size are reduced by a factor of 4 with device version 2.
+
+ azoteq,timeout-swipe-ms:
+ multipleOf: 16
+ minimum: 0
+ maximum: 4080
+ default: 2000
+ description:
+ Specifies the length of time (in ms) within which an axial gesture must be
+ completed in order to be interpreted as a flick or swipe. Default and max-
+ imum values as well as step size are reduced by a factor of 4 with device
+ version 2.
+
+ azoteq,thresh-swipe:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 255
+ default: 128
+ description:
+ Specifies the number of points across which an axial gesture must travel
+ in order to be interpreted as a flick or swipe.
+
+dependencies:
+ azoteq,gesture-swipe: ["linux,keycodes"]
+ azoteq,timeout-tap-ms: ["linux,keycodes"]
+ azoteq,timeout-swipe-ms: ["linux,keycodes"]
+ azoteq,thresh-swipe: ["linux,keycodes"]
+
patternProperties:
"^channel@[0-7]$":
type: object
@@ -484,6 +544,14 @@ examples:
azoteq,hall-enable;
azoteq,suspend-mode = <2>;
+ linux,keycodes = <KEY_PLAYPAUSE>,
+ <KEY_STOPCD>,
+ <KEY_NEXTSONG>,
+ <KEY_PREVIOUSSONG>;
+
+ azoteq,timeout-tap-ms = <400>;
+ azoteq,timeout-swipe-ms = <800>;
+
channel@0 {
reg = <0x0>;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 2/4] Input: iqs269a - add support for slider gestures
2024-01-01 20:00 [PATCH v3 0/4] Add support for slider gestures and OTP variants Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 1/4] dt-bindings: input: iqs269a: Add bindings for slider gestures Jeff LaBundy
@ 2024-01-01 20:02 ` Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 3/4] dt-bindings: input: iqs269a: Add bindings for OTP variants Jeff LaBundy
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jeff LaBundy @ 2024-01-01 20:02 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt
Cc: linux-input, devicetree, jeff
This patch adds support for slider gestures that can be expressed
by the device. Each gesture (e.g. tap or hold) can be mapped to a
unique keycode for either slider 0 or 1.
With this change, raw slider coordinates are reported only if the
slider has no keycodes defined. This prevents unwanted mouse cur-
sor movement when expressing axial gestures (e.g. swipe) and also
eliminates some unnecessary I2C traffic.
Different revisions of silicon use different tap and swipe timeout
step sizes. Apply an appropriate scaling factor depending on which
revision is found.
To facilitate this change, store the iqs269_ver_info struct in the
driver's private data so that other functions can use it after the
driver has probed.
Last but not least, a former reserved field in iqs269_ver_info now
contains useful information; give it a name (fw_num).
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
---
Changes in v3:
- None
Changes in v2:
- Rebased onto latest driver
- Renamed 'azoteq,slider-swipe' to 'azoteq,gesture-swipe' to match IQS626A
- Renamed 'gs_code' to 'sl_code'
drivers/input/misc/iqs269a.c | 220 ++++++++++++++++++++++++++++++-----
1 file changed, 191 insertions(+), 29 deletions(-)
diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c
index 1abce35b955e..0d0b5cdc7830 100644
--- a/drivers/input/misc/iqs269a.c
+++ b/drivers/input/misc/iqs269a.c
@@ -9,6 +9,7 @@
* axial sliders presented by the device.
*/
+#include <linux/bits.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -26,6 +27,8 @@
#define IQS269_VER_INFO 0x00
#define IQS269_VER_INFO_PROD_NUM 0x4F
+#define IQS269_VER_INFO_FW_NUM_2 0x03
+#define IQS269_VER_INFO_FW_NUM_3 0x10
#define IQS269_SYS_FLAGS 0x02
#define IQS269_SYS_FLAGS_SHOW_RESET BIT(15)
@@ -53,6 +56,7 @@
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MASK GENMASK(10, 8)
#define IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT 8
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MAX 7
+#define IQS269_SYS_SETTINGS_SLIDER_SWIPE BIT(7)
#define IQS269_SYS_SETTINGS_RESEED_OFFSET BIT(6)
#define IQS269_SYS_SETTINGS_EVENT_MODE BIT(5)
#define IQS269_SYS_SETTINGS_EVENT_MODE_LP BIT(4)
@@ -69,6 +73,7 @@
#define IQS269_FILT_STR_MAX 3
#define IQS269_EVENT_MASK_SYS BIT(6)
+#define IQS269_EVENT_MASK_GESTURE BIT(3)
#define IQS269_EVENT_MASK_DEEP BIT(2)
#define IQS269_EVENT_MASK_TOUCH BIT(1)
#define IQS269_EVENT_MASK_PROX BIT(0)
@@ -97,6 +102,10 @@
#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)
#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0)
+#define IQS269_TIMEOUT_TAP_MS_MAX 4080
+#define IQS269_TIMEOUT_SWIPE_MS_MAX 4080
+#define IQS269_THRESH_SWIPE_MAX 255
+
#define IQS269_CHx_ENG_A_MEAS_CAP_SIZE BIT(15)
#define IQS269_CHx_ENG_A_RX_GND_INACTIVE BIT(13)
#define IQS269_CHx_ENG_A_LOCAL_CAP_SIZE BIT(12)
@@ -175,6 +184,20 @@ enum iqs269_event_id {
IQS269_EVENT_DEEP_UP,
};
+enum iqs269_slider_id {
+ IQS269_SLIDER_NONE,
+ IQS269_SLIDER_KEY,
+ IQS269_SLIDER_RAW,
+};
+
+enum iqs269_gesture_id {
+ IQS269_GESTURE_TAP,
+ IQS269_GESTURE_HOLD,
+ IQS269_GESTURE_FLICK_POS,
+ IQS269_GESTURE_FLICK_NEG,
+ IQS269_NUM_GESTURES,
+};
+
struct iqs269_switch_desc {
unsigned int code;
bool enabled;
@@ -234,7 +257,7 @@ struct iqs269_ver_info {
u8 prod_num;
u8 sw_num;
u8 hw_num;
- u8 padding;
+ u8 fw_num;
} __packed;
struct iqs269_ch_reg {
@@ -285,16 +308,33 @@ struct iqs269_private {
struct regmap *regmap;
struct mutex lock;
struct iqs269_switch_desc switches[ARRAY_SIZE(iqs269_events)];
+ struct iqs269_ver_info ver_info;
struct iqs269_sys_reg sys_reg;
struct completion ati_done;
struct input_dev *keypad;
struct input_dev *slider[IQS269_NUM_SL];
unsigned int keycode[ARRAY_SIZE(iqs269_events) * IQS269_NUM_CH];
+ unsigned int sl_code[IQS269_NUM_SL][IQS269_NUM_GESTURES];
unsigned int ch_num;
bool hall_enable;
bool ati_current;
};
+static enum iqs269_slider_id iqs269_slider_type(struct iqs269_private *iqs269,
+ int slider_num)
+{
+ int i;
+
+ if (!iqs269->sys_reg.slider_select[slider_num])
+ return IQS269_SLIDER_NONE;
+
+ for (i = 0; i < IQS269_NUM_GESTURES; i++)
+ if (iqs269->sl_code[slider_num][i] != KEY_RESERVED)
+ return IQS269_SLIDER_KEY;
+
+ return IQS269_SLIDER_RAW;
+}
+
static int iqs269_ati_mode_set(struct iqs269_private *iqs269,
unsigned int ch_num, unsigned int mode)
{
@@ -1004,6 +1044,76 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
general |= (val << IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT);
}
+ if (device_property_present(&client->dev, "linux,keycodes")) {
+ int scale = 1;
+ int count = device_property_count_u32(&client->dev,
+ "linux,keycodes");
+ if (count > IQS269_NUM_GESTURES * IQS269_NUM_SL) {
+ dev_err(&client->dev, "Too many keycodes present\n");
+ return -EINVAL;
+ } else if (count < 0) {
+ dev_err(&client->dev, "Failed to count keycodes: %d\n",
+ count);
+ return count;
+ }
+
+ error = device_property_read_u32_array(&client->dev,
+ "linux,keycodes",
+ *iqs269->sl_code, count);
+ if (error) {
+ dev_err(&client->dev, "Failed to read keycodes: %d\n",
+ error);
+ return error;
+ }
+
+ if (device_property_present(&client->dev,
+ "azoteq,gesture-swipe"))
+ general |= IQS269_SYS_SETTINGS_SLIDER_SWIPE;
+
+ /*
+ * Early revisions of silicon use a more granular step size for
+ * tap and swipe gesture timeouts; scale them appropriately.
+ */
+ if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3)
+ scale = 4;
+
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,timeout-tap-ms", &val)) {
+ if (val > IQS269_TIMEOUT_TAP_MS_MAX / scale) {
+ dev_err(&client->dev, "Invalid timeout: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->timeout_tap = val / (16 / scale);
+ }
+
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,timeout-swipe-ms",
+ &val)) {
+ if (val > IQS269_TIMEOUT_SWIPE_MS_MAX / scale) {
+ dev_err(&client->dev, "Invalid timeout: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->timeout_swipe = val / (16 / scale);
+ }
+
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,thresh-swipe", &val)) {
+ if (val > IQS269_THRESH_SWIPE_MAX) {
+ dev_err(&client->dev, "Invalid threshold: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->thresh_swipe = val;
+ }
+
+ sys_reg->event_mask &= ~IQS269_EVENT_MASK_GESTURE;
+ }
+
general &= ~IQS269_SYS_SETTINGS_RESEED_OFFSET;
if (device_property_present(&client->dev, "azoteq,reseed-offset"))
general |= IQS269_SYS_SETTINGS_RESEED_OFFSET;
@@ -1012,10 +1122,11 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
/*
* As per the datasheet, enable streaming during normal-power mode if
- * either slider is in use. In that case, the device returns to event
- * mode during low-power mode.
+ * raw coordinates will be read from either slider. In that case, the
+ * device returns to event mode during low-power mode.
*/
- if (sys_reg->slider_select[0] || sys_reg->slider_select[1])
+ if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
+ iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW)
general |= IQS269_SYS_SETTINGS_EVENT_MODE_LP;
general |= IQS269_SYS_SETTINGS_REDO_ATI;
@@ -1106,19 +1217,37 @@ static int iqs269_input_init(struct iqs269_private *iqs269)
}
for (i = 0; i < IQS269_NUM_SL; i++) {
- if (!iqs269->sys_reg.slider_select[i])
+ if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_NONE)
continue;
iqs269->slider[i] = devm_input_allocate_device(&client->dev);
if (!iqs269->slider[i])
return -ENOMEM;
+ iqs269->slider[i]->keycodemax = ARRAY_SIZE(iqs269->sl_code[i]);
+ iqs269->slider[i]->keycode = iqs269->sl_code[i];
+ iqs269->slider[i]->keycodesize = sizeof(**iqs269->sl_code);
+
iqs269->slider[i]->name = i ? "iqs269a_slider_1"
: "iqs269a_slider_0";
iqs269->slider[i]->id.bustype = BUS_I2C;
- input_set_capability(iqs269->slider[i], EV_KEY, BTN_TOUCH);
- input_set_abs_params(iqs269->slider[i], ABS_X, 0, 255, 0, 0);
+ for (j = 0; j < IQS269_NUM_GESTURES; j++)
+ if (iqs269->sl_code[i][j] != KEY_RESERVED)
+ input_set_capability(iqs269->slider[i], EV_KEY,
+ iqs269->sl_code[i][j]);
+
+ /*
+ * Present the slider as a narrow trackpad if one or more chan-
+ * nels have been selected to participate, but no gestures have
+ * been mapped to a keycode.
+ */
+ if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_RAW) {
+ input_set_capability(iqs269->slider[i],
+ EV_KEY, BTN_TOUCH);
+ input_set_abs_params(iqs269->slider[i],
+ ABS_X, 0, 255, 0, 0);
+ }
error = input_register_device(iqs269->slider[i]);
if (error) {
@@ -1167,28 +1296,62 @@ static int iqs269_report(struct iqs269_private *iqs269)
if (be16_to_cpu(flags.system) & IQS269_SYS_FLAGS_IN_ATI)
return 0;
- error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X, slider_x,
- sizeof(slider_x));
- if (error) {
- dev_err(&client->dev, "Failed to read slider position: %d\n",
- error);
- return error;
+ if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
+ iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW) {
+ error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X,
+ slider_x, sizeof(slider_x));
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to read slider position: %d\n", error);
+ return error;
+ }
}
for (i = 0; i < IQS269_NUM_SL; i++) {
- if (!iqs269->sys_reg.slider_select[i])
+ flags.gesture >>= (i * IQS269_NUM_GESTURES);
+
+ switch (iqs269_slider_type(iqs269, i)) {
+ case IQS269_SLIDER_NONE:
continue;
- /*
- * Report BTN_TOUCH if any channel that participates in the
- * slider is in a state of touch.
- */
- if (flags.states[IQS269_ST_OFFS_TOUCH] &
- iqs269->sys_reg.slider_select[i]) {
- input_report_key(iqs269->slider[i], BTN_TOUCH, 1);
- input_report_abs(iqs269->slider[i], ABS_X, slider_x[i]);
- } else {
- input_report_key(iqs269->slider[i], BTN_TOUCH, 0);
+ case IQS269_SLIDER_KEY:
+ for (j = 0; j < IQS269_NUM_GESTURES; j++)
+ input_report_key(iqs269->slider[i],
+ iqs269->sl_code[i][j],
+ flags.gesture & BIT(j));
+
+ if (!(flags.gesture & (BIT(IQS269_GESTURE_FLICK_NEG) |
+ BIT(IQS269_GESTURE_FLICK_POS) |
+ BIT(IQS269_GESTURE_TAP))))
+ break;
+
+ input_sync(iqs269->slider[i]);
+
+ /*
+ * Momentary gestures are followed by a complementary
+ * release cycle so as to emulate a full keystroke.
+ */
+ for (j = 0; j < IQS269_NUM_GESTURES; j++)
+ if (j != IQS269_GESTURE_HOLD)
+ input_report_key(iqs269->slider[i],
+ iqs269->sl_code[i][j],
+ 0);
+ break;
+
+ case IQS269_SLIDER_RAW:
+ /*
+ * The slider is considered to be in a state of touch
+ * if any selected channels are in a state of touch.
+ */
+ state = flags.states[IQS269_ST_OFFS_TOUCH];
+ state &= iqs269->sys_reg.slider_select[i];
+
+ input_report_key(iqs269->slider[i], BTN_TOUCH, state);
+
+ if (state)
+ input_report_abs(iqs269->slider[i],
+ ABS_X, slider_x[i]);
+ break;
}
input_sync(iqs269->slider[i]);
@@ -1595,7 +1758,6 @@ static const struct regmap_config iqs269_regmap_config = {
static int iqs269_probe(struct i2c_client *client)
{
- struct iqs269_ver_info ver_info;
struct iqs269_private *iqs269;
int error;
@@ -1617,14 +1779,14 @@ static int iqs269_probe(struct i2c_client *client)
mutex_init(&iqs269->lock);
init_completion(&iqs269->ati_done);
- error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO, &ver_info,
- sizeof(ver_info));
+ error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO,
+ &iqs269->ver_info, sizeof(iqs269->ver_info));
if (error)
return error;
- if (ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
+ if (iqs269->ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
dev_err(&client->dev, "Unrecognized product number: 0x%02X\n",
- ver_info.prod_num);
+ iqs269->ver_info.prod_num);
return -EINVAL;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 3/4] dt-bindings: input: iqs269a: Add bindings for OTP variants
2024-01-01 20:00 [PATCH v3 0/4] Add support for slider gestures and OTP variants Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 1/4] dt-bindings: input: iqs269a: Add bindings for slider gestures Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 2/4] Input: iqs269a - add support " Jeff LaBundy
@ 2024-01-01 20:02 ` Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 4/4] Input: iqs269a - add support " Jeff LaBundy
2024-01-01 21:47 ` [PATCH v3 0/4] Add support for slider gestures and " Dmitry Torokhov
4 siblings, 0 replies; 6+ messages in thread
From: Jeff LaBundy @ 2024-01-01 20:02 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt
Cc: linux-input, devicetree, jeff
This patch adds bindings for the D0 order code of the device. This
order code represents an OTP variant that enables a touch-and-hold
function in place of slider 1.
Also included is the ability to specify the 00 order code (default
option with no OTP customization) explicitly.
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v3:
- None
Changes in v2:
- None
.../devicetree/bindings/input/iqs269a.yaml | 30 ++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/input/iqs269a.yaml b/Documentation/devicetree/bindings/input/iqs269a.yaml
index b42f07542d27..2c3f693b8982 100644
--- a/Documentation/devicetree/bindings/input/iqs269a.yaml
+++ b/Documentation/devicetree/bindings/input/iqs269a.yaml
@@ -20,7 +20,10 @@ description: |
properties:
compatible:
- const: azoteq,iqs269a
+ enum:
+ - azoteq,iqs269a
+ - azoteq,iqs269a-00
+ - azoteq,iqs269a-d0
reg:
maxItems: 1
@@ -207,6 +210,16 @@ properties:
default: 1
description: Specifies the slider coordinate filter strength.
+ azoteq,touch-hold-ms:
+ multipleOf: 256
+ minimum: 256
+ maximum: 65280
+ default: 5120
+ description:
+ Specifies the length of time (in ms) for which the channel selected by
+ 'azoteq,gpio3-select' must be held in a state of touch in order for an
+ approximately 60-ms pulse to be asserted on the GPIO4 pin.
+
linux,keycodes:
minItems: 1
maxItems: 8
@@ -514,6 +527,21 @@ patternProperties:
additionalProperties: false
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - azoteq,iqs269a-d0
+then:
+ patternProperties:
+ "^channel@[0-7]$":
+ properties:
+ azoteq,slider1-select: false
+else:
+ properties:
+ azoteq,touch-hold-ms: false
+
required:
- compatible
- reg
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 4/4] Input: iqs269a - add support for OTP variants
2024-01-01 20:00 [PATCH v3 0/4] Add support for slider gestures and OTP variants Jeff LaBundy
` (2 preceding siblings ...)
2024-01-01 20:02 ` [PATCH v3 3/4] dt-bindings: input: iqs269a: Add bindings for OTP variants Jeff LaBundy
@ 2024-01-01 20:02 ` Jeff LaBundy
2024-01-01 21:47 ` [PATCH v3 0/4] Add support for slider gestures and " Dmitry Torokhov
4 siblings, 0 replies; 6+ messages in thread
From: Jeff LaBundy @ 2024-01-01 20:02 UTC (permalink / raw)
To: dmitry.torokhov, robh+dt, krzysztof.kozlowski+dt, conor+dt
Cc: linux-input, devicetree, jeff
This patch adds support for each available OTP variant of the device.
The OTP configuration cannot be read over I2C, so it is derived from
a compatible string instead.
Early revisions of the D0 order code require their OTP-enabled func-
tionality to be manually restored following a soft reset; this patch
accommodates this erratum as well.
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
---
Changes in v3:
- Replaced of_device_get_match_data() with device_get_match_data()
Changes in v2:
- Rebased onto latest driver
drivers/input/misc/iqs269a.c | 92 ++++++++++++++++++++++++++++++++++--
1 file changed, 89 insertions(+), 3 deletions(-)
diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c
index 0d0b5cdc7830..cd14ff9f57cf 100644
--- a/drivers/input/misc/iqs269a.c
+++ b/drivers/input/misc/iqs269a.c
@@ -102,6 +102,11 @@
#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)
#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0)
+#define IQS269_TOUCH_HOLD_SLIDER_SEL 0x89
+#define IQS269_TOUCH_HOLD_DEFAULT 0x14
+#define IQS269_TOUCH_HOLD_MS_MIN 256
+#define IQS269_TOUCH_HOLD_MS_MAX 65280
+
#define IQS269_TIMEOUT_TAP_MS_MAX 4080
#define IQS269_TIMEOUT_SWIPE_MS_MAX 4080
#define IQS269_THRESH_SWIPE_MAX 255
@@ -151,6 +156,10 @@
#define IQS269_MAX_REG 0xFF
+#define IQS269_OTP_OPTION_DEFAULT 0x00
+#define IQS269_OTP_OPTION_TWS 0xD0
+#define IQS269_OTP_OPTION_HOLD BIT(7)
+
#define IQS269_NUM_CH 8
#define IQS269_NUM_SL 2
@@ -315,6 +324,7 @@ struct iqs269_private {
struct input_dev *slider[IQS269_NUM_SL];
unsigned int keycode[ARRAY_SIZE(iqs269_events) * IQS269_NUM_CH];
unsigned int sl_code[IQS269_NUM_SL][IQS269_NUM_GESTURES];
+ unsigned int otp_option;
unsigned int ch_num;
bool hall_enable;
bool ati_current;
@@ -325,6 +335,14 @@ static enum iqs269_slider_id iqs269_slider_type(struct iqs269_private *iqs269,
{
int i;
+ /*
+ * Slider 1 is unavailable if the touch-and-hold option is enabled via
+ * OTP. In that case, the channel selection register is repurposed for
+ * the touch-and-hold timer ceiling.
+ */
+ if (slider_num && (iqs269->otp_option & IQS269_OTP_OPTION_HOLD))
+ return IQS269_SLIDER_NONE;
+
if (!iqs269->sys_reg.slider_select[slider_num])
return IQS269_SLIDER_NONE;
@@ -565,7 +583,8 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
if (fwnode_property_present(ch_node, "azoteq,slider0-select"))
iqs269->sys_reg.slider_select[0] |= BIT(reg);
- if (fwnode_property_present(ch_node, "azoteq,slider1-select"))
+ if (fwnode_property_present(ch_node, "azoteq,slider1-select") &&
+ !(iqs269->otp_option & IQS269_OTP_OPTION_HOLD))
iqs269->sys_reg.slider_select[1] |= BIT(reg);
ch_reg = &iqs269->sys_reg.ch_reg[reg];
@@ -990,7 +1009,43 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
sys_reg->blocking = 0;
sys_reg->slider_select[0] = 0;
- sys_reg->slider_select[1] = 0;
+
+ /*
+ * If configured via OTP to do so, the device asserts a pulse on the
+ * GPIO4 pin for approximately 60 ms once a selected channel is held
+ * in a state of touch for a configurable length of time.
+ *
+ * In that case, the register used for slider 1 channel selection is
+ * repurposed for the touch-and-hold timer ceiling.
+ */
+ if (iqs269->otp_option & IQS269_OTP_OPTION_HOLD) {
+ if (!device_property_read_u32(&client->dev,
+ "azoteq,touch-hold-ms", &val)) {
+ if (val < IQS269_TOUCH_HOLD_MS_MIN ||
+ val > IQS269_TOUCH_HOLD_MS_MAX) {
+ dev_err(&client->dev,
+ "Invalid touch-and-hold ceiling: %u\n",
+ val);
+ return -EINVAL;
+ }
+
+ sys_reg->slider_select[1] = val / 256;
+ } else if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3) {
+ /*
+ * The default touch-and-hold timer ceiling initially
+ * read from early revisions of silicon is invalid if
+ * the device experienced a soft reset between power-
+ * on and the read operation.
+ *
+ * To protect against this case, explicitly cache the
+ * default value so that it is restored each time the
+ * device is re-initialized.
+ */
+ sys_reg->slider_select[1] = IQS269_TOUCH_HOLD_DEFAULT;
+ }
+ } else {
+ sys_reg->slider_select[1] = 0;
+ }
sys_reg->event_mask = ~((u8)IQS269_EVENT_MASK_SYS);
@@ -1137,12 +1192,30 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
return 0;
}
+static const struct reg_sequence iqs269_tws_init[] = {
+ { IQS269_TOUCH_HOLD_SLIDER_SEL, IQS269_TOUCH_HOLD_DEFAULT },
+ { 0xF0, 0x580F },
+ { 0xF0, 0x59EF },
+};
+
static int iqs269_dev_init(struct iqs269_private *iqs269)
{
int error;
mutex_lock(&iqs269->lock);
+ /*
+ * Early revisions of silicon require the following workaround in order
+ * to restore any OTP-enabled functionality after a soft reset.
+ */
+ if (iqs269->otp_option == IQS269_OTP_OPTION_TWS &&
+ iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3) {
+ error = regmap_multi_reg_write(iqs269->regmap, iqs269_tws_init,
+ ARRAY_SIZE(iqs269_tws_init));
+ if (error)
+ goto err_mutex;
+ }
+
error = regmap_update_bits(iqs269->regmap, IQS269_HALL_UI,
IQS269_HALL_UI_ENABLE,
iqs269->hall_enable ? ~0 : 0);
@@ -1779,6 +1852,8 @@ static int iqs269_probe(struct i2c_client *client)
mutex_init(&iqs269->lock);
init_completion(&iqs269->ati_done);
+ iqs269->otp_option = (uintptr_t)device_get_match_data(&client->dev);
+
error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO,
&iqs269->ver_info, sizeof(iqs269->ver_info));
if (error)
@@ -1889,7 +1964,18 @@ static int iqs269_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(iqs269_pm, iqs269_suspend, iqs269_resume);
static const struct of_device_id iqs269_of_match[] = {
- { .compatible = "azoteq,iqs269a" },
+ {
+ .compatible = "azoteq,iqs269a",
+ .data = (void *)IQS269_OTP_OPTION_DEFAULT,
+ },
+ {
+ .compatible = "azoteq,iqs269a-00",
+ .data = (void *)IQS269_OTP_OPTION_DEFAULT,
+ },
+ {
+ .compatible = "azoteq,iqs269a-d0",
+ .data = (void *)IQS269_OTP_OPTION_TWS,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, iqs269_of_match);
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/4] Add support for slider gestures and OTP variants
2024-01-01 20:00 [PATCH v3 0/4] Add support for slider gestures and OTP variants Jeff LaBundy
` (3 preceding siblings ...)
2024-01-01 20:02 ` [PATCH v3 4/4] Input: iqs269a - add support " Jeff LaBundy
@ 2024-01-01 21:47 ` Dmitry Torokhov
4 siblings, 0 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2024-01-01 21:47 UTC (permalink / raw)
To: Jeff LaBundy
Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, linux-input,
devicetree
On Mon, Jan 01, 2024 at 02:00:13PM -0600, Jeff LaBundy wrote:
> This series introduces support for some additional features offered by the
> Azoteq IQS269A capacitive touch controller.
>
> Patches 1 and 2 add support for slider gestures (e.g. tap or swipe). Gestures
> are recognized by the hardware itself based on touch activity across the chan-
> nels associated with the slider. This feature is useful for lightweight systems
> that do not post-process absolute coordinates to determine gestures expressed
> by the user.
>
> Gestures are presented to user space as keycodes. An example use-case is an
> array of multimedia keys as seen in the following demo:
>
> https://youtu.be/k_vMRQiHLgA
>
> Patches 3 and 4 add support for the device's available OTP variants, which
> trade features or exhibit errata that require workarounds.
Applied the lot, thank you.
--
Dmitry
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-01-01 21:47 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-01 20:00 [PATCH v3 0/4] Add support for slider gestures and OTP variants Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 1/4] dt-bindings: input: iqs269a: Add bindings for slider gestures Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 2/4] Input: iqs269a - add support " Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 3/4] dt-bindings: input: iqs269a: Add bindings for OTP variants Jeff LaBundy
2024-01-01 20:02 ` [PATCH v3 4/4] Input: iqs269a - add support " Jeff LaBundy
2024-01-01 21:47 ` [PATCH v3 0/4] Add support for slider gestures and " Dmitry Torokhov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).