Skip to content

Commit 00521a9

Browse files
jlabundydtor
authored andcommitted
Input: iqs269a - add support for slider gestures
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> Link: https://lore.kernel.org/r/ZZMaT46WQq1/Nrsb@nixie71 Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
1 parent 65cdd3a commit 00521a9

File tree

1 file changed

+191
-29
lines changed

1 file changed

+191
-29
lines changed

drivers/input/misc/iqs269a.c

Lines changed: 191 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* axial sliders presented by the device.
1010
*/
1111

12+
#include <linux/bits.h>
1213
#include <linux/completion.h>
1314
#include <linux/delay.h>
1415
#include <linux/device.h>
@@ -26,6 +27,8 @@
2627

2728
#define IQS269_VER_INFO 0x00
2829
#define IQS269_VER_INFO_PROD_NUM 0x4F
30+
#define IQS269_VER_INFO_FW_NUM_2 0x03
31+
#define IQS269_VER_INFO_FW_NUM_3 0x10
2932

3033
#define IQS269_SYS_FLAGS 0x02
3134
#define IQS269_SYS_FLAGS_SHOW_RESET BIT(15)
@@ -53,6 +56,7 @@
5356
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MASK GENMASK(10, 8)
5457
#define IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT 8
5558
#define IQS269_SYS_SETTINGS_ULP_UPDATE_MAX 7
59+
#define IQS269_SYS_SETTINGS_SLIDER_SWIPE BIT(7)
5660
#define IQS269_SYS_SETTINGS_RESEED_OFFSET BIT(6)
5761
#define IQS269_SYS_SETTINGS_EVENT_MODE BIT(5)
5862
#define IQS269_SYS_SETTINGS_EVENT_MODE_LP BIT(4)
@@ -69,6 +73,7 @@
6973
#define IQS269_FILT_STR_MAX 3
7074

7175
#define IQS269_EVENT_MASK_SYS BIT(6)
76+
#define IQS269_EVENT_MASK_GESTURE BIT(3)
7277
#define IQS269_EVENT_MASK_DEEP BIT(2)
7378
#define IQS269_EVENT_MASK_TOUCH BIT(1)
7479
#define IQS269_EVENT_MASK_PROX BIT(0)
@@ -97,6 +102,10 @@
97102
#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)
98103
#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0)
99104

105+
#define IQS269_TIMEOUT_TAP_MS_MAX 4080
106+
#define IQS269_TIMEOUT_SWIPE_MS_MAX 4080
107+
#define IQS269_THRESH_SWIPE_MAX 255
108+
100109
#define IQS269_CHx_ENG_A_MEAS_CAP_SIZE BIT(15)
101110
#define IQS269_CHx_ENG_A_RX_GND_INACTIVE BIT(13)
102111
#define IQS269_CHx_ENG_A_LOCAL_CAP_SIZE BIT(12)
@@ -175,6 +184,20 @@ enum iqs269_event_id {
175184
IQS269_EVENT_DEEP_UP,
176185
};
177186

