All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Henrik Rydberg <rydberg@euromail.se>
Cc: jcbian <jcbian@pixcir.com.cn>,
	linux-input@vger.kernel.org, dqmeng <dqmeng@pixcir.com.cn>,
	zlchen <zlchen@pixcir.com.cn>
Subject: Re: [PATCH v3] input: add driver for pixcir i2c touchscreens
Date: Sat, 9 Jul 2011 13:12:10 -0700	[thread overview]
Message-ID: <20110709201209.GA27874@core.coreip.homeip.net> (raw)
In-Reply-To: <20110705193020.GB29549@polaris.bitmath.org>

On Tue, Jul 05, 2011 at 09:30:20PM +0200, Henrik Rydberg wrote:
> 
> If the above function handles zero fingers as well, the MT finger
> count comes out wrong in that case.
> 

Hmm, indeed. How about the patch below instead?

Thanks.

-- 
Dmitry

Input: add driver for pixcir i2c touchscreens

From: Jianchun Bian <jcbian@pixcir.com.cn>

This patch adds a driver for PIXCIR's I2C connected touchscreens.

Signed-off-by: Jianchun <jcbian@pixcir.com.cn>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/input/touchscreen/Kconfig         |   12 +
 drivers/input/touchscreen/Makefile        |    1 
 drivers/input/touchscreen/pixcir_i2c_ts.c |  242 +++++++++++++++++++++++++++++
 include/linux/input/pixcir_ts.h           |   10 +
 4 files changed, 265 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/pixcir_i2c_ts.c
 create mode 100644 include/linux/input/pixcir_ts.h


diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index a369c94..358be1f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -464,6 +464,18 @@ config TOUCHSCREEN_UCB1400
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_ts.
 
