From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dmitry Torokhov Subject: Re: [PATCH 1/2] Input: add support for Semtech SX8654 I2C touchscreen controller Date: Fri, 6 Mar 2015 10:21:55 -0800 Message-ID: <20150306182155.GB4540@dtor-ws> References: <1425666099-8365-1-git-send-email-sebastien.szymanski@armadeus.com> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: Content-Disposition: inline In-Reply-To: <1425666099-8365-1-git-send-email-sebastien.szymanski-d2DlULPkwbNWk0Htik3J/w@public.gmane.org> Sender: devicetree-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: =?iso-8859-1?Q?S=E9bastien?= Szymanski Cc: linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Kumar Gala List-Id: linux-input@vger.kernel.org On Fri, Mar 06, 2015 at 07:21:38PM +0100, S=E9bastien Szymanski wrote: > Signed-off-by: S=E9bastien Szymanski > --- > drivers/input/touchscreen/Kconfig | 11 ++ > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/sx8654.c | 285 +++++++++++++++++++++++++++= ++++++++++ > 3 files changed, 297 insertions(+) > create mode 100644 drivers/input/touchscreen/sx8654.c >=20 > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchs= creen/Kconfig > index 5891752..6f713fd0 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -961,6 +961,17 @@ config TOUCHSCREEN_SUR40 > To compile this driver as a module, choose M here: the > module will be called sur40. > =20 > +config TOUCHSCREEN_SX8654 > + tristate "Semtech SX8654 touchscreen" > + depends on I2C && OF Does it have to depend on OF? I do not see anything OF-specific there..= =2E No need to resumbit. > + help > + Say Y here if you have a Semtech SX8654 touchscreen controller. > + > + If unsure, say N > + > + To compile this driver as a module, choose M here: the > + module will be called sx8654. > + > config TOUCHSCREEN_TPS6507X > tristate "TPS6507x based touchscreens" > depends on I2C > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touch= screen/Makefile > index 0242fea..a06a752 100644 > --- a/drivers/input/touchscreen/Makefile > +++ b/drivers/input/touchscreen/Makefile > @@ -79,5 +79,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) +=3D atmel-w= m97xx.o > obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) +=3D mainstone-wm97xx.o > obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) +=3D zylonite-wm97xx.o > obj-$(CONFIG_TOUCHSCREEN_W90X900) +=3D w90p910_ts.o > +obj-$(CONFIG_TOUCHSCREEN_SX8654) +=3D sx8654.o > obj-$(CONFIG_TOUCHSCREEN_TPS6507X) +=3D tps6507x-ts.o > obj-$(CONFIG_TOUCHSCREEN_ZFORCE) +=3D zforce_ts.o > diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touch= screen/sx8654.c > new file mode 100644 > index 0000000..58cc478 > --- /dev/null > +++ b/drivers/input/touchscreen/sx8654.c > @@ -0,0 +1,285 @@ > +/* > + * drivers/input/touchscreen/sx8654.c > + * > + * Copyright (c) 2015 Armadeus Systems > + * S=E9bastien Szymanski > + * > + * Using code from: > + * - sx865x.c > + * Copyright (c) 2013 U-MoBo Srl > + * Pierluigi Passaro > + * - sx8650.c > + * Copyright (c) 2009 Wayne Roberts > + * - tsc2007.c > + * Copyright (c) 2008 Kwangwoo Lee > + * - ads7846.c > + * Copyright (c) 2005 David Brownell > + * Copyright (c) 2006 Nokia Corporation > + * - corgi_ts.c > + * Copyright (C) 2004-2005 Richard Purdie > + * - omap_ts.[hc], ads7846.h, ts_osk.c > + * Copyright (C) 2002 MontaVista Software > + * Copyright (C) 2004 Texas Instruments > + * Copyright (C) 2005 Dirk Behme > + * > + * This program is free software; you can redistribute it and/or mo= dify > + * it under the terms of the GNU General Public License version 2 a= s > + * published by the Free Software Foundation. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* register addresses */ > +#define I2C_REG_TOUCH0 0x00 > +#define I2C_REG_TOUCH1 0x01 > +#define I2C_REG_CHANMASK 0x04 > +#define I2C_REG_IRQMASK 0x22 > +#define I2C_REG_IRQSRC 0x23 > +#define I2C_REG_SOFTRESET 0x3f > + > +/* commands */ > +#define CMD_READ_REGISTER 0x40 > +#define CMD_MANUAL 0xc0 > +#define CMD_PENTRG 0xe0 > + > +/* value for I2C_REG_SOFTRESET */ > +#define SOFTRESET_VALUE 0xde > + > +/* bits for I2C_REG_IRQSRC */ > +#define IRQ_PENTOUCH_TOUCHCONVDONE 0x08 > +#define IRQ_PENRELEASE 0x04 > + > +/* bits for RegTouch1 */ > +#define CONDIRQ 0x20 > +#define FILT_7SA 0x03 > + > +/* bits for I2C_REG_CHANMASK */ > +#define CONV_X 0x80 > +#define CONV_Y 0x40 > + > +/* coordinates rate: higher nibble of CTRL0 register */ > +#define RATE_MANUAL 0x00 > +#define RATE_5000CPS 0xf0 > + > +/* power delay: lower nibble of CTRL0 register */ > +#define POWDLY_1_1MS 0x0b > + > +#define MAX_12BIT ((1 << 12) - 1) > + > +struct sx8654 { > + struct input_dev *input; > + struct i2c_client *client; > +}; > + > +static irqreturn_t sx8654_irq(int irq, void *handle) > +{ > + struct sx8654 *sx8654 =3D handle; > + u8 irqsrc; > + u8 data[4]; > + unsigned int x, y; > + int retval; > + > + irqsrc =3D i2c_smbus_read_byte_data(sx8654->client, > + (CMD_READ_REGISTER | I2C_REG_IRQSRC)); > + dev_dbg(&sx8654->client->dev, "irqsrc =3D 0x%x", irqsrc); > + > + if (irqsrc < 0) > + goto out; > + > + if (irqsrc & IRQ_PENRELEASE) { > + dev_dbg(&sx8654->client->dev, "pen release interrupt"); > + > + input_report_key(sx8654->input, BTN_TOUCH, 0); > + input_sync(sx8654->input); > + } > + > + if (irqsrc & IRQ_PENTOUCH_TOUCHCONVDONE) { > + dev_dbg(&sx8654->client->dev, "pen touch interrupt"); > + > + retval =3D i2c_master_recv(sx8654->client, data, sizeof(data)); > + if (retval !=3D sizeof(data)) > + goto out; > + > + /* invalid data */ > + if (unlikely(data[0] & 0x80 || data[2] & 0x80)) > + goto out; > + > + x =3D ((data[0] & 0xf) << 8) | (data[1]); > + y =3D ((data[2] & 0xf) << 8) | (data[3]); > + > + input_report_abs(sx8654->input, ABS_X, x); > + input_report_abs(sx8654->input, ABS_Y, y); > + input_report_key(sx8654->input, BTN_TOUCH, 1); > + input_sync(sx8654->input); > + > + dev_dbg(&sx8654->client->dev, "point(%4d,%4d)\n", x, y); > + } > + > +out: > + return IRQ_HANDLED; > +} > + > +static int sx8654_open(struct input_dev *dev) > +{ > + struct sx8654 *sx8654 =3D input_get_drvdata(dev); > + struct i2c_client *client =3D sx8654->client; > + int error; > + > + /* enable pen trigger mode */ > + error =3D i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, > + (RATE_5000CPS | POWDLY_1_1MS)); > + if (error < 0) { > + dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); > + return -EIO; > + } > + > + error =3D i2c_smbus_write_byte(client, CMD_PENTRG); > + if (error < 0) { > + dev_err(&client->dev, "writing command CMD_PENTRG failed"); > + return -EIO; > + } > + > + enable_irq(client->irq); > + > + return 0; > +} > + > +static void sx8654_close(struct input_dev *dev) > +{ > + struct sx8654 *sx8654 =3D input_get_drvdata(dev); > + struct i2c_client *client =3D sx8654->client; > + int error; > + > + disable_irq(client->irq); > + > + /* enable manual mode mode */ > + error =3D i2c_smbus_write_byte(client, CMD_MANUAL); > + if (error < 0) { > + dev_err(&client->dev, "writing command CMD_MANUAL failed"); > + return; > + } > + > + error =3D i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 0); > + if (error < 0) { > + dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); > + return; > + } > +} > + > +static int sx8654_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct sx8654 *sx8654; > + struct input_dev *input; > + int error; > + > + if (!i2c_check_functionality(client->adapter, > + I2C_FUNC_SMBUS_READ_WORD_DATA)) > + return -ENXIO; > + > + sx8654 =3D devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL); > + if (!sx8654) > + return -ENOMEM; > + > + input =3D devm_input_allocate_device(&client->dev); > + if (!sx8654) > + return -ENOMEM; > + > + input->name =3D "SX8654 I2C Touchscreen"; > + input->id.bustype =3D BUS_I2C; > + input->dev.parent =3D &client->dev; > + input->open =3D sx8654_open; > + input->close =3D sx8654_close; > + > + __set_bit(INPUT_PROP_DIRECT, input->propbit); > + input_set_capability(input, EV_KEY, BTN_TOUCH); > + input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0); > + input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0); > + > + sx8654->client =3D client; > + sx8654->input =3D input; > + > + input_set_drvdata(sx8654->input, sx8654); > + > + error =3D i2c_smbus_write_byte_data(client, I2C_REG_SOFTRESET, > + SOFTRESET_VALUE); > + if (error < 0) { > + dev_err(&client->dev, "writing softreset value failed"); > + return -EIO; > + } > + > + error =3D i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK, > + (CONV_X | CONV_Y)); > + if (error < 0) { > + dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed"); > + return -EIO; > + } > + > + error =3D i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK, > + (IRQ_PENTOUCH_TOUCHCONVDONE | > + IRQ_PENRELEASE)); > + if (error < 0) { > + dev_err(&client->dev, "writing to I2C_REG_IRQMASK failed"); > + return -EIO; > + } > + > + error =3D i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1, > + (CONDIRQ | FILT_7SA)); > + if (error < 0) { > + dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed"); > + return -EIO; > + } > + > + error =3D devm_request_threaded_irq(&client->dev, client->irq, > + NULL, sx8654_irq, > + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, > + client->name, sx8654); > + if (error) { > + dev_err(&client->dev, > + "Failed to enable IRQ %d, error: %d\n", > + client->irq, error); > + return error; > + } > + > + /* Disable the IRQ, we'll enable it in sx8654_open() */ > + disable_irq(client->irq); > + > + error =3D input_register_device(sx8654->input); > + if (error) > + return error; > + > + i2c_set_clientdata(client, sx8654); > + return 0; > +} > + > +static const struct of_device_id sx8654_of_match[] =3D { > + { .compatible =3D "semtech,sx8654", }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, sx8654_of_match); > + > +static const struct i2c_device_id sx8654_id_table[] =3D { > + { "semtech_sx8654", 0 }, > + { }, > +}; > +MODULE_DEVICE_TABLE(i2c, sx8654_id_table); > + > +static struct i2c_driver sx8654_driver =3D { > + .driver =3D { > + .name =3D "sx8654", > + .of_match_table =3D sx8654_of_match, > + }, > + > + .id_table =3D sx8654_id_table, > + .probe =3D sx8654_probe, > +}; > +module_i2c_driver(sx8654_driver); > + > +MODULE_AUTHOR("S=E9bastien Szymanski "); > +MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver"); > +MODULE_LICENSE("GPL"); > --=20 > 2.0.5 >=20 --=20 Dmitry -- To unsubscribe from this list: send the line "unsubscribe devicetree" i= n the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html