From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Roger Quadros <rogerq@ti.com>
Cc: rydberg@euromail.se, jcbian@pixcir.com.cn,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH 7/9] Input: pixcir_i2c_ts: Implement Type B Multi Touch reporting
Date: Wed, 18 Dec 2013 06:18:41 -0800 [thread overview]
Message-ID: <20131218141841.GE28504@core.coreip.homeip.net> (raw)
In-Reply-To: <1387358480-8313-8-git-send-email-rogerq@ti.com>
On Wed, Dec 18, 2013 at 02:51:18PM +0530, Roger Quadros wrote:
> Some pixcir controllers e.g. tangoC family report finger IDs with
> the co-ordinates and are more suitable for Type-B MT protocol.
>
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
> ---
> drivers/input/touchscreen/pixcir_i2c_ts.c | 202 +++++++++++++++++++++++-------
> 1 file changed, 155 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
> index ff68246..9e14415 100644
> --- a/drivers/input/touchscreen/pixcir_i2c_ts.c
> +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
> @@ -23,84 +23,173 @@
> #include <linux/slab.h>
> #include <linux/i2c.h>
> #include <linux/input.h>
> +#include <linux/input/mt.h>
> #include <linux/input/pixcir_ts.h>
> #include <linux/gpio.h>
> #include <linux/of.h>
> #include <linux/of_gpio.h>
> #include <linux/of_device.h>
>
> +#define MAX_FINGERS 5 /* Maximum supported by the driver */
> +
> struct pixcir_i2c_ts_data {
> struct i2c_client *client;
> struct input_dev *input;
> const struct pixcir_ts_platform_data *pdata;
> bool exiting;
> + u8 max_fingers; /* Maximum supported by the chip */
> };
>
> -static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
> +static void pixcir_ts_typea_report(struct pixcir_i2c_ts_data *tsdata)
Hmm, I do not think we should keep Type A reports if we can do Type B.
The protocols are not new and userspace should be able to handle MT-B by
now.
> {
> - struct pixcir_i2c_ts_data *tsdata = data;
> + const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
> u8 rdbuf[10], wrbuf[1] = { 0 };
> u8 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;
> - }
> + while (!tsdata->exiting) {
>
> - 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;
> - }
> + 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];
> - 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);
> + touch = rdbuf[0];
> + 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);
> }
> - } else {
> - input_report_key(tsdata->input, BTN_TOUCH, 0);
> - }
>
> - input_sync(tsdata->input);
> + input_sync(tsdata->input);
> +
> + if (gpio_get_value(pdata->gpio_attb))
> + break;
> +
> + msleep(20);
> + }
> }
>
> -static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
> +static void pixcir_ts_typeb_report(struct pixcir_i2c_ts_data *ts)
> {
> - struct pixcir_i2c_ts_data *tsdata = dev_id;
> - const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
> + const struct pixcir_ts_platform_data *pdata = ts->pdata;
> + struct device *dev = &ts->client->dev;
> + u8 rdbuf[32], wrbuf[1] = { 0 };
> + u8 *bufptr;
> + u8 num_fingers;
> + u8 unreliable;
> + int ret, i;
> +
> + while (!ts->exiting) {
> +
> + ret = i2c_master_send(ts->client, wrbuf, sizeof(wrbuf));
> + if (ret != sizeof(wrbuf)) {
> + dev_err(dev, "%s: i2c_master_send failed(), ret=%d\n",
> + __func__, ret);
> + return;
> + }
>
> - while (!tsdata->exiting) {
> - pixcir_ts_poscheck(tsdata);
> + ret = i2c_master_recv(ts->client, rdbuf, sizeof(rdbuf));
> + if (ret != sizeof(rdbuf)) {
> + dev_err(dev, "%s: i2c_master_recv failed(), ret=%d\n",
> + __func__, ret);
> + return;
> + }
> +
> + unreliable = rdbuf[0] & 0xe0;
> +
> + if (unreliable)
> + goto next; /* ignore unreliable data */
> +
> + num_fingers = rdbuf[0] & 0x7;
> + bufptr = &rdbuf[2];
>
> + if (num_fingers > ts->max_fingers) {
> + num_fingers = ts->max_fingers;
> + dev_dbg(dev, "limiting num_fingers to %d\n",
> + num_fingers);
> + }
> +
> + for (i = 0; i < num_fingers; i++) {
> + u8 id;
> + unsigned int x, y;
> + int slot;
> +
> + id = bufptr[4];
> + slot = input_mt_get_slot_by_key(ts->input, id);
> + if (slot < 0) {
> + dev_dbg(dev, "no free slot for id 0x%x\n", id);
> + continue;
> + }
> +
> +
> + x = bufptr[1] << 8 | bufptr[0];
> + y = bufptr[3] << 8 | bufptr[2];
> +
> + input_mt_slot(ts->input, slot);
> + input_mt_report_slot_state(ts->input,
> + MT_TOOL_FINGER, true);
> +
> + input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, x);
> + input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, y);
> +
> + bufptr = &bufptr[5];
> + dev_dbg(dev, "%d: id 0x%x slot %d, x %d, y %d\n",
> + i, id, slot, x, y);
> + }
> +
> + /* One frame is complete so sync it */
> + input_mt_sync_frame(ts->input);
> + input_sync(ts->input);
> +
> +next:
> if (gpio_get_value(pdata->gpio_attb))
> break;
>
> - msleep(20);
> + usleep_range(2000, 5000);
> }
> +}
> +
> +static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
> +{
> + struct pixcir_i2c_ts_data *tsdata = dev_id;
> +
> + if (tsdata->input->mt)
> + pixcir_ts_typeb_report(tsdata);
> + else
> + pixcir_ts_typea_report(tsdata);
>
> return IRQ_HANDLED;
> }
> @@ -376,9 +465,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
> input->open = pixcir_input_open;
> input->close = pixcir_input_close;
>
> - __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_size - 1, 0, 0);
> input_set_abs_params(input, ABS_Y,
> @@ -388,6 +477,25 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
> input_set_abs_params(input, ABS_MT_POSITION_Y,
> 0, pdata->y_size - 1, 0, 0);
>
> + /* Type-B Multi-Touch support */
> + if (pdata->chip.num_report_ids) {
> + const struct pixcir_i2c_chip_data *chip = &pdata->chip;
> +
> + tsdata->max_fingers = chip->num_report_ids;
> + if (tsdata->max_fingers > MAX_FINGERS) {
> + dev_info(dev, "Limiting maximum fingers to %d\n",
> + MAX_FINGERS);
> + tsdata->max_fingers = MAX_FINGERS;
> + }
> +
> + error = input_mt_init_slots(input, tsdata->max_fingers,
> + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
> + if (error) {
> + dev_err(dev, "Error initializing Multi-Touch slots\n");
> + return error;
> + }
> + }
> +
> input_set_drvdata(input, tsdata);
>
> error = devm_gpio_request_one(dev, pdata->gpio_attb,
> --
> 1.8.3.2
>
--
Dmitry
next prev parent reply other threads:[~2013-12-18 14:18 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-18 9:21 [PATCH 0/9] Input: pixcir_i2c_ts: Add Type-B Multitouch support Roger Quadros
2013-12-18 9:21 ` [PATCH 1/9] Input: pixcir_i2c_ts: Add device tree support Roger Quadros
2013-12-18 14:09 ` Dmitry Torokhov
2013-12-19 6:12 ` Roger Quadros
2013-12-18 9:21 ` [PATCH 2/9] Input: pixcir_i2c_ts: Add register definitions Roger Quadros
2013-12-18 14:09 ` Dmitry Torokhov
2013-12-18 9:21 ` [PATCH 3/9] Input: pixcir_i2c_ts: Initialize interrupt mode and power mode Roger Quadros
[not found] ` <1387358480-8313-4-git-send-email-rogerq-l0cyMroinI0@public.gmane.org>
2013-12-18 14:14 ` Dmitry Torokhov
2013-12-19 5:57 ` Roger Quadros
2013-12-18 9:21 ` [PATCH 4/9] Input: pixcir_i2c_ts: Use devres managed resource allocations Roger Quadros
2013-12-18 14:15 ` Dmitry Torokhov
2013-12-18 9:21 ` [PATCH 5/9] Input: pixcir_i2c_ts: Get rid of pdata->attb_read_val() Roger Quadros
2013-12-18 14:20 ` Dmitry Torokhov
2013-12-19 5:54 ` Roger Quadros
2013-12-18 9:21 ` [PATCH 6/9] Input: pixcir_i2c_ts: Add chip specific data structure Roger Quadros
2013-12-18 9:21 ` [PATCH 7/9] Input: pixcir_i2c_ts: Implement Type B Multi Touch reporting Roger Quadros
2013-12-18 14:18 ` Dmitry Torokhov [this message]
[not found] ` <20131218141841.GE28504-WlK9ik9hQGAhIp7JRqBPierSzoNAToWh@public.gmane.org>
2013-12-19 5:49 ` Roger Quadros
2013-12-21 20:02 ` Henrik Rydberg
2013-12-18 9:21 ` [PATCH 8/9] Input: pixcir_i2c_ts: Add support for TangoC family Roger Quadros
2013-12-18 9:21 ` [PATCH 9/9] Input: pixcir_i2c_ts: Implement wakeup from suspend Roger Quadros
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=20131218141841.GE28504@core.coreip.homeip.net \
--to=dmitry.torokhov@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=jcbian@pixcir.com.cn \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rogerq@ti.com \
--cc=rydberg@euromail.se \
/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 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).