Skip to contentSkip to conversation

Synaptics TM1217 Touchscreen Controller driver

PATCH In review Alan Cox 3 participants 4 messages Jul 16, 2010 – Jul 27, 2010

Subsystems (3)
lore
Share & tools
lore

Alan Cox

author
#0 lore raw

PATCH 1/1 Synaptics TM1217 Touchscreen Controller driver

From: Ramesh Agarwal <[email protected]>

Driver for the Synaptics TM1217 touchscreen controller, connected via an SPI and GPIO interface.

Some clean up by Alan Cox
- Extract gpio support and IRQ support more sanely
- Tidying

---

 drivers/input/touchscreen/Kconfig           |   12 
 drivers/input/touchscreen/Makefile          |    1 
 drivers/input/touchscreen/clearpad_tm1217.c |  674 +++++++++++++++++++++++++++
 include/linux/spi/cp_tm1217.h               |    9 
 4 files changed, 696 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/clearpad_tm1217.c
 create mode 100644 include/linux/spi/cp_tm1217.h
drivers/input/touchscreen/Kconfig +12 -0
index 8393f47..0aa3c0b 100644
@@ -626,4 +626,16 @@ config TOUCHSCREEN_CY8CTMG110
 	  To compile this driver as a module, choose M here: the
 	  module will be called cy8ctmg110_ts.
 
+config TOUCHSCREEN_CLEARPAD_TM1217
+	tristate "Synaptics Clearpad TM1217"
+	depends on I2C
+	depends on GPIOLIB
+	help
+	  Say Y here if you have a Synaptics Clearpad TM1217 Controller
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called clearpad_tm1217.
+
 endif
drivers/input/touchscreen/Makefile +1 -0
index 662d066..fd6720a 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)    += cy8ctmg110_ts.o
+obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217)	+= clearpad_tm1217.o
 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)	+= dynapro.o
 obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)	+= hampshire.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
drivers/input/touchscreen/clearpad_tm1217.c new file +674 -0

674 lines not on this page · raw message

include/linux/spi/cp_tm1217.h new file +9 -0
new file mode 100644
index 0000000..5ab13a8
@@ -0,0 +1,9 @@
+#ifndef __LINUX_SPI_CP_TM1217_H
+#define __LINUX_SPI_CP_TM1217_H
+
+struct cp_tm1217_platform_data
+{
+	int gpio;		/* If not set uses the IRQ resource 0 */
+};
+
+#endif
maintainer
#1 lore raw

Hi Alan,

Quoted 5 lines · Alan Cox

From: Ramesh Agarwal <[email protected]>

Driver for the Synaptics TM1217 touchscreen controller, connected via an SPI and GPIO interface.

Is this RMI3 or RMI4 hardware? Synaptics has posted and generic-ish framework for RMI4 devices so if it is RMI4 we'd need to move over to it.

drivers/input/touchscreen/clearpad_tm1217.c line 122