+config TOUCHSCREEN_PIXCIR
+	tristate "PIXCIR I2C touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a pixcir i2c touchscreen
+	  controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pixcir_i2c_ts.
+
 config TOUCHSCREEN_WM831X
 	tristate "Support for WM831x touchscreen controllers"
 	depends on MFD_WM831X
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 141ee3e..c0727a4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
+obj-$(CONFIG_TOUCHSCREEN_PIXCIR)	+= pixcir_i2c_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
new file mode 100644
index 0000000..80067b2
--- /dev/null
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -0,0 +1,242 @@
+/*
+ * Driver for Pixcir I2C touchscreen controllers.
+ *
+ * Copyright (C) 2010-2011 Pixcir, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/pixcir_ts.h>
+
+struct pixcir_i2c_ts_data {
+	struct i2c_client *client;
+	struct input_dev *input;
+	const struct pixcir_ts_platform_data *chip;
+	bool exiting;
+};
+
+static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
+{
+	struct pixcir_i2c_ts_data *tsdata = data;
+	u8 rdbuf[10], wrbuf[1] = { 0 };
+	u8 touch, old_touch;
+	int ret;
+
+	ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
+	if (ret != sizeof(wrbuf)) {
+		dev_err(&tsdata->client->dev,
+			"%s: i2c_master_send failed(), ret=%d\n",
+			__func__, ret);
+		return;
+	}
+
+	ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
+	if (ret != sizeof(rdbuf)) {
+		dev_err(&tsdata->client->dev,
+			"%s: i2c_master_recv failed(), ret=%d\n",
+			__func__, ret);
+		return;
+	}
+
+	touch = rdbuf[0];
+	old_touch = rdbuf[1];
+	if (touch) {
+		u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
+		u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
+		u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
+		u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
+
+		input_report_key(tsdata->input, BTN_TOUCH, 1);
+		input_report_abs(tsdata->input, ABS_X, posx1);
+		input_report_abs(tsdata->input, ABS_Y, posy1);
+
+		input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
+		input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
+		input_mt_sync(tsdata->input);
+
+		if (touch == 2) {
+			input_report_abs(tsdata->input,
+					 ABS_MT_POSITION_X, posx2);
+			input_report_abs(tsdata->input,
+					 ABS_MT_POSITION_Y, posy2);
+			input_mt_sync(tsdata->input);
+		}
+	} else {
+		input_report_key(tsdata->input, BTN_TOUCH, 0);
+		if (old_touch)
+			input_mt_sync(tsdata->input);
+	}
+
+	input_sync(tsdata->input);
+}
+
+static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
+{
+	struct pixcir_i2c_ts_data *tsdata = dev_id;
+
+	while (!tsdata->exiting) {
+		pixcir_ts_poscheck(tsdata);
+
+		if (tsdata->chip->attb_read_val())
+			break;
+
+		msleep(20);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pixcir_i2c_ts_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(client->irq);
+
+	return 0;
+}
+
+static int pixcir_i2c_ts_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(client->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
+			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
+
+static int __devinit pixcir_i2c_ts_probe(struct i2c_client *client,
+					 const struct i2c_device_id *id)
+{
+	const struct pixcir_ts_platform_data *pdata = client->dev.platform_data;
+	struct pixcir_i2c_ts_data *tsdata;
+	struct input_dev *input;
+	int error;
+
+	if (!pdata) {
+		dev_err(&client->dev, "platform data not defined\n");
+		return -EINVAL;
+	}
+
+	tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!tsdata || !input) {
+		dev_err(&client->dev, "Failed to allocate driver data!\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	tsdata->client = client;
+	tsdata->input = input;
+	tsdata->chip = pdata;
+
+	input->name = client->name;
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(EV_ABS, input->evbit);
+	__set_bit(BTN_TOUCH, input->keybit);
+	input_set_abs_params(input, ABS_X, 0, pdata->x_max, 0, 0);
+	input_set_abs_params(input, ABS_Y, 0, pdata->y_max, 0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
+
+	input_set_drvdata(input, tsdata);
+
+	error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr,
+				     IRQF_TRIGGER_FALLING,
+				     client->name, tsdata);
+	if (error) {
+		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+		goto err_free_mem;
+	}
+
+	error = input_register_device(input);
+	if (error)
+		goto err_free_irq;
+
+	i2c_set_clientdata(client, tsdata);
+	device_init_wakeup(&client->dev, 1);
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, tsdata);
+err_free_mem:
+	input_free_device(input);
+	kfree(tsdata);
+	return error;
+}
+
+static int __devexit pixcir_i2c_ts_remove(struct i2c_client *client)
+{
+	struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
+
+	device_init_wakeup(&client->dev, 0);
+
+	tsdata->exiting = true;
+	mb();
+	free_irq(client->irq, tsdata);
+
+	input_unregister_device(tsdata->input);
+	kfree(tsdata);
+
+	return 0;
+}
+
+static const struct i2c_device_id pixcir_i2c_ts_id[] = {
+	{ "pixcir_ts", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
+
+static struct i2c_driver pixcir_i2c_ts_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "pixcir_ts",
+		.pm	= &pixcir_dev_pm_ops,
+	},
+	.probe		= pixcir_i2c_ts_probe,
+	.remove		= __devexit_p(pixcir_i2c_ts_remove),
+	.id_table	= pixcir_i2c_ts_id,
+};
+
+static int __init pixcir_i2c_ts_init(void)
+{
+	return i2c_add_driver(&pixcir_i2c_ts_driver);
+}
+module_init(pixcir_i2c_ts_init);
+
+static void __exit pixcir_i2c_ts_exit(void)
+{
+	i2c_del_driver(&pixcir_i2c_ts_driver);
+}
+module_exit(pixcir_i2c_ts_exit);
+
+MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
+MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h
new file mode 100644
index 0000000..7163d91
--- /dev/null
+++ b/include/linux/input/pixcir_ts.h
@@ -0,0 +1,10 @@
+#ifndef	_PIXCIR_I2C_TS_H
+#define	_PIXCIR_I2C_TS_H
+
+struct pixcir_ts_platform_data {
+	int (*attb_read_val)(void);
+	int x_max;
+	int y_max;
+};
+
+#endif

  reply	other threads:[~2011-07-09 20:12 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-24  3:25 [PATCH v3] input: add driver for pixcir i2c touchscreens jcbian
2011-07-04 16:50 ` Dmitry Torokhov
2011-07-05 19:30   ` Henrik Rydberg
2011-07-09 20:12     ` Dmitry Torokhov [this message]
2011-07-23 18:18       ` Henrik Rydberg
2011-07-14  2:21     ` jcbian
2011-07-23 18:24       ` Henrik Rydberg
2011-07-04 20:49 ` Henrik Rydberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110709201209.GA27874@core.coreip.homeip.net \
    --to=dmitry.torokhov@gmail.com \
    --cc=dqmeng@pixcir.com.cn \
    --cc=jcbian@pixcir.com.cn \
    --cc=linux-input@vger.kernel.org \
    --cc=rydberg@euromail.se \
    --cc=zlchen@pixcir.com.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.