* Re: [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1
[not found] <201512071608.oGt2n0Wn%fengguang.wu@intel.com>
@ 2015-12-07 8:34 ` Julia Lawall
2015-12-07 9:10 ` Priit Laes
0 siblings, 1 reply; 5+ messages in thread
From: Julia Lawall @ 2015-12-07 8:34 UTC (permalink / raw)
To: Priit Laes
Cc: Maxime Ripard, Chen-Yu Tsai, Dmitry Torokhov, Rob Herring,
Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, devicetree,
linux-kernel, linux-arm-kernel, linux-input, Aleksei Mamlin,
linux-sunxi, Priit Laes, kbuild-all
It looks like braces may be mising. Please check.
julia
On Mon, 7 Dec 2015, kbuild test robot wrote:
> Hi Priit,
>
> [auto build test WARNING on mripard/sunxi/for-next]
> [also build test WARNING on next-20151203]
> [cannot apply to input/next v4.4-rc4]
>
> url: https://github.com/0day-ci/linux/commits/Priit-Laes/input-Driver-for-Goodix-GT801-2-1-touchscreen/20151207-152831
> base: https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git sunxi/for-next
> :::::: branch date: 46 minutes ago
> :::::: commit date: 46 minutes ago
>
> >> drivers/input/touchscreen/gt801_2plus1.c:119:3-30: code aligned with following code on line 120
>
> git remote add linux-review https://github.com/0day-ci/linux
> git remote update linux-review
> git checkout d66df313f96e04572821e49cada65cb5c1bea9e2
> vim +119 drivers/input/touchscreen/gt801_2plus1.c
>
> d66df313 Priit Laes 2015-12-07 113 return;
> d66df313 Priit Laes 2015-12-07 114
> d66df313 Priit Laes 2015-12-07 115 /* Build touch map */
> d66df313 Priit Laes 2015-12-07 116 touch_num = 0;
> d66df313 Priit Laes 2015-12-07 117 for (i = 0; (touch_raw != 0) && (i < ts->max_touch_num); i++) {
> d66df313 Priit Laes 2015-12-07 118 if (touch_raw & 1)
> d66df313 Priit Laes 2015-12-07 @119 touch_map[touch_num++] = i;
> d66df313 Priit Laes 2015-12-07 @120 touch_raw >>= 1;
> d66df313 Priit Laes 2015-12-07 121 }
> d66df313 Priit Laes 2015-12-07 122
> d66df313 Priit Laes 2015-12-07 123 /* Calculate checksum */
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1
2015-12-07 8:34 ` [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1 Julia Lawall
@ 2015-12-07 9:10 ` Priit Laes
0 siblings, 0 replies; 5+ messages in thread
From: Priit Laes @ 2015-12-07 9:10 UTC (permalink / raw)
To: Julia Lawall
Cc: Maxime Ripard, Chen-Yu Tsai, Dmitry Torokhov, Rob Herring,
Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, devicetree,
linux-kernel, linux-arm-kernel, linux-input, Aleksei Mamlin,
linux-sunxi, kbuild-all
On Mon, 2015-12-07 at 09:34 +0100, Julia Lawall wrote:
> It looks like braces may be mising. Please check.
Thanks, nice catch!
It's actually messed up indenting. Code works as intended.
>
> julia
>
> On Mon, 7 Dec 2015, kbuild test robot wrote:
>
> > Hi Priit,
> >
> > [auto build test WARNING on mripard/sunxi/for-next]
> > [also build test WARNING on next-20151203]
> > [cannot apply to input/next v4.4-rc4]
> >
> > url: https://github.com/0day-ci/linux/commits/Priit-Laes/input-D
> river-for-Goodix-GT801-2-1-touchscreen/20151207-152831
> > base: https://git.kernel.org/pub/scm/linux/kernel/git/mripard/lin
> ux.git sunxi/for-next
> > :::::: branch date: 46 minutes ago
> > :::::: commit date: 46 minutes ago
> >
> > >> drivers/input/touchscreen/gt801_2plus1.c:119:3-30: code aligned
> with following code on line 120
> >
> > git remote add linux-review https://github.com/0day-ci/linux
> > git remote update linux-review
> > git checkout d66df313f96e04572821e49cada65cb5c1bea9e2
> > vim +119 drivers/input/touchscreen/gt801_2plus1.c
> >
> > d66df313 Priit Laes 2015-12-07 113 return;
> > d66df313 Priit Laes 2015-12-07 114
> > d66df313 Priit Laes 2015-12-07 115 /* Build touch map */
> > d66df313 Priit Laes 2015-12-07 116 touch_num = 0;
> > d66df313 Priit Laes 2015-12-07 117 for (i = 0; (touch_raw != 0)
> && (i < ts->max_touch_num); i++) {
> > d66df313 Priit Laes 2015-12-07 118 if (touch_raw & 1)
> > d66df313 Priit Laes 2015-12-07
> @119 touch_map[touch_num++] = i;
> > d66df313 Priit Laes 2015-12-07 @120 touch_raw >>=
> 1;
> > d66df313 Priit Laes 2015-12-07 121 }
> > d66df313 Priit Laes 2015-12-07 122
> > d66df313 Priit Laes 2015-12-07 123 /* Calculate checksum */
> >
> > ---
> > 0-DAY kernel test infrastructure Open Source
> Technology Center
> > https://lists.01.org/pipermail/kbuild-all ; Intel
> Corporation
> >
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1
2015-12-07 7:26 ` [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1 Priit Laes
2015-12-08 12:14 ` Bastien Nocera
@ 2015-12-08 15:18 ` Rob Herring
1 sibling, 0 replies; 5+ messages in thread
From: Rob Herring @ 2015-12-08 15:18 UTC (permalink / raw)
To: Priit Laes
Cc: Maxime Ripard, Chen-Yu Tsai, Dmitry Torokhov, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, devicetree, linux-kernel,
linux-arm-kernel, linux-input, Aleksei Mamlin, linux-sunxi
On Mon, Dec 07, 2015 at 09:26:01AM +0200, Priit Laes wrote:
> This patch adds Goodix GT801 2+1 touchscreen controller support.
>
> GT801 2+1 is a 10-finger touch controller consisting of
> ARM controller interfacing two GT801 5-finger controllers.
>
> Signed-off-by: Priit Laes <plaes@plaes.org>
> ---
> .../bindings/input/touchscreen/gt801_2plus1.txt | 23 ++
For the binding:
Acked-by: Rob Herring <robh@kernel.org>
> MAINTAINERS | 6 +
> drivers/input/touchscreen/Kconfig | 19 +-
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/gt801_2plus1.c | 375 +++++++++++++++++++++
> 5 files changed, 421 insertions(+), 3 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt
> create mode 100644 drivers/input/touchscreen/gt801_2plus1.c
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt b/Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt
> new file mode 100644
> index 0000000..070ff5b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt
> @@ -0,0 +1,23 @@
> +Device tree bindings for Goodix GT801 2+1 series touchscreen controller
> +
> +Required properties:
> +
> + - compatible : Should be "goodix,gt801_2plus1"
> + - reg : I2C address of the chip. Should be 0x55
> + - interrupt-parent : Interrupt controller to which the chip is connected
> + - interrupts : Interrupt to which the chip is connected
> +
> +Example:
> +
> + i2c@00000000 {
> + /* ... */
> +
> + touchscreen@55 {
> + compatible = "goodix,gt801_2plus1";
> + reg = <0x55>;
> + interrupt-parent = <&gpio>;
> + interrupts = <0 0>;
> + };
> +
> + /* ... */
> + };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index cba790b..e292126 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4743,6 +4743,12 @@ L: linux-input@vger.kernel.org
> S: Maintained
> F: drivers/input/touchscreen/goodix.c
>
> +GOODIX GT801 2PLUS1 TOUCHSCREEN
> +M: Priit Laes <plaes@plaes.org>
> +L: linux-input@vger.kernel.org
> +S: Maintained
> +F: drivers/input/touchscreen/gt801_2plus1.c
> +
> GPIO SUBSYSTEM
> M: Linus Walleij <linus.walleij@linaro.org>
> M: Alexandre Courbot <gnurou@gmail.com>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index ae33da7..c7c3324 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -322,11 +322,11 @@ config TOUCHSCREEN_FUJITSU
> module will be called fujitsu-ts.
>
> config TOUCHSCREEN_GOODIX
> - tristate "Goodix I2C touchscreen"
> + tristate "Goodix GT9xx I2C touchscreen"
> depends on I2C
> help
> - Say Y here if you have the Goodix touchscreen (such as one
> - installed in Onda v975w tablets) connected to your
> + Say Y here if you have one of the Goodix GT9xx touchscreens
> + (such as one installed in Onda v975w tablet) connected to your
> system. It also supports 5-finger chip models, which can be
> found on ARM tablets, like Wexler TAB7200 and MSI Primo73.
>
> @@ -335,6 +335,19 @@ config TOUCHSCREEN_GOODIX
> To compile this driver as a module, choose M here: the
> module will be called goodix.
>
> +config TOUCHSCREEN_GT801_2PLUS1
> + tristate "Goodix GT801 2+1 I2C touchscreen"
> + depends on I2C
> + help
> + Say Y here if you have the Goodix GT801 2+1 touchscreen.
> + This controller is found on some older ARM tablets like
> + (Gemei G9 and Zareason Zatab).
> +
> + If unsure, say N.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called gt801_2plus1.
> +
> config TOUCHSCREEN_ILI210X
> tristate "Ilitek ILI210X based touchscreen"
> depends on I2C
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index cbaa6ab..ff25d1b4 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
> obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o
> obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
> obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
> +obj-$(CONFIG_TOUCHSCREEN_GT801_2PLUS1) += gt801_2plus1.o
> obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
> obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
> obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
> diff --git a/drivers/input/touchscreen/gt801_2plus1.c b/drivers/input/touchscreen/gt801_2plus1.c
> new file mode 100644
> index 0000000..e2be479
> --- /dev/null
> +++ b/drivers/input/touchscreen/gt801_2plus1.c
> @@ -0,0 +1,375 @@
> +/*
> + * Driver for Goodix GT801 2+1 ARM touchscreen controllers
> + *
> + * Copyright (c) 2015 Priit Laes <plaes@plaes.org>.
> + *
> + * This code is based on goodix.c driver (c) 2014 Red Hat Inc,
> + * various Android codedumps (c) 2010 - 2012 Goodix Technology
> + * and cleanups done by Emilio López (turl) for linux-sunxi.
> + *
> + * 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; version 2 of the License.
> + */
> +#include <asm/unaligned.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/input/mt.h>
> +
> +struct gt801x_ts_data {
> + struct i2c_client *client;
> + struct input_dev *input_dev;
> + int abs_x_max;
> + int abs_y_max;
> + unsigned int max_touch_num;
> + unsigned int int_trigger_type;
> +};
> +
> +#define GOODIX_MAX_HEIGHT 4096
> +#define GOODIX_MAX_WIDTH 4096
> +#define GOODIX_INT_TRIGGER 1
> +#define GOODIX_MAX_CONTACTS 10
> +#define MAX_CONTACTS_LOC 5
> +#define RESOLUTION_LOC 1
> +#define TRIGGER_LOC 6
> +
> +/* Register defines */
> +#define GT801X_COOR_ADDR 0x01
> +#define GT801X_CONFIG_DATA 0x65
> +#define GT801X_REG_ID 0xf0
> +
> +/* Device specific defines */
> +#define GT801X_CONFIG_MAX_LENGTH 7
> +#define GT801X_CONTACT_SIZE 5
> +
> +static const unsigned long goodix_irq_flags[] = {
> + IRQ_TYPE_EDGE_RISING,
> + IRQ_TYPE_EDGE_FALLING,
> + IRQ_TYPE_LEVEL_LOW,
> + IRQ_TYPE_LEVEL_HIGH,
> +};
> +
> +/**
> + * gt801x_i2c_read - read data from a register of the i2c slave device.
> + *
> + * @client: i2c device.
> + * @reg: the register to read from.
> + * @buf: raw write data buffer.
> + * @len: length of the buffer to write
> + */
> +static int gt801x_i2c_read(struct i2c_client *client,
> + u8 reg, u8 *buf, int len)
> +{
> + struct i2c_msg msgs[2];
> + int ret;
> +
> + msgs[0].flags = 0;
> + msgs[0].addr = client->addr;
> + msgs[0].len = 1;
> + msgs[0].buf = ®
> +
> + msgs[1].flags = I2C_M_RD;
> + msgs[1].addr = client->addr;
> + msgs[1].len = len;
> + msgs[1].buf = buf;
> +
> + ret = i2c_transfer(client->adapter, msgs, 2);
> + return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
> +}
> +
> +/**
> + * gt801x_process_events - Process incoming events
> + *
> + * @ts: our gt801x_ts_data pointer
> + *
> + * Called when the IRQ is triggered. Read the current device state, and push
> + * the input events to the user space.
> + */
> +static void gt801x_process_events(struct gt801x_ts_data *ts)
> +{
> + u8 point_data[3 + GT801X_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
> + u8 touch_map[GOODIX_MAX_CONTACTS] = {0};
> + int input_x, input_y, input_w;
> + u8 checksum = 0;
> + u16 touch_raw;
> + u8 touch_num;
> + int error;
> + int loc;
> + int i;
> +
> + error = gt801x_i2c_read(ts->client, GT801X_COOR_ADDR,
> + point_data, sizeof(point_data));
> + if (error) {
> + dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
> + return;
> + }
> +
> + /* Fetch touch mapping bits */
> + touch_raw = get_unaligned_le16(&point_data[0]);
> + if (!touch_raw)
> + return;
> +
> + /* Build touch map */
> + touch_num = 0;
> + for (i = 0; (touch_raw != 0) && (i < ts->max_touch_num); i++) {
> + if (touch_raw & 1)
> + touch_map[touch_num++] = i;
> + touch_raw >>= 1;
> + }
> +
> + /* Calculate checksum */
> + for (i = 0; i < (touch_num*GT801X_CONTACT_SIZE + 3); i++)
> + checksum += point_data[i];
> + if (checksum != 0)
> + return;
> +
> + /* Report touches */
> + for (i = 0; i < touch_num; i++) {
> + loc = 2 + GT801X_CONTACT_SIZE * i;
> + input_x = get_unaligned_be16(&point_data[loc]);
> + input_y = get_unaligned_be16(&point_data[loc + 2]);
> + input_w = point_data[loc + 4];
> +
> + input_mt_slot(ts->input_dev, i);
> + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
> + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
> + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
> + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
> + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
> + }
> +
> + input_mt_sync_frame(ts->input_dev);
> + input_sync(ts->input_dev);
> +}
> +
> +/**
> + * gt801x_ts_irq_handler - The IRQ handler
> + *
> + * @irq: interrupt number.
> + * @dev_id: private data pointer.
> + */
> +static irqreturn_t gt801x_ts_irq_handler(int irq, void *dev_id)
> +{
> + gt801x_process_events((struct gt801x_ts_data *)dev_id);
> +
> + return IRQ_HANDLED;
> +}
> +
> +/**
> + * gt801x_read_config - Read the embedded configuration of the panel
> + *
> + * @ts: our gt801x_ts_data pointer
> + *
> + * Must be called during probe
> + */
> +static void gt801x_read_config(struct gt801x_ts_data *ts)
> +{
> + u8 config[GT801X_CONFIG_MAX_LENGTH];
> + int error;
> +
> + error = gt801x_i2c_read(ts->client, GT801X_CONFIG_DATA,
> + config,
> + GT801X_CONFIG_MAX_LENGTH);
> + if (error) {
> + dev_warn(&ts->client->dev,
> + "Error reading config (%d), using defaults\n",
> + error);
> + ts->abs_x_max = GOODIX_MAX_WIDTH;
> + ts->abs_y_max = GOODIX_MAX_HEIGHT;
> + ts->int_trigger_type = GOODIX_INT_TRIGGER;
> + ts->max_touch_num = GOODIX_MAX_CONTACTS;
> + return;
> + }
> +
> + ts->abs_x_max = get_unaligned_be16(&config[RESOLUTION_LOC]);
> + ts->abs_y_max = get_unaligned_be16(&config[RESOLUTION_LOC + 2]);
> + ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
> + ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
> + if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
> + dev_err(&ts->client->dev,
> + "Invalid config, using defaults\n");
> + ts->abs_x_max = GOODIX_MAX_WIDTH;
> + ts->abs_y_max = GOODIX_MAX_HEIGHT;
> + ts->max_touch_num = GOODIX_MAX_CONTACTS;
> + }
> +}
> +
> +/**
> + * gt801x_read_version - Read GT801 2+1 touchscreen version
> + *
> + * @client: the i2c client
> + * @version: output buffer containing the version on success
> + * @id: output buffer containing the id on success
> + */
> +static int gt801x_read_version(struct i2c_client *client, u16 *version, u16 *id)
> +{
> + int error;
> + u8 buf[16];
> +
> + error = gt801x_i2c_read(client, GT801X_REG_ID, buf, sizeof(buf));
> + if (error) {
> + dev_err(&client->dev, "read version failed: %d\n", error);
> + return error;
> + }
> + /* TODO: version info contains 'GT801NI_3R15_1AV' */
> + print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, ARRAY_SIZE(buf));
> + *id = 0x802;
> + *version = 0x15;
> + dev_info(&client->dev, "ID %d, version: %04x\n", *id, *version);
> + return 0;
> +}
> +
> +/**
> + * gt801x_i2c_test - I2C test function to check if the device answers.
> + *
> + * @client: the i2c client
> + */
> +static int gt801x_i2c_test(struct i2c_client *client)
> +{
> + int retry = 0;
> + int error;
> + u8 test;
> +
> + while (retry++ < 2) {
> + error = gt801x_i2c_read(client, GT801X_CONFIG_DATA,
> + &test, 1);
> + if (!error)
> + return 0;
> +
> + dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
> + retry, error);
> + msleep(20);
> + }
> +
> + return error;
> +}
> +
> +/**
> + * gt801x_request_input_dev - Allocate, populate and register the input device
> + *
> + * @ts: our gt801x_ts_data pointer
> + * @version: device firmware version
> + * @id: device ID
> + *
> + * Must be called during probe
> + */
> +static int gt801x_request_input_dev(struct gt801x_ts_data *ts,
> + u16 version, u16 id)
> +{
> + int error;
> +
> + ts->input_dev = devm_input_allocate_device(&ts->client->dev);
> + if (!ts->input_dev) {
> + dev_err(&ts->client->dev, "Failed to allocate input device.");
> + return -ENOMEM;
> + }
> +
> + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
> + 0, ts->abs_x_max, 0, 0);
> + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
> + 0, ts->abs_y_max, 0, 0);
> + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
> + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
> +
> + input_mt_init_slots(ts->input_dev, ts->max_touch_num,
> + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
> +
> + ts->input_dev->name = "Goodix Capacitive TouchScreen (GT801 2+1)";
> + ts->input_dev->phys = "input/ts";
> + ts->input_dev->id.bustype = BUS_I2C;
> + ts->input_dev->id.vendor = 0x0416;
> + ts->input_dev->id.product = id;
> + ts->input_dev->id.version = version;
> +
> + error = input_register_device(ts->input_dev);
> + if (error) {
> + dev_err(&ts->client->dev,
> + "Failed to register input device: %d", error);
> + return error;
> + }
> +
> + return 0;
> +}
> +
> +static int gt801x_ts_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct gt801x_ts_data *ts;
> + unsigned long irq_flags;
> + int error;
> + u16 version_info, id_info;
> +
> + dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> + dev_err(&client->dev, "I2C check functionality failed.\n");
> + return -ENXIO;
> + }
> +
> + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
> + if (!ts)
> + return -ENOMEM;
> +
> + ts->client = client;
> + i2c_set_clientdata(client, ts);
> +
> + error = gt801x_i2c_test(client);
> + if (error) {
> + dev_err(&client->dev, "I2C communication failure: %d\n", error);
> + return error;
> + }
> +
> + error = gt801x_read_version(client, &version_info, &id_info);
> + if (error) {
> + dev_err(&client->dev, "Read version failed.\n");
> + return error;
> + }
> +
> + gt801x_read_config(ts);
> +
> + error = gt801x_request_input_dev(ts, version_info, id_info);
> + if (error)
> + return error;
> +
> + irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
> + error = devm_request_threaded_irq(&ts->client->dev, client->irq,
> + NULL, gt801x_ts_irq_handler,
> + irq_flags, client->name, ts);
> + if (error) {
> + dev_err(&client->dev, "request IRQ failed: %d\n", error);
> + return error;
> + }
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id gt801x_ts_id[] = {
> + { "GDIX1001:00", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, gt801x_ts_id);
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id gt801x_of_match[] = {
> + { .compatible = "goodix,gt801_2plus1" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, gt801x_of_match);
> +#endif
> +
> +static struct i2c_driver gt801x_ts_driver = {
> + .probe = gt801x_ts_probe,
> + .id_table = gt801x_ts_id,
> + .driver = {
> + .name = "Goodix-TS",
> + .of_match_table = of_match_ptr(gt801x_of_match),
> + },
> +};
> +module_i2c_driver(gt801x_ts_driver);
> +
> +MODULE_AUTHOR("Priit Laes <plaes@plaes.org>");
> +MODULE_DESCRIPTION("Goodix GT801 2+1 touchscreen driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.6.3
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1
2015-12-07 7:26 ` [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1 Priit Laes
@ 2015-12-08 12:14 ` Bastien Nocera
2015-12-08 15:18 ` Rob Herring
1 sibling, 0 replies; 5+ messages in thread
From: Bastien Nocera @ 2015-12-08 12:14 UTC (permalink / raw)
To: Priit Laes, Maxime Ripard, Chen-Yu Tsai, Dmitry Torokhov,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-input,
Aleksei Mamlin, linux-sunxi
Hey Priit,
On Mon, 2015-12-07 at 09:26 +0200, Priit Laes wrote:
> This patch adds Goodix GT801 2+1 touchscreen controller support.
>
> GT801 2+1 is a 10-finger touch controller consisting of
> ARM controller interfacing two GT801 5-finger controllers.
This would implement support for the "Guitar" protocol used by a few
more variants of the GT80x devices. Can you rename the driver/docs to that effect?
<snip>
> +
> +static const struct i2c_device_id gt801x_ts_id[] = {
> + { "GDIX1001:00", 0 },
This clashes with the ID used in the goodix.c driver.
Cheers
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1
2015-12-07 7:25 [PATCH 0/2] input: Driver for Goodix GT801 2+1 touchscreen Priit Laes
@ 2015-12-07 7:26 ` Priit Laes
2015-12-08 12:14 ` Bastien Nocera
2015-12-08 15:18 ` Rob Herring
0 siblings, 2 replies; 5+ messages in thread
From: Priit Laes @ 2015-12-07 7:26 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Dmitry Torokhov, Rob Herring,
Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-input,
Aleksei Mamlin, linux-sunxi, Priit Laes
This patch adds Goodix GT801 2+1 touchscreen controller support.
GT801 2+1 is a 10-finger touch controller consisting of
ARM controller interfacing two GT801 5-finger controllers.
Signed-off-by: Priit Laes <plaes@plaes.org>
---
.../bindings/input/touchscreen/gt801_2plus1.txt | 23 ++
MAINTAINERS | 6 +
drivers/input/touchscreen/Kconfig | 19 +-
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/gt801_2plus1.c | 375 +++++++++++++++++++++
5 files changed, 421 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt
create mode 100644 drivers/input/touchscreen/gt801_2plus1.c
diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt b/Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt
new file mode 100644
index 0000000..070ff5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/gt801_2plus1.txt
@@ -0,0 +1,23 @@
+Device tree bindings for Goodix GT801 2+1 series touchscreen controller
+
+Required properties:
+
+ - compatible : Should be "goodix,gt801_2plus1"
+ - reg : I2C address of the chip. Should be 0x55
+ - interrupt-parent : Interrupt controller to which the chip is connected
+ - interrupts : Interrupt to which the chip is connected
+
+Example:
+
+ i2c@00000000 {
+ /* ... */
+
+ touchscreen@55 {
+ compatible = "goodix,gt801_2plus1";
+ reg = <0x55>;
+ interrupt-parent = <&gpio>;
+ interrupts = <0 0>;
+ };
+
+ /* ... */
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index cba790b..e292126 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4743,6 +4743,12 @@ L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/goodix.c
+GOODIX GT801 2PLUS1 TOUCHSCREEN
+M: Priit Laes <plaes@plaes.org>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: drivers/input/touchscreen/gt801_2plus1.c
+
GPIO SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
M: Alexandre Courbot <gnurou@gmail.com>
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index ae33da7..c7c3324 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -322,11 +322,11 @@ config TOUCHSCREEN_FUJITSU
module will be called fujitsu-ts.
config TOUCHSCREEN_GOODIX
- tristate "Goodix I2C touchscreen"
+ tristate "Goodix GT9xx I2C touchscreen"
depends on I2C
help
- Say Y here if you have the Goodix touchscreen (such as one
- installed in Onda v975w tablets) connected to your
+ Say Y here if you have one of the Goodix GT9xx touchscreens
+ (such as one installed in Onda v975w tablet) connected to your
system. It also supports 5-finger chip models, which can be
found on ARM tablets, like Wexler TAB7200 and MSI Primo73.
@@ -335,6 +335,19 @@ config TOUCHSCREEN_GOODIX
To compile this driver as a module, choose M here: the
module will be called goodix.
+config TOUCHSCREEN_GT801_2PLUS1
+ tristate "Goodix GT801 2+1 I2C touchscreen"
+ depends on I2C
+ help
+ Say Y here if you have the Goodix GT801 2+1 touchscreen.
+ This controller is found on some older ARM tablets like
+ (Gemei G9 and Zareason Zatab).
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gt801_2plus1.
+
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index cbaa6ab..ff25d1b4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
+obj-$(CONFIG_TOUCHSCREEN_GT801_2PLUS1) += gt801_2plus1.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
diff --git a/drivers/input/touchscreen/gt801_2plus1.c b/drivers/input/touchscreen/gt801_2plus1.c
new file mode 100644
index 0000000..e2be479
--- /dev/null
+++ b/drivers/input/touchscreen/gt801_2plus1.c
@@ -0,0 +1,375 @@
+/*
+ * Driver for Goodix GT801 2+1 ARM touchscreen controllers
+ *
+ * Copyright (c) 2015 Priit Laes <plaes@plaes.org>.
+ *
+ * This code is based on goodix.c driver (c) 2014 Red Hat Inc,
+ * various Android codedumps (c) 2010 - 2012 Goodix Technology
+ * and cleanups done by Emilio López (turl) for linux-sunxi.
+ *
+ * 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; version 2 of the License.
+ */
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input/mt.h>
+
+struct gt801x_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ int abs_x_max;
+ int abs_y_max;
+ unsigned int max_touch_num;
+ unsigned int int_trigger_type;
+};
+
+#define GOODIX_MAX_HEIGHT 4096
+#define GOODIX_MAX_WIDTH 4096
+#define GOODIX_INT_TRIGGER 1
+#define GOODIX_MAX_CONTACTS 10
+#define MAX_CONTACTS_LOC 5
+#define RESOLUTION_LOC 1
+#define TRIGGER_LOC 6
+
+/* Register defines */
+#define GT801X_COOR_ADDR 0x01
+#define GT801X_CONFIG_DATA 0x65
+#define GT801X_REG_ID 0xf0
+
+/* Device specific defines */
+#define GT801X_CONFIG_MAX_LENGTH 7
+#define GT801X_CONTACT_SIZE 5
+
+static const unsigned long goodix_irq_flags[] = {
+ IRQ_TYPE_EDGE_RISING,
+ IRQ_TYPE_EDGE_FALLING,
+ IRQ_TYPE_LEVEL_LOW,
+ IRQ_TYPE_LEVEL_HIGH,
+};
+
+/**
+ * gt801x_i2c_read - read data from a register of the i2c slave device.
+ *
+ * @client: i2c device.
+ * @reg: the register to read from.
+ * @buf: raw write data buffer.
+ * @len: length of the buffer to write
+ */
+static int gt801x_i2c_read(struct i2c_client *client,
+ u8 reg, u8 *buf, int len)
+{
+ struct i2c_msg msgs[2];
+ int ret;
+
+ msgs[0].flags = 0;
+ msgs[0].addr = client->addr;
+ msgs[0].len = 1;
+ msgs[0].buf = ®
+
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].addr = client->addr;
+ msgs[1].len = len;
+ msgs[1].buf = buf;
+
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
+}
+
+/**
+ * gt801x_process_events - Process incoming events
+ *
+ * @ts: our gt801x_ts_data pointer
+ *
+ * Called when the IRQ is triggered. Read the current device state, and push
+ * the input events to the user space.
+ */
+static void gt801x_process_events(struct gt801x_ts_data *ts)
+{
+ u8 point_data[3 + GT801X_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
+ u8 touch_map[GOODIX_MAX_CONTACTS] = {0};
+ int input_x, input_y, input_w;
+ u8 checksum = 0;
+ u16 touch_raw;
+ u8 touch_num;
+ int error;
+ int loc;
+ int i;
+
+ error = gt801x_i2c_read(ts->client, GT801X_COOR_ADDR,
+ point_data, sizeof(point_data));
+ if (error) {
+ dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
+ return;
+ }
+
+ /* Fetch touch mapping bits */
+ touch_raw = get_unaligned_le16(&point_data[0]);
+ if (!touch_raw)
+ return;
+
+ /* Build touch map */
+ touch_num = 0;
+ for (i = 0; (touch_raw != 0) && (i < ts->max_touch_num); i++) {
+ if (touch_raw & 1)
+ touch_map[touch_num++] = i;
+ touch_raw >>= 1;
+ }
+
+ /* Calculate checksum */
+ for (i = 0; i < (touch_num*GT801X_CONTACT_SIZE + 3); i++)
+ checksum += point_data[i];
+ if (checksum != 0)
+ return;
+
+ /* Report touches */
+ for (i = 0; i < touch_num; i++) {
+ loc = 2 + GT801X_CONTACT_SIZE * i;
+ input_x = get_unaligned_be16(&point_data[loc]);
+ input_y = get_unaligned_be16(&point_data[loc + 2]);
+ input_w = point_data[loc + 4];
+
+ input_mt_slot(ts->input_dev, i);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
+ input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
+ }
+
+ input_mt_sync_frame(ts->input_dev);
+ input_sync(ts->input_dev);
+}
+
+/**
+ * gt801x_ts_irq_handler - The IRQ handler
+ *
+ * @irq: interrupt number.
+ * @dev_id: private data pointer.
+ */
+static irqreturn_t gt801x_ts_irq_handler(int irq, void *dev_id)
+{
+ gt801x_process_events((struct gt801x_ts_data *)dev_id);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * gt801x_read_config - Read the embedded configuration of the panel
+ *
+ * @ts: our gt801x_ts_data pointer
+ *
+ * Must be called during probe
+ */
+static void gt801x_read_config(struct gt801x_ts_data *ts)
+{
+ u8 config[GT801X_CONFIG_MAX_LENGTH];
+ int error;
+
+ error = gt801x_i2c_read(ts->client, GT801X_CONFIG_DATA,
+ config,
+ GT801X_CONFIG_MAX_LENGTH);
+ if (error) {
+ dev_warn(&ts->client->dev,
+ "Error reading config (%d), using defaults\n",
+ error);
+ ts->abs_x_max = GOODIX_MAX_WIDTH;
+ ts->abs_y_max = GOODIX_MAX_HEIGHT;
+ ts->int_trigger_type = GOODIX_INT_TRIGGER;
+ ts->max_touch_num = GOODIX_MAX_CONTACTS;
+ return;
+ }
+
+ ts->abs_x_max = get_unaligned_be16(&config[RESOLUTION_LOC]);
+ ts->abs_y_max = get_unaligned_be16(&config[RESOLUTION_LOC + 2]);
+ ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
+ ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
+ if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
+ dev_err(&ts->client->dev,
+ "Invalid config, using defaults\n");
+ ts->abs_x_max = GOODIX_MAX_WIDTH;
+ ts->abs_y_max = GOODIX_MAX_HEIGHT;
+ ts->max_touch_num = GOODIX_MAX_CONTACTS;
+ }
+}
+
+/**
+ * gt801x_read_version - Read GT801 2+1 touchscreen version
+ *
+ * @client: the i2c client
+ * @version: output buffer containing the version on success
+ * @id: output buffer containing the id on success
+ */
+static int gt801x_read_version(struct i2c_client *client, u16 *version, u16 *id)
+{
+ int error;
+ u8 buf[16];
+
+ error = gt801x_i2c_read(client, GT801X_REG_ID, buf, sizeof(buf));
+ if (error) {
+ dev_err(&client->dev, "read version failed: %d\n", error);
+ return error;
+ }
+ /* TODO: version info contains 'GT801NI_3R15_1AV' */
+ print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, ARRAY_SIZE(buf));
+ *id = 0x802;
+ *version = 0x15;
+ dev_info(&client->dev, "ID %d, version: %04x\n", *id, *version);
+ return 0;
+}
+
+/**
+ * gt801x_i2c_test - I2C test function to check if the device answers.
+ *
+ * @client: the i2c client
+ */
+static int gt801x_i2c_test(struct i2c_client *client)
+{
+ int retry = 0;
+ int error;
+ u8 test;
+
+ while (retry++ < 2) {
+ error = gt801x_i2c_read(client, GT801X_CONFIG_DATA,
+ &test, 1);
+ if (!error)
+ return 0;
+
+ dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
+ retry, error);
+ msleep(20);
+ }
+
+ return error;
+}
+
+/**
+ * gt801x_request_input_dev - Allocate, populate and register the input device
+ *
+ * @ts: our gt801x_ts_data pointer
+ * @version: device firmware version
+ * @id: device ID
+ *
+ * Must be called during probe
+ */
+static int gt801x_request_input_dev(struct gt801x_ts_data *ts,
+ u16 version, u16 id)
+{
+ int error;
+
+ ts->input_dev = devm_input_allocate_device(&ts->client->dev);
+ if (!ts->input_dev) {
+ dev_err(&ts->client->dev, "Failed to allocate input device.");
+ return -ENOMEM;
+ }
+
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
+ 0, ts->abs_x_max, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
+ 0, ts->abs_y_max, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+
+ input_mt_init_slots(ts->input_dev, ts->max_touch_num,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+
+ ts->input_dev->name = "Goodix Capacitive TouchScreen (GT801 2+1)";
+ ts->input_dev->phys = "input/ts";
+ ts->input_dev->id.bustype = BUS_I2C;
+ ts->input_dev->id.vendor = 0x0416;
+ ts->input_dev->id.product = id;
+ ts->input_dev->id.version = version;
+
+ error = input_register_device(ts->input_dev);
+ if (error) {
+ dev_err(&ts->client->dev,
+ "Failed to register input device: %d", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int gt801x_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct gt801x_ts_data *ts;
+ unsigned long irq_flags;
+ int error;
+ u16 version_info, id_info;
+
+ dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C check functionality failed.\n");
+ return -ENXIO;
+ }
+
+ ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+
+ error = gt801x_i2c_test(client);
+ if (error) {
+ dev_err(&client->dev, "I2C communication failure: %d\n", error);
+ return error;
+ }
+
+ error = gt801x_read_version(client, &version_info, &id_info);
+ if (error) {
+ dev_err(&client->dev, "Read version failed.\n");
+ return error;
+ }
+
+ gt801x_read_config(ts);
+
+ error = gt801x_request_input_dev(ts, version_info, id_info);
+ if (error)
+ return error;
+
+ irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
+ error = devm_request_threaded_irq(&ts->client->dev, client->irq,
+ NULL, gt801x_ts_irq_handler,
+ irq_flags, client->name, ts);
+ if (error) {
+ dev_err(&client->dev, "request IRQ failed: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id gt801x_ts_id[] = {
+ { "GDIX1001:00", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, gt801x_ts_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id gt801x_of_match[] = {
+ { .compatible = "goodix,gt801_2plus1" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gt801x_of_match);
+#endif
+
+static struct i2c_driver gt801x_ts_driver = {
+ .probe = gt801x_ts_probe,
+ .id_table = gt801x_ts_id,
+ .driver = {
+ .name = "Goodix-TS",
+ .of_match_table = of_match_ptr(gt801x_of_match),
+ },
+};
+module_i2c_driver(gt801x_ts_driver);
+
+MODULE_AUTHOR("Priit Laes <plaes@plaes.org>");
+MODULE_DESCRIPTION("Goodix GT801 2+1 touchscreen driver");
+MODULE_LICENSE("GPL v2");
--
2.6.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-12-08 15:18 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <201512071608.oGt2n0Wn%fengguang.wu@intel.com>
2015-12-07 8:34 ` [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1 Julia Lawall
2015-12-07 9:10 ` Priit Laes
2015-12-07 7:25 [PATCH 0/2] input: Driver for Goodix GT801 2+1 touchscreen Priit Laes
2015-12-07 7:26 ` [PATCH 2/2] input: gt801_2plus1 - Add initial support for Goodix GT801 2+1 Priit Laes
2015-12-08 12:14 ` Bastien Nocera
2015-12-08 15:18 ` Rob Herring
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).