From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 856E11D6188; Fri, 12 Dec 2025 13:55:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765547702; cv=none; b=N9c7mttydMU5p+Dh9R3hnO5VvIwqpiF7ytel14AUO1qv2p85ztb6qSEvK5BZjHqFJrdVYIeQN/tj+3o6XJ4fAMhjQ1IJb86P2Kp2rvwsHcfD3Jjkm4Kqhlb6b4fwJAmebzsAVVxYl045DnjeaXeSUSwuID/KwVk2E55hCwnIbPg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765547702; c=relaxed/simple; bh=ja5RAH3JrbpsA8s0/nC3AEEl2jfCLiSnmb8m8mERPIs=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=OXmORFL+k4kjgB+9FWquB4/EQF2fKvROfUsANzImWsRFr9uzjAj/HxNRGF9X7utg9OGXqJlLvxJqITdIQ8kNpl6RZ15Fl887g+XNe4YMeuoUZUuOvBV22FNeCdWE/H9z4AZEVWIEsZgnW8z2EU8eva66SlQJQ3ievKCuEC12rH0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UdZFLLMy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UdZFLLMy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C749EC4CEF1; Fri, 12 Dec 2025 13:55:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1765547702; bh=ja5RAH3JrbpsA8s0/nC3AEEl2jfCLiSnmb8m8mERPIs=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=UdZFLLMyvuoLM7FxLukM+vPIfSWm12rhEqX3bzjeRxooYjMXSo8YoUy6xnb3xMooy jCAkFbLBnRGnmjIXHRExQ/LhUsr6sula0hbILDkoU7boKUdEjqZ9fkRcw3rZ+kNwk6 SAj73M+wn8+zgtOPwJl8SWuv51xhZAxfTBu6norL62ZjoImHqaMeQ/4hHLD1/4QjLQ bD9XuaUXxGkmWpp/cYLB/1854U9x8znalDTf37qaG7LIVYrIci6uniaT8r9Hsk5AJz jxV+fJ83jK+gqeEHSdx1mrgEfsMP8Qqd2N7DWTvagwdKTlIpeS7Jj/ZM9HqxTmPD6i Tbt1yyHs1/2iA== Date: Fri, 12 Dec 2025 22:54:57 +0900 From: Mike Rapoport To: Dmitry Torokhov Cc: linux-kernel@vger.kernel.org, Minseong Kim , linux-input@vger.kernel.org Subject: Re: [PATCH] Input: synaptics_i2c - remove the driver Message-ID: References: <7fjjlb5wmwberkwljagmmbetvcvcijoduu2cqpilressbrnn4y@4574molvgnqu> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <7fjjlb5wmwberkwljagmmbetvcvcijoduu2cqpilressbrnn4y@4574molvgnqu> On Fri, Dec 12, 2025 at 12:50:49AM -0800, Dmitry Torokhov wrote: > 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. > > -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) += pc110pad.o > obj-$(CONFIG_MOUSE_PS2) += psmouse.o > obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o > obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o > -obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o > obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o > obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o > > diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_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 Public > - * 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 = true; > -module_param(no_decel, bool, 0644); > -MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 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 = 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 = 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 = 0 (use irq)"); > - > -/* Control Polling Rate */ > -static int scan_rate = 80; > -module_param(scan_rate, int, 0644); > -MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 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_rate) > -{ > - touch->scan_ms = MSEC_PER_SEC / scan_rate; > - touch->scan_rate_param = 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 = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); > - if (ret == 0) > - ret = i2c_smbus_read_byte_data(client, reg & 0xff); > - > - return ret; > -} > - > -static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val) > -{ > - int ret; > - > - ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); > - if (ret == 0) > - ret = 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 = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); > - if (ret == 0) > - ret = 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 (>=80) and Sleep to normal */ > - ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); > - if (ret) > - return ret; > - > - /* set Interrupt Disable to Func20 / Enable to Func10) */ > - int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; > - ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); > - if (ret) > - return ret; > - > - control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); > - /* No Deceleration */ > - control |= no_decel ? 1 << NO_DECELERATION : 0; > - /* Reduced Reporting */ > - control |= reduce_report ? 1 << REDUCE_REPORTING : 0; > - /* No Filter */ > - control |= no_filter ? 1 << NO_FILTER : 0; > - ret = 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 = 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 = 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 = 0; > - > - status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & > - (CONFIGURED_MSK | ERROR_MSK); > - > - if (status != CONFIGURED_MSK) > - ret = synaptics_i2c_reset_config(client); > - > - return ret; > -} > - > -static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) > -{ > - struct input_dev *input = 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 = synaptics_i2c_reg_get(touch->client, DATA_REG0); > - gesture = (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 = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; > - > - /* Separate X from Y */ > - x_delta = xy_delta & 0xff; > - y_delta = (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 = 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 = false; > - > - if (scan_rate != touch->scan_rate_param) > - set_scan_rate(touch, scan_rate); > - > - if (no_decel != touch->no_decel_param) { > - touch->no_decel_param = no_decel; > - reset = true; > - } > - > - if (no_filter != touch->no_filter_param) { > - touch->no_filter_param = no_filter; > - reset = true; > - } > - > - if (reduce_report != touch->reduce_report_param) { > - touch->reduce_report_param = reduce_report; > - reset = 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 *touch, > - bool have_data) > -{ > - unsigned long delay, nodata_count_thres; > - > - if (polling_req) { > - delay = touch->scan_ms; > - if (have_data) { > - touch->no_data_count = 0; > - } else { > - nodata_count_thres = NO_DATA_THRES / touch->scan_ms; > - if (touch->no_data_count < nodata_count_thres) > - touch->no_data_count++; > - else > - delay = NO_DATA_SLEEP_MSECS; > - } > - return msecs_to_jiffies(delay); > - } else { > - delay = 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 = > - container_of(work, struct synaptics_i2c, dwork.work); > - unsigned long delay; > - > - synaptics_i2c_check_params(touch); > - > - have_data = synaptics_i2c_get_input(touch); > - delay = 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 = input_get_drvdata(input); > - int ret; > - > - ret = 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 = 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 = touch->input; > - > - input->name = touch->client->name; > - input->phys = touch->client->adapter->name; > - input->id.bustype = BUS_I2C; > - input->id.version = synaptics_i2c_word_get(touch->client, > - INFO_QUERY_REG0); > - input->dev.parent = &touch->client->dev; > - input->open = synaptics_i2c_open; > - input->close = 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 = kzalloc(sizeof(*touch), GFP_KERNEL); > - if (!touch) > - return NULL; > - > - touch->client = client; > - touch->no_decel_param = no_decel; > - touch->scan_rate_param = 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 = synaptics_i2c_touch_create(client); > - if (!touch) > - return -ENOMEM; > - > - ret = synaptics_i2c_reset_config(client); > - if (ret) > - goto err_mem_free; > - > - if (client->irq < 1) > - polling_req = true; > - > - touch->input = input_allocate_device(); > - if (!touch->input) { > - ret = -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 = 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 = 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 = 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 = 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 = to_i2c_client(dev); > - struct synaptics_i2c *touch = 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 = to_i2c_client(dev); > - struct synaptics_i2c *touch = i2c_get_clientdata(client); > - > - ret = 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[] = { > - { "synaptics_i2c" }, > - { } > -}; > -MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); > - > -#ifdef CONFIG_OF > -static const struct of_device_id synaptics_i2c_of_match[] = { > - { .compatible = "synaptics,synaptics_i2c", }, > - { }, > -}; > -MODULE_DEVICE_TABLE(of, synaptics_i2c_of_match); > -#endif > - > -static struct i2c_driver synaptics_i2c_driver = { > - .driver = { > - .name = DRIVER_NAME, > - .of_match_table = of_match_ptr(synaptics_i2c_of_match), > - .pm = pm_sleep_ptr(&synaptics_i2c_pm), > - }, > - > - .probe = synaptics_i2c_probe, > - .remove = synaptics_i2c_remove, > - > - .id_table = 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"); > - > -- > 2.52.0.239.gd5f0c6e74e-goog > > > -- > Dmitry -- Sincerely yours, Mike.