From patchwork Fri Jun 24 19:44:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Felice X-Patchwork-Id: 9198089 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 471BA6075F for ; Fri, 24 Jun 2016 19:46:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3553E284D1 for ; Fri, 24 Jun 2016 19:46:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A3F8284D3; Fri, 24 Jun 2016 19:46:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A1EE284D2 for ; Fri, 24 Jun 2016 19:46:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751476AbcFXTpc (ORCPT ); Fri, 24 Jun 2016 15:45:32 -0400 Received: from mail-qk0-f172.google.com ([209.85.220.172]:35948 "EHLO mail-qk0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751438AbcFXTp0 (ORCPT ); Fri, 24 Jun 2016 15:45:26 -0400 Received: by mail-qk0-f172.google.com with SMTP id p10so158475993qke.3 for ; Fri, 24 Jun 2016 12:45:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=timesys-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=TfMeqtbM+mWDafDUlPFheW4zD1Tl2OP5VqW41OPPf90=; b=tYeJrFStddxrvZ+z0t0++tXoAQf8Vln/bAeq7fXfIkqFAuHSIqHvUrUj9u3Bc5Jlfi QnkI2JkYiyFRVHzWMWlvAiHuc94/I2JU6uNDS+wWAzNvwmt98vEnz36vbtMjmwLAubZ/ SoI8ryxL4QojEpPjnKp1hrHEBP2DfxXeCn7IGBP6vNQvkEJJcT0+DYHM9uRgHGf9kOva v1SemqlSB9wAfGppot21j4nzAdOiEhzNXwBFlozVnZ4mCTfAX+ntg+9Xboypqr+XPCb5 Gc6eVTeWBYZAssfd5GCHbPmqCSpccBwiEXo1JBC/TfNrYpfF5A0dQK7zEfZBcZMQlEKB N5yA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=TfMeqtbM+mWDafDUlPFheW4zD1Tl2OP5VqW41OPPf90=; b=TzKTK2aOQe8xhwEz4wxLLnzFnpe+ycOb7qdCvAkB94Gh5nzWJor5OvWxOsnFH2QFXu N+9qhXvB5ZTZfGcUgkHb3HNNhSSPRaoW8nyFA0bnXr/JwUBFWtf1dNiGYp31E5dutULb 5gU1j1rAm7wGTFPMXs+wzL/OfPJeB5vrYSXGmD1OcPWeoIswiCW1ZlWU0mNnPHbUSZV9 K67KgAm1lmBrCS47MLLKuLYOIOKRr7QqInWb2/MmeOWmBb8V6hoJfHllBJm51OvdbZQt 0DRlLLB5Ah58cPLFdtA9NthVVuEmzAA2bSWA2MgzSjWzOWv1O1tqJ58zBJPWx6T3A3QA FpgA== X-Gm-Message-State: ALyK8tKpbU9fFUpd1LHYvaFa9u69n1KlOAVLRG4pDEaZYdbXD+PtSdxn5Sglru6FLqTYFmrv X-Received: by 10.200.37.9 with SMTP id 9mr7223292qtm.31.1466797524918; Fri, 24 Jun 2016 12:45:24 -0700 (PDT) Received: from tony-Gazelle.timesys.com ([96.94.100.129]) by smtp.gmail.com with ESMTPSA id 132sm2683156qkh.41.2016.06.24.12.45.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 24 Jun 2016 12:45:24 -0700 (PDT) From: Anthony Felice To: dri-devel@lists.freedesktop.org, shawnguo@kernel.org, tony.felice@timesys.com Cc: dmitry.torokhov@gmail.com, robh+dt@kernel.org, mark.rutland@arm.com, kernel@pengutronix.de, stefan@agner.ch, linux@armlinux.org.uk, fabio.estevam@nxp.com, geert@linux-m68k.org, mwelling@ieee.org, sre@kernel.org, damien.riegel@savoirfairelinux.com, maitysanchayan@gmail.com, linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/4] input: touchscreen: crtouch_ts: Add driver Date: Fri, 24 Jun 2016 15:44:44 -0400 Message-Id: <1466797486-31558-3-git-send-email-tony.felice@timesys.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1466797486-31558-1-git-send-email-tony.felice@timesys.com> References: <1466797486-31558-1-git-send-email-tony.felice@timesys.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add driver for the Vybrid Tower CRTouch-based touchscreen. This is required for the touchscreen on the TWR-LCD-RGB to work on the Vybrid Tower platform. There is a known issue with this driver: rarely, SW1 on the TWR-LCD-RGB module needs to be pressed in order for the touchscreen to begin functioning. Signed-off-by: Anthony Felice --- .../bindings/input/touchscreen/crtouch_ts.txt | 14 ++ drivers/input/touchscreen/Kconfig | 10 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/crtouch_ts.c | 279 +++++++++++++++++++++ 4 files changed, 304 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/crtouch_ts.txt create mode 100644 drivers/input/touchscreen/crtouch_ts.c diff --git a/Documentation/devicetree/bindings/input/touchscreen/crtouch_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/crtouch_ts.txt new file mode 100644 index 0000000..cfb966c --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/crtouch_ts.txt @@ -0,0 +1,14 @@ +* Freescale CRTOUCH based touchscreen + +Required Properties: +- compatible must be fsl,crtouch_ts +- reg: I2C address of the touchscreen +- irq-gpio: GPIO to use as event IRQ + +Example: + + touch: crtouch@49 { + compatible = "fsl,crtouch_ts"; + reg = <0x49>; + irq-gpio = <&gpio0 21 GPIO_ACTIVE_HIGH>; + }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8ecdc38..799e342 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1155,4 +1155,14 @@ config TOUCHSCREEN_ROHM_BU21023 To compile this driver as a module, choose M here: the module will be called bu21023_ts. +config TOUCHSCREEN_CRTOUCH + tristate "Freescale CRTOUCH based touchscreen" + depends on I2C + help + Say Y here if you have a CRTOUCH based touchscreen + controller. + + To compile this driver as a module, choose M here: the + module will be called crtouch_ts. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index f42975e..8cb0a7a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -95,3 +95,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o +obj-$(CONFIG_TOUCHSCREEN_CRTOUCH) += crtouch_ts.o diff --git a/drivers/input/touchscreen/crtouch_ts.c b/drivers/input/touchscreen/crtouch_ts.c new file mode 100644 index 0000000..bb87a8e --- /dev/null +++ b/drivers/input/touchscreen/crtouch_ts.c @@ -0,0 +1,279 @@ +/* + * Driver for Freescale Semiconductor CRTOUCH - A Resistive and Capacitive + * touch device with i2c interface + * + * Copyright 2012 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Resistive touch sense status registers */ +#define RES_STA_ERROR 0x00 +#define RES_STA_STATUS1 0x01 +#define RES_STA_STATUS2 0x02 +#define RES_STA_X_MSB 0x03 +#define RES_STA_X_LSB 0x04 +#define RES_STA_Y_MSB 0x05 +#define RES_STA_Y_LSB 0x06 +#define RES_STA_PRES_MSB 0x07 +#define RES_STA_RRES_LSB 0x08 +#define RES_STA_FIFO_STATUS 0x09 +#define RES_STA_FIFO_X_MSB 0x0a +#define RES_STA_FIFO_X_LSB 0x0b +#define RES_STA_FIFO_Y_MSB 0x0c +#define RES_STA_FIFO_Y_LSB 0x0d +#define RES_STA_FIFO_PRES_MSB 0x0e +#define RES_STA_FIFO_PRES_LSB 0x0f +#define RES_STA_UART_BRATE_MSB 0x10 +#define RES_STA_UART_BRATE_MID 0x11 +#define RES_STA_UART_BRATE_LSB 0x12 +#define RES_STA_DEV_IDEN 0x13 +#define RES_STA_SLIDE_DISPLACE 0x14 +#define RES_STA_ROTATE_ANGLE 0x15 + +/* Resistive touch configuration registers */ +#define CR_CON_SYSTEM 0x40 +#define CR_CON_TRIG_EVENT 0x41 +#define CR_CON_FIFO_SETUP 0x42 +#define CR_CON_SAMPLING_RATE 0x43 +#define CR_CON_X_DELAY_MSB 0x44 +#define CR_CON_X_DELAY_LSB 0x45 +#define CR_CON_Y_DELAY_MSB 0x46 +#define CR_CON_Y_DELAY_LSB 0x47 +#define CR_CON_Z_DELAY_MSB 0x48 +#define CR_CON_Z_DELAY_LSB 0x49 +#define CR_CON_DIS_HOR_MSB 0x4a +#define CR_CON_DIS_HOR_LSB 0x4b +#define CR_CON_DIS_VER_MSB 0x4c +#define CR_CON_DIS_VER_LSB 0x4d +#define CR_CON_SLIDE_STEPS 0x4e + +#define RTST_EVENT BIT(7) +#define RTS2T_EVENT BIT(6) +#define RTSZ_EVENT BIT(5) +#define RTSR_EVENT BIT(4) +#define RTSS_EVENT BIT(3) +#define RTSF_EVENT BIT(2) +#define RTSRDY_EVENT BIT(0) + +#define RTSSD_MASK BIT(2) +#define RTSSD_H_NEG BIT(2) +#define RTSSD_V_POS BIT(3) +#define RTSSD_V_NEG BIT(4) + +#define RTSRD_MASK BIT(4) +#define RTSRD_COUNTER_CLK_WISE BIT(4) + +#define RTSZD_MASK BIT(5) +#define RTSZD_ZOOM_OUT BIT(5) + +#define CRTOUCH_MAX_FINGER 2 +#define CRTOUCH_MAX_AREA 0xfff +#define CRTOUCH_MAX_X 0x01df +#define CRTOUCH_MAX_Y 0x010f + +struct crtouch_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; +}; + +static u8 crtouch_read_reg(struct i2c_client *client, int addr) +{ + return i2c_smbus_read_byte_data(client, addr); +} + +static int crtouch_write_reg(struct i2c_client *client, int addr, int data) +{ + return i2c_smbus_write_byte_data(client, addr, data); +} + +static void calibration_pointer(u16 *x_orig, u16 *y_orig) +{ + u16 x, y; + + x = CRTOUCH_MAX_X - *x_orig; + *x_orig = x; + + y = CRTOUCH_MAX_Y - *y_orig; + *y_orig = y; +} + +static irqreturn_t crtouch_ts_interrupt(int irq, void *dev_id) +{ + struct crtouch_ts_data *data = dev_id; + struct i2c_client *client = data->client; + u8 status1; + u16 valuep, valuex, valuey; + + status1 = crtouch_read_reg(client, RES_STA_STATUS1); + + /* For single touch */ + if (status1 & RTST_EVENT) { + valuep = crtouch_read_reg(client, RES_STA_PRES_MSB); + valuep = ((valuep << 8) | + crtouch_read_reg(client, RES_STA_RRES_LSB)); + valuex = crtouch_read_reg(client, RES_STA_X_MSB); + valuex = ((valuex << 8) | + crtouch_read_reg(client, RES_STA_X_LSB)); + valuey = crtouch_read_reg(client, RES_STA_Y_MSB); + valuey = ((valuey << 8) | + crtouch_read_reg(client, RES_STA_Y_LSB)); + calibration_pointer(&valuex, &valuey); + input_report_key(data->input_dev, BTN_TOUCH, 1); + input_report_abs(data->input_dev, ABS_X, valuex); + input_report_abs(data->input_dev, ABS_Y, valuey); + input_report_abs(data->input_dev, ABS_PRESSURE, valuep); + input_sync(data->input_dev); + } else { + input_report_abs(data->input_dev, ABS_PRESSURE, 0); + input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0); + input_sync(data->input_dev); + } + + return IRQ_HANDLED; +} + +static void crtouch_ts_reg_init(struct crtouch_ts_data *data) +{ + struct i2c_client *client = data->client; + + crtouch_write_reg(client, CR_CON_SYSTEM, 0x9c); + crtouch_write_reg(client, CR_CON_TRIG_EVENT, 0xf9); + crtouch_write_reg(client, CR_CON_FIFO_SETUP, 0x1f); + crtouch_write_reg(client, CR_CON_SAMPLING_RATE, 0x08); + crtouch_write_reg(client, CR_CON_DIS_HOR_MSB, 0x01); + crtouch_write_reg(client, CR_CON_DIS_HOR_LSB, 0xdf); + crtouch_write_reg(client, CR_CON_DIS_VER_MSB, 0x01); + crtouch_write_reg(client, CR_CON_DIS_VER_LSB, 0x0f); +} + +static int crtouch_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct crtouch_ts_data *data; + struct input_dev *input_dev; + int error = -1, irq_gpio; + + dev_info(&client->dev, "Freescale CRTOUCH driver\n"); + + data = kzalloc(sizeof(*data), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!data || !input_dev) { + dev_err(&client->dev, "Failed to allocate memory\n"); + error = -ENOMEM; + goto err_free_mem; + } + + data->client = client; + data->input_dev = input_dev; + + input_dev->name = "crtouch_ts"; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &client->dev; + + /* For single touch */ + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(ABS_X, input_dev->absbit); + __set_bit(ABS_Y, input_dev->absbit); + __set_bit(ABS_PRESSURE, input_dev->absbit); + + input_set_abs_params(input_dev, ABS_X, 0, CRTOUCH_MAX_X, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, CRTOUCH_MAX_Y, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, + CRTOUCH_MAX_AREA, 0, 0); + + input_set_drvdata(input_dev, data); + + crtouch_ts_reg_init(data); + + irq_gpio = of_get_named_gpio(client->dev.of_node, "irq-gpio", 0); + if (!gpio_is_valid(irq_gpio)) + goto err_free_mem; + + error = gpio_request_one(irq_gpio, GPIOF_IN, "TS_IRQ"); + if (error) { + dev_err(&client->dev, "Failed to request gpio\n"); + goto err_free_mem; + } + + error = request_threaded_irq(gpio_to_irq(irq_gpio), NULL, + crtouch_ts_interrupt, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + "crtouch_ts", data); + + if (error) { + dev_err(&client->dev, "Failed to register interrupt\n"); + goto err_free_mem; + } + + error = input_register_device(data->input_dev); + if (error) + goto err_free_irq; + + i2c_set_clientdata(client, data); + return 0; + +err_free_irq: + free_irq(client->irq, data); +err_free_mem: + input_free_device(input_dev); + kfree(data); + return error; +} + +static int crtouch_ts_remove(struct i2c_client *client) +{ + struct crtouch_ts_data *data = i2c_get_clientdata(client); + + free_irq(client->irq, data); + input_unregister_device(data->input_dev); + kfree(data); + + return 0; +} + +static const struct i2c_device_id crtouch_ts_id[] = { + {"crtouch_ts", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, crtouch_ts_id); + +static const struct of_device_id crtouch_ts_dt_ids[] = { + { .compatible = "fsl,crtouch_ts", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, crtouch_ts_dt_ids); + +static struct i2c_driver crtouch_ts_i2c_driver = { + .driver = { + .name = "crtouch_ts", + .owner = THIS_MODULE, + .of_match_table = crtouch_ts_dt_ids, + }, + .probe = crtouch_ts_probe, + .remove = crtouch_ts_remove, + .id_table = crtouch_ts_id, +}; + +module_i2c_driver(crtouch_ts_i2c_driver); + +MODULE_AUTHOR("Alison Wang "); +MODULE_DESCRIPTION("Touchscreen driver for Freescale CRTOUCH"); +MODULE_LICENSE("GPL");