All of lore.kernel.org
 help / color / mirror / Atom feed
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

  reply	other threads:[~2013-12-18 14:18 UTC|newest]

Thread overview: 36+ 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 ` Roger Quadros
2013-12-18  9:21 ` [PATCH 1/9] Input: pixcir_i2c_ts: Add device tree support Roger Quadros
2013-12-18  9:21   ` Roger Quadros
2013-12-18 14:09   ` Dmitry Torokhov
2013-12-19  6:12     ` Roger Quadros
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  9:21   ` 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
2013-12-18  9:21   ` Roger Quadros
2013-12-18 14:14   ` Dmitry Torokhov
2013-12-18 14:14     ` Dmitry Torokhov
2013-12-19  5:57     ` Roger Quadros
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  9:21   ` 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  9:21   ` Roger Quadros
2013-12-18 14:20   ` Dmitry Torokhov
2013-12-19  5:54     ` Roger Quadros
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   ` 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  9:21   ` Roger Quadros
2013-12-18 14:18   ` Dmitry Torokhov [this message]
2013-12-19  5:49     ` Roger Quadros
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   ` Roger Quadros
2013-12-18  9:21 ` [PATCH 9/9] Input: pixcir_i2c_ts: Implement wakeup from suspend Roger Quadros
2013-12-18  9:21   ` 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 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.