From patchwork Thu Jan 30 09:29:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Gmeiner X-Patchwork-Id: 3556031 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3275B9F2E9 for ; Thu, 30 Jan 2014 09:30:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1A86720161 for ; Thu, 30 Jan 2014 09:29:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E8A9720149 for ; Thu, 30 Jan 2014 09:29:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751097AbaA3J34 (ORCPT ); Thu, 30 Jan 2014 04:29:56 -0500 Received: from mail-ea0-f170.google.com ([209.85.215.170]:34918 "EHLO mail-ea0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751107AbaA3J3x (ORCPT ); Thu, 30 Jan 2014 04:29:53 -0500 Received: by mail-ea0-f170.google.com with SMTP id k10so1500776eaj.1 for ; Thu, 30 Jan 2014 01:29:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=SwjZhBRaDbna2hKjitd7hPaI49DNzX8ORlz4NWuVXtU=; b=d/6uW9nOEZ5Y3QBglA28TKh+McpYvYKK1/E+dmH+OtYT02IyVIIBSQ20sZhTC77e4w Yykm21fjB+BdoCFmOmY1FhSk2Cz8mVrvLgzC6lOfYxwt/YJaTg2TnWhf+jt4C793N4oE a6y1YJSFAHKSVclEemx8Usug9o4vmiRcb71VHs7nohzq7wakr13zz494lTk/W/MgTgqF 9B6NFwtNr2npmyPiqeikqOGiDSEKEPWW5wtWtgjUktAwOR4yvcjmkZJUtJnLH1SHooXa X1dusSxN5SF/yW6gvzjtSI8WJ5mdXrd16PHzzoUObMFNIPtzSRSfaDhMJ1/eTzINNQwt CUBA== X-Received: by 10.14.111.201 with SMTP id w49mr185411eeg.92.1391074192407; Thu, 30 Jan 2014 01:29:52 -0800 (PST) Received: from chgm-pc.lan (089144207106.atnat0016.highway.bob.at. [89.144.207.106]) by mx.google.com with ESMTPSA id 4sm19958595eed.14.2014.01.30.01.29.51 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 30 Jan 2014 01:29:51 -0800 (PST) From: Christian Gmeiner To: linux-input@vger.kernel.org Cc: Christian Gmeiner Subject: [PATCH RFC] Input: Add Microchip AR1021 i2c touchscreen Date: Thu, 30 Jan 2014 10:29:45 +0100 Message-Id: <1391074185-26973-1-git-send-email-christian.gmeiner@gmail.com> X-Mailer: git-send-email 1.7.10.4 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This driver is quite simple and only supports the Touch Reporting Protocol. Signed-off-by: Christian Gmeiner --- drivers/input/touchscreen/Kconfig | 12 ++ drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/ar1021_i2c.c | 201 ++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 drivers/input/touchscreen/ar1021_i2c.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 07e9e82..15cc9a1 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -86,6 +86,18 @@ config TOUCHSCREEN_AD7879_SPI To compile this driver as a module, choose M here: the module will be called ad7879-spi. +config TOUCHSCREEN_AR1021_I2C + tristate "Microchip AR1021 i2c touchscreen" + depends on I2C && OF + help + Say Y here if you have the Microchip AR1021 touchscreen controller + chip in your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called microchip_ar1021_i2c. + config TOUCHSCREEN_ATMEL_MXT tristate "Atmel mXT I2C Touchscreen" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 62801f2..efaa328 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o +obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c new file mode 100644 index 0000000..c77ce05 --- /dev/null +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -0,0 +1,201 @@ +/* + * Microchip AR1021 driver for I2C + * + * Author: Christian Gmeiner + * + * License: GPL as published by the FSF. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AR1021_TOCUH_PKG_SIZE 5 + +struct ar1021_i2c { + struct i2c_client *client; + struct input_dev *input; + u8 data[AR1021_TOCUH_PKG_SIZE]; +}; + +static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id) +{ + struct ar1021_i2c *ar1021 = dev_id; + struct input_dev *input = ar1021->input; + u8 *data = ar1021->data; + unsigned int x, y, button; + int error; + + error = i2c_master_recv(ar1021->client, + ar1021->data, sizeof(ar1021->data)); + if (error < 0) + goto out; + + button = !(data[0] & BIT(0)); + x = ((data[2] & 0x1f) << 7) | (data[1] & 0x7f); + y = ((data[4] & 0x1f) << 7) | (data[3] & 0x7f); + + input_report_key(input, BTN_TOUCH, button); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_sync(input); + +out: + return IRQ_HANDLED; +} + +static int ar1021_i2c_open(struct input_dev *dev) +{ + struct ar1021_i2c *wac_i2c = input_get_drvdata(dev); + struct i2c_client *client = wac_i2c->client; + + enable_irq(client->irq); + + return 0; +} + +static void ar1021_i2c_close(struct input_dev *dev) +{ + struct ar1021_i2c *wac_i2c = input_get_drvdata(dev); + struct i2c_client *client = wac_i2c->client; + + disable_irq(client->irq); +} + +static int ar1021_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ar1021_i2c *ar1021; + struct input_dev *input; + int error; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "i2c_check_functionality error\n"); + return -EIO; + } + + ar1021 = devm_kzalloc(client->dev, sizeof(*ar1021), GFP_KERNEL); + input = input_allocate_device(); + if (!ar1021 || !input) { + error = -ENOMEM; + goto err_free_mem; + } + + ar1021->client = client; + ar1021->input = input; + + input->name = "ar1021 I2C Touchscreen"; + input->id.bustype = BUS_I2C; + input->dev.parent = &client->dev; + input->open = ar1021_i2c_open; + input->close = ar1021_i2c_close; + + input->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + __set_bit(BTN_TOOL_PEN, input->keybit); + + input_set_abs_params(input, ABS_X, 0, 4095, 0, 0); + input_set_abs_params(input, ABS_Y, 0, 4095, 0, 0); + + input_set_drvdata(input, ar1021); + + error = request_threaded_irq(client->irq, NULL, ar1021_i2c_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "ar1021_i2c", ar1021); + if (error) { + dev_err(&client->dev, + "Failed to enable IRQ, error: %d\n", error); + goto err_free_mem; + } + + /* Disable the IRQ, we'll enable it in wac_i2c_open() */ + disable_irq(client->irq); + + error = input_register_device(ar1021->input); + if (error) { + dev_err(&client->dev, + "Failed to register input device, error: %d\n", error); + goto err_free_irq; + } + + i2c_set_clientdata(client, ar1021); + return 0; + +err_free_irq: + free_irq(client->irq, ar1021); +err_free_mem: + input_free_device(input); + + return error; +} + +static int ar1021_i2c_remove(struct i2c_client *client) +{ + struct ar1021_i2c *ar1021 = i2c_get_clientdata(client); + + free_irq(client->irq, ar1021); + input_unregister_device(ar1021->input); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ar1021_i2c_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + disable_irq(client->irq); + + return 0; +} + +static int ar1021_i2c_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + enable_irq(client->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(ar1021_i2c_pm, ar1021_i2c_suspend, ar1021_i2c_resume); + +static const struct i2c_device_id ar1021_i2c_id[] = { + { "MICROCHIP_AR1021_I2C", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); + +#ifdef CONFIG_OF +static struct of_device_id ar1021_i2c_of_match[] = { + { .compatible = "mc,ar1021-i2c", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ar1021_i2c_of_match); +#endif + +static struct i2c_driver ar1021_i2c_driver = { + .driver = { + .name = "ar1021_i2c", + .owner = THIS_MODULE, + .pm = &ar1021_i2c_pm, + .of_match_table = of_match_ptr(ar1021_i2c_of_match), + }, + + .probe = ar1021_i2c_probe, + .remove = ar1021_i2c_remove, + .id_table = ar1021_i2c_id, +}; +module_i2c_driver(ar1021_i2c_driver); + +MODULE_AUTHOR("Christian Gmeiner "); +MODULE_DESCRIPTION("Microchip AR1021 I2C Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ar1021_i2c");