187+
enum iqs269_slider_id {
188+
IQS269_SLIDER_NONE,
189+
IQS269_SLIDER_KEY,
190+
IQS269_SLIDER_RAW,
191+
};
192+
193+
enum iqs269_gesture_id {
194+
IQS269_GESTURE_TAP,
195+
IQS269_GESTURE_HOLD,
196+
IQS269_GESTURE_FLICK_POS,
197+
IQS269_GESTURE_FLICK_NEG,
198+
IQS269_NUM_GESTURES,
199+
};
200+
178201
struct iqs269_switch_desc {
179202
unsigned int code;
180203
bool enabled;
@@ -234,7 +257,7 @@ struct iqs269_ver_info {
234257
u8 prod_num;
235258
u8 sw_num;
236259
u8 hw_num;
237-
u8 padding;
260+
u8 fw_num;
238261
} __packed;
239262

240263
struct iqs269_ch_reg {
@@ -285,16 +308,33 @@ struct iqs269_private {
285308
struct regmap *regmap;
286309
struct mutex lock;
287310
struct iqs269_switch_desc switches[ARRAY_SIZE(iqs269_events)];
311+
struct iqs269_ver_info ver_info;
288312
struct iqs269_sys_reg sys_reg;
289313
struct completion ati_done;
290314
struct input_dev *keypad;
291315
struct input_dev *slider[IQS269_NUM_SL];
292316
unsigned int keycode[ARRAY_SIZE(iqs269_events) * IQS269_NUM_CH];
317+
unsigned int sl_code[IQS269_NUM_SL][IQS269_NUM_GESTURES];
293318
unsigned int ch_num;
294319
bool hall_enable;
295320
bool ati_current;
296321
};
297322

323+
static enum iqs269_slider_id iqs269_slider_type(struct iqs269_private *iqs269,
324+
int slider_num)
325+
{
326+
int i;
327+
328+
if (!iqs269->sys_reg.slider_select[slider_num])
329+
return IQS269_SLIDER_NONE;
330+
331+
for (i = 0; i < IQS269_NUM_GESTURES; i++)
332+
if (iqs269->sl_code[slider_num][i] != KEY_RESERVED)
333+
return IQS269_SLIDER_KEY;
334+
335+
return IQS269_SLIDER_RAW;
336+
}
337+
298338
static int iqs269_ati_mode_set(struct iqs269_private *iqs269,
299339
unsigned int ch_num, unsigned int mode)
300340
{
@@ -1004,6 +1044,76 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
10041044
general |= (val << IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT);
10051045
}
10061046

1047+
if (device_property_present(&client->dev, "linux,keycodes")) {
1048+
int scale = 1;
1049+
int count = device_property_count_u32(&client->dev,
1050+
"linux,keycodes");
1051+
if (count > IQS269_NUM_GESTURES * IQS269_NUM_SL) {
1052+
dev_err(&client->dev, "Too many keycodes present\n");
1053+
return -EINVAL;
1054+
} else if (count < 0) {
1055+
dev_err(&client->dev, "Failed to count keycodes: %d\n",
1056+
count);
1057+
return count;
1058+
}
1059+
1060+
error = device_property_read_u32_array(&client->dev,
1061+
"linux,keycodes",
1062+
*iqs269->sl_code, count);
1063+
if (error) {
1064+
dev_err(&client->dev, "Failed to read keycodes: %d\n",
1065+
error);
1066+
return error;
1067+
}
1068+
1069+
if (device_property_present(&client->dev,
1070+
"azoteq,gesture-swipe"))
1071+
general |= IQS269_SYS_SETTINGS_SLIDER_SWIPE;
1072+
1073+
/*
1074+
* Early revisions of silicon use a more granular step size for
1075+
* tap and swipe gesture timeouts; scale them appropriately.
1076+
*/
1077+
if (iqs269->ver_info.fw_num < IQS269_VER_INFO_FW_NUM_3)
1078+
scale = 4;
1079+
1080+
if (!device_property_read_u32(&client->dev,
1081+
"azoteq,timeout-tap-ms", &val)) {
1082+
if (val > IQS269_TIMEOUT_TAP_MS_MAX / scale) {
1083+
dev_err(&client->dev, "Invalid timeout: %u\n",
1084+
val);
1085+
return -EINVAL;
1086+
}
1087+
1088+
sys_reg->timeout_tap = val / (16 / scale);
1089+
}
1090+
1091+
if (!device_property_read_u32(&client->dev,
1092+
"azoteq,timeout-swipe-ms",
1093+
&val)) {
1094+
if (val > IQS269_TIMEOUT_SWIPE_MS_MAX / scale) {
1095+
dev_err(&client->dev, "Invalid timeout: %u\n",
1096+
val);
1097+
return -EINVAL;
1098+
}
1099+
1100+
sys_reg->timeout_swipe = val / (16 / scale);
1101+
}
1102+
1103+
if (!device_property_read_u32(&client->dev,
1104+
"azoteq,thresh-swipe", &val)) {
1105+
if (val > IQS269_THRESH_SWIPE_MAX) {
1106+
dev_err(&client->dev, "Invalid threshold: %u\n",
1107+
val);
1108+
return -EINVAL;
1109+
}
1110+
1111+
sys_reg->thresh_swipe = val;
1112+
}
1113+
1114+
sys_reg->event_mask &= ~IQS269_EVENT_MASK_GESTURE;
1115+
}
1116+
10071117
general &= ~IQS269_SYS_SETTINGS_RESEED_OFFSET;
10081118
if (device_property_present(&client->dev, "azoteq,reseed-offset"))
10091119
general |= IQS269_SYS_SETTINGS_RESEED_OFFSET;
@@ -1012,10 +1122,11 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
10121122

10131123
/*
10141124
* As per the datasheet, enable streaming during normal-power mode if
1015-
* either slider is in use. In that case, the device returns to event
1016-
* mode during low-power mode.
1125+
* raw coordinates will be read from either slider. In that case, the
1126+
* device returns to event mode during low-power mode.
10171127
*/
1018-
if (sys_reg->slider_select[0] || sys_reg->slider_select[1])
1128+
if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
1129+
iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW)
10191130
general |= IQS269_SYS_SETTINGS_EVENT_MODE_LP;
10201131

10211132
general |= IQS269_SYS_SETTINGS_REDO_ATI;
@@ -1106,19 +1217,37 @@ static int iqs269_input_init(struct iqs269_private *iqs269)
11061217
}
11071218

