Skip to content

Commit 95215d3

Browse files
jlabundydtor
authored andcommitted
Input: iqs7222 - fortify slider event reporting
The release cycle of any key mapped to a slider gesture relies upon trailing interrupts generated by other unmasked sources, the timing and presence of which are inconsistent. To solve this problem, explicitly report a release cycle to emulate a full keystroke. Also, unmask touch interrupts if the slider press event is defined; this ensures the device reports a final interrupt with coordinate = 0xFFFF once the finger is lifted. As a result of how the logic has been refactored, the press/release event can now be mapped to a GPIO. This is more convenient than the previous solution, which required each channel within the slider to specify the same GPIO. As part of this change, use the device's resolution rather than its number of interrupt status registers to more safely determine if it is capable of reporting gestures. Last but not least, make the code a bit simpler by eliminating some unnecessarily complex conditional statements and a macro that could be derived using information that is already available. Fixes: e505eda ("Input: add support for Azoteq IQS7222A/B/C") Signed-off-by: Jeff LaBundy <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 56a0c54 commit 95215d3

File tree

1 file changed

+58
-38
lines changed

1 file changed

+58
-38
lines changed

drivers/input/misc/iqs7222.c

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#define IQS7222_SLDR_SETUP_2_RES_MASK GENMASK(15, 8)
4141
#define IQS7222_SLDR_SETUP_2_RES_SHIFT 8
4242
#define IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK GENMASK(7, 0)
43-
#define IQS7222_SLDR_SETUP_3_CHAN_SEL_MASK GENMASK(9, 0)
4443

4544
#define IQS7222_GPIO_SETUP_0_GPIO_EN BIT(0)
4645

@@ -54,6 +53,9 @@
5453
#define IQS7222_SYS_SETUP_ACK_RESET BIT(0)
5554

5655
#define IQS7222_EVENT_MASK_ATI BIT(12)
56+
#define IQS7222_EVENT_MASK_SLDR BIT(10)
57+
#define IQS7222_EVENT_MASK_TOUCH BIT(1)
58+
#define IQS7222_EVENT_MASK_PROX BIT(0)
5759

