Skip to content

Commit 08fea55

Browse files
mitadtor
authored andcommitted
Input: mpr121 - handle multiple bits change of status register
This driver reports input events on their interrupts which are triggered by the sensor's status register changes. But only single bit change is reported in the interrupt handler. So if there are multiple bits are changed at almost the same time, other press or release events are ignored. This fixes it by detecting all changed bits in the status register. Signed-off-by: Akinobu Mita <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 9723ddc commit 08fea55

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

drivers/input/keyboard/mpr121_touchkey.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
8686
struct mpr121_touchkey *mpr121 = dev_id;
8787
struct i2c_client *client = mpr121->client;
8888
struct input_dev *input = mpr121->input_dev;
89-
unsigned int key_num, key_val, pressed;
89+
unsigned long bit_changed;
90+
unsigned int key_num;
9091
int reg;
9192

9293
reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
@@ -104,18 +105,22 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
104105

105106
reg &= TOUCH_STATUS_MASK;
106107
/* use old press bit to figure out which bit changed */
107-
key_num = ffs(reg ^ mpr121->statusbits) - 1;
108-
pressed = reg & (1 << key_num);
108+
bit_changed = reg ^ mpr121->statusbits;
109109
mpr121->statusbits = reg;
110+
for_each_set_bit(key_num, &bit_changed, mpr121->keycount) {
111+
unsigned int key_val, pressed;
110112

111-
key_val = mpr121->keycodes[key_num];
113+
pressed = reg & BIT(key_num);
114+
key_val = mpr121->keycodes[key_num];
112115

113-
input_event(input, EV_MSC, MSC_SCAN, key_num);
114-
input_report_key(input, key_val, pressed);
115-
input_sync(input);
116+
input_event(input, EV_MSC, MSC_SCAN, key_num);
117+
input_report_key(input, key_val, pressed);
118+
119+
dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
120+
pressed ? "pressed" : "released");
116121

117-
dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
118-
pressed ? "pressed" : "released");
122+
}
123+
input_sync(input);
119124

120125
out:
121126
return IRQ_HANDLED;

0 commit comments

Comments
 (0)