11081219
for (i = 0; i < IQS269_NUM_SL; i++) {
1109-
if (!iqs269->sys_reg.slider_select[i])
1220+
if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_NONE)
11101221
continue;
11111222

11121223
iqs269->slider[i] = devm_input_allocate_device(&client->dev);
11131224
if (!iqs269->slider[i])
11141225
return -ENOMEM;
11151226

1227+
iqs269->slider[i]->keycodemax = ARRAY_SIZE(iqs269->sl_code[i]);
1228+
iqs269->slider[i]->keycode = iqs269->sl_code[i];
1229+
iqs269->slider[i]->keycodesize = sizeof(**iqs269->sl_code);
1230+
11161231
iqs269->slider[i]->name = i ? "iqs269a_slider_1"
11171232
: "iqs269a_slider_0";
11181233
iqs269->slider[i]->id.bustype = BUS_I2C;
11191234

1120-
input_set_capability(iqs269->slider[i], EV_KEY, BTN_TOUCH);
1121-
input_set_abs_params(iqs269->slider[i], ABS_X, 0, 255, 0, 0);
1235+
for (j = 0; j < IQS269_NUM_GESTURES; j++)
1236+
if (iqs269->sl_code[i][j] != KEY_RESERVED)
1237+
input_set_capability(iqs269->slider[i], EV_KEY,
1238+
iqs269->sl_code[i][j]);
1239+
1240+
/*
1241+
* Present the slider as a narrow trackpad if one or more chan-
1242+
* nels have been selected to participate, but no gestures have
1243+
* been mapped to a keycode.
1244+
*/
1245+
if (iqs269_slider_type(iqs269, i) == IQS269_SLIDER_RAW) {
1246+
input_set_capability(iqs269->slider[i],
1247+
EV_KEY, BTN_TOUCH);
1248+
input_set_abs_params(iqs269->slider[i],
1249+
ABS_X, 0, 255, 0, 0);
1250+
}
11221251

11231252
error = input_register_device(iqs269->slider[i]);
11241253
if (error) {
@@ -1167,28 +1296,62 @@ static int iqs269_report(struct iqs269_private *iqs269)
11671296
if (be16_to_cpu(flags.system) & IQS269_SYS_FLAGS_IN_ATI)
11681297
return 0;
11691298

1170-
error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X, slider_x,
1171-
sizeof(slider_x));
1172-
if (error) {
1173-
dev_err(&client->dev, "Failed to read slider position: %d\n",
1174-
error);
1175-
return error;
1299+
if (iqs269_slider_type(iqs269, 0) == IQS269_SLIDER_RAW ||
1300+
iqs269_slider_type(iqs269, 1) == IQS269_SLIDER_RAW) {
1301+
error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X,
1302+
slider_x, sizeof(slider_x));
1303+
if (error) {
1304+
dev_err(&client->dev,
1305+
"Failed to read slider position: %d\n", error);
1306+
return error;
1307+
}
11761308
}
11771309

11781310
for (i = 0; i < IQS269_NUM_SL; i++) {
1179-
if (!iqs269->sys_reg.slider_select[i])
1311+
flags.gesture >>= (i * IQS269_NUM_GESTURES);
1312+
1313+
switch (iqs269_slider_type(iqs269, i)) {
1314+
case IQS269_SLIDER_NONE:
11801315
continue;
11811316

1182-
/*
1183-
* Report BTN_TOUCH if any channel that participates in the
1184-
* slider is in a state of touch.
1185-
*/
1186-
if (flags.states[IQS269_ST_OFFS_TOUCH] &
1187-
iqs269->sys_reg.slider_select[i]) {
1188-
input_report_key(iqs269->slider[i], BTN_TOUCH, 1);
1189-
input_report_abs(iqs269->slider[i], ABS_X, slider_x[i]);
1190-
} else {
1191-
input_report_key(iqs269->slider[i], BTN_TOUCH, 0);
1317+
case IQS269_SLIDER_KEY:
1318+
for (j = 0; j < IQS269_NUM_GESTURES; j++)
1319+
input_report_key(iqs269->slider[i],
1320+
iqs269->sl_code[i][j],
1321+
flags.gesture & BIT(j));
1322+
1323+
if (!(flags.gesture & (BIT(IQS269_GESTURE_FLICK_NEG) |
1324+
BIT(IQS269_GESTURE_FLICK_POS) |
1325+
BIT(IQS269_GESTURE_TAP))))
1326+
break;
1327+
1328+
input_sync(iqs269->slider[i]);
1329+
1330+
/*
1331+
* Momentary gestures are followed by a complementary
1332+
* release cycle so as to emulate a full keystroke.
1333+
*/
1334+
for (j = 0; j < IQS269_NUM_GESTURES; j++)
1335+
if (j != IQS269_GESTURE_HOLD)
1336+
input_report_key(iqs269->slider[i],
1337+
iqs269->sl_code[i][j],
1338+
0);
1339+
break;
1340+
1341+
case IQS269_SLIDER_RAW:
1342+
/*
1343+
* The slider is considered to be in a state of touch
1344+
* if any selected channels are in a state of touch.
1345+
*/
1346+
state = flags.states[IQS269_ST_OFFS_TOUCH];
1347+
state &= iqs269->sys_reg.slider_select[i];
1348+
1349+
input_report_key(iqs269->slider[i], BTN_TOUCH, state);
1350+
1351+
if (state)
1352+
input_report_abs(iqs269->slider[i],
1353+
ABS_X, slider_x[i]);
1354+
break;
11921355
}
11931356

11941357
input_sync(iqs269->slider[i]);
@@ -1595,7 +1758,6 @@ static const struct regmap_config iqs269_regmap_config = {
15951758

15961759
static int iqs269_probe(struct i2c_client *client)
15971760
{
1598-
struct iqs269_ver_info ver_info;
15991761
struct iqs269_private *iqs269;
16001762
int error;
16011763

@@ -1617,14 +1779,14 @@ static int iqs269_probe(struct i2c_client *client)
16171779
mutex_init(&iqs269->lock);
16181780
init_completion(&iqs269->ati_done);
16191781

1620-
error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO, &ver_info,
1621-
sizeof(ver_info));
1782+
error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO,
1783+
&iqs269->ver_info, sizeof(iqs269->ver_info));
16221784
if (error)
16231785
return error;
16241786

1625-
if (ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
1787+
if (iqs269->ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) {
16261788
dev_err(&client->dev, "Unrecognized product number: 0x%02X\n",
1627-
ver_info.prod_num);
1789+
iqs269->ver_info.prod_num);
16281790
return -EINVAL;
16291791
}
16301792

0 commit comments

Comments
 (0)