From 05b8465025466f30300941a16d4bbf53c755c3f1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 6 Jul 2020 17:38:16 -0700 Subject: Input: elantech - remove redundant assignments to variable error The variable error is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200603140431.131347-1-colin.king@canonical.com Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 2d8434b7b623..e4f394cc0520 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1897,7 +1897,7 @@ static bool elantech_use_host_notify(struct psmouse *psmouse, int elantech_init_smbus(struct psmouse *psmouse) { struct elantech_device_info info; - int error = -EINVAL; + int error; psmouse_reset(psmouse); @@ -2015,7 +2015,7 @@ static int elantech_setup_ps2(struct psmouse *psmouse, int elantech_init_ps2(struct psmouse *psmouse) { struct elantech_device_info info; - int error = -EINVAL; + int error; psmouse_reset(psmouse); @@ -2036,7 +2036,7 @@ int elantech_init_ps2(struct psmouse *psmouse) int elantech_init(struct psmouse *psmouse) { struct elantech_device_info info; - int error = -EINVAL; + int error; psmouse_reset(psmouse); -- cgit v1.2.3-58-ga151 From deae576455bbeb84a3a86bc359d322d66dfc841c Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 20 May 2020 10:30:55 -0700 Subject: Input: exc3000 - switch to i2c's probe_new API Switch to the "new" I2C probe API. Signed-off-by: Sebastian Reichel Reviewed-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20200520153936.46869-3-sebastian.reichel@collabora.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/exc3000.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index e007e2e8f626..555a14305cd4 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -145,8 +145,7 @@ out: return IRQ_HANDLED; } -static int exc3000_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int exc3000_probe(struct i2c_client *client) { struct exc3000_data *data; struct input_dev *input; @@ -210,7 +209,7 @@ static struct i2c_driver exc3000_driver = { .of_match_table = of_match_ptr(exc3000_of_match), }, .id_table = exc3000_id, - .probe = exc3000_probe, + .probe_new = exc3000_probe, }; module_i2c_driver(exc3000_driver); -- cgit v1.2.3-58-ga151 From 08a6caaed8c12a158e88c0e0e1369203f9cff020 Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Mon, 6 Jul 2020 21:17:46 -0700 Subject: Input: cm109 - remove needless check before usb_free_coherent() usb_free_coherent() is safe with NULL addr and this check is not required. Signed-off-by: Xu Wang Link: https://lore.kernel.org/r/20200707030905.3123-1-vulab@iscas.ac.cn Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cm109.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index c09b9628ad34..e413801f0491 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -663,12 +663,8 @@ static const struct usb_device_id cm109_usb_table[] = { static void cm109_usb_cleanup(struct cm109_dev *dev) { kfree(dev->ctl_req); - if (dev->ctl_data) - usb_free_coherent(dev->udev, USB_PKT_LEN, - 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_coherent(dev->udev, USB_PKT_LEN, dev->ctl_data, dev->ctl_dma); + 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_ctl); /* parameter validation in core/urb */ -- cgit v1.2.3-58-ga151 From 6f49c4f5b95b9ac8ead1ec39066489fb10fcbde8 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 7 Jul 2020 11:24:55 -0700 Subject: Input: Use fallthrough pseudo-keyword Replace the existing /* fall through */ comments and its variants with the new pseudo-keyword macro fallthrough[1]. Also, remove unnecessary fall-through markings when it is the case. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html?highlight=fallthrough#implicit-switch-case-fall-through Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200707180857.GA30600@embeddedor Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/db9.c | 10 +++++----- drivers/input/joystick/gamecon.c | 10 ++++++---- drivers/input/joystick/sidewinder.c | 15 ++++++++++----- drivers/input/joystick/spaceball.c | 8 ++++---- drivers/input/keyboard/adp5589-keys.c | 2 +- drivers/input/keyboard/atkbd.c | 2 +- drivers/input/keyboard/gpio_keys.c | 1 - drivers/input/misc/iqs269a.c | 21 +++++++-------------- drivers/input/misc/pwm-vibra.c | 2 +- drivers/input/misc/xen-kbdfront.c | 4 ++-- drivers/input/mouse/appletouch.c | 2 +- drivers/input/mouse/cyapa_gen3.c | 4 ++-- drivers/input/mouse/cyapa_gen5.c | 2 +- drivers/input/mouse/cyapa_gen6.c | 2 +- drivers/input/mouse/elantech.c | 6 ++---- drivers/input/mouse/hgpk.c | 4 ++-- drivers/input/mouse/navpoint.c | 2 +- drivers/input/mouse/sentelic.c | 2 +- drivers/input/mouse/sermouse.c | 4 ++-- drivers/input/serio/i8042.c | 2 +- drivers/input/serio/libps2.c | 2 +- drivers/input/sparse-keymap.c | 2 +- drivers/input/tablet/gtco.c | 6 +++--- drivers/input/tablet/pegasus_notetaker.c | 2 +- drivers/input/touchscreen/edt-ft5x06.c | 3 +-- drivers/input/touchscreen/elants_i2c.c | 2 +- drivers/input/touchscreen/elo.c | 2 +- drivers/input/touchscreen/iqs5xx.c | 2 +- drivers/input/touchscreen/max11801_ts.c | 1 - drivers/input/touchscreen/stmfts.c | 2 +- 30 files changed, 62 insertions(+), 67 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index a7bc576eb342..434d265fa2e8 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -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); return data[0] = 0xe3; } - /* fall through */ + fallthrough; default: return data[0]; } @@ -267,14 +267,14 @@ static int db9_saturn_report(unsigned char id, unsigned char data[60], struct in switch (data[j]) { case 0x16: /* multi controller (analog 4 axis) */ input_report_abs(dev, db9_abs[5], data[j + 6]); - /* fall through */ + fallthrough; case 0x15: /* mission stick (analog 3 axis) */ input_report_abs(dev, db9_abs[3], data[j + 4]); input_report_abs(dev, db9_abs[4], data[j + 5]); - /* fall through */ + fallthrough; case 0x13: /* racing controller (analog 1 axis) */ input_report_abs(dev, db9_abs[2], data[j + 3]); - /* fall through */ + fallthrough; case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */ case 0x02: /* digital pad (digital 2 axis + buttons) */ 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) 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_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1); - /* fall through */ + fallthrough; case DB9_MULTI_0802: diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index e0a362be5812..88df68cc4ac6 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -485,7 +485,7 @@ static void gc_multi_process_packet(struct gc *gc) switch (pad->type) { case GC_MULTI2: input_report_key(dev, BTN_THUMB, s & data[5]); - /* fall through */ + fallthrough; case GC_MULTI: input_report_abs(dev, ABS_X, @@ -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_THUMBR, ~data[0] & 0x02); - /* fall through */ + fallthrough; case GC_PSX_NEGCON: case GC_PSX_ANALOG: @@ -872,7 +872,8 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) case GC_SNES: for (i = 4; i < 8; i++) input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); - /* fall through */ + fallthrough; + case GC_NES: for (i = 0; i < 4; 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) case GC_MULTI2: input_set_capability(input_dev, EV_KEY, BTN_THUMB); - /* fall through */ + fallthrough; + case GC_MULTI: input_set_capability(input_dev, EV_KEY, BTN_TRIGGER); /* fall through */ diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 1777e68c9f02..fac91ea14f17 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -656,16 +656,19 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) switch (i * m) { case 60: - sw->number++; /* fall through */ + sw->number++; + fallthrough; case 45: /* Ambiguous packet length */ if (j <= 40) { /* ID length less or eq 40 -> FSP */ case 43: sw->type = SW_ID_FSP; break; } - sw->number++; /* fall through */ + sw->number++; + fallthrough; case 30: - sw->number++; /* fall through */ + sw->number++; + fallthrough; case 15: sw->type = SW_ID_GP; break; @@ -681,9 +684,11 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) sw->type = SW_ID_PP; break; case 66: - sw->bits = 3; /* fall through */ + sw->bits = 3; + fallthrough; case 198: - sw->length = 22; /* fall through */ + sw->length = 22; + fallthrough; case 64: sw->type = SW_ID_3DP; if (j == 160) diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index cf7cbcd0c29d..429411c6c0a8 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -146,7 +146,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, break; } spaceball->escape = 0; - /* fall through */ + fallthrough; case 'M': case 'Q': case 'S': @@ -154,7 +154,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, spaceball->escape = 0; data &= 0x1f; } - /* fall through */ + fallthrough; default: if (spaceball->escape) spaceball->escape = 0; @@ -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) | BIT_MASK(BTN_B) | BIT_MASK(BTN_C) | BIT_MASK(BTN_MODE); - /* fall through */ + fallthrough; default: input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) | BIT_MASK(BTN_3) | BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7) | BIT_MASK(BTN_8); - /* fall through */ + fallthrough; case SPACEBALL_3003C: input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) | BIT_MASK(BTN_8); diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index e7d58e7f0257..eb0e9cd66bcb 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -1016,7 +1016,7 @@ static int adp5589_probe(struct i2c_client *client, switch (id->driver_data) { case ADP5585_02: kpad->support_row5 = true; - /* fall through */ + fallthrough; case ADP5585_01: kpad->is_adp5585 = true; kpad->var = &const_adp5585; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 6ec28265771d..edc613efc158 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -1241,7 +1241,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) case SERIO_8042_XL: atkbd->translated = true; - /* Fall through */ + fallthrough; case SERIO_8042: if (serio->write) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 53c9ff338dea..f2d4e4daa818 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -574,7 +574,6 @@ static int gpio_keys_setup_key(struct platform_device *pdev, IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING; break; case EV_ACT_ANY: - /* fall through */ default: /* * For other cases, we are OK letting suspend/resume diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c index 6699eb160a0f..a348247d3d38 100644 --- a/drivers/input/misc/iqs269a.c +++ b/drivers/input/misc/iqs269a.c @@ -575,8 +575,7 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, case IQS269_LOCAL_CAP_SIZE_GLOBAL_0pF5: engine_a |= IQS269_CHx_ENG_A_LOCAL_CAP_SIZE; - - /* fall through */ + fallthrough; case IQS269_LOCAL_CAP_SIZE_GLOBAL_ONLY: engine_b |= IQS269_CHx_ENG_B_LOCAL_CAP_ENABLE; @@ -731,14 +730,12 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, iqs269->switches[i].code = val; iqs269->switches[i].enabled = true; } - - /* fall through */ + fallthrough; case IQS269_CHx_HALL_INACTIVE: if (iqs269->hall_enable) break; - - /* fall through */ + fallthrough; default: iqs269->keycode[i * IQS269_NUM_CH + reg] = val; @@ -1143,14 +1140,12 @@ static int iqs269_input_init(struct iqs269_private *iqs269) sw_code, state & BIT(j)); } - - /* fall through */ + fallthrough; case IQS269_CHx_HALL_INACTIVE: if (iqs269->hall_enable) continue; - - /* fall through */ + fallthrough; default: if (keycode != KEY_RESERVED) @@ -1273,14 +1268,12 @@ static int iqs269_report(struct iqs269_private *iqs269) input_report_switch(iqs269->keypad, sw_code, state & BIT(j)); - - /* fall through */ + fallthrough; case IQS269_CHx_HALL_INACTIVE: if (iqs269->hall_enable) continue; - - /* fall through */ + fallthrough; default: input_report_key(iqs269->keypad, keycode, diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c index 8ceaf7db2882..81e777a04b88 100644 --- a/drivers/input/misc/pwm-vibra.c +++ b/drivers/input/misc/pwm-vibra.c @@ -190,7 +190,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "Failed to request direction pwm: %d", err); - /* Fall through */ + fallthrough; case -EPROBE_DEFER: return err; diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index a1bba722b234..4ff5cd2a6d8d 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -124,7 +124,7 @@ static void xenkbd_handle_mt_event(struct xenkbd_info *info, switch (mtouch->event_type) { case XENKBD_MT_EV_DOWN: input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true); - /* fall through */ + fallthrough; case XENKBD_MT_EV_MOTION: input_report_abs(info->mtouch, ABS_MT_POSITION_X, @@ -524,7 +524,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's CLOSING state */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 3f06e8a495d8..bfa26651c0be 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -458,7 +458,7 @@ static int atp_status_check(struct urb *urb) dev->info->datalen, dev->urb->actual_length); dev->overflow_warned = true; } - /* fall through */ + fallthrough; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 00e395dfc3d5..a0361f9325f8 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -1067,7 +1067,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) return error; } - /* Fall through */ + fallthrough; case CYAPA_STATE_BL_IDLE: /* Try to get firmware version in bootloader mode. */ cyapa_gen3_bl_query_data(cyapa); @@ -1078,7 +1078,7 @@ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) return error; } - /* Fall through */ + fallthrough; case CYAPA_STATE_OP: /* * Reading query data before going back to the full mode diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 7f012bfa2658..bb3a63d1268d 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -2554,7 +2554,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) } cyapa->state = CYAPA_STATE_GEN5_APP; - /* fall through */ + fallthrough; case CYAPA_STATE_GEN5_APP: /* diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c index c1b524ab4623..7eba66fbef58 100644 --- a/drivers/input/mouse/cyapa_gen6.c +++ b/drivers/input/mouse/cyapa_gen6.c @@ -680,7 +680,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa) } cyapa->state = CYAPA_STATE_GEN6_APP; - /* fall through */ + fallthrough; case CYAPA_STATE_GEN6_APP: /* diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index e4f394cc0520..90f8765f9efc 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -383,7 +383,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) */ if (packet[3] & 0x80) fingers = 4; - /* fall through */ + fallthrough; case 1: /* * byte 1: . . . . x11 x10 x9 x8 @@ -1146,7 +1146,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) case 2: __set_bit(BTN_TOOL_QUADTAP, dev->keybit); __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - /* fall through */ + fallthrough; case 3: if (info->hw_version == 3) elantech_set_buttonpad_prop(psmouse); @@ -1877,12 +1877,10 @@ static bool elantech_use_host_notify(struct psmouse *psmouse, /* expected case */ break; case ETP_BUS_SMB_ALERT_ONLY: - /* fall-through */ case ETP_BUS_PS2_SMB_ALERT: psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n"); break; case ETP_BUS_SMB_HST_NTFY_ONLY: - /* fall-through */ case ETP_BUS_PS2_SMB_HST_NTFY: return true; default: diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 72a083f3fc4a..4dc441309aac 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -238,7 +238,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, /* we're not spewing, but this packet might be the start */ priv->spew_flag = MAYBE_SPEWING; - /* fall-through */ + fallthrough; case MAYBE_SPEWING: priv->spew_count++; @@ -249,7 +249,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, /* excessive spew detected, request recalibration */ priv->spew_flag = SPEW_DETECTED; - /* fall-through */ + fallthrough; case SPEW_DETECTED: /* only recalibrate when the overall delta to the cursor diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c index 0b75248c8380..c112980c2341 100644 --- a/drivers/input/mouse/navpoint.c +++ b/drivers/input/mouse/navpoint.c @@ -105,7 +105,7 @@ static void navpoint_packet(struct navpoint *navpoint) case 0x19: /* Module 0, Hello packet */ if ((navpoint->data[1] & 0xf0) == 0x10) break; - /* FALLTHROUGH */ + fallthrough; default: dev_warn(navpoint->dev, "spurious packet: data=0x%02x,0x%02x,...\n", diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index e99d9bf1a267..9f7ecc72093a 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -794,7 +794,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) /* on-pad click, filter it if necessary */ if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) packet[0] &= ~FSP_PB0_LBTN; - /* fall through */ + fallthrough; case FSP_PKT_TYPE_NORMAL: /* normal packet */ diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index ea9242d53899..caa79c177c55 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -128,7 +128,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data) case SERIO_MS: sermouse->type = SERIO_MP; - /* fall through */ + fallthrough; case SERIO_MP: if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */ @@ -139,7 +139,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data) case SERIO_MZP: case SERIO_MZPP: input_report_key(dev, BTN_SIDE, (data >> 5) & 1); - /* fall through */ + fallthrough; case SERIO_MZ: input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1); diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 0dddf273afd9..d3eda48032e3 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -562,7 +562,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) str = last_str; break; } - /* fall through - report timeout */ + fallthrough; /* report timeout */ case 0xfc: case 0xfd: case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index a8c94a940a79..8a16e41f7b7f 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -418,7 +418,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) ps2dev->nak = 0; break; } - /* Fall through */ + fallthrough; default: /* * Do not signal errors if we get unexpected reply while diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 530fd15eaeca..25bf8be6e711 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -247,7 +247,7 @@ void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *k case KE_SW: value = ke->sw.value; - /* fall through */ + fallthrough; case KE_VSW: input_report_switch(dev, ke->sw.code, value); diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 96d65575f75a..44bb1f69b4b2 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -676,8 +676,8 @@ static void gtco_urb_callback(struct urb *urbinfo) /* Mask out the Y tilt value used for pressure */ device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); + fallthrough; - /* Fall thru */ case 4: /* Tilt */ input_report_abs(inputdev, ABS_TILT_X, @@ -685,8 +685,8 @@ static void gtco_urb_callback(struct urb *urbinfo) input_report_abs(inputdev, ABS_TILT_Y, sign_extend32(device->buffer[7], 6)); + fallthrough; - /* Fall thru */ case 2: case 3: /* Convert buttons, only 5 bits possible */ @@ -695,8 +695,8 @@ static void gtco_urb_callback(struct urb *urbinfo) /* We don't apply any meaning to the bitmask, just report */ input_event(inputdev, EV_MSC, MSC_SERIAL, val); + fallthrough; - /* Fall thru */ case 1: /* All reports have X and Y coords in the same place */ val = get_unaligned_le16(&device->buffer[1]); diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c index 38f087404f7a..749edbdb7ffa 100644 --- a/drivers/input/tablet/pegasus_notetaker.c +++ b/drivers/input/tablet/pegasus_notetaker.c @@ -146,7 +146,7 @@ static void pegasus_parse_packet(struct pegasus *pegasus) /* xy data */ case BATTERY_LOW: dev_warn_once(&dev->dev, "Pen battery low\n"); - /* fall through */ + fallthrough; case BATTERY_NO_REPORT: case BATTERY_GOOD: diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 3a4f18d3450d..6ff81d48da86 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -288,7 +288,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); - /* fallthrough */ + case EDT_M09: case EDT_M12: case EV_FT: @@ -330,7 +330,6 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, } break; - /* fallthrough */ case EDT_M09: case EDT_M12: case EV_FT: diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 233cb1085bbd..a765aa876a8e 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -955,7 +955,7 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) break; ts->state = ELAN_STATE_NORMAL; - /* fall through */ + fallthrough; case ELAN_STATE_NORMAL: diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index d6772a2c2d09..e0bacd34866a 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -348,7 +348,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) case 1: /* 6-byte protocol */ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); - /* fall through */ + fallthrough; case 2: /* 4-byte protocol */ input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c index 5875bb1099a8..3162b68f7374 100644 --- a/drivers/input/touchscreen/iqs5xx.c +++ b/drivers/input/touchscreen/iqs5xx.c @@ -289,7 +289,7 @@ static int iqs5xx_bl_cmd(struct i2c_client *client, u8 bl_cmd, u16 bl_addr) break; case IQS5XX_BL_CMD_EXEC: usleep_range(10000, 10100); - /* fall through */ + fallthrough; default: return 0; } diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 1af08d3dfaf7..f15713aaebc2 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -130,7 +130,6 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id) switch (buf[1] & EVENT_TAG_MASK) { case EVENT_INIT: - /* fall through */ case EVENT_MIDDLE: input_report_abs(data->input_dev, ABS_X, x); input_report_abs(data->input_dev, ABS_Y, y); diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index b54cc64e4ea6..df946869d4cd 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -255,7 +255,7 @@ static void stmfts_parse_events(struct stmfts_data *sdata) case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY: case STMFTS_EV_STATUS: complete(&sdata->cmd_done); - /* fall through */ + fallthrough; case STMFTS_EV_NO_EVENT: case STMFTS_EV_DEBUG: -- cgit v1.2.3-58-ga151 From 606e7022078410ce4456e760e80f5e4b68c63476 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Wed, 15 Jul 2020 17:30:36 -0700 Subject: Input: mt - cleanup open-coded __set_bit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace open-coded __set_bit() with the function. Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/cf1dda3a372896cb01033ce084a7deb9620df7aa.1594599118.git.mirq-linux@rere.qmqm.pl Signed-off-by: Dmitry Torokhov --- drivers/input/input-mt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index a81e14148407..f699538bdac4 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -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)) { dev->absinfo[dst] = dev->absinfo[src]; dev->absinfo[dst].fuzz = 0; - dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); + __set_bit(dst, dev->absbit); } } -- cgit v1.2.3-58-ga151 From 77da21c5d3c698f5c9ce41d57c137244bc8b7b93 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Wed, 15 Jul 2020 17:40:27 -0700 Subject: Input: elan_i2c - handle firmware not implementing "get pattern" command Not all versions of firmware implement "get pattern" command. When encountering those assume that the controllers use older pattern. Signed-off-by: Jingle Wu Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_i2c.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 058b35b1f9a9..0d8a6a1b30d7 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -249,7 +249,13 @@ static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern) dev_err(&client->dev, "failed to get pattern: %d\n", 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; } -- cgit v1.2.3-58-ga151 From fc7c882aa9b1643273c4bb77d31163355dcbc0b8 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Wed, 15 Jul 2020 22:25:59 -0700 Subject: Input: elan_i2c - make fetching IC type of older controllers more robust On older controllers IC type is reported in the 2nd byte of ETP_I2C_OSM_VERSION_CMD, however if controller's firmware is not flashed correctly it may return incorrect data. Fortunately there is also ETP_I2C_IAP_VERSION_P0_CMD command that can be used when controller in either normal or IAP mode, and which is guaranteed to return accurate data, so let's use it. Signed-off-by: Jingle Wu Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 8 +------- drivers/input/mouse/elan_i2c_i2c.c | 10 +++++++++- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 8719da540383..f1dade60f407 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -312,7 +312,6 @@ static int elan_initialize(struct elan_tp_data *data) static int elan_query_device_info(struct elan_tp_data *data) { int error; - u16 ic_type; error = data->ops->get_version(data->client, false, &data->fw_version); if (error) @@ -336,12 +335,7 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - if (data->pattern == 0x01) - ic_type = data->ic_type; - else - ic_type = data->iap_version; - - error = elan_get_fwinfo(ic_type, &data->fw_validpage_count, + error = elan_get_fwinfo(data->ic_type, &data->fw_validpage_count, &data->fw_signature_address); if (error) dev_warn(&data->client->dev, diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 0d8a6a1b30d7..bceb4bc32697 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -43,6 +43,7 @@ #define ETP_I2C_RESOLUTION_CMD 0x0108 #define ETP_I2C_PRESSURE_CMD 0x010A #define ETP_I2C_IAP_VERSION_CMD 0x0110 +#define ETP_I2C_IC_TYPE_P0_CMD 0x0110 #define ETP_I2C_SET_CMD 0x0300 #define ETP_I2C_POWER_CMD 0x0307 #define ETP_I2C_FW_CHECKSUM_CMD 0x030F @@ -330,7 +331,14 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, return error; } *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, val); -- cgit v1.2.3-58-ga151 From 40d8aa97131d16fe880cd48f8faabcd6a45019c4 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Wed, 15 Jul 2020 22:12:08 -0700 Subject: Input: elan_i2c - handle devices with patterns above 1 Extend fetching and parsing parameters of the controllers to devices with "patterns" above 1 (which currently should be handled in the same fashion as devices with pattern 1). Signed-off-by: Jingle Wu Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index bceb4bc32697..bb499f0d0925 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -284,7 +284,7 @@ static int elan_i2c_get_version(struct i2c_client *client, return error; } - if (pattern_ver == 0x01) + if (pattern_ver >= 0x01) *version = iap ? val[1] : val[0]; else *version = val[0]; @@ -305,7 +305,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, return error; } - if (pattern_ver == 0x01) { + if (pattern_ver >= 0x01) { error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val); if (error) { dev_err(&client->dev, "failed to get ic type: %d\n", -- cgit v1.2.3-58-ga151 From df10cc8db1e13cfcbd851e02881e2ef815d21b37 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Wed, 15 Jul 2020 22:02:19 -0700 Subject: Input: elan_i2c - fix detecting IAP version on older controllers Older controllers in bootloader mode need a different command to retrieve the IAP version. Signed-off-by: Jingle Wu Link: https://lore.kernel.org/r/20200714105641.15151-1-jingle.wu@emc.com.tw Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_i2c.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index bb499f0d0925..317166a264e6 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -44,6 +44,7 @@ #define ETP_I2C_PRESSURE_CMD 0x010A #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_POWER_CMD 0x0307 #define ETP_I2C_FW_CHECKSUM_CMD 0x030F @@ -266,6 +267,7 @@ static int elan_i2c_get_version(struct i2c_client *client, { int error; u8 pattern_ver; + u16 cmd; u8 val[3]; error = elan_i2c_get_pattern(client, &pattern_ver); @@ -274,10 +276,14 @@ static int elan_i2c_get_version(struct i2c_client *client, return error; } - error = elan_i2c_read_cmd(client, - iap ? ETP_I2C_IAP_VERSION_CMD : - ETP_I2C_FW_VERSION_CMD, - val); + if (!iap) + cmd = ETP_I2C_FW_VERSION_CMD; + else if (pattern_ver == 0) + cmd = ETP_I2C_IAP_VERSION_P0_CMD; + else + cmd = ETP_I2C_IAP_VERSION_CMD; + + error = elan_i2c_read_cmd(client, cmd, val); if (error) { dev_err(&client->dev, "failed to get %s version: %d\n", iap ? "IAP" : "FW", error); -- cgit v1.2.3-58-ga151 From 059d6c2de6fd521d4d4a39d127eece3de114b767 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Thu, 16 Jul 2020 21:32:23 -0700 Subject: Input: elan_i2c - add support for different firmware page sizes Prepare driver for devices that use different sizes of firmware pages. Signed-off-by: Jingle Wu Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 4 +++- drivers/input/mouse/elan_i2c_core.c | 24 +++++++++++++++--------- drivers/input/mouse/elan_i2c_i2c.c | 30 +++++++++++++++++++----------- drivers/input/mouse/elan_i2c_smbus.c | 8 ++++---- 4 files changed, 41 insertions(+), 25 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index a9074ac9364f..b504f560a666 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -33,6 +33,8 @@ #define ETP_FW_IAP_PAGE_ERR (1 << 5) #define ETP_FW_IAP_INTF_ERR (1 << 4) #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 struct i2c_client; @@ -73,7 +75,7 @@ struct elan_transport_ops { int (*iap_reset)(struct i2c_client *client); int (*prepare_fw_update)(struct i2c_client *client); - int (*write_fw_block)(struct i2c_client *client, + int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size, const u8 *page, u16 checksum, int idx); int (*finish_fw_update)(struct i2c_client *client, struct completion *reset_done); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index f1dade60f407..46f334bcfc0e 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -89,7 +89,8 @@ struct elan_tp_data { u8 mode; u16 ic_type; u16 fw_validpage_count; - u16 fw_signature_address; + u16 fw_page_size; + u32 fw_signature_address; bool irq_wake; @@ -101,7 +102,7 @@ struct elan_tp_data { }; static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, - u16 *signature_address) + u32 *signature_address, u16 *page_size) { switch (ic_type) { case 0x00: @@ -130,12 +131,15 @@ static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, /* unknown ic type clear value */ *validpage_count = 0; *signature_address = 0; + *page_size = 0; return -ENXIO; } *signature_address = (*validpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; + *page_size = ETP_FW_PAGE_SIZE; + return 0; } @@ -336,7 +340,8 @@ static int elan_query_device_info(struct elan_tp_data *data) return error; error = elan_get_fwinfo(data->ic_type, &data->fw_validpage_count, - &data->fw_signature_address); + &data->fw_signature_address, + &data->fw_page_size); if (error) dev_warn(&data->client->dev, "unexpected iap version %#04x (ic type: %#04x), firmware update will not work\n", @@ -424,14 +429,14 @@ static int elan_query_device_parameters(struct elan_tp_data *data) * IAP firmware updater related routines ********************************************************** */ -static int elan_write_fw_block(struct elan_tp_data *data, +static int elan_write_fw_block(struct elan_tp_data *data, u16 page_size, const u8 *page, u16 checksum, int idx) { int retry = ETP_RETRY_COUNT; int error; do { - error = data->ops->write_fw_block(data->client, + error = data->ops->write_fw_block(data->client, page_size, page, checksum, idx); if (!error) return 0; @@ -460,15 +465,16 @@ static int __elan_update_firmware(struct elan_tp_data *data, iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]); - boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE; + boot_page_count = (iap_start_addr * 2) / data->fw_page_size; for (i = boot_page_count; i < data->fw_validpage_count; i++) { u16 checksum = 0; - const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE]; + const u8 *page = &fw->data[i * data->fw_page_size]; - for (j = 0; j < ETP_FW_PAGE_SIZE; j += 2) + for (j = 0; j < data->fw_page_size; j += 2) checksum += ((page[j + 1] << 8) | page[j]); - error = elan_write_fw_block(data, page, checksum, i); + error = elan_write_fw_block(data, data->fw_page_size, + page, checksum, i); if (error) { dev_err(dev, "write page %d fail: %d\n", i, error); return error; diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 317166a264e6..4dfc3c2b4706 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -592,45 +593,52 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client) 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) { struct device *dev = &client->dev; - u8 page_store[ETP_FW_PAGE_SIZE + 4]; + u8 *page_store; u8 val[3]; u16 result; 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[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 */ - 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)); - if (ret != sizeof(page_store)) { + ret = i2c_master_send(client, page_store, fw_page_size + 4); + if (ret != fw_page_size + 4) { error = ret < 0 ? ret : -EIO; 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. */ - 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); if (error) { dev_err(dev, "Failed to read IAP write result: %d\n", error); - return error; + goto exit; } result = le16_to_cpup((__le16 *)val); if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { dev_err(dev, "IAP reports failed write: %04hx\n", 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, diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index 8c3185d54c73..59eec1a2ed5c 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -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) { struct device *dev = &client->dev; @@ -429,7 +429,7 @@ static int elan_smbus_write_fw_block(struct i2c_client *client, */ error = i2c_smbus_write_block_data(client, ETP_SMBUS_WRITE_FW_BLOCK, - ETP_FW_PAGE_SIZE / 2, + fw_page_size / 2, page); if (error) { 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, error = i2c_smbus_write_block_data(client, ETP_SMBUS_WRITE_FW_BLOCK, - ETP_FW_PAGE_SIZE / 2, - page + ETP_FW_PAGE_SIZE / 2); + fw_page_size / 2, + page + fw_page_size / 2); if (error) { dev_err(dev, "Failed to write page %d (part %d): %d\n", idx, 2, error); -- cgit v1.2.3-58-ga151 From bfd9b92bc8f9a3777961d27a08f62872a21ac507 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Thu, 16 Jul 2020 22:49:09 -0700 Subject: Input: elan_i2c - handle firmware updated on newer ICs Newer ICs with IC type value starting with 0x0D and newer bootloader code use 128-byte firmware pages. Their bootloader also needs to be switched to proper mode before executing firmware update. Signed-off-by: Jingle Wu Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 3 ++- drivers/input/mouse/elan_i2c_core.c | 15 ++++++++---- drivers/input/mouse/elan_i2c_i2c.c | 46 +++++++++++++++++++++++++++++++++++- drivers/input/mouse/elan_i2c_smbus.c | 3 ++- 4 files changed, 60 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index b504f560a666..de10a78f0fc9 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -74,7 +74,8 @@ struct elan_transport_ops { int (*iap_get_mode)(struct i2c_client *client, enum tp_mode *mode); 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, + u8 iap_version); int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size, const u8 *page, u16 checksum, int idx); int (*finish_fw_update)(struct i2c_client *client, diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 46f334bcfc0e..e0f42def99aa 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -101,7 +101,7 @@ struct elan_tp_data { bool middle_button; }; -static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, +static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, u32 *signature_address, u16 *page_size) { switch (ic_type) { @@ -138,7 +138,12 @@ static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, *signature_address = (*validpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; - *page_size = ETP_FW_PAGE_SIZE; + if (ic_type >= 0x0D && iap_version >= 1) { + *validpage_count /= 2; + *page_size = ETP_FW_PAGE_SIZE_128; + } else { + *page_size = ETP_FW_PAGE_SIZE; + } return 0; } @@ -339,7 +344,8 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = elan_get_fwinfo(data->ic_type, &data->fw_validpage_count, + error = elan_get_fwinfo(data->ic_type, data->iap_version, + &data->fw_validpage_count, &data->fw_signature_address, &data->fw_page_size); if (error) @@ -459,7 +465,8 @@ static int __elan_update_firmware(struct elan_tp_data *data, u16 boot_page_count; u16 sw_checksum = 0, fw_checksum = 0; - error = data->ops->prepare_fw_update(client); + error = data->ops->prepare_fw_update(client, data->ic_type, + data->iap_version); if (error) return error; diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 4dfc3c2b4706..4dfac2ea5084 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -56,6 +56,8 @@ #define ETP_I2C_CALIBRATE_CMD 0x0316 #define ETP_I2C_MAX_BASELINE_CMD 0x0317 #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_DESC_LENGTH 30 @@ -528,7 +530,43 @@ static int elan_i2c_set_flash_key(struct i2c_client *client) 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; int error; @@ -568,6 +606,12 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client) return -EIO; } + if (ic_type >= 0x0D && iap_version >= 1) { + error = elan_read_write_iap_type(client); + if (error) + return error; + } + /* Set flash key again */ error = elan_i2c_set_flash_key(client); if (error) diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index 59eec1a2ed5c..97c2c46be5f6 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -340,7 +340,8 @@ static int elan_smbus_set_flash_key(struct i2c_client *client) 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; int len; -- cgit v1.2.3-58-ga151 From 8d73ec7411e084de8266bc3cb031d85a222458be Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Thu, 16 Jul 2020 22:55:57 -0700 Subject: Input: elan_i2c - add firmware update info for ICs 0x11, 0x13, 0x14 This adds firmware size and page sizes for ic types 0x11, 0x13 and 0x14. IC 0x14 uses 512-byte firmware page size. Signed-off-by: Jingle Wu . Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index e0f42def99aa..5c933e16abc1 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -127,6 +127,15 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, case 0x10: *validpage_count = 1024; break; + case 0x11: + *validpage_count = 1280; + break; + case 0x13: + *validpage_count = 2048; + break; + case 0x14: + *validpage_count = 1024; + break; default: /* unknown ic type clear value */ *validpage_count = 0; @@ -138,7 +147,10 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, *signature_address = (*validpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; - if (ic_type >= 0x0D && iap_version >= 1) { + if (ic_type == 0x14 && iap_version >= 2) { + *validpage_count /= 8; + *page_size = ETP_FW_PAGE_SIZE_512; + } else if (ic_type >= 0x0D && iap_version >= 1) { *validpage_count /= 2; *page_size = ETP_FW_PAGE_SIZE_128; } else { -- cgit v1.2.3-58-ga151 From 3d712af637e19a1c139c2b586c08b2a56bdff8c8 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 20 Jul 2020 14:56:54 -0700 Subject: Input: elan_i2c - do not constantly re-query pattern ID We do not need to constantly re-query pattern ID, we can instead query it once and then pass to methods that need it. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 5 +++-- drivers/input/mouse/elan_i2c_core.c | 19 +++++++++++-------- drivers/input/mouse/elan_i2c_i2c.c | 27 ++++++--------------------- drivers/input/mouse/elan_i2c_smbus.c | 7 +++---- 4 files changed, 23 insertions(+), 35 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index de10a78f0fc9..6e6f13a4489c 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -57,8 +57,9 @@ struct elan_transport_ops { int (*get_baseline_data)(struct i2c_client *client, bool max_baseliune, u8 *value); - int (*get_version)(struct i2c_client *client, bool iap, u8 *version); - int (*get_sm_version)(struct i2c_client *client, + int (*get_version)(struct i2c_client *client, u8 pattern, bool iap, + u8 *version); + int (*get_sm_version)(struct i2c_client *client, u8 pattern, u16 *ic_type, u8 *version, u8 *clickpad); int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); int (*get_product_id)(struct i2c_client *client, u16 *id); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 5c933e16abc1..3230aaf63dab 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -236,8 +236,13 @@ static int elan_query_product(struct elan_tp_data *data) if (error) return error; - error = data->ops->get_sm_version(data->client, &data->ic_type, - &data->sm_version, &data->clickpad); + error = data->ops->get_pattern(data->client, &data->pattern); + if (error) + return error; + + error = data->ops->get_sm_version(data->client, data->pattern, + &data->ic_type, &data->sm_version, + &data->clickpad); if (error) return error; @@ -334,7 +339,8 @@ static int elan_query_device_info(struct elan_tp_data *data) { int error; - error = data->ops->get_version(data->client, false, &data->fw_version); + error = data->ops->get_version(data->client, data->pattern, false, + &data->fw_version); if (error) return error; @@ -343,7 +349,8 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = data->ops->get_version(data->client, true, &data->iap_version); + error = data->ops->get_version(data->client, data->pattern, + true, &data->iap_version); if (error) return error; @@ -352,10 +359,6 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = data->ops->get_pattern(data->client, &data->pattern); - if (error) - return error; - error = elan_get_fwinfo(data->ic_type, data->iap_version, &data->fw_validpage_count, &data->fw_signature_address, diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 4dfac2ea5084..b84e3bbe62b5 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -266,22 +266,15 @@ static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern) } static int elan_i2c_get_version(struct i2c_client *client, - bool iap, u8 *version) + u8 pattern, bool iap, u8 *version) { int error; - u8 pattern_ver; u16 cmd; u8 val[3]; - error = elan_i2c_get_pattern(client, &pattern_ver); - if (error) { - dev_err(&client->dev, "failed to get pattern version\n"); - return error; - } - if (!iap) cmd = ETP_I2C_FW_VERSION_CMD; - else if (pattern_ver == 0) + else if (pattern == 0) cmd = ETP_I2C_IAP_VERSION_P0_CMD; else cmd = ETP_I2C_IAP_VERSION_CMD; @@ -293,28 +286,20 @@ static int elan_i2c_get_version(struct i2c_client *client, return error; } - if (pattern_ver >= 0x01) + if (pattern >= 0x01) *version = iap ? val[1] : val[0]; else *version = val[0]; return 0; } -static int elan_i2c_get_sm_version(struct i2c_client *client, - u16 *ic_type, u8 *version, - u8 *clickpad) +static int elan_i2c_get_sm_version(struct i2c_client *client, u8 pattern, + u16 *ic_type, u8 *version, u8 *clickpad) { int error; - u8 pattern_ver; u8 val[3]; - error = elan_i2c_get_pattern(client, &pattern_ver); - if (error) { - dev_err(&client->dev, "failed to get pattern version\n"); - return error; - } - - if (pattern_ver >= 0x01) { + if (pattern >= 0x01) { error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val); if (error) { dev_err(&client->dev, "failed to get ic type: %d\n", diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index 97c2c46be5f6..f7af8b7b345f 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -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, - bool iap, u8 *version) + u8 pattern, bool iap, u8 *version) { int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; @@ -166,9 +166,8 @@ static int elan_smbus_get_version(struct i2c_client *client, return 0; } -static int elan_smbus_get_sm_version(struct i2c_client *client, - u16 *ic_type, u8 *version, - u8 *clickpad) +static int elan_smbus_get_sm_version(struct i2c_client *client, u8 pattern, + u16 *ic_type, u8 *version, u8 *clickpad) { int error; u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; -- cgit v1.2.3-58-ga151 From 04d5ce620f794f1df69b5f1b9ad62910fea547f1 Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Mon, 20 Jul 2020 12:46:10 -0700 Subject: Input: elan_i2c - add support for high resolution reports Newer controllers (identified as "pattern" version 2) send higher resolution reports, with 16-bit X and Y coordinates (previous generations used 12-bit values). These new high resolution reports use report ID of 0x60. SMbus controllers use the same buffer size for both the new and old reports, and because of that high resolution reports no longer carry area of contact data with SMbus. Signed-off-by: Jingle Wu Link: https://lore.kernel.org/r/20200710054116.5529-1-jingle.wu@emc.com.tw Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 8 ++- drivers/input/mouse/elan_i2c_core.c | 126 ++++++++++++++++++++++------------- drivers/input/mouse/elan_i2c_i2c.c | 34 +++++++--- drivers/input/mouse/elan_i2c_smbus.c | 17 ++++- 4 files changed, 126 insertions(+), 59 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index 6e6f13a4489c..c75b00c45d75 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -26,6 +26,8 @@ #define ETP_CALIBRATE_MAX_LEN 3 +#define ETP_FEATURE_REPORT_MK BIT(0) + /* IAP Firmware handling */ #define ETP_PRODUCT_ID_FORMAT_STRING "%d.0" #define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin" @@ -82,7 +84,11 @@ struct elan_transport_ops { int (*finish_fw_update)(struct i2c_client *client, 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 *adjustment); int (*get_pattern)(struct i2c_client *client, u8 *pattern); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 3230aaf63dab..f10635a0b189 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -50,12 +50,14 @@ #define ETP_MAX_FINGERS 5 #define ETP_FINGER_DATA_LEN 5 #define ETP_REPORT_ID 0x5D +#define ETP_REPORT_ID2 0x60 /* High precision report */ #define ETP_TP_REPORT_ID 0x5E #define ETP_REPORT_ID_OFFSET 2 #define ETP_TOUCH_INFO_OFFSET 3 #define ETP_FINGER_DATA_OFFSET 4 #define ETP_HOVER_INFO_OFFSET 30 -#define ETP_MAX_REPORT_LEN 34 +#define ETP_MK_DATA_OFFSET 33 /* For high precision reports */ +#define ETP_MAX_REPORT_LEN 39 /* The main device structure */ struct elan_tp_data { @@ -85,6 +87,8 @@ struct elan_tp_data { u8 sm_version; u8 iap_version; u16 fw_checksum; + unsigned int report_features; + unsigned int report_len; int pressure_adjustment; u8 mode; u16 ic_type; @@ -359,6 +363,12 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; + error = data->ops->get_report_features(data->client, data->pattern, + &data->report_features, + &data->report_len); + if (error) + return error; + error = elan_get_fwinfo(data->ic_type, data->iap_version, &data->fw_validpage_count, &data->fw_signature_address, @@ -371,16 +381,21 @@ static int elan_query_device_info(struct elan_tp_data *data) return 0; } -static unsigned int elan_convert_resolution(u8 val) +static unsigned int elan_convert_resolution(u8 val, u8 pattern) { /* - * (value from firmware) * 10 + 790 = dpi - * + * pattern <= 0x01: + * (value from firmware) * 10 + 790 = dpi + * else + * ((value from firmware) + 3) * 100 = dpi + */ + int res = pattern <= 0x01 ? + (int)(char)val * 10 + 790 : ((int)(char)val + 3) * 100; + /* * We also have to convert dpi to dots/mm (*10/254 to avoid floating * point). */ - - return ((int)(char)val * 10 + 790) * 10 / 254; + return res * 10 / 254; } static int elan_query_device_parameters(struct elan_tp_data *data) @@ -429,8 +444,8 @@ static int elan_query_device_parameters(struct elan_tp_data *data) if (error) return error; - data->x_res = elan_convert_resolution(hw_x_res); - data->y_res = elan_convert_resolution(hw_y_res); + data->x_res = elan_convert_resolution(hw_x_res, data->pattern); + data->y_res = elan_convert_resolution(hw_y_res, data->pattern); } else { data->x_res = (data->max_x + 1) / x_mm; data->y_res = (data->max_y + 1) / y_mm; @@ -908,24 +923,22 @@ static const struct attribute_group *elan_sysfs_groups[] = { * Elan isr functions ****************************************************************** */ -static void elan_report_contact(struct elan_tp_data *data, - int contact_num, bool contact_valid, - u8 *finger_data) +static void elan_report_contact(struct elan_tp_data *data, int contact_num, + bool contact_valid, bool high_precision, + u8 *packet, u8 *finger_data) { struct input_dev *input = data->input; unsigned int pos_x, pos_y; - unsigned int pressure, mk_x, mk_y; - unsigned int area_x, area_y, major, minor; - unsigned int scaled_pressure; + unsigned int pressure, scaled_pressure; if (contact_valid) { - pos_x = ((finger_data[0] & 0xf0) << 4) | - finger_data[1]; - pos_y = ((finger_data[0] & 0x0f) << 8) | - finger_data[2]; - mk_x = (finger_data[3] & 0x0f); - mk_y = (finger_data[3] >> 4); - pressure = finger_data[4]; + if (high_precision) { + pos_x = get_unaligned_be16(&finger_data[0]); + pos_y = get_unaligned_be16(&finger_data[2]); + } else { + pos_x = ((finger_data[0] & 0xf0) << 4) | finger_data[1]; + pos_y = ((finger_data[0] & 0x0f) << 8) | finger_data[2]; + } if (pos_x > data->max_x || pos_y > data->max_y) { dev_dbg(input->dev.parent, @@ -935,18 +948,8 @@ static void elan_report_contact(struct elan_tp_data *data, return; } - /* - * To avoid treating large finger as palm, let's reduce the - * width x and y per trace. - */ - area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE); - area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE); - - major = max(area_x, area_y); - minor = min(area_x, area_y); - + pressure = finger_data[4]; scaled_pressure = pressure + data->pressure_adjustment; - if (scaled_pressure > ETP_MAX_PRESSURE) scaled_pressure = ETP_MAX_PRESSURE; @@ -955,16 +958,37 @@ static void elan_report_contact(struct elan_tp_data *data, input_report_abs(input, ABS_MT_POSITION_X, pos_x); input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure); - input_report_abs(input, ABS_TOOL_WIDTH, mk_x); - input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); - input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); + + if (data->report_features & ETP_FEATURE_REPORT_MK) { + unsigned int mk_x, mk_y, area_x, area_y; + u8 mk_data = high_precision ? + packet[ETP_MK_DATA_OFFSET + contact_num] : + finger_data[3]; + + mk_x = mk_data & 0x0f; + mk_y = mk_data >> 4; + + /* + * To avoid treating large finger as palm, let's reduce + * the width x and y per trace. + */ + area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE); + area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE); + + input_report_abs(input, ABS_TOOL_WIDTH, mk_x); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, + max(area_x, area_y)); + input_report_abs(input, ABS_MT_TOUCH_MINOR, + min(area_x, area_y)); + } } else { input_mt_slot(input, contact_num); input_mt_report_slot_state(input, MT_TOOL_FINGER, false); } } -static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) +static void elan_report_absolute(struct elan_tp_data *data, u8 *packet, + bool high_precision) { struct input_dev *input = data->input; u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET]; @@ -973,11 +997,12 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) u8 hover_info = packet[ETP_HOVER_INFO_OFFSET]; bool contact_valid, hover_event; - hover_event = hover_info & 0x40; - for (i = 0; i < ETP_MAX_FINGERS; i++) { - contact_valid = tp_info & (1U << (3 + i)); - elan_report_contact(data, i, contact_valid, finger_data); + hover_event = hover_info & BIT(6); + for (i = 0; i < ETP_MAX_FINGERS; i++) { + contact_valid = tp_info & BIT(3 + i); + elan_report_contact(data, i, contact_valid, high_precision, + packet, finger_data); if (contact_valid) finger_data += ETP_FINGER_DATA_LEN; } @@ -1034,7 +1059,7 @@ static irqreturn_t elan_isr(int irq, void *dev_id) goto out; } - error = data->ops->get_report(data->client, report); + error = data->ops->get_report(data->client, report, data->report_len); if (error) goto out; @@ -1042,7 +1067,10 @@ static irqreturn_t elan_isr(int irq, void *dev_id) switch (report[ETP_REPORT_ID_OFFSET]) { case ETP_REPORT_ID: - elan_report_absolute(data, report); + elan_report_absolute(data, report, false); + break; + case ETP_REPORT_ID2: + elan_report_absolute(data, report, true); break; case ETP_TP_REPORT_ID: elan_report_trackpoint(data, report); @@ -1133,7 +1161,9 @@ static int elan_setup_input_device(struct elan_tp_data *data) input_abs_set_res(input, ABS_X, data->x_res); input_abs_set_res(input, ABS_Y, data->y_res); input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); - input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0); + if (data->report_features & ETP_FEATURE_REPORT_MK) + input_set_abs_params(input, ABS_TOOL_WIDTH, + 0, ETP_FINGER_WIDTH, 0, 0); input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0); /* And MT parameters */ @@ -1143,10 +1173,12 @@ static int elan_setup_input_device(struct elan_tp_data *data) input_abs_set_res(input, ABS_MT_POSITION_Y, data->y_res); input_set_abs_params(input, ABS_MT_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, - ETP_FINGER_WIDTH * max_width, 0, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, - ETP_FINGER_WIDTH * min_width, 0, 0); + if (data->report_features & ETP_FEATURE_REPORT_MK) { + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, + 0, ETP_FINGER_WIDTH * max_width, 0, 0); + input_set_abs_params(input, ABS_MT_TOUCH_MINOR, + 0, ETP_FINGER_WIDTH * min_width, 0, 0); + } data->input = input; diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index b84e3bbe62b5..5a496d4ffa49 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -60,6 +60,8 @@ #define ETP_I2C_IAP_TYPE_CMD 0x0304 #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_REPORT_DESC_LENGTH 158 #define ETP_I2C_INF_LENGTH 2 @@ -394,7 +396,7 @@ static int elan_i2c_get_max(struct i2c_client *client, 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); if (error) { @@ -402,7 +404,7 @@ static int elan_i2c_get_max(struct i2c_client *client, return error; } - *max_y = le16_to_cpup((__le16 *)val) & 0x0fff; + *max_y = le16_to_cpup((__le16 *)val); return 0; } @@ -674,12 +676,12 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client, struct completion *completion) { struct device *dev = &client->dev; - int error; + int error = 0; 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); - if (len != ETP_I2C_REPORT_LEN) { + len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_MAX_LEN); + if (len <= 0) { error = len < 0 ? len : -EIO; dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n", error, len); @@ -713,20 +715,31 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client, 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; - len = i2c_master_recv(client, report, ETP_I2C_REPORT_LEN); + len = i2c_master_recv(client, report, report_len); if (len < 0) { dev_err(&client->dev, "failed to read report data: %d\n", len); return len; } - if (len != ETP_I2C_REPORT_LEN) { + if (len != report_len) { dev_err(&client->dev, "wrong report length (%d vs %d expected)\n", - len, ETP_I2C_REPORT_LEN); + len, report_len); return -EIO; } @@ -763,5 +776,6 @@ const struct elan_transport_ops elan_i2c_ops = { .get_pattern = elan_i2c_get_pattern, + .get_report_features = elan_i2c_get_report_features, .get_report = elan_i2c_get_report, }; diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index f7af8b7b345f..8ff823751f3b 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -469,7 +469,21 @@ static int elan_smbus_write_fw_block(struct i2c_client *client, u16 fw_page_size 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; @@ -534,6 +548,7 @@ const struct elan_transport_ops elan_smbus_ops = { .write_fw_block = elan_smbus_write_fw_block, .finish_fw_update = elan_smbus_finish_fw_update, + .get_report_features = elan_smbus_get_report_features, .get_report = elan_smbus_get_report, .get_pattern = elan_smbus_get_pattern, }; -- cgit v1.2.3-58-ga151 From 4aec14de3a15cf9789a0e19c847f164776f49473 Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang Date: Tue, 21 Jul 2020 22:24:07 -0700 Subject: Input: psmouse - add a newline when printing 'proto' by sysfs When I cat parameter 'proto' by sysfs, it displays as follows. It's better to add a newline for easy reading. root@syzkaller:~# cat /sys/module/psmouse/parameters/proto autoroot@syzkaller:~# Signed-off-by: Xiongfeng Wang Link: https://lore.kernel.org/r/20200720073846.120724-1-wangxiongfeng2@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 527ae0b9a191..0b4a3039f312 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -2042,7 +2042,7 @@ static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) { 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) -- cgit v1.2.3-58-ga151 From 37bd9e803daea816f2dc2c8f6dc264097eb3ebd2 Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang Date: Tue, 21 Jul 2020 22:24:24 -0700 Subject: Input: ati_remote2 - add missing newlines when printing module parameters When I cat some module parameters by sysfs, it displays as follows. It's better to add a newline for easy reading. root@syzkaller:~# cat /sys/module/ati_remote2/parameters/mode_mask 0x1froot@syzkaller:~# cat /sys/module/ati_remote2/parameters/channel_mask 0xffffroot@syzkaller:~# Signed-off-by: Xiongfeng Wang Link: https://lore.kernel.org/r/20200720092148.9320-1-wangxiongfeng2@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ati_remote2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 305f0160506a..8a36d78fed63 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -68,7 +68,7 @@ static int ati_remote2_get_channel_mask(char *buffer, { 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, @@ -84,7 +84,7 @@ static int ati_remote2_get_mode_mask(char *buffer, { 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; -- cgit v1.2.3-58-ga151 From 74d905d2d38ad00246e1f22c6ccad7ebb5731839 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Tue, 28 Jul 2020 18:25:29 -0700 Subject: Input: atmel_mxt_ts - only read messages in mxt_acquire_irq() when necessary The workaround of reading all messages until an invalid is received is a way of forcing the CHG line high, which means that when using edge-triggered interrupts the interrupt can be acquired. With level-triggered interrupts the workaround is unnecessary. Also, most recent maXTouch chips have a feature called RETRIGEN which, when enabled, reasserts the interrupt line every cycle if there are messages waiting. This also makes the workaround unnecessary. Note: the RETRIGEN feature is only in some firmware versions/chips, it's not valid simply to enable the bit. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen (cherry picked from ndyer/linux/for-upstream commit 1ae4e8281e491b22442cd5acdfca1862555f8ecb) [gdavis: Fix conflicts due to v4.6-rc7 commit eb43335c4095 ("Input: atmel_mxt_ts - use mxt_acquire_irq in mxt_soft_reset").] Signed-off-by: George G. Davis [jiada: reset use_retrigen_workaround at beginning of mxt_check_retrigen() call mxt_check_retrigen() after mxt_acquire_irq() in mxt_initialize() replace white-spaces with tab for MXT_COMMS_RETRIGEN Changed to check if IRQ is level type] Signed-off-by: Jiada Wang Link: https://lore.kernel.org/r/20200727151637.23810-1-jiada_wang@mentor.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 56 ++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index a2189739e30f..6b71b0aff115 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,7 @@ struct t9_range { /* MXT_SPT_COMMSCONFIG_T18 */ #define MXT_COMMS_CTRL 0 #define MXT_COMMS_CMD 1 +#define MXT_COMMS_RETRIGEN BIT(6) /* MXT_DEBUG_DIAGNOSTIC_T37 */ #define MXT_DIAGNOSTIC_PAGEUP 0x01 @@ -308,6 +310,7 @@ struct mxt_data { struct t7_config t7_cfg; struct mxt_dbg dbg; struct gpio_desc *reset_gpio; + bool use_retrigen_workaround; /* Cached parameters from object table */ u16 T5_address; @@ -318,6 +321,7 @@ struct mxt_data { u16 T71_address; u8 T9_reportid_min; u8 T9_reportid_max; + u16 T18_address; u8 T19_reportid; u16 T44_address; u8 T100_reportid_min; @@ -1190,9 +1194,11 @@ static int mxt_acquire_irq(struct mxt_data *data) enable_irq(data->irq); - error = mxt_process_messages_until_invalid(data); - if (error) - return error; + if (data->use_retrigen_workaround) { + error = mxt_process_messages_until_invalid(data); + if (error) + return error; + } return 0; } @@ -1282,6 +1288,38 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off) 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) { struct device *dev = &data->client->dev; @@ -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); + ret = mxt_check_retrigen(data); + if (ret) + goto release_mem; + ret = mxt_soft_reset(data); if (ret) goto release_mem; @@ -1604,6 +1646,7 @@ static void mxt_free_object_table(struct mxt_data *data) data->T71_address = 0; data->T9_reportid_min = 0; data->T9_reportid_max = 0; + data->T18_address = 0; data->T19_reportid = 0; data->T44_address = 0; data->T100_reportid_min = 0; @@ -1678,6 +1721,9 @@ static int mxt_parse_object_table(struct mxt_data *data, object->num_report_ids - 1; data->num_touchids = object->num_report_ids; break; + case MXT_SPT_COMMSCONFIG_T18: + data->T18_address = object->start_address; + break; case MXT_SPT_MESSAGECOUNT_T44: data->T44_address = object->start_address; break; @@ -2141,6 +2187,10 @@ static int mxt_initialize(struct mxt_data *data) if (error) return error; + error = mxt_check_retrigen(data); + if (error) + return error; + error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, &client->dev, GFP_KERNEL, data, mxt_config_cb); -- cgit v1.2.3-58-ga151 From 873a3a14a47e819bb2d1e3cf4dc8c59c200ec32b Mon Sep 17 00:00:00 2001 From: Jingle Wu Date: Wed, 29 Jul 2020 23:31:33 -0700 Subject: Input: elan_i2c - add ic type 0x15 The update firmware flow of ic type 0x15 is same with ic type 0x14. Signed-off-by: Jingle Wu Link: https://lore.kernel.org/r/20200730060526.12439-1-jingle.wu@emc.com.tw Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 8a0f224da423..c599e21a8478 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -138,6 +138,7 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, *validpage_count = 2048; break; case 0x14: + case 0x15: *validpage_count = 1024; break; default: @@ -151,7 +152,7 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, *signature_address = (*validpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; - if (ic_type == 0x14 && iap_version >= 2) { + if ((ic_type == 0x14 || ic_type == 0x15) && iap_version >= 2) { *validpage_count /= 8; *page_size = ETP_FW_PAGE_SIZE_512; } else if (ic_type >= 0x0D && iap_version >= 1) { -- cgit v1.2.3-58-ga151 From d431b9e6af1903e112f5f773a0137be4fe5b17e8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 6 Aug 2020 15:34:07 -0700 Subject: Input: ims-pcu - return error code rather than -ENOMEM Currently the assignment of -ENOMEM to error is redundant because error is not being read and -ENOMEM is being hard coded as an error return. Fix this by returning the error code in variable 'error'; this also allows the error code from a failed call to input_register_device to be preserved and returned to the caller rather than just returning a possibly inappropriate -ENOMEM. Kudos to Dan Carpenter for the suggestion of an improved fix. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20200603152151.139337-1-colin.king@canonical.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ims-pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index d8dbfc030d0f..08b9b5cdb943 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -335,7 +335,7 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu) err_free_mem: input_free_device(input); kfree(gamepad); - return -ENOMEM; + return error; } static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) -- cgit v1.2.3-58-ga151 From 47fcd0f969e98c4a82a12efb956c6f8d39aa918a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 6 Aug 2020 15:35:17 -0700 Subject: Input: alps - remove redundant assignment to variable ret The variable ret is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200603135742.130852-1-colin.king@canonical.com Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 34700eda0429..b067bfd2699c 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -1929,7 +1929,7 @@ static int alps_monitor_mode(struct psmouse *psmouse, bool enable) static int alps_absolute_mode_v6(struct psmouse *psmouse) { u16 reg_val = 0x181; - int ret = -1; + int ret; /* enter monitor mode, to write the register */ if (alps_monitor_mode(psmouse, true)) -- cgit v1.2.3-58-ga151 From ea38f06e0291986eb93beb6d61fd413607a30ca4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 6 Aug 2020 15:35:34 -0700 Subject: Input: sentelic - fix error return when fsp_reg_write fails Currently when the call to fsp_reg_write fails -EIO is not being returned because the count is being returned instead of the return value in retval. Fix this by returning the value in retval instead of count. Addresses-Coverity: ("Unused value") Fixes: fc69f4a6af49 ("Input: add new driver for Sentelic Finger Sensing Pad") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200603141218.131663-1-colin.king@canonical.com Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/sentelic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 9f7ecc72093a..2716d2ba386a 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -441,7 +441,7 @@ static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, fsp_reg_write_enable(psmouse, false); - return count; + return retval; } PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); -- cgit v1.2.3-58-ga151 From 3bdd21c6937a07f2877409bcdafc0ae2265fc981 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 6 Aug 2020 16:00:43 -0700 Subject: Input: exc3000 - add EXC80H60 and EXC80H84 support This adds support for EXC80H60 and EXCH84 controllers, which use a different event type id and have two extra bits for the resolution (so the maximum is 16K instead of 4K). Signed-off-by: Sebastian Reichel Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200805160520.456570-3-sebastian.reichel@collabora.com Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/eeti,exc3000.yaml | 5 +- drivers/input/touchscreen/exc3000.c | 80 ++++++++++++++++++---- 2 files changed, 70 insertions(+), 15 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml index 022aa69a5dfe..7e6e23f8fa00 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml @@ -14,7 +14,10 @@ allOf: properties: compatible: - const: eeti,exc3000 + enum: + - eeti,exc3000 + - eeti,exc80h60 + - eeti,exc80h84 reg: const: 0x2a interrupts: diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index 555a14305cd4..b497bd2ae41d 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,11 +24,43 @@ #define EXC3000_SLOTS_PER_FRAME 5 #define EXC3000_LEN_FRAME 66 #define EXC3000_LEN_POINT 10 -#define EXC3000_MT_EVENT 6 + +#define EXC3000_MT1_EVENT 0x06 +#define EXC3000_MT2_EVENT 0x18 + #define EXC3000_TIMEOUT_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 i2c_client *client; + const struct eeti_dev_info *info; struct input_dev *input; struct touchscreen_properties prop; struct timer_list timer; @@ -58,10 +91,15 @@ static void exc3000_timer(struct timer_list *t) 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; + if (data->info->max_xy == SZ_16K - 1) + expected_event = EXC3000_MT2_EVENT; + ret = i2c_master_send(client, "'", 2); if (ret < 0) return ret; @@ -76,19 +114,21 @@ static int exc3000_read_frame(struct i2c_client *client, u8 *buf) if (ret != EXC3000_LEN_FRAME) return -EIO; - if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME || - buf[2] != EXC3000_MT_EVENT) + if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME) + return -EINVAL; + + if (buf[2] != expected_event) return -EINVAL; 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) { int error; - error = exc3000_read_frame(client, buf); + error = exc3000_read_frame(data, buf); if (error) return error; @@ -98,7 +138,7 @@ static int exc3000_read_data(struct i2c_client *client, if (*n_slots > EXC3000_SLOTS_PER_FRAME) { /* 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) return error; @@ -118,7 +158,7 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id) int slots, total_slots; int error; - error = exc3000_read_data(data->client, buf, &total_slots); + error = exc3000_read_data(data, buf, &total_slots); if (error) { /* Schedule a timer to release "stuck" contacts */ mod_timer(&data->timer, @@ -149,13 +189,19 @@ static int exc3000_probe(struct i2c_client *client) { struct exc3000_data *data; struct input_dev *input; - int error; + int error, max_xy; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; 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); input = devm_input_allocate_device(&client->dev); @@ -164,11 +210,13 @@ static int exc3000_probe(struct i2c_client *client) data->input = input; - input->name = "EETI EXC3000 Touch Screen"; + input->name = data->info->name; input->id.bustype = BUS_I2C; - input_set_abs_params(input, ABS_MT_POSITION_X, 0, 4095, 0, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 4095, 0, 0); + max_xy = data->info->max_xy; + 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); error = input_mt_init_slots(input, EXC3000_NUM_SLOTS, @@ -190,14 +238,18 @@ static int exc3000_probe(struct i2c_client *client) } 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); #ifdef CONFIG_OF 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); -- cgit v1.2.3-58-ga151 From 27aced19e098ba00e87a09d6ba6d4518e89319c3 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 6 Aug 2020 16:06:36 -0700 Subject: Input: exc3000 - add reset gpio support Add basic support for an optional reset gpio. Reviewed-by: Enric Balletbo i Serra Signed-off-by: Sebastian Reichel Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200805160520.456570-4-sebastian.reichel@collabora.com Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/eeti,exc3000.yaml | 2 ++ drivers/input/touchscreen/exc3000.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml index 7e6e23f8fa00..007adbc89c14 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml @@ -22,6 +22,8 @@ properties: const: 0x2a interrupts: maxItems: 1 + reset-gpios: + maxItems: 1 touchscreen-size-x: true touchscreen-size-y: true touchscreen-inverted-x: true diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index b497bd2ae41d..203f50acaab7 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -8,7 +8,9 @@ */ #include +#include #include +#include #include #include #include @@ -30,6 +32,9 @@ #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 { @@ -63,6 +68,7 @@ struct exc3000_data { const struct eeti_dev_info *info; struct input_dev *input; struct touchscreen_properties prop; + struct gpio_desc *reset; struct timer_list timer; u8 buf[2 * EXC3000_LEN_FRAME]; }; @@ -204,6 +210,17 @@ static int exc3000_probe(struct i2c_client *client) } timer_setup(&data->timer, exc3000_timer, 0); + 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); if (!input) return -ENOMEM; -- cgit v1.2.3-58-ga151 From d862a3068ea593dc904ef524d8548467755ce36f Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 6 Aug 2020 16:08:00 -0700 Subject: Input: exc3000 - add support to query model and fw_version Expose model and fw_version via sysfs. Also query the model in probe to make sure, that the I2C communication with the device works before successfully probing the driver. This is a bit complicated, since EETI devices do not have a sync interface. Sending the commands and directly reading does not work. Sending the command and waiting for some time is also not an option, since there might be touch events in the mean time. Last but not least we do not cache the results, since this interface can be used to check the I2C communication is still working as expected. Reviewed-by: Enric Balletbo i Serra Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20200805160520.456570-5-sebastian.reichel@collabora.com Signed-off-by: Dmitry Torokhov --- .../ABI/testing/sysfs-driver-input-exc3000 | 15 +++ drivers/input/touchscreen/exc3000.c | 148 ++++++++++++++++++++- 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-driver-input-exc3000 (limited to 'drivers/input') diff --git a/Documentation/ABI/testing/sysfs-driver-input-exc3000 b/Documentation/ABI/testing/sysfs-driver-input-exc3000 new file mode 100644 index 000000000000..3d316d54f81c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-input-exc3000 @@ -0,0 +1,15 @@ +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 diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index 203f50acaab7..a6597f026980 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -27,6 +27,9 @@ #define EXC3000_LEN_FRAME 66 #define EXC3000_LEN_POINT 10 +#define EXC3000_LEN_MODEL_NAME 16 +#define EXC3000_LEN_FW_VERSION 16 + #define EXC3000_MT1_EVENT 0x06 #define EXC3000_MT2_EVENT 0x18 @@ -71,6 +74,11 @@ struct exc3000_data { struct gpio_desc *reset; struct timer_list timer; 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, @@ -156,6 +164,28 @@ static int exc3000_read_data(struct exc3000_data *data, 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) { struct exc3000_data *data = dev_id; @@ -164,6 +194,12 @@ static irqreturn_t exc3000_interrupt(int irq, void *dev_id) int slots, total_slots; int error; + 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) { /* Schedule a timer to release "stuck" contacts */ @@ -191,11 +227,91 @@ out: return IRQ_HANDLED; } +static ssize_t fw_version_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); + 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 input_dev *input; - int error, max_xy; + int error, max_xy, retry; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -209,6 +325,8 @@ static int exc3000_probe(struct i2c_client *client) data->info = &exc3000_info[eeti_dev_id]; } 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); @@ -226,6 +344,7 @@ static int exc3000_probe(struct i2c_client *client) return -ENOMEM; data->input = input; + input_set_drvdata(input, data); input->name = data->info->name; input->id.bustype = BUS_I2C; @@ -251,6 +370,33 @@ static int exc3000_probe(struct i2c_client *client) if (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; } -- cgit v1.2.3-58-ga151