Quoted 11 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +11 -0
+struct cp_tm1217_device {
+	struct i2c_client	*client;
+	struct device		*dev;
+	struct cp_vendor_info	vinfo;
+	struct cp_dev_info	dinfo;
+	struct input_dev_info {
+		char			phys[32];
+		char			name[128];
+		struct input_dev	*input;
+		struct touch_state	touch;
+	} cp_input_info[MAX_TOUCH_SUPPORTED];

This is a non-starter. If this is a multitouch device please use multitouch protocol for it, not register 2 separate input devices.

Quoted 153 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +153 -0
+
+	int	thread_running;
+	struct mutex	thread_mutex;
+
+	int gpio;
+};
+
+
+/* The following functions are used to read/write registers on the device
+ * as per the RMI prorocol. Technically, a page select should be written
+ * before doing read/write but since the register offsets are below 0xFF
+ * we can use the default value of page which is 0x00
+ */
+static int cp_tm1217_read(struct cp_tm1217_device *ts,
+				u8 *req, int size)
+{
+	int i, retval;
+
+	/* Send the address */
+	retval = i2c_master_send(ts->client, &req[0], 1);
+	if (retval != 1) {
+		dev_err(ts->dev, "cp_tm1217: I2C send failed\n");
+		return retval;
+	}
+	msleep(WAIT_FOR_RESPONSE);
+	for (i = 0; i < MAX_RETRIES; i++) {
+		retval = i2c_master_recv(ts->client, &req[1], size);
+		if (retval == size) {
+			break;
+		} else {
+			msleep(INCREMENTAL_DELAY);
+			dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i);
+		}
+	}
+	if (retval != size)
+		dev_err(ts->dev, "cp_tm1217: Read from device failed\n");
+
+	return retval;
+}
+
+static int cp_tm1217_write(struct cp_tm1217_device *ts,
+				u8 *req, int size)
+{
+	int retval;
+
+	/* Send the address and the data to be written */
+	retval = i2c_master_send(ts->client, &req[0], size + 1);
+	if (retval != size + 1) {
+		dev_err(ts->dev, "cp_tm1217: I2C write  failed: %d\n", retval);
+		return retval;
+	}
+	/* Wait for the write to complete. TBD why this is required */
+	msleep(WAIT_FOR_RESPONSE);
+
+	return size;
+}
+
+static int cp_tm1217_mask_interrupt(struct cp_tm1217_device *ts)
+{
+	u8 req[2];
+	int retval;
+
+	req[0] = TMA1217_INTERRUPT_ENABLE;
+	req[1] = 0x0;
+	retval = cp_tm1217_write(ts, req, 1);
+	if (retval != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static int cp_tm1217_unmask_interrupt(struct cp_tm1217_device *ts)
+{
+	u8 req[2];
+	int retval;
+
+	req[0] = TMA1217_INTERRUPT_ENABLE;
+	req[1] = 0xa;
+	retval = cp_tm1217_write(ts, req, 1);
+	if (retval != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static void process_touch(struct cp_tm1217_device *ts, int index)
+{
+	int retval;
+	struct input_dev_info *input_info =
+		(struct input_dev_info *)&ts->cp_input_info[index];
+	u8 xy_data[6];
+
+	if (index == 0)
+		xy_data[0] = TMA1217_FINGER1_X_HIGHER8;
+	else
+		xy_data[0] = TMA1217_FINGER2_X_HIGHER8;
+
+	retval = cp_tm1217_read(ts, xy_data, 5);
+	if (retval < 5) {
+		dev_err(ts->dev, "cp_tm1217: XY read from device failed\n");
+		return;
+	}
+
+	/* Note: Currently not using the Z values but may be requried in
+	   the future. */
+	input_info->touch.x = (xy_data[1] << 4)
+					| (xy_data[3] & 0x0F);
+	input_info->touch.y = (xy_data[2] << 4)
+					| ((xy_data[3] & 0xF0) >> 4);
+	input_report_abs(input_info->input, ABS_X, input_info->touch.x);
+	input_report_abs(input_info->input, ABS_Y, input_info->touch.y);
+	input_sync(input_info->input);
+}
+
+static void cp_tm1217_get_data(struct cp_tm1217_device *ts)
+{
+	u8 req[2];
+	int retval, i, finger_touched;
+
+	do {
+		req[0] = TMA1217_FINGER_STATE;
+		retval = cp_tm1217_read(ts, req, 1);
+		if (retval != 1) {
+			dev_err(ts->dev,
+				"cp_tm1217: Read from device failed\n");
+			continue;
+		}
+		finger_touched = 0;
+		/* Start sampling until the pressure is below
+		  threshold */
+		for (i = 0; i < TOUCH_SUPPORTED; i++) {
+			if (req[1] & 0x3) {
+				finger_touched++;
+				if (ts->cp_input_info[i].touch.button == 0) {
+					/* send the button touch event */
+					input_report_key(
+						ts->cp_input_info[i].input,
+						BTN_TOUCH, 1);
+					ts->cp_input_info[i].touch.button = 1;
+				}
+				process_touch(ts, i);
+			} else {
+				if (ts->cp_input_info[i].touch.button == 1) {
+					/* send the button release event */
+					input_report_key(
+						ts->cp_input_info[i].input,
+						BTN_TOUCH, 0);
+					ts->cp_input_info[i].touch.button = 0;
+				}
+			}
+			req[1] = req[1] >> 2;
+		}
+		msleep(DELAY_BTWIN_SAMPLE);

drivers/input/touchscreen/clearpad_tm1217.c line 285

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+	} while (finger_touched > 0);
+}
+
+static irqreturn_t cp_tm1217_sample_thread(int irq, void *handle)
+{
+	struct cp_tm1217_device *ts = (struct cp_tm1217_device *) handle;
+	u8 req[2];
+	int retval;
+
+	/* Chedk if another thread is already running */

Just how exactly can it ihappen?

Quoted 115 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +115 -0
+	mutex_lock(&ts->thread_mutex);
+	if (ts->thread_running == 1) {
+		mutex_unlock(&ts->thread_mutex);
+		return IRQ_HANDLED;
+	} else {
+		ts->thread_running = 1;
+		mutex_unlock(&ts->thread_mutex);
+	}
+
+	/* Mask the interrupts */
+	retval = cp_tm1217_mask_interrupt(ts);
+
+	/* Read the Interrupt Status register to find the cause of the
+	   Interrupt */
+	req[0] = TMA1217_INT_STATUS;
+	retval = cp_tm1217_read(ts, req, 1);
+	if (retval != 1)
+		goto exit_thread;
+
+	if (!(req[1] & 0x8))
+		goto exit_thread;
+
+	cp_tm1217_get_data(ts);
+
+exit_thread:
+	/* Unmask the interrupts before going to sleep */
+	retval = cp_tm1217_unmask_interrupt(ts);
+
+	mutex_lock(&ts->thread_mutex);
+	ts->thread_running = 0;
+	mutex_unlock(&ts->thread_mutex);
+
+	return IRQ_HANDLED;
+}
+
+static int cp_tm1217_init_data(struct cp_tm1217_device *ts)
+{
+	int retval;
+	u8	req[2];
+
+	/* Read the vendor id/ fw revision etc. Ignoring return check as this
+	   is non critical info  */
+	req[0] = TMA1217_MANUFACTURER_ID;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->vinfo.vendor_id = req[1];
+
+	req[0] = TMA1217_PRODUCT_FAMILY;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->vinfo.product_family = req[1];
+
+	req[0] = TMA1217_FIRMWARE_REVISION;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->vinfo.firmware_rev = req[1];
+
+	req[0] = TMA1217_SERIAL_NO_HIGH;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->vinfo.serial_no = (req[1] << 8);
+
+	req[0] = TMA1217_SERIAL_NO_LOW;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->vinfo.serial_no = ts->vinfo.serial_no | req[1];
+
+	req[0] = TMA1217_MAX_X_HIGHER4;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->dinfo.maxX = (req[1] & 0xF) << 8;
+
+	req[0] = TMA1217_MAX_X_LOWER8;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->dinfo.maxX = ts->dinfo.maxX | req[1];
+
+	req[0] = TMA1217_MAX_Y_HIGHER4;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->dinfo.maxY = (req[1] & 0xF) << 8;
+
+	req[0] = TMA1217_MAX_Y_LOWER8;
+	retval = cp_tm1217_read(ts, req, 1);
+	ts->dinfo.maxY = ts->dinfo.maxY | req[1];
+
+	return 0;
+
+}
+
+/*
+ *	Set up a GPIO for use as the interrupt. We can't simply do this at
+ *	boot time because the GPIO drivers themselves may not be around at
+ *	boot/firmware set up time to do the work. Instead defer it to driver
+ *	detection.
+ */
+
+static int cp_tm1217_setup_gpio_irq(struct cp_tm1217_device *ts)
+{
+	int retval;
+
+	/* Hook up the irq handler */
+	retval = gpio_request(ts->gpio, "cp_tm1217_touch");
+	if (retval < 0) {
+		dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n",
+								retval);
+		return retval;
+	}
+
+	retval = gpio_direction_input(ts->gpio);
+	if (retval < 0) {
+		dev_err(ts->dev,
+		"cp_tm1217: GPIO direction configuration failed, error %d\n",
+								retval);
+		gpio_free(ts->gpio);
+		return retval;
+	}
+
+	retval = gpio_to_irq(ts->gpio);
+	if (retval < 0) {
+		dev_err(ts->dev, "cp_tm1217: GPIO to IRQ failedi,"
+		" error %d\n", retval);
+		gpio_free(ts->gpio);

drivers/input/touchscreen/clearpad_tm1217.c line 410

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+	}
+	dev_dbg(ts->dev,
+		"cp_tm1217: Got IRQ number is %d for GPIO %d\n",
+		retval, ts->gpio);
+	return retval;
+}
+
+static int cp_tm1217_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{

__devinit

Quoted 23 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +23 -0
+	struct cp_tm1217_device *ts;
+	struct input_dev *input_dev;
+	struct input_dev_info	*input_info;
+	struct cp_tm1217_platform_data *pdata;
+	u8 req[2];
+	int i, retval;
+
+	/* No pdata is fine - we then use "normal" IRQ mode */
+
+	pdata = client->dev.platform_data;
+
+	ts = kzalloc(sizeof(struct cp_tm1217_device), GFP_KERNEL);
+	if (!ts) {
+		dev_err(ts->dev,
+			"cp_tm1217: Private Device Struct alloc failed\n");
+		return -ENOMEM;
+	}
+
+	ts->client = client;
+	ts->dev = &client->dev;
+	i2c_set_clientdata(client, ts);
+
+	ts->thread_running = 0;

drivers/input/touchscreen/clearpad_tm1217.c line 443

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+	mutex_init(&ts->thread_mutex);
+
+	/* Reset the Controller */
+	req[0] = TMA1217_DEVICE_CMD_RESET;
+	req[1] = 0x1;
+	retval = cp_tm1217_write(ts, req, 1);
+	if (retval != 1) {
+		dev_err(ts->dev, "cp_tm1217: Controller reset failed\n");
+		kfree(ts);
+		return -EIO;

This mixes in-line and out-of line error unwinding, very confusing. Just goto into error path as you do in the rest of the function.

Quoted 44 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +44 -0
+	}
+
+	/* Clear up the interrupt status from reset. */
+	req[0] = TMA1217_INT_STATUS;
+	retval = cp_tm1217_read(ts, req, 1);
+
+	/* Mask all the interrupts */
+	retval = cp_tm1217_mask_interrupt(ts);
+
+	/* Read the controller information */
+	cp_tm1217_init_data(ts);
+
+	/* The following code will register multiple event devices when
+	   multi-pointer is enabled, the code has not been tested
+	   with MPX */
+	for (i = 0; i < TOUCH_SUPPORTED; i++) {
+		input_dev = input_allocate_device();
+		if (input_dev == NULL) {
+			kfree(ts);
+			dev_err(ts->dev,
+				"cp_tm1217:Input Device Struct alloc failed\n");
+			return -ENOMEM;
+		}
+		input_info = &ts->cp_input_info[i];
+		snprintf(input_info->name, sizeof(input_info->name),
+			"cp_tm1217_touchscreen_%d", i);
+		input_dev->name = input_info->name;
+		snprintf(input_info->phys, sizeof(input_info->phys),
+			"%s/input%d", dev_name(&client->dev), i);
+
+		input_dev->phys = input_info->phys;
+		input_dev->id.bustype = BUS_I2C;
+
+		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+		input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+		input_set_abs_params(input_dev, ABS_X, 0, ts->dinfo.maxX, 0, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0, ts->dinfo.maxY, 0, 0);
+
+		retval = input_register_device(input_dev);
+		if (retval) {
+			dev_err(ts->dev,
+				"Input dev registration failed for %s\n",
+					input_dev->name);

drivers/input/touchscreen/clearpad_tm1217.c line 497

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+			goto fail;
+		}
+		input_info->input = input_dev;
+	}
+
+	/* Setup the reporting mode to send an interrupt only when
+	   finger arrives or departs. */
+	req[0] = TMA1217_REPORT_MODE;
+	req[1] = 0x02;
+	retval = cp_tm1217_write(ts, req, 1);

Not acting upon retval?

drivers/input/touchscreen/clearpad_tm1217.c line 502

Quoted 5 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +5 -0
+
+	/* Setup the device to no sleep mode for now and make it configured */
+	req[0] = TMA1217_DEVICE_CTRL;
+	req[1] = 0x84;
+	retval = cp_tm1217_write(ts, req, 1);

Same...

drivers/input/touchscreen/clearpad_tm1217.c line 506

Quoted 4 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +4 -0
+
+	/* Check for the status of the device */
+	req[0] = TMA1217_DEV_STATUS;
+	retval = cp_tm1217_read(ts, req, 1);

Same...

Quoted 48 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +48 -0
+	if (req[1] != 0) {
+		dev_err(ts->dev,
+			"cp_tm1217: Device Status 0x%x != 0: config failed\n",
+			req[1]);
+
+		retval = -EIO;
+		goto fail;
+	}
+
+	if (pdata && pdata->gpio) {
+		ts->gpio = pdata->gpio;
+		retval = cp_tm1217_setup_gpio_irq(ts);
+	} else
+		retval = client->irq;
+
+	if (retval < 0) {
+		dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n",
+								retval);
+		goto fail;
+	}
+
+	client->irq = retval;
+
+
+	retval = request_threaded_irq(client->irq,
+		NULL, cp_tm1217_sample_thread,
+		IRQF_TRIGGER_FALLING, "cp_tm1217_touch", ts);
+	if (retval < 0) {
+		dev_err(ts->dev, "cp_tm1217: Request IRQ error %d\n", retval);
+		goto fail_gpio;
+	}
+
+	/* Unmask the interrupts */
+	retval = cp_tm1217_unmask_interrupt(ts);
+	if (retval == 0)
+		return 0;
+
+	free_irq(client->irq, ts);
+fail_gpio:
+	if (ts->gpio)
+		gpio_free(ts->gpio);
+fail:
+	/* Clean up before returning failure */
+	for (i = 0; i < TOUCH_SUPPORTED; i++) {
+		if (ts->cp_input_info[i].input) {
+			input_unregister_device(ts->cp_input_info[i].input);
+			input_free_device(ts->cp_input_info[i].input);
+		}

drivers/input/touchscreen/clearpad_tm1217.c line 564

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+	}
+	kfree(ts);
+	return retval;
+
+}
+
+/*
+ * cp_tm1217 suspend
+ *
+ */

#ifdef CONFIG_PM

Quoted 52 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +52 -0
+static int cp_tm1217_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct cp_tm1217_device *ts = i2c_get_clientdata(client);
+	u8 req[2];
+	int retval;
+
+	/* Put the controller to sleep */
+	req[0] = TMA1217_DEVICE_CTRL;
+	retval = cp_tm1217_read(ts, req, 1);
+	req[1] = (req[1] & 0xF8) | 0x1;
+	retval = cp_tm1217_write(ts, req, 1);
+
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(client->irq);
+
+	return 0;
+}
+
+/*
+ * cp_tm1217_resume
+ *
+ */
+static int cp_tm1217_resume(struct i2c_client *client)
+{
+	struct cp_tm1217_device *ts = i2c_get_clientdata(client);
+	u8 req[2];
+	int retval;
+
+	/* Take the controller out of sleep */
+	req[0] = TMA1217_DEVICE_CTRL;
+	retval = cp_tm1217_read(ts, req, 1);
+	req[1] = (req[1] & 0xF8) | 0x4;
+	retval = cp_tm1217_write(ts, req, 1);
+
+	/* Restore the register settings sinc the power to the
+	   could have been cut off */
+
+	/* Setup the reporting mode to send an interrupt only when
+	   finger arrives or departs. */
+	req[0] = TMA1217_REPORT_MODE;
+	req[1] = 0x02;
+	retval = cp_tm1217_write(ts, req, 1);
+
+	/* Setup the device to no sleep mode for now and make it configured */
+	req[0] = TMA1217_DEVICE_CTRL;
+	req[1] = 0x84;
+	retval = cp_tm1217_write(ts, req, 1);
+
+	/* Setup the interrupt mask */
+	retval = cp_tm1217_unmask_interrupt(ts);
+
+	if (device_may_wakeup(&client->dev))

drivers/input/touchscreen/clearpad_tm1217.c line 626

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+		disable_irq_wake(client->irq);
+
+	return 0;
+}
+
+/*
+ * cp_tm1217_remove
+ *
+ */
+static int cp_tm1217_remove(struct i2c_client *client)

__devexit

Quoted 18 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +18 -0
+{
+	struct cp_tm1217_device *ts = i2c_get_clientdata(client);
+	int i;
+
+	free_irq(client->irq, ts);
+	if (ts->gpio)
+		gpio_free(ts->gpio);
+	for (i = 0; i < TOUCH_SUPPORTED; i++)
+		input_unregister_device(ts->cp_input_info[i].input);
+	kfree(ts);
+	return 0;
+}
+
+static struct i2c_device_id cp_tm1217_idtable[] = {
+	{ CPTM1217_DEVICE_NAME, 0 },
+	{ }
+};
+

drivers/input/touchscreen/clearpad_tm1217.c line 654

Quoted 10 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +10 -0
+MODULE_DEVICE_TABLE(i2c, cp_tm1217_idtable);
+
+static struct i2c_driver cp_tm1217_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= CPTM1217_DRIVER_NAME,
+	},
+	.id_table	= cp_tm1217_idtable,
+	.probe		= cp_tm1217_probe,
+	.remove		= cp_tm1217_remove,

