From nobody Sun Dec 14 05:55:31 2025 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B5B6A2868B2 for ; Fri, 12 Dec 2025 08:50:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765529455; cv=none; b=JgV88GAX2qO3i1mDucwV4xJPFudxCgbv4xW1U1e18RNqOgoutdcQCODKixp6U5Tr1VYK/TnIEb/syNydD0Slj8jC2EZv/JWN9U+X/KhvNhZpqu+uTxwcltmko/fXSot1yUX3CyWd+3syeJia2Qvj3/CuRAwmUSal4lt75E53gXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765529455; c=relaxed/simple; bh=det+0eMhx7bM0HqhE0i9jIuS0s1Wp28tOlG7acJ6zZ4=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=IwVzKXDoh9XBsgAH/kERjkqtiMOlCsru7NLsEj/dtLkoH31huDzGxDlXPsH4ceqp35tdl8Rpeu6hTmxmDkjElcPT8kRrsCQyBMoZIAOupGbotW1LNO+NN52co7RYipyXa5f9foB5dBUoS7ee201l3BadZFO8VReyc3hqKyB6+3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UaDdcycI; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UaDdcycI" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-3436cbb723fso803622a91.2 for ; Fri, 12 Dec 2025 00:50:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1765529453; x=1766134253; darn=vger.kernel.org; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=0QQCt8EpxSPEQ/uGwwQJL57+NDYgoWNX4u6W6WYEP8o=; b=UaDdcycI9ly45TjWG9jknkOkq3YhtEQNdbNUXP/WLdqWm5D70jnopQJVz6LcMXvRo9 okElLQGbe4Bm3GPRhaFrBUQxD7qqZwKfIfO8Xsa+8FPoMcLSLIqw4pICqcOVoWY+d/8l GblpKMi6U4ScPJPgaDzv9Mzh5e1m9LvIjUwZQlad6YHqwu7xs6+bGlSNHJIWsCaGwizY Xvl7lja/Szneor+3d3T+Q8lxTBFvBLPmMkWqM333EXp2gOMYi/s8GAhfLiGBpC0n67a0 AVLvOj/lgaBRK0zXBs0lXH13OBUYQPy9Rw7XpooWqRHnIbQz4AGVdK/SxPAPElf4kFbM nw5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765529453; x=1766134253; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=0QQCt8EpxSPEQ/uGwwQJL57+NDYgoWNX4u6W6WYEP8o=; b=vetc1NXd46Fx8oQSQaH6LpNHaic5r1kkouy4bLjD4BzijgTnZ5bDneljNlorzePyYi 9AwTUdCorNJyxlcmXz4vO+LrKqVyfHag7YRrZ1v1mZllRuq5XnD2xYy8QCnFy1Hqryze Cz5/e/o1MbVJLj43o9s2VUQzCzHGrBKEnrTAOh07q40GpOcGqLlxf6r1yFRYXlGFHSBO l6LCjRYHMZY2Jl2snig+UjfgAZ/IdtdeipvYA6np01/UNrwPFuPtPq8xWuGv7Z5K/d58 EFO8KeWg+dKp/4zRJwrx4MYuCzXBTe2wZH9gjXn+2IRsXv3uWsRd/tdkSjChTOMLj+qm ot2A== X-Gm-Message-State: AOJu0YwYnEze4GH2MLpsqZ0OWAfxNhw+4y+3SG88eH6y/A2nnzuCTYNt xxUbEExGsD1Buhn5cgFgE/PY72yxTcbtO32g7CbRefRxB6o11Rng1sZDA414yZcc X-Gm-Gg: AY/fxX5KzExRMfW4NB/0fstD/utyIjCDG0UiaZAozI+tH/Ay0bM7S3YEKMgXlUzCD8A 8vuQvYrcQ86RpNlILgAzNg5Zn99VAgWoHQBK/rmPgLXF9evFI1zOJGjZwK7PHd5k9/Zl5ToNZRG EJGfLNk3YTu3h8yWekney/9wBAF/NXPeJyDNF0CtSlebYUc/F9Nced4jigURbPKl3fGHl3q2z+i lzGxBheITrHNhTXo+P2AO1qzXwJLDXIOGsaScU+T650hdaTerKsDraIO7/UbGMsriy/17eXSkS/ O6mlpomMVamMG9gERXjvTcwAnxYnfpVC7PtERPKoIh/QOLYfB//ZnT0yYiAGI415QdoOVTjW+81 6L8k83sTjMFt8QvOhDewbyOHhCgVZ2oDbilrGWaJ4YZOn97yXN1MXw2UplyinmScO11PHt19WOX MOpnMhjN7dvk6COCqlcstXPlLhqk6aAgmZtjp5DbcY1iCMV1biflbU0kIcgg0BBQ== X-Google-Smtp-Source: AGHT+IFt4f6Ms3ZI6m/5cqoXvEyWA94yoYqqrEY7a5oUzIKSBjmkf6nVztc2PJBqfr/GKJEM2Ih2fg== X-Received: by 2002:a05:701a:ca0a:b0:11f:1e59:4c28 with SMTP id a92af1059eb24-11f34c4ec23mr803478c88.29.1765529452500; Fri, 12 Dec 2025 00:50:52 -0800 (PST) Received: from google.com ([2a00:79e0:2ebe:8:fafd:f9bf:2a4:2a0b]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-11f2e2ff110sm16415603c88.10.2025.12.12.00.50.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Dec 2025 00:50:52 -0800 (PST) Date: Fri, 12 Dec 2025 00:50:49 -0800 From: Dmitry Torokhov To: linux-kernel@vger.kernel.org Cc: Mike Rapoport , Minseong Kim , linux-input@vger.kernel.org Subject: [PATCH] Input: synaptics_i2c - remove the driver Message-ID: <7fjjlb5wmwberkwljagmmbetvcvcijoduu2cqpilressbrnn4y@4574molvgnqu> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The board support for the device using this Synaptics controller (eXeda mobile device) has been removed long time ago, it is time to remove the driver as well. Signed-off-by: Dmitry Torokhov Acked-by: Mike Rapoport (Microsoft) --- drivers/input/mouse/Kconfig | 18 - drivers/input/mouse/Makefile | 1 - drivers/input/mouse/synaptics_i2c.c | 664 ---------------------------- 3 files changed, 683 deletions(-) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 833b643f0616..3638a5ebb51f 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -404,24 +404,6 @@ config MOUSE_MAPLE To compile this driver as a module choose M here: the module will be called maplemouse. =20 -config MOUSE_SYNAPTICS_I2C - tristate "Synaptics I2C Touchpad support" - depends on I2C - help - This driver supports Synaptics I2C touchpad controller on eXeda - mobile device. - The device will not work the synaptics X11 driver because - (i) it reports only relative coordinates and has no capabilities - to report absolute coordinates - (ii) the eXeda device itself uses Xfbdev as X Server and it does - not allow using xf86-input-* drivers. - - Say y here if you have eXeda device and want to use a Synaptics - I2C Touchpad. - - To compile this driver as a module, choose M here: the - module will be called synaptics_i2c. - config MOUSE_SYNAPTICS_USB tristate "Synaptics USB device support" depends on USB_ARCH_HAS_HCD diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index a1336d5bee6f..4d6251fbe38b 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_MOUSE_PC110PAD) +=3D pc110pad.o obj-$(CONFIG_MOUSE_PS2) +=3D psmouse.o obj-$(CONFIG_MOUSE_RISCPC) +=3D rpcmouse.o obj-$(CONFIG_MOUSE_SERIAL) +=3D sermouse.o -obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) +=3D synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) +=3D synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA) +=3D vsxxxaa.o =20 diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/syna= ptics_i2c.c deleted file mode 100644 index a0d707e47d93..000000000000 --- a/drivers/input/mouse/synaptics_i2c.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Synaptics touchpad with I2C interface - * - * Copyright (C) 2009 Compulab, Ltd. - * Mike Rapoport - * Igor Grinberg - * - * This file is subject to the terms and conditions of the GNU General Pub= lic - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "synaptics_i2c" -/* maximum product id is 15 characters */ -#define PRODUCT_ID_LENGTH 15 -#define REGISTER_LENGTH 8 - -/* - * after soft reset, we should wait for 1 ms - * before the device becomes operational - */ -#define SOFT_RESET_DELAY_US 3000 -/* and after hard reset, we should wait for max 500ms */ -#define HARD_RESET_DELAY_MS 500 - -/* Registers by SMBus address */ -#define PAGE_SEL_REG 0xff -#define DEVICE_STATUS_REG 0x09 - -/* Registers by RMI address */ -#define DEV_CONTROL_REG 0x0000 -#define INTERRUPT_EN_REG 0x0001 -#define ERR_STAT_REG 0x0002 -#define INT_REQ_STAT_REG 0x0003 -#define DEV_COMMAND_REG 0x0004 - -#define RMI_PROT_VER_REG 0x0200 -#define MANUFACT_ID_REG 0x0201 -#define PHYS_INT_VER_REG 0x0202 -#define PROD_PROPERTY_REG 0x0203 -#define INFO_QUERY_REG0 0x0204 -#define INFO_QUERY_REG1 (INFO_QUERY_REG0 + 1) -#define INFO_QUERY_REG2 (INFO_QUERY_REG0 + 2) -#define INFO_QUERY_REG3 (INFO_QUERY_REG0 + 3) - -#define PRODUCT_ID_REG0 0x0210 -#define PRODUCT_ID_REG1 (PRODUCT_ID_REG0 + 1) -#define PRODUCT_ID_REG2 (PRODUCT_ID_REG0 + 2) -#define PRODUCT_ID_REG3 (PRODUCT_ID_REG0 + 3) -#define PRODUCT_ID_REG4 (PRODUCT_ID_REG0 + 4) -#define PRODUCT_ID_REG5 (PRODUCT_ID_REG0 + 5) -#define PRODUCT_ID_REG6 (PRODUCT_ID_REG0 + 6) -#define PRODUCT_ID_REG7 (PRODUCT_ID_REG0 + 7) -#define PRODUCT_ID_REG8 (PRODUCT_ID_REG0 + 8) -#define PRODUCT_ID_REG9 (PRODUCT_ID_REG0 + 9) -#define PRODUCT_ID_REG10 (PRODUCT_ID_REG0 + 10) -#define PRODUCT_ID_REG11 (PRODUCT_ID_REG0 + 11) -#define PRODUCT_ID_REG12 (PRODUCT_ID_REG0 + 12) -#define PRODUCT_ID_REG13 (PRODUCT_ID_REG0 + 13) -#define PRODUCT_ID_REG14 (PRODUCT_ID_REG0 + 14) -#define PRODUCT_ID_REG15 (PRODUCT_ID_REG0 + 15) - -#define DATA_REG0 0x0400 -#define ABS_PRESSURE_REG 0x0401 -#define ABS_MSB_X_REG 0x0402 -#define ABS_LSB_X_REG (ABS_MSB_X_REG + 1) -#define ABS_MSB_Y_REG 0x0404 -#define ABS_LSB_Y_REG (ABS_MSB_Y_REG + 1) -#define REL_X_REG 0x0406 -#define REL_Y_REG 0x0407 - -#define DEV_QUERY_REG0 0x1000 -#define DEV_QUERY_REG1 (DEV_QUERY_REG0 + 1) -#define DEV_QUERY_REG2 (DEV_QUERY_REG0 + 2) -#define DEV_QUERY_REG3 (DEV_QUERY_REG0 + 3) -#define DEV_QUERY_REG4 (DEV_QUERY_REG0 + 4) -#define DEV_QUERY_REG5 (DEV_QUERY_REG0 + 5) -#define DEV_QUERY_REG6 (DEV_QUERY_REG0 + 6) -#define DEV_QUERY_REG7 (DEV_QUERY_REG0 + 7) -#define DEV_QUERY_REG8 (DEV_QUERY_REG0 + 8) - -#define GENERAL_2D_CONTROL_REG 0x1041 -#define SENSOR_SENSITIVITY_REG 0x1044 -#define SENS_MAX_POS_MSB_REG 0x1046 -#define SENS_MAX_POS_LSB_REG (SENS_MAX_POS_UPPER_REG + 1) - -/* Register bits */ -/* Device Control Register Bits */ -#define REPORT_RATE_1ST_BIT 6 - -/* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */ -#define F10_ABS_INT_ENA 0 -#define F10_REL_INT_ENA 1 -#define F20_INT_ENA 2 - -/* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) = */ -#define F10_ABS_INT_REQ 0 -#define F10_REL_INT_REQ 1 -#define F20_INT_REQ 2 -/* Device Status Register Bits (DEVICE_STATUS_REG) */ -#define STAT_CONFIGURED 6 -#define STAT_ERROR 7 - -/* Device Command Register Bits (DEV_COMMAND_REG) */ -#define RESET_COMMAND 0x01 -#define REZERO_COMMAND 0x02 - -/* Data Register 0 Bits (DATA_REG0) */ -#define GESTURE 3 - -/* Device Query Registers Bits */ -/* DEV_QUERY_REG3 */ -#define HAS_PALM_DETECT 1 -#define HAS_MULTI_FING 2 -#define HAS_SCROLLER 4 -#define HAS_2D_SCROLL 5 - -/* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */ -#define NO_DECELERATION 1 -#define REDUCE_REPORTING 3 -#define NO_FILTER 5 - -/* Function Masks */ -/* Device Control Register Masks (DEV_CONTROL_REG) */ -#define REPORT_RATE_MSK 0xc0 -#define SLEEP_MODE_MSK 0x07 - -/* Device Sleep Modes */ -#define FULL_AWAKE 0x0 -#define NORMAL_OP 0x1 -#define LOW_PWR_OP 0x2 -#define VERY_LOW_PWR_OP 0x3 -#define SENS_SLEEP 0x4 -#define SLEEP_MOD 0x5 -#define DEEP_SLEEP 0x6 -#define HIBERNATE 0x7 - -/* Interrupt Register Mask */ -/* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */ -#define INT_ENA_REQ_MSK 0x07 -#define INT_ENA_ABS_MSK 0x01 -#define INT_ENA_REL_MSK 0x02 -#define INT_ENA_F20_MSK 0x04 - -/* Device Status Register Masks (DEVICE_STATUS_REG) */ -#define CONFIGURED_MSK 0x40 -#define ERROR_MSK 0x80 - -/* Data Register 0 Masks */ -#define FINGER_WIDTH_MSK 0xf0 -#define GESTURE_MSK 0x08 -#define SENSOR_STATUS_MSK 0x07 - -/* - * MSB Position Register Masks - * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG | - * DEV_QUERY_REG3 | DEV_QUERY_REG5 - */ -#define MSB_POSITION_MSK 0x1f - -/* Device Query Registers Masks */ - -/* DEV_QUERY_REG2 */ -#define NUM_EXTRA_POS_MSK 0x07 - -/* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ -#define THREAD_IRQ_SLEEP_SECS 2 -#define THREAD_IRQ_SLEEP_MSECS (THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) - -/* - * When in Polling mode and no data received for NO_DATA_THRES msecs - * reduce the polling rate to NO_DATA_SLEEP_MSECS - */ -#define NO_DATA_THRES (MSEC_PER_SEC) -#define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) - -/* Control touchpad's No Deceleration option */ -static bool no_decel =3D true; -module_param(no_decel, bool, 0644); -MODULE_PARM_DESC(no_decel, "No Deceleration. Default =3D 1 (on)"); - -/* Control touchpad's Reduced Reporting option */ -static bool reduce_report; -module_param(reduce_report, bool, 0644); -MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default =3D 0 (off)"); - -/* Control touchpad's No Filter option */ -static bool no_filter; -module_param(no_filter, bool, 0644); -MODULE_PARM_DESC(no_filter, "No Filter. Default =3D 0 (off)"); - -/* - * touchpad Attention line is Active Low and Open Drain, - * therefore should be connected to pulled up line - * and the irq configuration should be set to Falling Edge Trigger - */ -/* Control IRQ / Polling option */ -static bool polling_req; -module_param(polling_req, bool, 0444); -MODULE_PARM_DESC(polling_req, "Request Polling. Default =3D 0 (use irq)"); - -/* Control Polling Rate */ -static int scan_rate =3D 80; -module_param(scan_rate, int, 0644); -MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default =3D 80"); - -/* The main device structure */ -struct synaptics_i2c { - struct i2c_client *client; - struct input_dev *input; - struct delayed_work dwork; - int no_data_count; - int no_decel_param; - int reduce_report_param; - int no_filter_param; - int scan_rate_param; - int scan_ms; -}; - -static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rat= e) -{ - touch->scan_ms =3D MSEC_PER_SEC / scan_rate; - touch->scan_rate_param =3D scan_rate; -} - -/* - * Driver's initial design makes no race condition possible on i2c bus, - * so there is no need in any locking. - * Keep it in mind, while playing with the code. - */ -static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg) -{ - int ret; - - ret =3D i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); - if (ret =3D=3D 0) - ret =3D i2c_smbus_read_byte_data(client, reg & 0xff); - - return ret; -} - -static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 va= l) -{ - int ret; - - ret =3D i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); - if (ret =3D=3D 0) - ret =3D i2c_smbus_write_byte_data(client, reg & 0xff, val); - - return ret; -} - -static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg) -{ - int ret; - - ret =3D i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); - if (ret =3D=3D 0) - ret =3D i2c_smbus_read_word_data(client, reg & 0xff); - - return ret; -} - -static int synaptics_i2c_config(struct i2c_client *client) -{ - int ret, control; - u8 int_en; - - /* set Report Rate to Device Highest (>=3D80) and Sleep to normal */ - ret =3D synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); - if (ret) - return ret; - - /* set Interrupt Disable to Func20 / Enable to Func10) */ - int_en =3D (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; - ret =3D synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); - if (ret) - return ret; - - control =3D synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); - /* No Deceleration */ - control |=3D no_decel ? 1 << NO_DECELERATION : 0; - /* Reduced Reporting */ - control |=3D reduce_report ? 1 << REDUCE_REPORTING : 0; - /* No Filter */ - control |=3D no_filter ? 1 << NO_FILTER : 0; - ret =3D synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control); - if (ret) - return ret; - - return 0; -} - -static int synaptics_i2c_reset_config(struct i2c_client *client) -{ - int ret; - - /* Reset the Touchpad */ - ret =3D synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND); - if (ret) { - dev_err(&client->dev, "Unable to reset device\n"); - } else { - usleep_range(SOFT_RESET_DELAY_US, SOFT_RESET_DELAY_US + 100); - ret =3D synaptics_i2c_config(client); - if (ret) - dev_err(&client->dev, "Unable to config device\n"); - } - - return ret; -} - -static int synaptics_i2c_check_error(struct i2c_client *client) -{ - int status, ret =3D 0; - - status =3D i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & - (CONFIGURED_MSK | ERROR_MSK); - - if (status !=3D CONFIGURED_MSK) - ret =3D synaptics_i2c_reset_config(client); - - return ret; -} - -static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) -{ - struct input_dev *input =3D touch->input; - int xy_delta, gesture; - s32 data; - s8 x_delta, y_delta; - - /* Deal with spontaneous resets and errors */ - if (synaptics_i2c_check_error(touch->client)) - return false; - - /* Get Gesture Bit */ - data =3D synaptics_i2c_reg_get(touch->client, DATA_REG0); - gesture =3D (data >> GESTURE) & 0x1; - - /* - * Get Relative axes. we have to get them in one shot, - * so we get 2 bytes starting from REL_X_REG. - */ - xy_delta =3D synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; - - /* Separate X from Y */ - x_delta =3D xy_delta & 0xff; - y_delta =3D (xy_delta >> REGISTER_LENGTH) & 0xff; - - /* Report the button event */ - input_report_key(input, BTN_LEFT, gesture); - - /* Report the deltas */ - input_report_rel(input, REL_X, x_delta); - input_report_rel(input, REL_Y, -y_delta); - input_sync(input); - - return xy_delta || gesture; -} - -static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) -{ - struct synaptics_i2c *touch =3D dev_id; - - mod_delayed_work(system_wq, &touch->dwork, 0); - - return IRQ_HANDLED; -} - -static void synaptics_i2c_check_params(struct synaptics_i2c *touch) -{ - bool reset =3D false; - - if (scan_rate !=3D touch->scan_rate_param) - set_scan_rate(touch, scan_rate); - - if (no_decel !=3D touch->no_decel_param) { - touch->no_decel_param =3D no_decel; - reset =3D true; - } - - if (no_filter !=3D touch->no_filter_param) { - touch->no_filter_param =3D no_filter; - reset =3D true; - } - - if (reduce_report !=3D touch->reduce_report_param) { - touch->reduce_report_param =3D reduce_report; - reset =3D true; - } - - if (reset) - synaptics_i2c_reset_config(touch->client); -} - -/* Control the Device polling rate / Work Handler sleep time */ -static unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touc= h, - bool have_data) -{ - unsigned long delay, nodata_count_thres; - - if (polling_req) { - delay =3D touch->scan_ms; - if (have_data) { - touch->no_data_count =3D 0; - } else { - nodata_count_thres =3D NO_DATA_THRES / touch->scan_ms; - if (touch->no_data_count < nodata_count_thres) - touch->no_data_count++; - else - delay =3D NO_DATA_SLEEP_MSECS; - } - return msecs_to_jiffies(delay); - } else { - delay =3D msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS); - return round_jiffies_relative(delay); - } -} - -/* Work Handler */ -static void synaptics_i2c_work_handler(struct work_struct *work) -{ - bool have_data; - struct synaptics_i2c *touch =3D - container_of(work, struct synaptics_i2c, dwork.work); - unsigned long delay; - - synaptics_i2c_check_params(touch); - - have_data =3D synaptics_i2c_get_input(touch); - delay =3D synaptics_i2c_adjust_delay(touch, have_data); - - /* - * While interrupt driven, there is no real need to poll the device. - * But touchpads are very sensitive, so there could be errors - * related to physical environment and the attention line isn't - * necessarily asserted. In such case we can lose the touchpad. - * We poll the device once in THREAD_IRQ_SLEEP_SECS and - * if error is detected, we try to reset and reconfigure the touchpad. - */ - mod_delayed_work(system_wq, &touch->dwork, delay); -} - -static int synaptics_i2c_open(struct input_dev *input) -{ - struct synaptics_i2c *touch =3D input_get_drvdata(input); - int ret; - - ret =3D synaptics_i2c_reset_config(touch->client); - if (ret) - return ret; - - if (polling_req) - mod_delayed_work(system_wq, &touch->dwork, - msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); - - return 0; -} - -static void synaptics_i2c_close(struct input_dev *input) -{ - struct synaptics_i2c *touch =3D input_get_drvdata(input); - - if (!polling_req) - synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); - - cancel_delayed_work_sync(&touch->dwork); - - /* Save some power */ - synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); -} - -static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) -{ - struct input_dev *input =3D touch->input; - - input->name =3D touch->client->name; - input->phys =3D touch->client->adapter->name; - input->id.bustype =3D BUS_I2C; - input->id.version =3D synaptics_i2c_word_get(touch->client, - INFO_QUERY_REG0); - input->dev.parent =3D &touch->client->dev; - input->open =3D synaptics_i2c_open; - input->close =3D synaptics_i2c_close; - input_set_drvdata(input, touch); - - /* Register the device as mouse */ - __set_bit(EV_REL, input->evbit); - __set_bit(REL_X, input->relbit); - __set_bit(REL_Y, input->relbit); - - /* Register device's buttons and keys */ - __set_bit(EV_KEY, input->evbit); - __set_bit(BTN_LEFT, input->keybit); -} - -static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client = *client) -{ - struct synaptics_i2c *touch; - - touch =3D kzalloc(sizeof(*touch), GFP_KERNEL); - if (!touch) - return NULL; - - touch->client =3D client; - touch->no_decel_param =3D no_decel; - touch->scan_rate_param =3D scan_rate; - set_scan_rate(touch, scan_rate); - INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); - - return touch; -} - -static int synaptics_i2c_probe(struct i2c_client *client) -{ - int ret; - struct synaptics_i2c *touch; - - touch =3D synaptics_i2c_touch_create(client); - if (!touch) - return -ENOMEM; - - ret =3D synaptics_i2c_reset_config(client); - if (ret) - goto err_mem_free; - - if (client->irq < 1) - polling_req =3D true; - - touch->input =3D input_allocate_device(); - if (!touch->input) { - ret =3D -ENOMEM; - goto err_mem_free; - } - - synaptics_i2c_set_input_params(touch); - - if (!polling_req) { - dev_dbg(&touch->client->dev, - "Requesting IRQ: %d\n", touch->client->irq); - - ret =3D request_irq(touch->client->irq, synaptics_i2c_irq, - IRQ_TYPE_EDGE_FALLING, - DRIVER_NAME, touch); - if (ret) { - dev_warn(&touch->client->dev, - "IRQ request failed: %d, " - "falling back to polling\n", ret); - polling_req =3D true; - synaptics_i2c_reg_set(touch->client, - INTERRUPT_EN_REG, 0); - } - } - - if (polling_req) - dev_dbg(&touch->client->dev, - "Using polling at rate: %d times/sec\n", scan_rate); - - /* Register the device in input subsystem */ - ret =3D input_register_device(touch->input); - if (ret) { - dev_err(&client->dev, - "Input device register failed: %d\n", ret); - goto err_input_free; - } - - i2c_set_clientdata(client, touch); - - return 0; - -err_input_free: - input_free_device(touch->input); -err_mem_free: - kfree(touch); - - return ret; -} - -static void synaptics_i2c_remove(struct i2c_client *client) -{ - struct synaptics_i2c *touch =3D i2c_get_clientdata(client); - - if (!polling_req) - free_irq(client->irq, touch); - - input_unregister_device(touch->input); - kfree(touch); -} - -static int synaptics_i2c_suspend(struct device *dev) -{ - struct i2c_client *client =3D to_i2c_client(dev); - struct synaptics_i2c *touch =3D i2c_get_clientdata(client); - - cancel_delayed_work_sync(&touch->dwork); - - /* Save some power */ - synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); - - return 0; -} - -static int synaptics_i2c_resume(struct device *dev) -{ - int ret; - struct i2c_client *client =3D to_i2c_client(dev); - struct synaptics_i2c *touch =3D i2c_get_clientdata(client); - - ret =3D synaptics_i2c_reset_config(client); - if (ret) - return ret; - - mod_delayed_work(system_wq, &touch->dwork, - msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, - synaptics_i2c_resume); - -static const struct i2c_device_id synaptics_i2c_id_table[] =3D { - { "synaptics_i2c" }, - { } -}; -MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); - -#ifdef CONFIG_OF -static const struct of_device_id synaptics_i2c_of_match[] =3D { - { .compatible =3D "synaptics,synaptics_i2c", }, - { }, -}; -MODULE_DEVICE_TABLE(of, synaptics_i2c_of_match); -#endif - -static struct i2c_driver synaptics_i2c_driver =3D { - .driver =3D { - .name =3D DRIVER_NAME, - .of_match_table =3D of_match_ptr(synaptics_i2c_of_match), - .pm =3D pm_sleep_ptr(&synaptics_i2c_pm), - }, - - .probe =3D synaptics_i2c_probe, - .remove =3D synaptics_i2c_remove, - - .id_table =3D synaptics_i2c_id_table, -}; - -module_i2c_driver(synaptics_i2c_driver); - -MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); -MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); -MODULE_LICENSE("GPL"); - --=20 2.52.0.239.gd5f0c6e74e-goog --=20 Dmitry