Commit 4bcf69e5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:

 - an update to Elan touchpad controller driver supporting newer ICs
   with enhanced precision reports and a new firmware update process

 - an update to EXC3000 touch controller supporting additional parts

 - assorted driver fixups

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (27 commits)
  Input: exc3000 - add support to query model and fw_version
  Input: exc3000 - add reset gpio support
  Input: exc3000 - add EXC80H60 and EXC80H84 support
  dt-bindings: touchscreen: Convert EETI EXC3000 touchscreen to json-schema
  Input: sentelic - fix error return when fsp_reg_write fails
  Input: alps - remove redundant assignment to variable ret
  Input: ims-pcu - return error code rather than -ENOMEM
  Input: elan_i2c - add ic type 0x15
  Input: atmel_mxt_ts - only read messages in mxt_acquire_irq() when necessary
  Input: uinput - fix typo in function name documentation
  Input: ati_remote2 - add missing newlines when printing module parameters
  Input: psmouse - add a newline when printing 'proto' by sysfs
  Input: synaptics-rmi4 - drop a duplicated word
  Input: elan_i2c - add support for high resolution reports
  Input: elan_i2c - do not constantly re-query pattern ID
  Input: elan_i2c - add firmware update info for ICs 0x11, 0x13, 0x14
  Input: elan_i2c - handle firmware updated on newer ICs
  Input: elan_i2c - add support for different firmware page sizes
  Input: elan_i2c - fix detecting IAP version on older controllers
  Input: elan_i2c - handle devices with patterns above 1
  ...