5860
#define IQS7222_COMMS_HOLD BIT(0)
5961
#define IQS7222_COMMS_ERROR 0xEEEE
@@ -135,12 +137,12 @@ struct iqs7222_event_desc {
135137
static const struct iqs7222_event_desc iqs7222_kp_events[] = {
136138
{
137139
.name = "event-prox",
138-
.enable = BIT(0),
140+
.enable = IQS7222_EVENT_MASK_PROX,
139141
.reg_key = IQS7222_REG_KEY_PROX,
140142
},
141143
{
142144
.name = "event-touch",
143-
.enable = BIT(1),
145+
.enable = IQS7222_EVENT_MASK_TOUCH,
144146
.reg_key = IQS7222_REG_KEY_TOUCH,
145147
},
146148
};
@@ -1957,8 +1959,8 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
19571959
int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row;
19581960
int ext_chan = rounddown(num_chan, 10);
19591961
int count, error, reg_offset, i;
1962+
u16 *event_mask = &iqs7222->sys_setup[dev_desc->event_offset];
19601963
u16 *sldr_setup = iqs7222->sldr_setup[sldr_index];
1961-
u16 *sys_setup = iqs7222->sys_setup;
19621964
unsigned int chan_sel[4], val;
19631965

19641966
error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index,
@@ -2003,7 +2005,7 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
20032005
reg_offset = dev_desc->sldr_res < U16_MAX ? 0 : 1;
20042006

20052007
sldr_setup[0] |= count;
2006-
sldr_setup[3 + reg_offset] &= ~IQS7222_SLDR_SETUP_3_CHAN_SEL_MASK;
2008+
sldr_setup[3 + reg_offset] &= ~GENMASK(ext_chan - 1, 0);
20072009

20082010
for (i = 0; i < ARRAY_SIZE(chan_sel); i++) {
20092011
sldr_setup[5 + reg_offset + i] = 0;
@@ -2106,6 +2108,22 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
21062108
if (error)
21072109
return error;
21082110

2111+
/*
2112+
* The press/release event does not expose a direct GPIO link,
2113+
* but one can be emulated by tying each of the participating
2114+
* channels to the same GPIO.
2115+
*/
2116+
error = iqs7222_gpio_select(iqs7222, event_node,
2117+
i ? iqs7222_sl_events[i].enable
2118+
: sldr_setup[3 + reg_offset],
2119+
i ? 1568 + sldr_index * 30
2120+
: sldr_setup[4 + reg_offset]);
2121+
if (error)
2122+
return error;
2123+
2124+
if (!reg_offset)
2125+
sldr_setup[9] |= iqs7222_sl_events[i].enable;
2126+
21092127
error = fwnode_property_read_u32(event_node, "linux,code",
21102128
&val);
21112129
if (error) {
@@ -2117,26 +2135,20 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
21172135
iqs7222->sl_code[sldr_index][i] = val;
21182136
input_set_capability(iqs7222->keypad, EV_KEY, val);
21192137

2120-
/*
2121-
* The press/release event is determined based on whether the
2122-
* coordinate field reports 0xFFFF and has no explicit enable
2123-
* control.
2124-
*/
2125-
if (!iqs7222_sl_events[i].enable || reg_offset)
2126-
continue;
2127-
2128-
sldr_setup[9] |= iqs7222_sl_events[i].enable;
2129-
2130-
error = iqs7222_gpio_select(iqs7222, event_node,
2131-
iqs7222_sl_events[i].enable,
2132-
1568 + sldr_index * 30);
2133-
if (error)
2134-
return error;
2135-
21362138
if (!dev_desc->event_offset)
21372139
continue;
21382140

2139-
sys_setup[dev_desc->event_offset] |= BIT(10 + sldr_index);
2141+
/*
2142+
* The press/release event is determined based on whether the
2143+
* coordinate field reports 0xFFFF and solely relies on touch
2144+
* or proximity interrupts to be unmasked.
2145+
*/
2146+
if (i && !reg_offset)
2147+
*event_mask |= (IQS7222_EVENT_MASK_SLDR << sldr_index);
2148+
else if (sldr_setup[4 + reg_offset] == dev_desc->touch_link)
2149+
*event_mask |= IQS7222_EVENT_MASK_TOUCH;
2150+
else
2151+
*event_mask |= IQS7222_EVENT_MASK_PROX;
21402152
}
21412153

21422154
/*
@@ -2301,29 +2313,37 @@ static int iqs7222_report(struct iqs7222_private *iqs7222)
23012313
input_report_abs(iqs7222->keypad, iqs7222->sl_axis[i],
23022314
sldr_pos);
23032315

2304-
for (j = 0; j < ARRAY_SIZE(iqs7222_sl_events); j++) {
2305-
u16 mask = iqs7222_sl_events[j].mask;
2306-
u16 val = iqs7222_sl_events[j].val;
2316+
input_report_key(iqs7222->keypad, iqs7222->sl_code[i][0],
2317+
sldr_pos < dev_desc->sldr_res);
23072318

2308-
if (!iqs7222_sl_events[j].enable) {
2309-
input_report_key(iqs7222->keypad,
2310-
iqs7222->sl_code[i][j],
2311-
sldr_pos < dev_desc->sldr_res);
2312-
continue;
2313-
}
2319+
/*
2320+
* A maximum resolution indicates the device does not support
2321+
* gestures, in which case the remaining fields are ignored.
2322+
*/
2323+
if (dev_desc->sldr_res == U16_MAX)
2324+
continue;
23142325

2315-
/*
2316-
* The remaining offsets represent gesture state, and
2317-
* are discarded in the case of IQS7222C because only
2318-
* absolute position is reported.
2319-
*/
2320-
if (num_stat < IQS7222_MAX_COLS_STAT)
2321-
continue;
2326+
if (!(le16_to_cpu(status[1]) & IQS7222_EVENT_MASK_SLDR << i))
2327+
continue;
2328+
2329+
/*
2330+
* Skip the press/release event, as it does not have separate
2331+
* status fields and is handled separately.
2332+
*/
2333+
for (j = 1; j < ARRAY_SIZE(iqs7222_sl_events); j++) {
2334+
u16 mask = iqs7222_sl_events[j].mask;
2335+
u16 val = iqs7222_sl_events[j].val;
23222336

23232337
input_report_key(iqs7222->keypad,
23242338
iqs7222->sl_code[i][j],
23252339
(state & mask) == val);
23262340
}
2341+
2342+
input_sync(iqs7222->keypad);
2343+
2344+
for (j = 1; j < ARRAY_SIZE(iqs7222_sl_events); j++)
2345+
input_report_key(iqs7222->keypad,
2346+
iqs7222->sl_code[i][j], 0);
23272347
}
23282348

23292349
input_sync(iqs7222->keypad);

0 commit comments

Comments
 (0)