devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Maxime Ripard
	<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>,
	Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>,
	Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	Henrik Rydberg <rydberg-FFUHeuDi6mxAfugRpC6u6w@public.gmane.org>,
	Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>,
	Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>,
	Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Jarkko Sakkinen
	<jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>,
	Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>,
	Rask Ingemann Lambertsen
	<ccc94453-1EA3ORoCGBhoJ7GROcy7lA@public.gmane.org>,
	Greg Kroah-Hartman
	<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
	Geert Uytterhoeven
	<geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>,
	Andrew Morton
	<akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>,
	Michael Welling <mwelling-EkmVulN54Sk@public.gmane.org>,
	Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
	Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
	Damien Riegel
	<damien.riegel-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org>,
	Benjamin Tissoires
	<benjamin.tissoires-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	Jeffrey Lin <jeffrey.lin-s3Ivl27awEzQT0dZR+AlfA@public.gmane.org>,
	Javier
Subject: Re: [PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC
Date: Tue, 11 Oct 2016 10:40:46 -0700	[thread overview]
Message-ID: <20161011174046.GA27925@dtor-ws> (raw)
In-Reply-To: <20161011003359.26079-3-icenowy-ymACFijhrKM@public.gmane.org>

Hi Icenowy,

On Tue, Oct 11, 2016 at 08:33:57AM +0800, Icenowy Zheng wrote:
> This driver adds support for Ilitek ili2139 touch IC, which is used in
> several Colorfly tablets (for example, Colorfly E708 Q1, which is an
> Allwinner A31s tablet with mainline kernel support).
> 
> Theortically it may support more Ilitek touch ICs, however, only ili2139
> is used in any mainlined device.
> 
> It supports device tree enumeration, with screen resolution and axis
> quirks configurable.
> 
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

Please extend ili210x.c instead of adding brand new driver, they look
very similar.

Thanks.

> ---
>  drivers/input/touchscreen/Kconfig   |  14 ++
>  drivers/input/touchscreen/Makefile  |   1 +
>  drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 335 insertions(+)
>  create mode 100644 drivers/input/touchscreen/ili2139.c
> 
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 5079813..bb4d9d2 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called ili210x.
>  
> +config TOUCHSCREEN_ILI2139
> +	tristate "Ilitek ILI2139 based touchscreen"
> +	depends on I2C
> +	depends on OF
> +	help
> +	  Say Y here if you have a ILI2139 based touchscreen
> +	  controller. Such kind of chipsets can be found in several
> +	  Colorfly tablets.
> +
> +	  If unsure, say N.
> +
> +	  To compile this driver as a module, choose M here; the
> +	  module will be called ili2139.
> +
>  config TOUCHSCREEN_IPROC
>  	tristate "IPROC touch panel driver support"
>  	depends on ARCH_BCM_IPROC || COMPILE_TEST
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 81b8645..930b5e2 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)	+= egalax_ts_serial.o
>  obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
>  obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix.o
>  obj-$(CONFIG_TOUCHSCREEN_ILI210X)	+= ili210x.o
> +obj-$(CONFIG_TOUCHSCREEN_ILI2139)	+= ili2139.o
>  obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC)	+= imx6ul_tsc.o
>  obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
>  obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
> diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c
> new file mode 100644
> index 0000000..65c2dea
> --- /dev/null
> +++ b/drivers/input/touchscreen/ili2139.c
> @@ -0,0 +1,320 @@
> +/* -------------------------------------------------------------------------
> + * Copyright (C) 2016, Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> + *
> + * Derived from:
> + *  ili210x.c
> + *  Copyright (C) Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  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.
> + * -------------------------------------------------------------------------
> + */
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <linux/input.h>
> +#include <linux/input/mt.h>
> +#include <linux/input/touchscreen.h>
> +#include <linux/delay.h>
> +#include <linux/workqueue.h>
> +
> +#define DEFAULT_POLL_PERIOD	20
> +
> +#define MAX_TOUCHES		10
> +#define COMPATIBLE_TOUCHES	2
> +
> +/* Touchscreen commands */
> +#define REG_TOUCHDATA		0x10
> +#define REG_TOUCHSUBDATA	0x11
> +#define REG_PANEL_INFO		0x20
> +#define REG_FIRMWARE_VERSION	0x40
> +#define REG_PROTO_VERSION	0x42
> +
> +#define SUBDATA_STATUS_TOUCH_POINT	0x80
> +#define SUBDATA_STATUS_RELEASE_POINT	0x00
> +
> +struct finger {
> +	u8 x_low;
> +	u8 x_high;
> +	u8 y_low;
> +	u8 y_high;
> +} __packed;
> +
> +struct touchdata {
> +	u8 length;
> +	struct finger finger[COMPATIBLE_TOUCHES];
> +} __packed;
> +
> +struct touch_subdata {
> +	u8 status;
> +	struct finger finger;
> +} __packed;
> +
> +struct panel_info {
> +	struct finger finger_max;
> +	u8 xchannel_num;
> +	u8 ychannel_num;
> +} __packed;
> +
> +struct firmware_version {
> +	u8 id;
> +	u8 major;
> +	u8 minor;
> +} __packed;
> +
> +struct ili2139 {
> +	struct i2c_client *client;
> +	struct input_dev *input;
> +	unsigned int poll_period;
> +	struct delayed_work dwork;
> +	struct touchscreen_properties prop;
> +	int slots[MAX_TOUCHES];
> +	int ids[MAX_TOUCHES];
> +	struct input_mt_pos pos[MAX_TOUCHES];
> +};
> +
> +static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf,
> +			    size_t len)
> +{
> +	struct i2c_msg msg[2] = {
> +		{
> +			.addr	= client->addr,
> +			.flags	= 0,
> +			.len	= 1,
> +			.buf	= &reg,
> +		},
> +		{
> +			.addr	= client->addr,
> +			.flags	= I2C_M_RD,
> +			.len	= len,
> +			.buf	= buf,
> +		}
> +	};
> +
> +	if (i2c_transfer(client->adapter, msg, 2) != 2) {
> +		dev_err(&client->dev, "i2c transfer failed\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static void ili2139_work(struct work_struct *work)
> +{
> +	int id;
> +	struct ili2139 *priv = container_of(work, struct ili2139,
> +					    dwork.work);
> +	struct i2c_client *client = priv->client;
> +	struct touchdata touchdata;
> +	struct touch_subdata subdata;
> +	int error;
> +
> +	error = ili2139_read_reg(client, REG_TOUCHDATA,
> +				 &touchdata, sizeof(touchdata));
> +	if (error) {
> +		dev_err(&client->dev,
> +			"Unable to get touchdata, err = %d\n", error);
> +		return;
> +	}
> +
> +	for (id = 0; id < touchdata.length; id++) {
> +		error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata,
> +					 sizeof(subdata));
> +		if (error) {
> +			dev_err(&client->dev,
> +				"Unable to get touch subdata, err = %d\n",
> +				error);
> +			return;
> +		}
> +
> +		priv->ids[id] = subdata.status & 0x3F;
> +
> +		/* The sequence changed in the v2 subdata protocol. */
> +		touchscreen_set_mt_pos(&priv->pos[id], &priv->prop,
> +			(subdata.finger.x_high | (subdata.finger.x_low << 8)),
> +			(subdata.finger.y_high | (subdata.finger.y_low << 8)));
> +	}
> +
> +	input_mt_assign_slots(priv->input, priv->slots, priv->pos,
> +			      touchdata.length, 0);
> +
> +	for (id = 0; id < touchdata.length; id++) {
> +		input_mt_slot(priv->input, priv->slots[id]);
> +		input_mt_report_slot_state(priv->input, MT_TOOL_FINGER,
> +					   subdata.status &
> +					   SUBDATA_STATUS_TOUCH_POINT);
> +		input_report_abs(priv->input, ABS_MT_POSITION_X,
> +				 priv->pos[id].x);
> +		input_report_abs(priv->input, ABS_MT_POSITION_Y,
> +				 priv->pos[id].y);
> +	}
> +
> +	input_mt_sync_frame(priv->input);
> +	input_sync(priv->input);
> +
> +	schedule_delayed_work(&priv->dwork,
> +			      msecs_to_jiffies(priv->poll_period));
> +}
> +
> +static irqreturn_t ili2139_irq(int irq, void *irq_data)
> +{
> +	struct ili2139 *priv = irq_data;
> +
> +	schedule_delayed_work(&priv->dwork, 0);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int ili2139_i2c_probe(struct i2c_client *client,
> +				       const struct i2c_device_id *id)
> +{
> +	struct device *dev = &client->dev;
> +	struct ili2139 *priv;
> +	struct input_dev *input;
> +	struct panel_info panel;
> +	struct firmware_version firmware;
> +	int xmax, ymax;
> +	int error;
> +
> +	dev_dbg(dev, "Probing for ILI2139 I2C Touschreen driver");
> +
> +	if (client->irq <= 0) {
> +		dev_err(dev, "No IRQ!\n");
> +		return -ENODEV;
> +	}
> +
> +	/* Get firmware version */
> +	error = ili2139_read_reg(client, REG_FIRMWARE_VERSION,
> +				 &firmware, sizeof(firmware));
> +	if (error) {
> +		dev_err(dev, "Failed to get firmware version, err: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	/* get panel info */
> +	error = ili2139_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
> +	if (error) {
> +		dev_err(dev, "Failed to get panel information, err: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
> +	ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	input = devm_input_allocate_device(dev);
> +	if (!priv || !input)
> +		return -ENOMEM;
> +
> +	priv->client = client;
> +	priv->input = input;
> +	priv->poll_period = DEFAULT_POLL_PERIOD;
> +	INIT_DELAYED_WORK(&priv->dwork, ili2139_work);
> +
> +	/* Setup input device */
> +	input->name = "ILI2139 Touchscreen";
> +	input->id.bustype = BUS_I2C;
> +	input->dev.parent = dev;
> +
> +	__set_bit(EV_SYN, input->evbit);
> +	__set_bit(EV_KEY, input->evbit);
> +	__set_bit(EV_ABS, input->evbit);
> +
> +	/* Multi touch */
> +	input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT |
> +			    INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);
> +	input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
> +	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
> +
> +	touchscreen_parse_properties(input, true, &priv->prop);
> +
> +	input_set_drvdata(input, priv);
> +	i2c_set_clientdata(client, priv);
> +
> +	error = devm_request_irq(dev, client->irq, ili2139_irq,
> +				 IRQF_TRIGGER_FALLING, client->name, priv);
> +	if (error) {
> +		dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
> +			error);
> +		return error;
> +	}
> +
> +	error = input_register_device(priv->input);
> +	if (error) {
> +		dev_err(dev, "Cannot register input device, err: %d\n", error);
> +		return error;
> +	}
> +
> +	device_init_wakeup(&client->dev, 1);
> +
> +	dev_dbg(dev,
> +		"ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d",
> +		client->irq, firmware.id, firmware.major, firmware.minor);
> +
> +	return 0;
> +}
> +
> +static int ili2139_i2c_remove(struct i2c_client *client)
> +{
> +	struct ili2139 *priv = i2c_get_clientdata(client);
> +
> +	cancel_delayed_work_sync(&priv->dwork);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused ili2139_i2c_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 __maybe_unused ili2139_i2c_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;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm,
> +			 ili2139_i2c_suspend, ili2139_i2c_resume);
> +
> +static const struct i2c_device_id ili2139_i2c_id[] = {
> +	{ "ili2139", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id);
> +
> +static struct i2c_driver ili2139_ts_driver = {
> +	.driver = {
> +		.name = "ili2139_i2c",
> +		.pm = &ili2139_i2c_pm,
> +	},
> +	.id_table = ili2139_i2c_id,
> +	.probe = ili2139_i2c_probe,
> +	.remove = ili2139_i2c_remove,
> +};
> +
> +module_i2c_driver(ili2139_ts_driver);
> +
> +MODULE_AUTHOR("Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>");
> +MODULE_DESCRIPTION("ILI2139 I2C Touchscreen Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.10.1
> 

-- 
Dmitry

  parent reply	other threads:[~2016-10-11 17:40 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-11  0:33 [PATCH 1/5] dt-bindings: add vendor prefix for ILI Technology Corp Icenowy Zheng
     [not found] ` <20161011003359.26079-1-icenowy-ymACFijhrKM@public.gmane.org>
2016-10-11  0:33   ` [PATCH 2/5] dt-bindings: add binding for Ilitek ili2139 touchscreen IC Icenowy Zheng
2016-10-11  0:33   ` [PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC Icenowy Zheng
     [not found]     ` <20161011003359.26079-3-icenowy-ymACFijhrKM@public.gmane.org>
2016-10-11  9:37       ` Hans de Goede
2016-10-11 17:40       ` Dmitry Torokhov [this message]
2016-10-11 18:34         ` Icenowy Zheng
     [not found]           ` <220181476210841-OHkeJ68Zrv9uio3avFS2gg@public.gmane.org>
2016-10-11 18:51             ` Dmitry Torokhov
2016-10-11  0:33   ` [PATCH 4/5] MAINTAINERS: Add myself as maintainer of ili2139 touchscreen driver Icenowy Zheng
2016-10-11  0:33   ` [PATCH 5/5] ARM: dts: sun6i: enable ili2139 on Colorfly E708 Q1 Icenowy Zheng
2016-10-11  3:13   ` [PATCH 1/5] dt-bindings: add vendor prefix for ILI Technology Corp Dmitry Torokhov
     [not found]     ` <CAKdAkRT0WJ8EL62bumM1yz58LEAEqvmeX_hYzOZzAA0RvxJa3A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-11  3:39       ` Icenowy Zheng
  -- strict thread matches above, loose matches on Subject: below --
2016-10-11 10:21 [PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC Icenowy Zheng
     [not found] ` <20161011132149.LZ40KToV-7L+JOpG+lXQ0PDqKvflMoHmW9unr2Ajn@public.gmane.org>
2016-10-12 14:57   ` Hans de Goede

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=20161011174046.GA27925@dtor-ws \
    --to=dmitry.torokhov-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=arnd-r2nGTMty4D4@public.gmane.org \
    --cc=benjamin.tissoires-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=ccc94453-1EA3ORoCGBhoJ7GROcy7lA@public.gmane.org \
    --cc=damien.riegel-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org \
    --cc=geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org \
    --cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
    --cc=hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=icenowy-ymACFijhrKM@public.gmane.org \
    --cc=jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
    --cc=jeffrey.lin-s3Ivl27awEzQT0dZR+AlfA@public.gmane.org \
    --cc=linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org \
    --cc=marex-ynQEQJNshbs@public.gmane.org \
    --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
    --cc=maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org \
    --cc=mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
    --cc=mwelling-EkmVulN54Sk@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=rydberg-FFUHeuDi6mxAfugRpC6u6w@public.gmane.org \
    --cc=shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org \
    --cc=wens-jdAy2FN1RRM@public.gmane.org \
    /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).