| From foo@baz Thu Nov 9 09:48:01 CET 2017 |
| From: Akinobu Mita <akinobu.mita@gmail.com> |
| Date: Sun, 15 Jan 2017 14:44:30 -0800 |
| Subject: Input: mpr121 - handle multiple bits change of status register |
| |
| From: Akinobu Mita <akinobu.mita@gmail.com> |
| |
| |
| [ Upstream commit 08fea55e37f58371bffc5336a59e55d1f155955a ] |
| |
| 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 <akinobu.mita@gmail.com> |
| Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/input/keyboard/mpr121_touchkey.c | 23 ++++++++++++++--------- |
| 1 file changed, 14 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/input/keyboard/mpr121_touchkey.c |
| +++ b/drivers/input/keyboard/mpr121_touchkey.c |
| @@ -87,7 +87,8 @@ static irqreturn_t mpr_touchkey_interrup |
| struct mpr121_touchkey *mpr121 = dev_id; |
| struct i2c_client *client = mpr121->client; |
| struct input_dev *input = mpr121->input_dev; |
| - unsigned int key_num, key_val, pressed; |
| + unsigned long bit_changed; |
| + unsigned int key_num; |
| int reg; |
| |
| reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR); |
| @@ -105,18 +106,22 @@ static irqreturn_t mpr_touchkey_interrup |
| |
| reg &= TOUCH_STATUS_MASK; |
| /* use old press bit to figure out which bit changed */ |
| - key_num = ffs(reg ^ mpr121->statusbits) - 1; |
| - pressed = reg & (1 << key_num); |
| + bit_changed = reg ^ mpr121->statusbits; |
| mpr121->statusbits = reg; |
| + for_each_set_bit(key_num, &bit_changed, mpr121->keycount) { |
| + unsigned int key_val, pressed; |
| |
| - key_val = mpr121->keycodes[key_num]; |
| + pressed = reg & BIT(key_num); |
| + key_val = mpr121->keycodes[key_num]; |
| |
| - input_event(input, EV_MSC, MSC_SCAN, key_num); |
| - input_report_key(input, key_val, pressed); |
| - input_sync(input); |
| + input_event(input, EV_MSC, MSC_SCAN, key_num); |
| + input_report_key(input, key_val, pressed); |
| + |
| + dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val, |
| + pressed ? "pressed" : "released"); |
| |
| - dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val, |
| - pressed ? "pressed" : "released"); |
| + } |
| + input_sync(input); |
| |
| out: |
| return IRQ_HANDLED; |