linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Input: synaptics_i2c - remove the driver
@ 2025-12-12  8:50 Dmitry Torokhov
  2025-12-12 13:54 ` Mike Rapoport
  0 siblings, 1 reply; 2+ messages in thread
From: Dmitry Torokhov @ 2025-12-12  8:50 UTC (permalink / raw)
  To: linux-kernel; +Cc: Mike Rapoport, Minseong Kim, linux-input

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 <dmitry.torokhov@gmail.com>
---
 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 <mike@compulab.co.il>
- * Igor Grinberg <grinberg@compulab.co.il>
- *
- * 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 <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/slab.h>
-#include <linux/pm.h>
-
-#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

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] Input: synaptics_i2c - remove the driver
  2025-12-12  8:50 [PATCH] Input: synaptics_i2c - remove the driver Dmitry Torokhov
@ 2025-12-12 13:54 ` Mike Rapoport
  0 siblings, 0 replies; 2+ messages in thread
From: Mike Rapoport @ 2025-12-12 13:54 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-kernel, Minseong Kim, linux-input

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 <dmitry.torokhov@gmail.com>

Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

> ---
>  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 <mike@compulab.co.il>
> - * Igor Grinberg <grinberg@compulab.co.il>
> - *
> - * 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 <linux/module.h>
> -#include <linux/i2c.h>
> -#include <linux/irq.h>
> -#include <linux/interrupt.h>
> -#include <linux/input.h>
> -#include <linux/delay.h>
> -#include <linux/workqueue.h>
> -#include <linux/slab.h>
> -#include <linux/pm.h>
> -
> -#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.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-12-12 13:55 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-12  8:50 [PATCH] Input: synaptics_i2c - remove the driver Dmitry Torokhov
2025-12-12 13:54 ` Mike Rapoport

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).