__devexit_p

Quoted 36 lines
drivers/input/touchscreen/clearpad_tm1217.c new file +20 -0
+	.suspend    = cp_tm1217_suspend,
+	.resume     = cp_tm1217_resume,
+};
+
+static int __init clearpad_tm1217_init(void)
+{
+	return i2c_add_driver(&cp_tm1217_driver);
+}
+
+static void __exit clearpad_tm1217_exit(void)
+{
+	i2c_del_driver(&cp_tm1217_driver);
+}
+
+module_init(clearpad_tm1217_init);
+module_exit(clearpad_tm1217_exit);
+
+MODULE_AUTHOR("Ramesh Agarwal <[email protected]>");
+MODULE_DESCRIPTION("Synaptics TM1217 TouchScreen Driver");
+MODULE_LICENSE("GPL v2");
include/linux/spi/cp_tm1217.h new file +9 -0
new file mode 100644
index 0000000..5ab13a8
@@ -0,0 +1,9 @@
+#ifndef __LINUX_SPI_CP_TM1217_H
+#define __LINUX_SPI_CP_TM1217_H
+
+struct cp_tm1217_platform_data
+{
+	int gpio;		/* If not set uses the IRQ resource 0 */
+};
+
+#endif
Signature · 1 line
Dmitry
author
#2 lore raw
Quoted 3 lines

Is this RMI3 or RMI4 hardware? Synaptics has posted and generic-ish framework for RMI4 devices so if it is RMI4 we'd need to move over to it.

RIM4 - when will the Synaptics patches get merged ?

Moving over to use their framework providing its going to end up in tree soonish looks sensible enough.

#3 lore raw
Quoted 5 lines · Alan Cox
Quoted 3 lines

Is this RMI3 or RMI4 hardware? Synaptics has posted and generic-ish framework for RMI4 devices so if it is RMI4 we'd need to move over to it.

RIM4 - when will the Synaptics patches get merged ?

We'll be submitting an updated patch in the next 24 hours.

Quoted 2 lines

Moving over to use their framework providing its going to end up in tree soonish looks sensible enough.