parents b7b8e368 9e823802
What: /sys/bus/i2c/devices/xxx/fw_version
Date: Aug 2020
Contact: linux-input@vger.kernel.org
Description: Reports the firmware version provided by the touchscreen, for example "00_T6" on a EXC80H60
Access: Read
Valid values: Represented as string
What: /sys/bus/i2c/devices/xxx/model
Date: Aug 2020
Contact: linux-input@vger.kernel.org
Description: Reports the model identification provided by the touchscreen, for example "Orion_1320" on a EXC80H60
Access: Read
Valid values: Represented as string
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/eeti,exc3000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: EETI EXC3000 series touchscreen controller
maintainers:
- Dmitry Torokhov <dmitry.torokhov@gmail.com>
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
enum:
- eeti,exc3000
- eeti,exc80h60
- eeti,exc80h84
reg:
const: 0x2a
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-inverted-x: true
touchscreen-inverted-y: true
touchscreen-swapped-x-y: true
required:
- compatible
- reg
- interrupts
- touchscreen-size-x
- touchscreen-size-y
additionalProperties: false
examples:
- |
#include "dt-bindings/interrupt-controller/irq.h"
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@2a {
compatible = "eeti,exc3000";
reg = <0x2a>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
touchscreen-size-x = <4096>;
touchscreen-size-y = <4096>;
touchscreen-inverted-x;
touchscreen-swapped-x-y;
};
};
* EETI EXC3000 Multiple Touch Controller
Required properties:
- compatible: must be "eeti,exc3000"
- reg: i2c slave address
- interrupts: touch controller interrupt
- touchscreen-size-x: See touchscreen.txt
- touchscreen-size-y: See touchscreen.txt
Optional properties:
- touchscreen-inverted-x: See touchscreen.txt
- touchscreen-inverted-y: See touchscreen.txt
- touchscreen-swapped-x-y: See touchscreen.txt
Example:
touchscreen@2a {
compatible = "eeti,exc3000";
reg = <0x2a>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
touchscreen-size-x = <4096>;
touchscreen-size-y = <4096>;
touchscreen-inverted-x;
touchscreen-swapped-x-y;
};
...@@ -99,7 +99,7 @@ the sake of simplicity. ...@@ -99,7 +99,7 @@ the sake of simplicity.
/* /*
* Give userspace some time to read the events before we destroy the * Give userspace some time to read the events before we destroy the
* device with UI_DEV_DESTOY. * device with UI_DEV_DESTROY.
*/ */
sleep(1); sleep(1);
...@@ -164,7 +164,7 @@ mouse. ...@@ -164,7 +164,7 @@ mouse.
/* /*
* Give userspace some time to read the events before we destroy the * Give userspace some time to read the events before we destroy the
* device with UI_DEV_DESTOY. * device with UI_DEV_DESTROY.
*/ */
sleep(1); sleep(1);
...@@ -233,7 +233,7 @@ but interact with uinput via ioctl calls, or use libevdev. ...@@ -233,7 +233,7 @@ but interact with uinput via ioctl calls, or use libevdev.
/* /*
* Give userspace some time to read the events before we destroy the * Give userspace some time to read the events before we destroy the
* device with UI_DEV_DESTOY. * device with UI_DEV_DESTROY.
*/ */
sleep(1); sleep(1);
......
...@@ -16,7 +16,7 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) ...@@ -16,7 +16,7 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
if (dev->absinfo && test_bit(src, dev->absbit)) { if (dev->absinfo && test_bit(src, dev->absbit)) {
dev->absinfo[dst] = dev->absinfo[src]; dev->absinfo[dst] = dev->absinfo[src];
dev->absinfo[dst].fuzz = 0; dev->absinfo[dst].fuzz = 0;
dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); __set_bit(dst, dev->absbit);
} }
} }
......
...@@ -247,7 +247,7 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char ...@@ -247,7 +247,7 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char
db9_saturn_write_sub(port, type, 3, powered, 0); db9_saturn_write_sub(port, type, 3, powered, 0);
return data[0] = 0xe3; return data[0] = 0xe3;
} }
/* fall through */ fallthrough;
default: default:
return data[0]; return data[0];
} }
...@@ -267,14 +267,14 @@ static int db9_saturn_report(unsigned char id, unsigned char data[60], struct in ...@@ -267,14 +267,14 @@ static int db9_saturn_report(unsigned char id, unsigned char data[60], struct in
switch (data[j]) { switch (data[j]) {
case 0x16: /* multi controller (analog 4 axis) */ case 0x16: /* multi controller (analog 4 axis) */
input_report_abs(dev, db9_abs[5], data[j + 6]); input_report_abs(dev, db9_abs[5], data[j + 6]);
/* fall through */ fallthrough;
case 0x15: /* mission stick (analog 3 axis) */ case 0x15: /* mission stick (analog 3 axis) */
input_report_abs(dev, db9_abs[3], data[j + 4]); input_report_abs(dev, db9_abs[3], data[j + 4]);
input_report_abs(dev, db9_abs[4], data[j + 5]); input_report_abs(dev, db9_abs[4], data[j + 5]);
/* fall through */ fallthrough;
case 0x13: /* racing controller (analog 1 axis) */ case 0x13: /* racing controller (analog 1 axis) */
input_report_abs(dev, db9_abs[2], data[j + 3]); input_report_abs(dev, db9_abs[2], data[j + 3]);
/* fall through */ fallthrough;
case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */ case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
case 0x02: /* digital pad (digital 2 axis + buttons) */ case 0x02: /* digital pad (digital 2 axis + buttons) */
input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
...@@ -368,7 +368,7 @@ static void db9_timer(struct timer_list *t) ...@@ -368,7 +368,7 @@ static void db9_timer(struct timer_list *t)
input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1); input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
/* fall through */ fallthrough;
case DB9_MULTI_0802: case DB9_MULTI_0802:
......
...@@ -485,7 +485,7 @@ static void gc_multi_process_packet(struct gc *gc) ...@@ -485,7 +485,7 @@ static void gc_multi_process_packet(struct gc *gc)
switch (pad->type) { switch (pad->type) {
case GC_MULTI2: case GC_MULTI2:
input_report_key(dev, BTN_THUMB, s & data[5]); input_report_key(dev, BTN_THUMB, s & data[5]);
/* fall through */ fallthrough;
case GC_MULTI: case GC_MULTI:
input_report_abs(dev, ABS_X, input_report_abs(dev, ABS_X,
...@@ -638,7 +638,7 @@ static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, ...@@ -638,7 +638,7 @@ static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type,
input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04);
input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02);
/* fall through */ fallthrough;
case GC_PSX_NEGCON: case GC_PSX_NEGCON:
case GC_PSX_ANALOG: case GC_PSX_ANALOG:
...@@ -872,7 +872,8 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -872,7 +872,8 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
case GC_SNES: case GC_SNES:
for (i = 4; i < 8; i++) for (i = 4; i < 8; i++)
input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]);
/* fall through */ fallthrough;
case GC_NES: case GC_NES:
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]);
...@@ -880,7 +881,8 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -880,7 +881,8 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
case GC_MULTI2: case GC_MULTI2:
input_set_capability(input_dev, EV_KEY, BTN_THUMB); input_set_capability(input_dev, EV_KEY, BTN_THUMB);
/* fall through */ fallthrough;
case GC_MULTI: case GC_MULTI:
input_set_capability(input_dev, EV_KEY, BTN_TRIGGER); input_set_capability(input_dev, EV_KEY, BTN_TRIGGER);
/* fall through */ /* fall through */
......
...@@ -656,16 +656,19 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -656,16 +656,19 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
switch (i * m) { switch (i * m) {
case 60: case 60:
sw->number++; /* fall through */ sw->number++;
fallthrough;
case 45: /* Ambiguous packet length */ case 45: /* Ambiguous packet length */
if (j <= 40) { /* ID length less or eq 40 -> FSP */ if (j <= 40) { /* ID length less or eq 40 -> FSP */
case 43: case 43:
sw->type = SW_ID_FSP; sw->type = SW_ID_FSP;
break; break;
} }
sw->number++; /* fall through */ sw->number++;
fallthrough;
case 30: case 30:
sw->number++; /* fall through */ sw->number++;
fallthrough;
case 15: case 15:
sw->type = SW_ID_GP; sw->type = SW_ID_GP;
break; break;
...@@ -681,9 +684,11 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -681,9 +684,11 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
sw->type = SW_ID_PP; sw->type = SW_ID_PP;
break; break;
case 66: case 66:
sw->bits = 3; /* fall through */ sw->bits = 3;
fallthrough;
case 198: case 198:
sw->length = 22; /* fall through */ sw->length = 22;
fallthrough;
case 64: case 64:
sw->type = SW_ID_3DP; sw->type = SW_ID_3DP;
if (j == 160) if (j == 160)
......
...@@ -146,7 +146,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, ...@@ -146,7 +146,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio,
break; break;
} }
spaceball->escape = 0; spaceball->escape = 0;
/* fall through */ fallthrough;
case 'M': case 'M':
case 'Q': case 'Q':
case 'S': case 'S':
...@@ -154,7 +154,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, ...@@ -154,7 +154,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio,
spaceball->escape = 0; spaceball->escape = 0;
data &= 0x1f; data &= 0x1f;
} }
/* fall through */ fallthrough;
default: default:
if (spaceball->escape) if (spaceball->escape)
spaceball->escape = 0; spaceball->escape = 0;
...@@ -220,13 +220,13 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) ...@@ -220,13 +220,13 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) | input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) |
BIT_MASK(BTN_B) | BIT_MASK(BTN_C) | BIT_MASK(BTN_B) | BIT_MASK(BTN_C) |
BIT_MASK(BTN_MODE); BIT_MASK(BTN_MODE);
/* fall through */ fallthrough;
default: default:
input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) | input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) |
BIT_MASK(BTN_3) | BIT_MASK(BTN_4) | BIT_MASK(BTN_3) | BIT_MASK(BTN_4) |
BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) |
BIT_MASK(BTN_7) | BIT_MASK(BTN_8); BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
/* fall through */ fallthrough;
case SPACEBALL_3003C: case SPACEBALL_3003C:
input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) | input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) |
BIT_MASK(BTN_8); BIT_MASK(BTN_8);
......
...@@ -1016,7 +1016,7 @@ static int adp5589_probe(struct i2c_client *client, ...@@ -1016,7 +1016,7 @@ static int adp5589_probe(struct i2c_client *client,
switch (id->driver_data) { switch (id->driver_data) {
case ADP5585_02: case ADP5585_02:
kpad->support_row5 = true; kpad->support_row5 = true;
/* fall through */ fallthrough;
case ADP5585_01: case ADP5585_01:
kpad->is_adp5585 = true; kpad->is_adp5585 = true;
kpad->var = &const_adp5585; kpad->var = &const_adp5585;
......
...@@ -1241,7 +1241,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -1241,7 +1241,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
case SERIO_8042_XL: case SERIO_8042_XL:
atkbd->translated = true; atkbd->translated = true;
/* Fall through */ fallthrough;
case SERIO_8042: case SERIO_8042:
if (serio->write) if (serio->write)
......
...@@ -574,7 +574,6 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -574,7 +574,6 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING; IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
break; break;
case EV_ACT_ANY: case EV_ACT_ANY:
/* fall through */
default: default:
/* /*
* For other cases, we are OK letting suspend/resume * For other cases, we are OK letting suspend/resume
......
...@@ -68,7 +68,7 @@ static int ati_remote2_get_channel_mask(char *buffer, ...@@ -68,7 +68,7 @@ static int ati_remote2_get_channel_mask(char *buffer,
{ {
pr_debug("%s()\n", __func__); pr_debug("%s()\n", __func__);
return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); return sprintf(buffer, "0x%04x\n", *(unsigned int *)kp->arg);
} }
static int ati_remote2_set_mode_mask(const char *val, static int ati_remote2_set_mode_mask(const char *val,
...@@ -84,7 +84,7 @@ static int ati_remote2_get_mode_mask(char *buffer, ...@@ -84,7 +84,7 @@ static int ati_remote2_get_mode_mask(char *buffer,
{ {
pr_debug("%s()\n", __func__); pr_debug("%s()\n", __func__);
return sprintf(buffer, "0x%02x", *(unsigned int *)kp->arg); return sprintf(buffer, "0x%02x\n", *(unsigned int *)kp->arg);
} }
static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK;
......
...@@ -663,12 +663,8 @@ static const struct usb_device_id cm109_usb_table[] = { ...@@ -663,12 +663,8 @@ static const struct usb_device_id cm109_usb_table[] = {
static void cm109_usb_cleanup(struct cm109_dev *dev) static void cm109_usb_cleanup(struct cm109_dev *dev)
{ {
kfree(dev->ctl_req); kfree(dev->ctl_req);
if (dev->ctl_data) usb_free_coherent(dev->udev, USB_PKT_LEN, dev->ctl_data, dev->ctl_dma);
usb_free_coherent(dev->udev, USB_PKT_LEN, usb_free_coherent(dev->udev, USB_PKT_LEN, dev->irq_data, dev->irq_dma);
dev->ctl_data, dev->ctl_dma);
if (dev->irq_data)
usb_free_coherent(dev->udev, USB_PKT_LEN,
dev->irq_data, dev->irq_dma);
usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */
usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */
......
...@@ -335,7 +335,7 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu) ...@@ -335,7 +335,7 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
err_free_mem: err_free_mem:
input_free_device(input); input_free_device(input);
kfree(gamepad); kfree(gamepad);
return -ENOMEM; return error;
} }
static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
......
...@@ -575,8 +575,7 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, ...@@ -575,8 +575,7 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
case IQS269_LOCAL_CAP_SIZE_GLOBAL_0pF5: case IQS269_LOCAL_CAP_SIZE_GLOBAL_0pF5:
engine_a |= IQS269_CHx_ENG_A_LOCAL_CAP_SIZE; engine_a |= IQS269_CHx_ENG_A_LOCAL_CAP_SIZE;
fallthrough;
/* fall through */
case IQS269_LOCAL_CAP_SIZE_GLOBAL_ONLY: case IQS269_LOCAL_CAP_SIZE_GLOBAL_ONLY:
engine_b |= IQS269_CHx_ENG_B_LOCAL_CAP_ENABLE; engine_b |= IQS269_CHx_ENG_B_LOCAL_CAP_ENABLE;
...@@ -731,14 +730,12 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, ...@@ -731,14 +730,12 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
iqs269->switches[i].code = val; iqs269->switches[i].code = val;
iqs269->switches[i].enabled = true; iqs269->switches[i].enabled = true;
} }
fallthrough;
/* fall through */
case IQS269_CHx_HALL_INACTIVE: case IQS269_CHx_HALL_INACTIVE:
if (iqs269->hall_enable) if (iqs269->hall_enable)
break; break;
fallthrough;
/* fall through */
default: default:
iqs269->keycode[i * IQS269_NUM_CH + reg] = val; iqs269->keycode[i * IQS269_NUM_CH + reg] = val;
...@@ -1143,14 +1140,12 @@ static int iqs269_input_init(struct iqs269_private *iqs269) ...@@ -1143,14 +1140,12 @@ static int iqs269_input_init(struct iqs269_private *iqs269)
sw_code, sw_code,
state & BIT(j)); state & BIT(j));
} }
fallthrough;
/* fall through */
case IQS269_CHx_HALL_INACTIVE: case IQS269_CHx_HALL_INACTIVE:
if (iqs269->hall_enable) if (iqs269->hall_enable)
continue; continue;
fallthrough;
/* fall through */
default: default:
if (keycode != KEY_RESERVED) if (keycode != KEY_RESERVED)
...@@ -1273,14 +1268,12 @@ static int iqs269_report(struct iqs269_private *iqs269) ...@@ -1273,14 +1268,12 @@ static int iqs269_report(struct iqs269_private *iqs269)
input_report_switch(iqs269->keypad, input_report_switch(iqs269->keypad,
sw_code, sw_code,
state & BIT(j)); state & BIT(j));
fallthrough;
/* fall through */
case IQS269_CHx_HALL_INACTIVE: case IQS269_CHx_HALL_INACTIVE:
if (iqs269->hall_enable) if (iqs269->hall_enable)
continue; continue;
fallthrough;
/* fall through */
default: default:
input_report_key(iqs269->keypad, keycode, input_report_key(iqs269->keypad, keycode,
......
...@@ -190,7 +190,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev) ...@@ -190,7 +190,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
default: default:
dev_err(&pdev->dev, "Failed to request direction pwm: %d", err); dev_err(&pdev->dev, "Failed to request direction pwm: %d", err);
/* Fall through */ fallthrough;
case -EPROBE_DEFER: case -EPROBE_DEFER:
return err; return err;
......
...@@ -124,7 +124,7 @@ static void xenkbd_handle_mt_event(struct xenkbd_info *info, ...@@ -124,7 +124,7 @@ static void xenkbd_handle_mt_event(struct xenkbd_info *info,
switch (mtouch->event_type) { switch (mtouch->event_type) {
case XENKBD_MT_EV_DOWN: case XENKBD_MT_EV_DOWN:
input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true); input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true);
/* fall through */ fallthrough;
case XENKBD_MT_EV_MOTION: case XENKBD_MT_EV_MOTION:
input_report_abs(info->mtouch, ABS_MT_POSITION_X, input_report_abs(info->mtouch, ABS_MT_POSITION_X,
...@@ -524,7 +524,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, ...@@ -524,7 +524,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
case XenbusStateClosed: case XenbusStateClosed:
if (dev->state == XenbusStateClosed) if (dev->state == XenbusStateClosed)
break; break;
/* fall through - Missed the backend's CLOSING state */ fallthrough; /* Missed the backend's CLOSING state */
case XenbusStateClosing: case XenbusStateClosing:
xenbus_frontend_closed(dev); xenbus_frontend_closed(dev);
break; break;
......
...@@ -1929,7 +1929,7 @@ static int alps_monitor_mode(struct psmouse *psmouse, bool enable) ...@@ -1929,7 +1929,7 @@ static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
static int alps_absolute_mode_v6(struct psmouse *psmouse) static int alps_absolute_mode_v6(struct psmouse *psmouse)
{ {
u16 reg_val = 0x181; u16 reg_val = 0x181;
int ret = -1; int ret;
/* enter monitor mode, to write the register */ /* enter monitor mode, to write the register */
if (alps_monitor_mode(psmouse, true)) if (alps_monitor_mode(psmouse, true))
......
...@@ -458,7 +458,7 @@ static int atp_status_check(struct urb *urb) ...@@ -458,7 +458,7 @@ static int atp_status_check(struct urb *urb)
dev->info->datalen, dev->urb->actual_length); dev->info->datalen, dev->urb->actual_length);
dev->overflow_warned = true; dev->overflow_warned = true;
} }
/* fall through */ fallthrough;
case -ECONNRESET: case -ECONNRESET:
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: case -ESHUTDOWN:
......
...@@ -1067,7 +1067,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) ...@@ -1067,7 +1067,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa)
return error; return error;
} }
/* Fall through */ fallthrough;
case CYAPA_STATE_BL_IDLE: case CYAPA_STATE_BL_IDLE:
/* Try to get firmware version in bootloader mode. */ /* Try to get firmware version in bootloader mode. */
cyapa_gen3_bl_query_data(cyapa); cyapa_gen3_bl_query_data(cyapa);
...@@ -1078,7 +1078,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) ...@@ -1078,7 +1078,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa)
return error; return error;
} }
/* Fall through */ fallthrough;
case CYAPA_STATE_OP: case CYAPA_STATE_OP:
/* /*
* Reading query data before going back to the full mode * Reading query data before going back to the full mode
......
...@@ -2554,7 +2554,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) ...@@ -2554,7 +2554,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa)
} }
cyapa->state = CYAPA_STATE_GEN5_APP; cyapa->state = CYAPA_STATE_GEN5_APP;
/* fall through */ fallthrough;
case CYAPA_STATE_GEN5_APP: case CYAPA_STATE_GEN5_APP:
/* /*
......
...@@ -680,7 +680,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa) ...@@ -680,7 +680,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa)
} }
cyapa->state = CYAPA_STATE_GEN6_APP; cyapa->state = CYAPA_STATE_GEN6_APP;
/* fall through */ fallthrough;
case CYAPA_STATE_GEN6_APP: case CYAPA_STATE_GEN6_APP:
/* /*
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#define ETP_CALIBRATE_MAX_LEN 3 #define ETP_CALIBRATE_MAX_LEN 3
#define ETP_FEATURE_REPORT_MK BIT(0)
/* IAP Firmware handling */ /* IAP Firmware handling */
#define ETP_PRODUCT_ID_FORMAT_STRING "%d.0" #define ETP_PRODUCT_ID_FORMAT_STRING "%d.0"
#define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin" #define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin"
...@@ -33,6 +35,8 @@ ...@@ -33,6 +35,8 @@
#define ETP_FW_IAP_PAGE_ERR (1 << 5) #define ETP_FW_IAP_PAGE_ERR (1 << 5)
#define ETP_FW_IAP_INTF_ERR (1 << 4) #define ETP_FW_IAP_INTF_ERR (1 << 4)
#define ETP_FW_PAGE_SIZE 64 #define ETP_FW_PAGE_SIZE 64
#define ETP_FW_PAGE_SIZE_128 128
#define ETP_FW_PAGE_SIZE_512 512
#define ETP_FW_SIGNATURE_SIZE 6 #define ETP_FW_SIGNATURE_SIZE 6
struct i2c_client; struct i2c_client;
...@@ -55,8 +59,9 @@ struct elan_transport_ops { ...@@ -55,8 +59,9 @@ struct elan_transport_ops {
int (*get_baseline_data)(struct i2c_client *client, int (*get_baseline_data)(struct i2c_client *client,
bool max_baseliune, u8 *value); bool max_baseliune, u8 *value);
int (*get_version)(struct i2c_client *client, bool iap, u8 *version); int (*get_version)(struct i2c_client *client, u8 pattern, bool iap,
int (*get_sm_version)(struct i2c_client *client, u8 *version);
int (*get_sm_version)(struct i2c_client *client, u8 pattern,
u16 *ic_type, u8 *version, u8 *clickpad); u16 *ic_type, u8 *version, u8 *clickpad);
int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
int (*get_product_id)(struct i2c_client *client, u16 *id); int (*get_product_id)(struct i2c_client *client, u16 *id);
...@@ -72,13 +77,18 @@ struct elan_transport_ops { ...@@ -72,13 +77,18 @@ struct elan_transport_ops {
int (*iap_get_mode)(struct i2c_client *client, enum tp_mode *mode); int (*iap_get_mode)(struct i2c_client *client, enum tp_mode *mode);
int (*iap_reset)(struct i2c_client *client); int (*iap_reset)(struct i2c_client *client);
int (*prepare_fw_update)(struct i2c_client *client); int (*prepare_fw_update)(struct i2c_client *client, u16 ic_type,
int (*write_fw_block)(struct i2c_client *client, u8 iap_version);
int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size,
const u8 *page, u16 checksum, int idx); const u8 *page, u16 checksum, int idx);
int (*finish_fw_update)(struct i2c_client *client, int (*finish_fw_update)(struct i2c_client *client,
struct completion *reset_done); struct completion *reset_done);
int (*get_report)(struct i2c_client *client, u8 *report); int (*get_report_features)(struct i2c_client *client, u8 pattern,
unsigned int *features,
unsigned int *report_len);
int (*get_report)(struct i2c_client *client, u8 *report,
unsigned int report_len);
int (*get_pressure_adjustment)(struct i2c_client *client, int (*get_pressure_adjustment)(struct i2c_client *client,
int *adjustment); int *adjustment);
int (*get_pattern)(struct i2c_client *client, u8 *pattern); int (*get_pattern)(struct i2c_client *client, u8 *pattern);
......
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -43,6 +44,8 @@ ...@@ -43,6 +44,8 @@
#define ETP_I2C_RESOLUTION_CMD 0x0108 #define ETP_I2C_RESOLUTION_CMD 0x0108
#define ETP_I2C_PRESSURE_CMD 0x010A #define ETP_I2C_PRESSURE_CMD 0x010A
#define ETP_I2C_IAP_VERSION_CMD 0x0110 #define ETP_I2C_IAP_VERSION_CMD 0x0110
#define ETP_I2C_IC_TYPE_P0_CMD 0x0110
#define ETP_I2C_IAP_VERSION_P0_CMD 0x0111
#define ETP_I2C_SET_CMD 0x0300 #define ETP_I2C_SET_CMD 0x0300
#define ETP_I2C_POWER_CMD 0x0307 #define ETP_I2C_POWER_CMD 0x0307
#define ETP_I2C_FW_CHECKSUM_CMD 0x030F #define ETP_I2C_FW_CHECKSUM_CMD 0x030F
...@@ -53,8 +56,12 @@ ...@@ -53,8 +56,12 @@
#define ETP_I2C_CALIBRATE_CMD 0x0316 #define ETP_I2C_CALIBRATE_CMD 0x0316
#define ETP_I2C_MAX_BASELINE_CMD 0x0317 #define ETP_I2C_MAX_BASELINE_CMD 0x0317
#define ETP_I2C_MIN_BASELINE_CMD 0x0318 #define ETP_I2C_MIN_BASELINE_CMD 0x0318
#define ETP_I2C_IAP_TYPE_REG 0x0040
#define ETP_I2C_IAP_TYPE_CMD 0x0304
#define ETP_I2C_REPORT_LEN 34 #define ETP_I2C_REPORT_LEN 34
#define ETP_I2C_REPORT_LEN_ID2 39
#define ETP_I2C_REPORT_MAX_LEN 39
#define ETP_I2C_DESC_LENGTH 30 #define ETP_I2C_DESC_LENGTH 30
#define ETP_I2C_REPORT_DESC_LENGTH 158 #define ETP_I2C_REPORT_DESC_LENGTH 158
#define ETP_I2C_INF_LENGTH 2 #define ETP_I2C_INF_LENGTH 2
...@@ -249,56 +256,52 @@ static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern) ...@@ -249,56 +256,52 @@ static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern)
dev_err(&client->dev, "failed to get pattern: %d\n", error); dev_err(&client->dev, "failed to get pattern: %d\n", error);
return error; return error;
} }
*pattern = val[1];
/*
* Not all versions of firmware implement "get pattern" command.
* When this command is not implemented the device will respond
* with 0xFF 0xFF, which we will treat as "old" pattern 0.
*/
*pattern = val[0] == 0xFF && val[1] == 0xFF ? 0 : val[1];
return 0; return 0;
} }
static int elan_i2c_get_version(struct i2c_client *client, static int elan_i2c_get_version(struct i2c_client *client,
bool iap, u8 *version) u8 pattern, bool iap, u8 *version)
{ {
int error; int error;
u8 pattern_ver; u16 cmd;
u8 val[3]; u8 val[3];
error = elan_i2c_get_pattern(client, &pattern_ver); if (!iap)
if (error) { cmd = ETP_I2C_FW_VERSION_CMD;
dev_err(&client->dev, "failed to get pattern version\n"); else if (pattern == 0)
return error; cmd = ETP_I2C_IAP_VERSION_P0_CMD;
} else
cmd = ETP_I2C_IAP_VERSION_CMD;
error = elan_i2c_read_cmd(client, error = elan_i2c_read_cmd(client, cmd, val);
iap ? ETP_I2C_IAP_VERSION_CMD :
ETP_I2C_FW_VERSION_CMD,
val);
if (error) { if (error) {
dev_err(&client->dev, "failed to get %s version: %d\n", dev_err(&client->dev, "failed to get %s version: %d\n",
iap ? "IAP" : "FW", error); iap ? "IAP" : "FW", error);
return error; return error;
} }
if (pattern_ver == 0x01) if (pattern >= 0x01)
*version = iap ? val[1] : val[0]; *version = iap ? val[1] : val[0];
else else
*version = val[0]; *version = val[0];
return 0; return 0;
} }
static int elan_i2c_get_sm_version(struct i2c_client *client, static int elan_i2c_get_sm_version(struct i2c_client *client, u8 pattern,
u16 *ic_type, u8 *version, u16 *ic_type, u8 *version, u8 *clickpad)
u8 *clickpad)
{ {
int error; int error;
u8 pattern_ver;
u8 val[3]; u8 val[3];
error = elan_i2c_get_pattern(client, &pattern_ver); if (pattern >= 0x01) {
if (error) {
dev_err(&client->dev, "failed to get pattern version\n");
return error;
}
if (pattern_ver == 0x01) {
error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val); error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val);
if (error) { if (error) {
dev_err(&client->dev, "failed to get ic type: %d\n", dev_err(&client->dev, "failed to get ic type: %d\n",
...@@ -324,7 +327,14 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, ...@@ -324,7 +327,14 @@ static int elan_i2c_get_sm_version(struct i2c_client *client,
return error; return error;
} }
*version = val[0]; *version = val[0];
*ic_type = val[1];
error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_P0_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get ic type: %d\n",
error);
return error;
}
*ic_type = val[0];
error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD, error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD,
val); val);
...@@ -386,7 +396,7 @@ static int elan_i2c_get_max(struct i2c_client *client, ...@@ -386,7 +396,7 @@ static int elan_i2c_get_max(struct i2c_client *client,
return error; return error;
} }
*max_x = le16_to_cpup((__le16 *)val) & 0x0fff; *max_x = le16_to_cpup((__le16 *)val);
error = elan_i2c_read_cmd(client, ETP_I2C_MAX_Y_AXIS_CMD, val); error = elan_i2c_read_cmd(client, ETP_I2C_MAX_Y_AXIS_CMD, val);
if (error) { if (error) {
...@@ -394,7 +404,7 @@ static int elan_i2c_get_max(struct i2c_client *client, ...@@ -394,7 +404,7 @@ static int elan_i2c_get_max(struct i2c_client *client,
return error; return error;
} }
*max_y = le16_to_cpup((__le16 *)val) & 0x0fff; *max_y = le16_to_cpup((__le16 *)val);
return 0; return 0;
} }
...@@ -507,7 +517,43 @@ static int elan_i2c_set_flash_key(struct i2c_client *client) ...@@ -507,7 +517,43 @@ static int elan_i2c_set_flash_key(struct i2c_client *client)
return 0; return 0;
} }
static int elan_i2c_prepare_fw_update(struct i2c_client *client) static int elan_read_write_iap_type(struct i2c_client *client)
{
int error;
u16 constant;
u8 val[3];
int retry = 3;
do {
error = elan_i2c_write_cmd(client, ETP_I2C_IAP_TYPE_CMD,
ETP_I2C_IAP_TYPE_REG);
if (error) {
dev_err(&client->dev,
"cannot write iap type: %d\n", error);
return error;
}
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_TYPE_CMD, val);
if (error) {
dev_err(&client->dev,
"failed to read iap type register: %d\n",
error);
return error;
}
constant = le16_to_cpup((__le16 *)val);
dev_dbg(&client->dev, "iap type reg: 0x%04x\n", constant);
if (constant == ETP_I2C_IAP_TYPE_REG)
return 0;
} while (--retry > 0);
dev_err(&client->dev, "cannot set iap type\n");
return -EIO;
}
static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
u8 iap_version)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
int error; int error;
...@@ -547,6 +593,12 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client) ...@@ -547,6 +593,12 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client)
return -EIO; return -EIO;
} }
if (ic_type >= 0x0D && iap_version >= 1) {
error = elan_read_write_iap_type(client);
if (error)
return error;
}
/* Set flash key again */ /* Set flash key again */
error = elan_i2c_set_flash_key(client); error = elan_i2c_set_flash_key(client);
if (error) if (error)
...@@ -572,57 +624,64 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client) ...@@ -572,57 +624,64 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client)
return 0; return 0;
} }
static int elan_i2c_write_fw_block(struct i2c_client *client, static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size,
const u8 *page, u16 checksum, int idx) const u8 *page, u16 checksum, int idx)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
u8 page_store[ETP_FW_PAGE_SIZE + 4]; u8 *page_store;
u8 val[3]; u8 val[3];
u16 result; u16 result;
int ret, error; int ret, error;
page_store = kmalloc(fw_page_size + 4, GFP_KERNEL);
if (!page_store)
return -ENOMEM;
page_store[0] = ETP_I2C_IAP_REG_L; page_store[0] = ETP_I2C_IAP_REG_L;
page_store[1] = ETP_I2C_IAP_REG_H; page_store[1] = ETP_I2C_IAP_REG_H;
memcpy(&page_store[2], page, ETP_FW_PAGE_SIZE); memcpy(&page_store[2], page, fw_page_size);
/* recode checksum at last two bytes */ /* recode checksum at last two bytes */
put_unaligned_le16(checksum, &page_store[ETP_FW_PAGE_SIZE + 2]); put_unaligned_le16(checksum, &page_store[fw_page_size + 2]);
ret = i2c_master_send(client, page_store, sizeof(page_store)); ret = i2c_master_send(client, page_store, fw_page_size + 4);
if (ret != sizeof(page_store)) { if (ret != fw_page_size + 4) {
error = ret < 0 ? ret : -EIO; error = ret < 0 ? ret : -EIO;
dev_err(dev, "Failed to write page %d: %d\n", idx, error); dev_err(dev, "Failed to write page %d: %d\n", idx, error);
return error; goto exit;
} }
/* Wait for F/W to update one page ROM data. */ /* Wait for F/W to update one page ROM data. */
msleep(35); msleep(fw_page_size == ETP_FW_PAGE_SIZE_512 ? 50 : 35);
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val); error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
if (error) { if (error) {
dev_err(dev, "Failed to read IAP write result: %d\n", error); dev_err(dev, "Failed to read IAP write result: %d\n", error);
return error; goto exit;
} }
result = le16_to_cpup((__le16 *)val); result = le16_to_cpup((__le16 *)val);
if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
dev_err(dev, "IAP reports failed write: %04hx\n", dev_err(dev, "IAP reports failed write: %04hx\n",
result); result);
return -EIO; error = -EIO;
goto exit;
} }
return 0; exit:
kfree(page_store);
return error;
} }
static int elan_i2c_finish_fw_update(struct i2c_client *client, static int elan_i2c_finish_fw_update(struct i2c_client *client,
struct completion *completion) struct completion *completion)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
int error; int error = 0;
int len; int len;
u8 buffer[ETP_I2C_REPORT_LEN]; u8 buffer[ETP_I2C_REPORT_MAX_LEN];
len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN); len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_MAX_LEN);
if (len != ETP_I2C_REPORT_LEN) { if (len <= 0) {
error = len < 0 ? len : -EIO; error = len < 0 ? len : -EIO;
dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n", dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n",
error, len); error, len);
...@@ -656,20 +715,31 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client, ...@@ -656,20 +715,31 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client,
return 0; return 0;
} }
static int elan_i2c_get_report(struct i2c_client *client, u8 *report) static int elan_i2c_get_report_features(struct i2c_client *client, u8 pattern,
unsigned int *features,
unsigned int *report_len)
{
*features = ETP_FEATURE_REPORT_MK;
*report_len = pattern <= 0x01 ?
ETP_I2C_REPORT_LEN : ETP_I2C_REPORT_LEN_ID2;
return 0;
}
static int elan_i2c_get_report(struct i2c_client *client,
u8 *report, unsigned int report_len)
{ {
int len; int len;
len = i2c_master_recv(client, report, ETP_I2C_REPORT_LEN); len = i2c_master_recv(client, report, report_len);
if (len < 0) { if (len < 0) {
dev_err(&client->dev, "failed to read report data: %d\n", len); dev_err(&client->dev, "failed to read report data: %d\n", len);
return len; return len;
} }
if (len != ETP_I2C_REPORT_LEN) { if (len != report_len) {
dev_err(&client->dev, dev_err(&client->dev,
"wrong report length (%d vs %d expected)\n", "wrong report length (%d vs %d expected)\n",
len, ETP_I2C_REPORT_LEN); len, report_len);
return -EIO; return -EIO;
} }
...@@ -706,5 +776,6 @@ const struct elan_transport_ops elan_i2c_ops = { ...@@ -706,5 +776,6 @@ const struct elan_transport_ops elan_i2c_ops = {
.get_pattern = elan_i2c_get_pattern, .get_pattern = elan_i2c_get_pattern,
.get_report_features = elan_i2c_get_report_features,
.get_report = elan_i2c_get_report, .get_report = elan_i2c_get_report,
}; };
...@@ -147,7 +147,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client *client, ...@@ -147,7 +147,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client *client,
} }
static int elan_smbus_get_version(struct i2c_client *client, static int elan_smbus_get_version(struct i2c_client *client,
bool iap, u8 *version) u8 pattern, bool iap, u8 *version)
{ {
int error; int error;
u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
...@@ -166,9 +166,8 @@ static int elan_smbus_get_version(struct i2c_client *client, ...@@ -166,9 +166,8 @@ static int elan_smbus_get_version(struct i2c_client *client,
return 0; return 0;
} }
static int elan_smbus_get_sm_version(struct i2c_client *client, static int elan_smbus_get_sm_version(struct i2c_client *client, u8 pattern,
u16 *ic_type, u8 *version, u16 *ic_type, u8 *version, u8 *clickpad)
u8 *clickpad)
{ {
int error; int error;
u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
...@@ -340,7 +339,8 @@ static int elan_smbus_set_flash_key(struct i2c_client *client) ...@@ -340,7 +339,8 @@ static int elan_smbus_set_flash_key(struct i2c_client *client)
return 0; return 0;
} }
static int elan_smbus_prepare_fw_update(struct i2c_client *client) static int elan_smbus_prepare_fw_update(struct i2c_client *client, u16 ic_type,
u8 iap_version)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
int len; int len;
...@@ -414,7 +414,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client) ...@@ -414,7 +414,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client)
} }
static int elan_smbus_write_fw_block(struct i2c_client *client, static int elan_smbus_write_fw_block(struct i2c_client *client, u16 fw_page_size,
const u8 *page, u16 checksum, int idx) const u8 *page, u16 checksum, int idx)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
...@@ -429,7 +429,7 @@ static int elan_smbus_write_fw_block(struct i2c_client *client, ...@@ -429,7 +429,7 @@ static int elan_smbus_write_fw_block(struct i2c_client *client,
*/ */
error = i2c_smbus_write_block_data(client, error = i2c_smbus_write_block_data(client,
ETP_SMBUS_WRITE_FW_BLOCK, ETP_SMBUS_WRITE_FW_BLOCK,
ETP_FW_PAGE_SIZE / 2, fw_page_size / 2,
page); page);
if (error) { if (error) {
dev_err(dev, "Failed to write page %d (part %d): %d\n", dev_err(dev, "Failed to write page %d (part %d): %d\n",
...@@ -439,8 +439,8 @@ static int elan_smbus_write_fw_block(struct i2c_client *client, ...@@ -439,8 +439,8 @@ static int elan_smbus_write_fw_block(struct i2c_client *client,
error = i2c_smbus_write_block_data(client, error = i2c_smbus_write_block_data(client,
ETP_SMBUS_WRITE_FW_BLOCK, ETP_SMBUS_WRITE_FW_BLOCK,
ETP_FW_PAGE_SIZE / 2, fw_page_size / 2,
page + ETP_FW_PAGE_SIZE / 2); page + fw_page_size / 2);
if (error) { if (error) {
dev_err(dev, "Failed to write page %d (part %d): %d\n", dev_err(dev, "Failed to write page %d (part %d): %d\n",
idx, 2, error); idx, 2, error);
...@@ -469,7 +469,21 @@ static int elan_smbus_write_fw_block(struct i2c_client *client, ...@@ -469,7 +469,21 @@ static int elan_smbus_write_fw_block(struct i2c_client *client,
return 0; return 0;
} }
static int elan_smbus_get_report(struct i2c_client *client, u8 *report) static int elan_smbus_get_report_features(struct i2c_client *client, u8 pattern,
unsigned int *features,
unsigned int *report_len)
{
/*
* SMBus controllers with pattern 2 lack area info, as newer
* high-precision packets use that space for coordinates.
*/
*features = pattern <= 0x01 ? ETP_FEATURE_REPORT_MK : 0;
*report_len = ETP_SMBUS_REPORT_LEN;
return 0;
}
static int elan_smbus_get_report(struct i2c_client *client,
u8 *report, unsigned int report_len)
{ {
int len; int len;
...@@ -534,6 +548,7 @@ const struct elan_transport_ops elan_smbus_ops = { ...@@ -534,6 +548,7 @@ const struct elan_transport_ops elan_smbus_ops = {
.write_fw_block = elan_smbus_write_fw_block, .write_fw_block = elan_smbus_write_fw_block,
.finish_fw_update = elan_smbus_finish_fw_update, .finish_fw_update = elan_smbus_finish_fw_update,
.get_report_features = elan_smbus_get_report_features,
.get_report = elan_smbus_get_report, .get_report = elan_smbus_get_report,
.get_pattern = elan_smbus_get_pattern, .get_pattern = elan_smbus_get_pattern,
}; };
...@@ -383,7 +383,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) ...@@ -383,7 +383,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
*/ */
if (packet[3] & 0x80) if (packet[3] & 0x80)
fingers = 4; fingers = 4;
/* fall through */ fallthrough;
case 1: case 1:
/* /*
* byte 1: . . . . x11 x10 x9 x8 * byte 1: . . . . x11 x10 x9 x8
...@@ -1146,7 +1146,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) ...@@ -1146,7 +1146,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
case 2: case 2:
__set_bit(BTN_TOOL_QUADTAP, dev->keybit); __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit); __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
/* fall through */ fallthrough;
case 3: case 3:
if (info->hw_version == 3) if (info->hw_version == 3)
elantech_set_buttonpad_prop(psmouse); elantech_set_buttonpad_prop(psmouse);
...@@ -1877,12 +1877,10 @@ static bool elantech_use_host_notify(struct psmouse *psmouse, ...@@ -1877,12 +1877,10 @@ static bool elantech_use_host_notify(struct psmouse *psmouse,
/* expected case */ /* expected case */
break; break;
case ETP_BUS_SMB_ALERT_ONLY: case ETP_BUS_SMB_ALERT_ONLY:
/* fall-through */
case ETP_BUS_PS2_SMB_ALERT: case ETP_BUS_PS2_SMB_ALERT:
psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n"); psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n");
break; break;
case ETP_BUS_SMB_HST_NTFY_ONLY: case ETP_BUS_SMB_HST_NTFY_ONLY:
/* fall-through */
case ETP_BUS_PS2_SMB_HST_NTFY: case ETP_BUS_PS2_SMB_HST_NTFY:
return true; return true;
default: default:
...@@ -1897,7 +1895,7 @@ static bool elantech_use_host_notify(struct psmouse *psmouse, ...@@ -1897,7 +1895,7 @@ static bool elantech_use_host_notify(struct psmouse *psmouse,
int elantech_init_smbus(struct psmouse *psmouse) int elantech_init_smbus(struct psmouse *psmouse)
{ {
struct elantech_device_info info; struct elantech_device_info info;
int error = -EINVAL; int error;
psmouse_reset(psmouse); psmouse_reset(psmouse);
...@@ -2015,7 +2013,7 @@ static int elantech_setup_ps2(struct psmouse *psmouse, ...@@ -2015,7 +2013,7 @@ static int elantech_setup_ps2(struct psmouse *psmouse,
int elantech_init_ps2(struct psmouse *psmouse) int elantech_init_ps2(struct psmouse *psmouse)
{ {
struct elantech_device_info info; struct elantech_device_info info;
int error = -EINVAL; int error;
psmouse_reset(psmouse); psmouse_reset(psmouse);
...@@ -2036,7 +2034,7 @@ int elantech_init_ps2(struct psmouse *psmouse) ...@@ -2036,7 +2034,7 @@ int elantech_init_ps2(struct psmouse *psmouse)
int elantech_init(struct psmouse *psmouse) int elantech_init(struct psmouse *psmouse)
{ {
struct elantech_device_info info; struct elantech_device_info info;
int error = -EINVAL; int error;
psmouse_reset(psmouse); psmouse_reset(psmouse);
......
...@@ -238,7 +238,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, ...@@ -238,7 +238,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
/* we're not spewing, but this packet might be the start */ /* we're not spewing, but this packet might be the start */
priv->spew_flag = MAYBE_SPEWING; priv->spew_flag = MAYBE_SPEWING;
/* fall-through */ fallthrough;
case MAYBE_SPEWING: case MAYBE_SPEWING:
priv->spew_count++; priv->spew_count++;
...@@ -249,7 +249,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, ...@@ -249,7 +249,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
/* excessive spew detected, request recalibration */ /* excessive spew detected, request recalibration */
priv->spew_flag = SPEW_DETECTED; priv->spew_flag = SPEW_DETECTED;
/* fall-through */ fallthrough;
case SPEW_DETECTED: case SPEW_DETECTED:
/* only recalibrate when the overall delta to the cursor /* only recalibrate when the overall delta to the cursor
......
...@@ -105,7 +105,7 @@ static void navpoint_packet(struct navpoint *navpoint) ...@@ -105,7 +105,7 @@ static void navpoint_packet(struct navpoint *navpoint)
case 0x19: /* Module 0, Hello packet */ case 0x19: /* Module 0, Hello packet */
if ((navpoint->data[1] & 0xf0) == 0x10) if ((navpoint->data[1] & 0xf0) == 0x10)
break; break;
/* FALLTHROUGH */ fallthrough;
default: default:
dev_warn(navpoint->dev, dev_warn(navpoint->dev,
"spurious packet: data=0x%02x,0x%02x,...\n", "spurious packet: data=0x%02x,0x%02x,...\n",
......
...@@ -2042,7 +2042,7 @@ static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) ...@@ -2042,7 +2042,7 @@ static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp)
{ {
int type = *((unsigned int *)kp->arg); int type = *((unsigned int *)kp->arg);
return sprintf(buffer, "%s", psmouse_protocol_by_type(type)->name); return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
} }
static int __init psmouse_init(void) static int __init psmouse_init(void)
......
...@@ -441,7 +441,7 @@ static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, ...@@ -441,7 +441,7 @@ static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
fsp_reg_write_enable(psmouse, false); fsp_reg_write_enable(psmouse, false);
return count; return retval;
} }
PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg);
...@@ -794,7 +794,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) ...@@ -794,7 +794,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
/* on-pad click, filter it if necessary */ /* on-pad click, filter it if necessary */
if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC)
packet[0] &= ~FSP_PB0_LBTN; packet[0] &= ~FSP_PB0_LBTN;
/* fall through */ fallthrough;
case FSP_PKT_TYPE_NORMAL: case FSP_PKT_TYPE_NORMAL:
/* normal packet */ /* normal packet */
......
...@@ -128,7 +128,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data) ...@@ -128,7 +128,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
case SERIO_MS: case SERIO_MS:
sermouse->type = SERIO_MP; sermouse->type = SERIO_MP;
/* fall through */ fallthrough;
case SERIO_MP: case SERIO_MP:
if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */ if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
...@@ -139,7 +139,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data) ...@@ -139,7 +139,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
case SERIO_MZP: case SERIO_MZP:
case SERIO_MZPP: case SERIO_MZPP:
input_report_key(dev, BTN_SIDE, (data >> 5) & 1); input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
/* fall through */ fallthrough;
case SERIO_MZ: case SERIO_MZ:
input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1); input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
......
...@@ -562,7 +562,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) ...@@ -562,7 +562,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
str = last_str; str = last_str;
break; break;
} }
/* fall through - report timeout */ fallthrough; /* report timeout */
case 0xfc: case 0xfc:
case 0xfd: case 0xfd:
case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
......
...@@ -418,7 +418,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) ...@@ -418,7 +418,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
ps2dev->nak = 0; ps2dev->nak = 0;
break; break;
} }
/* Fall through */ fallthrough;
default: default:
/* /*
* Do not signal errors if we get unexpected reply while * Do not signal errors if we get unexpected reply while
......
...@@ -247,7 +247,7 @@ void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *k ...@@ -247,7 +247,7 @@ void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *k
case KE_SW: case KE_SW:
value = ke->sw.value; value = ke->sw.value;
/* fall through */ fallthrough;
case KE_VSW: case KE_VSW:
input_report_switch(dev, ke->sw.code, value); input_report_switch(dev, ke->sw.code, value);
......
...@@ -676,8 +676,8 @@ static void gtco_urb_callback(struct urb *urbinfo) ...@@ -676,8 +676,8 @@ static void gtco_urb_callback(struct urb *urbinfo)
/* Mask out the Y tilt value used for pressure */ /* Mask out the Y tilt value used for pressure */
device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);
fallthrough;
/* Fall thru */
case 4: case 4:
/* Tilt */ /* Tilt */
input_report_abs(inputdev, ABS_TILT_X, input_report_abs(inputdev, ABS_TILT_X,
...@@ -685,8 +685,8 @@ static void gtco_urb_callback(struct urb *urbinfo) ...@@ -685,8 +685,8 @@ static void gtco_urb_callback(struct urb *urbinfo)
input_report_abs(inputdev, ABS_TILT_Y, input_report_abs(inputdev, ABS_TILT_Y,
sign_extend32(device->buffer[7], 6)); sign_extend32(device->buffer[7], 6));
fallthrough;
/* Fall thru */
case 2: case 2:
case 3: case 3:
/* Convert buttons, only 5 bits possible */ /* Convert buttons, only 5 bits possible */
...@@ -695,8 +695,8 @@ static void gtco_urb_callback(struct urb *urbinfo) ...@@ -695,8 +695,8 @@ static void gtco_urb_callback(struct urb *urbinfo)
/* We don't apply any meaning to the bitmask, /* We don't apply any meaning to the bitmask,
just report */ just report */
input_event(inputdev, EV_MSC, MSC_SERIAL, val); input_event(inputdev, EV_MSC, MSC_SERIAL, val);
fallthrough;
/* Fall thru */
case 1: case 1:
/* All reports have X and Y coords in the same place */ /* All reports have X and Y coords in the same place */
val = get_unaligned_le16(&device->buffer[1]); val = get_unaligned_le16(&device->buffer[1]);
......
...@@ -146,7 +146,7 @@ static void pegasus_parse_packet(struct pegasus *pegasus) ...@@ -146,7 +146,7 @@ static void pegasus_parse_packet(struct pegasus *pegasus)
/* xy data */ /* xy data */
case BATTERY_LOW: case BATTERY_LOW:
dev_warn_once(&dev->dev, "Pen battery low\n"); dev_warn_once(&dev->dev, "Pen battery low\n");
/* fall through */ fallthrough;
case BATTERY_NO_REPORT: case BATTERY_NO_REPORT:
case BATTERY_GOOD: case BATTERY_GOOD:
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -129,6 +130,7 @@ struct t9_range { ...@@ -129,6 +130,7 @@ struct t9_range {
/* MXT_SPT_COMMSCONFIG_T18 */ /* MXT_SPT_COMMSCONFIG_T18 */
#define MXT_COMMS_CTRL 0 #define MXT_COMMS_CTRL 0
#define MXT_COMMS_CMD 1 #define MXT_COMMS_CMD 1
#define MXT_COMMS_RETRIGEN BIT(6)
/* MXT_DEBUG_DIAGNOSTIC_T37 */ /* MXT_DEBUG_DIAGNOSTIC_T37 */
#define MXT_DIAGNOSTIC_PAGEUP 0x01 #define MXT_DIAGNOSTIC_PAGEUP 0x01
...@@ -308,6 +310,7 @@ struct mxt_data { ...@@ -308,6 +310,7 @@ struct mxt_data {
struct t7_config t7_cfg; struct t7_config t7_cfg;
struct mxt_dbg dbg; struct mxt_dbg dbg;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
bool use_retrigen_workaround;
/* Cached parameters from object table */ /* Cached parameters from object table */
u16 T5_address; u16 T5_address;
...@@ -318,6 +321,7 @@ struct mxt_data { ...@@ -318,6 +321,7 @@ struct mxt_data {
u16 T71_address; u16 T71_address;
u8 T9_reportid_min; u8 T9_reportid_min;
u8 T9_reportid_max; u8 T9_reportid_max;
u16 T18_address;
u8 T19_reportid; u8 T19_reportid;
u16 T44_address; u16 T44_address;
u8 T100_reportid_min; u8 T100_reportid_min;
...@@ -1190,9 +1194,11 @@ static int mxt_acquire_irq(struct mxt_data *data) ...@@ -1190,9 +1194,11 @@ static int mxt_acquire_irq(struct mxt_data *data)
enable_irq(data->irq); enable_irq(data->irq);
if (data->use_retrigen_workaround) {
error = mxt_process_messages_until_invalid(data); error = mxt_process_messages_until_invalid(data);
if (error) if (error)
return error; return error;
}
return 0; return 0;
} }
...@@ -1282,6 +1288,38 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off) ...@@ -1282,6 +1288,38 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
return crc; return crc;
} }
static int mxt_check_retrigen(struct mxt_data *data)
{
struct i2c_client *client = data->client;
int error;
int val;
struct irq_data *irqd;
data->use_retrigen_workaround = false;
irqd = irq_get_irq_data(data->irq);
if (!irqd)
return -EINVAL;
if (irqd_is_level_type(irqd))
return 0;
if (data->T18_address) {
error = __mxt_read_reg(client,
data->T18_address + MXT_COMMS_CTRL,
1, &val);
if (error)
return error;
if (val & MXT_COMMS_RETRIGEN)
return 0;
}
dev_warn(&client->dev, "Enabling RETRIGEN workaround\n");
data->use_retrigen_workaround = true;
return 0;
}
static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg) static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
{ {
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
...@@ -1561,6 +1599,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) ...@@ -1561,6 +1599,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
ret = mxt_check_retrigen(data);
if (ret)
goto release_mem;
ret = mxt_soft_reset(data); ret = mxt_soft_reset(data);
if (ret) if (ret)
goto release_mem; goto release_mem;
...@@ -1604,6 +1646,7 @@ static void mxt_free_object_table(struct mxt_data *data) ...@@ -1604,6 +1646,7 @@ static void mxt_free_object_table(struct mxt_data *data)
data->T71_address = 0; data->T71_address = 0;
data->T9_reportid_min = 0; data->T9_reportid_min = 0;
data->T9_reportid_max = 0; data->T9_reportid_max = 0;
data->T18_address = 0;
data->T19_reportid = 0; data->T19_reportid = 0;
data->T44_address = 0; data->T44_address = 0;
data->T100_reportid_min = 0; data->T100_reportid_min = 0;
...@@ -1678,6 +1721,9 @@ static int mxt_parse_object_table(struct mxt_data *data, ...@@ -1678,6 +1721,9 @@ static int mxt_parse_object_table(struct mxt_data *data,
object->num_report_ids - 1; object->num_report_ids - 1;
data->num_touchids = object->num_report_ids; data->num_touchids = object->num_report_ids;
break; break;
case MXT_SPT_COMMSCONFIG_T18:
data->T18_address = object->start_address;
break;
case MXT_SPT_MESSAGECOUNT_T44: case MXT_SPT_MESSAGECOUNT_T44:
data->T44_address = object->start_address; data->T44_address = object->start_address;
break; break;
...@@ -2141,6 +2187,10 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -2141,6 +2187,10 @@ static int mxt_initialize(struct mxt_data *data)
if (error) if (error)
return error; return error;
error = mxt_check_retrigen(data);
if (error)
return error;
error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
&client->dev, GFP_KERNEL, data, &client->dev, GFP_KERNEL, data,
mxt_config_cb); mxt_config_cb);
......
...@@ -288,7 +288,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, ...@@ -288,7 +288,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
return edt_ft5x06_ts_readwrite(tsdata->client, 4, return edt_ft5x06_ts_readwrite(tsdata->client, 4,
wrbuf, 0, NULL); wrbuf, 0, NULL);
/* fallthrough */
case EDT_M09: case EDT_M09:
case EDT_M12: case EDT_M12:
case EV_FT: case EV_FT:
...@@ -330,7 +330,6 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, ...@@ -330,7 +330,6 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
} }
break; break;
/* fallthrough */
case EDT_M09: case EDT_M09:
case EDT_M12: case EDT_M12:
case EV_FT: case EV_FT:
......
...@@ -955,7 +955,7 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) ...@@ -955,7 +955,7 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
break; break;
ts->state = ELAN_STATE_NORMAL; ts->state = ELAN_STATE_NORMAL;
/* fall through */ fallthrough;
case ELAN_STATE_NORMAL: case ELAN_STATE_NORMAL:
......
...@@ -348,7 +348,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) ...@@ -348,7 +348,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
case 1: /* 6-byte protocol */ case 1: /* 6-byte protocol */
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
/* fall through */ fallthrough;
case 2: /* 4-byte protocol */ case 2: /* 4-byte protocol */
input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
*/ */
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
...@@ -16,6 +18,7 @@ ...@@ -16,6 +18,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/sizes.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -23,15 +26,59 @@ ...@@ -23,15 +26,59 @@
#define EXC3000_SLOTS_PER_FRAME 5 #define EXC3000_SLOTS_PER_FRAME 5
#define EXC3000_LEN_FRAME 66 #define EXC3000_LEN_FRAME 66
#define EXC3000_LEN_POINT 10 #define EXC3000_LEN_POINT 10
#define EXC3000_MT_EVENT 6
#define EXC3000_LEN_MODEL_NAME 16
#define EXC3000_LEN_FW_VERSION 16
#define EXC3000_MT1_EVENT 0x06
#define EXC3000_MT2_EVENT 0x18
#define EXC3000_TIMEOUT_MS 100 #define EXC3000_TIMEOUT_MS 100
#define EXC3000_RESET_MS 10
#define EXC3000_READY_MS 100
static const struct i2c_device_id exc3000_id[];
struct eeti_dev_info {
const char *name;
int max_xy;
};
enum eeti_dev_id {
EETI_EXC3000,
EETI_EXC80H60,
EETI_EXC80H84,
};
static struct eeti_dev_info exc3000_info[] = {
[EETI_EXC3000] = {
.name = "EETI EXC3000 Touch Screen",
.max_xy = SZ_4K - 1,
},
[EETI_EXC80H60] = {
.name = "EETI EXC80H60 Touch Screen",
.max_xy = SZ_16K - 1,
},
[EETI_EXC80H84] = {
.name = "EETI EXC80H84 Touch Screen",
.max_xy = SZ_16K - 1,
},
};
struct exc3000_data { struct exc3000_data {
struct i2c_client *client; struct i2c_client *client;
const struct eeti_dev_info *info;
struct input_dev *input; struct input_dev *input;
struct touchscreen_properties prop; struct touchscreen_properties prop;
struct gpio_desc *reset;
struct timer_list timer; struct timer_list timer;
u8 buf[2 * EXC3000_LEN_FRAME]; u8 buf[2 * EXC3000_LEN_FRAME];
struct completion wait_event;
struct mutex query_lock;
int query_result;
char model[EXC3000_LEN_MODEL_NAME];
char fw_version[EXC3000_LEN_FW_VERSION];
}; };
static void exc3000_report_slots(struct input_dev *input, static void exc3000_report_slots(struct input_dev *input,
...@@ -58,10 +105,15 @@ static void exc3000_timer(struct timer_list *t) ...@@ -58,10 +105,15 @@ static void exc3000_timer(struct timer_list *t)
input_sync(data->input); input_sync(data->input);
} }
static int exc3000_read_frame(struct i2c_client *client, u8 *buf) static int exc3000_read_frame(struct exc3000_data *data, u8 *buf)
{ {
struct i2c_client *client = data->client;
u8 expected_event = EXC3000_MT1_EVENT;
int ret; int ret;
if (data->info->max_xy == SZ_16K - 1)
expected_event = EXC3000_MT2_EVENT;
ret = i2c_master_send(client, "'", 2); ret = i2c_master_send(client, "'", 2);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -76,19 +128,21 @@ static int exc3000_read_frame(struct i2c_client *client, u8 *buf) ...@@ -76,19 +128,21 @@ static int exc3000_read_frame(struct i2c_client *client, u8 *buf)
if (ret != EXC3000_LEN_FRAME) if (ret != EXC3000_LEN_FRAME)
return -EIO; return -EIO;
if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME || if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME)
buf[2] != EXC3000_MT_EVENT) return -EINVAL;
if (buf[2] != expected_event)
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
static int exc3000_read_data(struct i2c_client *client, static int exc3000_read_data(struct exc3000_data *data,
u8 *buf, int *n_slots) u8 *buf, int *n_slots)
{ {
int error; int error;
error = exc3000_read_frame(client, buf); error = exc3000_read_frame(data, buf);
if (error) if (error)
return error; return error;
...@@ -98,7 +152,7 @@ static int exc3000_read_data(struct i2c_client *client, ...@@ -98,7 +152,7 @@ static int exc3000_read_data(struct i2c_client *client,
if (*n_slots > EXC3000_SLOTS_PER_FRAME) { if (*n_slots > EXC3000_SLOTS_PER_FRAME) {
/* Read 2nd frame to get the rest of the contacts. */ /* Read 2nd frame to get the rest of the contacts. */
error = exc3000_read_frame(client, buf + EXC3000_LEN_FRAME); error = exc3000_read_frame(data, buf + EXC3000_LEN_FRAME);
if (error) if (error)
return error; return error;
...@@ -110,6 +164,28 @@ static int exc3000_read_data(struct i2c_client *client, ...@@ -110,6 +164,28 @@ static int exc3000_read_data(struct i2c_client *client,
return 0; return 0;
} }
static int exc3000_query_interrupt(struct exc3000_data *data)
{
u8 *buf = data->buf;
int error;
error = i2c_master_recv(data->client, buf, EXC3000_LEN_FRAME);
if (error < 0)
return error;
if (buf[0] != 'B')
return -EPROTO;
if (buf[4] == 'E')
strlcpy(data->model, buf + 5, sizeof(data->model));
else if (buf[4] == 'D')
strlcpy(data->fw_version, buf + 5, sizeof(data->fw_version));
else
return -EPROTO;
return 0;
}
static irqreturn_t exc3000_interrupt(int irq, void *dev_id) static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
{ {
struct exc3000_data *data = dev_id; struct exc3000_data *data = dev_id;
...@@ -118,7 +194,13 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id) ...@@ -118,7 +194,13 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
int slots, total_slots; int slots, total_slots;
int error; int error;
error = exc3000_read_data(data->client, buf, &total_slots); if (mutex_is_locked(&data->query_lock)) {
data->query_result = exc3000_query_interrupt(data);
complete(&data->wait_event);
goto out;
}
error = exc3000_read_data(data, buf, &total_slots);
if (error) { if (error) {
/* Schedule a timer to release "stuck" contacts */ /* Schedule a timer to release "stuck" contacts */
mod_timer(&data->timer, mod_timer(&data->timer,
...@@ -145,31 +227,132 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id) ...@@ -145,31 +227,132 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int exc3000_probe(struct i2c_client *client, static ssize_t fw_version_show(struct device *dev,
const struct i2c_device_id *id) struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct exc3000_data *data = i2c_get_clientdata(client);
static const u8 request[68] = {
0x67, 0x00, 0x42, 0x00, 0x03, 0x01, 'D', 0x00
};
int error;
mutex_lock(&data->query_lock);
data->query_result = -ETIMEDOUT;
reinit_completion(&data->wait_event);
error = i2c_master_send(client, request, sizeof(request));
if (error < 0) {
mutex_unlock(&data->query_lock);
return error;
}
wait_for_completion_interruptible_timeout(&data->wait_event, 1 * HZ);
mutex_unlock(&data->query_lock);
if (data->query_result < 0)
return data->query_result;
return sprintf(buf, "%s\n", data->fw_version);
}
static DEVICE_ATTR_RO(fw_version);
static ssize_t exc3000_get_model(struct exc3000_data *data)
{
static const u8 request[68] = {
0x67, 0x00, 0x42, 0x00, 0x03, 0x01, 'E', 0x00
};
struct i2c_client *client = data->client;
int error;
mutex_lock(&data->query_lock);
data->query_result = -ETIMEDOUT;
reinit_completion(&data->wait_event);
error = i2c_master_send(client, request, sizeof(request));
if (error < 0) {
mutex_unlock(&data->query_lock);
return error;
}
wait_for_completion_interruptible_timeout(&data->wait_event, 1 * HZ);
mutex_unlock(&data->query_lock);
return data->query_result;
}
static ssize_t model_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct exc3000_data *data = i2c_get_clientdata(client);
int error;
error = exc3000_get_model(data);
if (error < 0)
return error;
return sprintf(buf, "%s\n", data->model);
}
static DEVICE_ATTR_RO(model);
static struct attribute *sysfs_attrs[] = {
&dev_attr_fw_version.attr,
&dev_attr_model.attr,
NULL
};
static struct attribute_group exc3000_attribute_group = {
.attrs = sysfs_attrs
};
static int exc3000_probe(struct i2c_client *client)
{ {
struct exc3000_data *data; struct exc3000_data *data;
struct input_dev *input; struct input_dev *input;
int error; int error, max_xy, retry;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
data->client = client; data->client = client;
data->info = device_get_match_data(&client->dev);
if (!data->info) {
enum eeti_dev_id eeti_dev_id =
i2c_match_id(exc3000_id, client)->driver_data;
data->info = &exc3000_info[eeti_dev_id];
}
timer_setup(&data->timer, exc3000_timer, 0); timer_setup(&data->timer, exc3000_timer, 0);
init_completion(&data->wait_event);
mutex_init(&data->query_lock);
data->reset = devm_gpiod_get_optional(&client->dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(data->reset))
return PTR_ERR(data->reset);
if (data->reset) {
msleep(EXC3000_RESET_MS);
gpiod_set_value_cansleep(data->reset, 0);
msleep(EXC3000_READY_MS);
}
input = devm_input_allocate_device(&client->dev); input = devm_input_allocate_device(&client->dev);
if (!input) if (!input)
return -ENOMEM; return -ENOMEM;
data->input = input; data->input = input;
input_set_drvdata(input, data);
input->name = "EETI EXC3000 Touch Screen"; input->name = data->info->name;
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
input_set_abs_params(input, ABS_MT_POSITION_X, 0, 4095, 0, 0); max_xy = data->info->max_xy;
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 4095, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0);
touchscreen_parse_properties(input, true, &data->prop); touchscreen_parse_properties(input, true, &data->prop);
error = input_mt_init_slots(input, EXC3000_NUM_SLOTS, error = input_mt_init_slots(input, EXC3000_NUM_SLOTS,
...@@ -187,18 +370,49 @@ static int exc3000_probe(struct i2c_client *client, ...@@ -187,18 +370,49 @@ static int exc3000_probe(struct i2c_client *client,
if (error) if (error)
return error; return error;
/*
* I²C does not have built-in recovery, so retry on failure. This
* ensures, that the device probe will not fail for temporary issues
* on the bus. This is not needed for the sysfs calls (userspace
* will receive the error code and can start another query) and
* cannot be done for touch events (but that only means loosing one
* or two touch events anyways).
*/
for (retry = 0; retry < 3; retry++) {
error = exc3000_get_model(data);
if (!error)
break;
dev_warn(&client->dev, "Retry %d get EETI EXC3000 model: %d\n",
retry + 1, error);
}
if (error)
return error;
dev_dbg(&client->dev, "TS Model: %s", data->model);
i2c_set_clientdata(client, data);
error = devm_device_add_group(&client->dev, &exc3000_attribute_group);
if (error)
return error;
return 0; return 0;
} }
static const struct i2c_device_id exc3000_id[] = { static const struct i2c_device_id exc3000_id[] = {
{ "exc3000", 0 }, { "exc3000", EETI_EXC3000 },
{ "exc80h60", EETI_EXC80H60 },
{ "exc80h84", EETI_EXC80H84 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, exc3000_id); MODULE_DEVICE_TABLE(i2c, exc3000_id);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id exc3000_of_match[] = { static const struct of_device_id exc3000_of_match[] = {
{ .compatible = "eeti,exc3000" }, { .compatible = "eeti,exc3000", .data = &exc3000_info[EETI_EXC3000] },
{ .compatible = "eeti,exc80h60", .data = &exc3000_info[EETI_EXC80H60] },
{ .compatible = "eeti,exc80h84", .data = &exc3000_info[EETI_EXC80H84] },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, exc3000_of_match); MODULE_DEVICE_TABLE(of, exc3000_of_match);
...@@ -210,7 +424,7 @@ static struct i2c_driver exc3000_driver = { ...@@ -210,7 +424,7 @@ static struct i2c_driver exc3000_driver = {
.of_match_table = of_match_ptr(exc3000_of_match), .of_match_table = of_match_ptr(exc3000_of_match),
}, },
.id_table = exc3000_id, .id_table = exc3000_id,
.probe = exc3000_probe, .probe_new = exc3000_probe,
}; };
module_i2c_driver(exc3000_driver); module_i2c_driver(exc3000_driver);
......
...@@ -289,7 +289,7 @@ static int iqs5xx_bl_cmd(struct i2c_client *client, u8 bl_cmd, u16 bl_addr) ...@@ -289,7 +289,7 @@ static int iqs5xx_bl_cmd(struct i2c_client *client, u8 bl_cmd, u16 bl_addr)
break; break;
case IQS5XX_BL_CMD_EXEC: case IQS5XX_BL_CMD_EXEC:
usleep_range(10000, 10100); usleep_range(10000, 10100);
/* fall through */ fallthrough;
default: default:
return 0; return 0;
} }
......
...@@ -130,7 +130,6 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id) ...@@ -130,7 +130,6 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
switch (buf[1] & EVENT_TAG_MASK) { switch (buf[1] & EVENT_TAG_MASK) {
case EVENT_INIT: case EVENT_INIT:
/* fall through */
case EVENT_MIDDLE: case EVENT_MIDDLE:
input_report_abs(data->input_dev, ABS_X, x); input_report_abs(data->input_dev, ABS_X, x);
input_report_abs(data->input_dev, ABS_Y, y); input_report_abs(data->input_dev, ABS_Y, y);
......
...@@ -255,7 +255,7 @@ static void stmfts_parse_events(struct stmfts_data *sdata) ...@@ -255,7 +255,7 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY: case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY:
case STMFTS_EV_STATUS: case STMFTS_EV_STATUS:
complete(&sdata->cmd_done); complete(&sdata->cmd_done);
/* fall through */ fallthrough;
case STMFTS_EV_NO_EVENT: case STMFTS_EV_NO_EVENT:
case STMFTS_EV_DEBUG: case STMFTS_EV_DEBUG:
......
...@@ -206,7 +206,7 @@ struct rmi_device_platform_data_spi { ...@@ -206,7 +206,7 @@ struct rmi_device_platform_data_spi {
* *
* @reset_delay_ms - after issuing a reset command to the touch sensor, the * @reset_delay_ms - after issuing a reset command to the touch sensor, the
* driver waits a few milliseconds to give the firmware a chance to * driver waits a few milliseconds to give the firmware a chance to
* to re-initialize. You can override the default wait period here. * re-initialize. You can override the default wait period here.
* @irq: irq associated with the attn gpio line, or negative * @irq: irq associated with the attn gpio line, or negative
*/ */
struct rmi_device_platform_data { struct rmi_device_platform_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment