All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] add tnetv107x input drivers
@ 2010-09-13 16:29 Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 1/7] davinci: define tnetv107x keypad platform data Cyril Chemparathy
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip
touchscreen and keypad controllers.  This patch series adds drivers for these
controllers.

Cyril Chemparathy (7):
  davinci: define tnetv107x keypad platform data
  input: add driver for tnetv107x on-chip keypad controller
  davinci: add tnetv107x keypad platform device
  davinci: add keypad config for tnetv107x evm board
  input: add driver for tnetv107x touchscreen controller
  davinci: add tnetv107x touchscreen platform device
  davinci: add touchscreen config for tnetv107x evm board

 arch/arm/mach-davinci/board-tnetv107x-evm.c    |   51 +++
 arch/arm/mach-davinci/devices-tnetv107x.c      |   54 +++
 arch/arm/mach-davinci/include/mach/tnetv107x.h |   24 ++
 drivers/input/keyboard/Kconfig                 |    9 +
 drivers/input/keyboard/Makefile                |    1 +
 drivers/input/keyboard/tnetv107x-keypad.c      |  324 ++++++++++++++++
 drivers/input/touchscreen/Kconfig              |    6 +
 drivers/input/touchscreen/Makefile             |    1 +
 drivers/input/touchscreen/tnetv107x-ts.c       |  481 ++++++++++++++++++++++++
 9 files changed, 951 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
 create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] davinci: define tnetv107x keypad platform data
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-14  1:26   ` Dmitry Torokhov
  2010-09-13 16:29 ` [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller Cyril Chemparathy
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds a definition for the platform data structure needed to
configure the keypad controller on tnetv107x socs.

Since this controller is (so far) present only on tnetv107x devices, the data
structure definition has been kept local to tnetv107x.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 arch/arm/mach-davinci/include/mach/tnetv107x.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
index c720647..1ee3035 100644
--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
+++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
@@ -37,6 +37,16 @@
 #include <mach/nand.h>
 #include <mach/serial.h>
 
+struct tnetv107x_keypad_data {
+	int		*keymap;
+	const char	**keynames;
+	int		keymap_size;
+	int		rows;
+	int		cols;
+	u32		debounce;
+	u32		stable;
+};
+
 struct tnetv107x_device_info {
 	struct davinci_uart_config	*serial_config;
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 1/7] davinci: define tnetv107x keypad platform data Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-14  1:26   ` Dmitry Torokhov
  2010-09-13 16:29 ` [PATCH 3/7] davinci: add tnetv107x keypad platform device Cyril Chemparathy
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds support for tnetv107x's on-chip keypad controller.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 drivers/input/keyboard/Kconfig            |    9 +
 drivers/input/keyboard/Makefile           |    1 +
 drivers/input/keyboard/tnetv107x-keypad.c |  324 +++++++++++++++++++++++++++++
 3 files changed, 334 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 9cc488d..0ea8648 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -457,4 +457,13 @@ config KEYBOARD_W90P910
 	  To compile this driver as a module, choose M here: the
 	  module will be called w90p910_keypad.
 
+config KEYBOARD_TNETV107X
+	tristate "TI TNETV107X keypad support"
+	depends on ARCH_DAVINCI_TNETV107X
+	help
+	  Say Y here if you want to use the TNETV107X keypad.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tnetv107x-keypad.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 504b591..63261b0 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
+obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
new file mode 100644
index 0000000..5039164
--- /dev/null
+++ b/drivers/input/keyboard/tnetv107x-keypad.c
@@ -0,0 +1,324 @@
+/*
+ * Texas Instruments TNETV107X Keypad Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <mach/tnetv107x.h>
+
+#define KEYPAD_ROWS		9
+#define KEYPAD_COLS		9
+
+struct keypad_regs {
+	u32	rev;
+	u32	mode;
+	u32	mask;
+	u32	pol;
+	u32	dclock;
+	u32	rclock;
+	u32	stable_cnt;
+	u32	in_en;
+	u32	out;
+	u32	out_en;
+	u32	in;
+	u32	lock;
+	u32	pres[3];
+};
+
+#define keypad_read(kp, reg)		__raw_readl(&(kp)->regs->reg)
+#define keypad_write(kp, reg, val)	__raw_writel(val, &(kp)->regs->reg)
+
+struct keypad_data {
+	struct tnetv107x_keypad_data	data;
+	struct input_dev		*input_dev;
+	struct resource			*res;
+	struct keypad_regs __iomem	*regs;
+	struct clk			*clk;
+	struct device			*dev;
+	u32				irq_press;
+	u32				irq_release;
+	u32				curr_keys[3];
+	u32				prev_keys[3];
+};
+
+static void handle_change(struct keypad_data *kp)
+{
+	int bit, i;
+
+	for (bit = 0; bit < (KEYPAD_ROWS * KEYPAD_COLS); bit++) {
+		int idx		= bit / 32;
+		u32 mask	= 1 << (bit % 32);
+		u32 curr	= kp->curr_keys[idx] & mask;
+		u32 prev	= kp->prev_keys[idx] & mask;
+		int row		= bit / KEYPAD_COLS;
+		int col		= bit % KEYPAD_COLS;
+		int ofs		= row * kp->data.cols + col;
+
+		if (col >= kp->data.cols || row >= kp->data.rows)
+			continue;
+
+		if (curr && !prev) {
+			/* Report key press */
+			if (kp->data.keynames && kp->data.keynames[ofs])
+				dev_dbg(kp->dev, "%s (%d) pressed\n",
+					kp->data.keynames[ofs], ofs);
+			input_report_key(kp->input_dev,
+					 kp->data.keymap[ofs], 1);
+		} else if (!curr && prev) {
+			/* Report key release */
+			if (kp->data.keynames && kp->data.keynames[ofs])
+				dev_dbg(kp->dev, "%s (%d) released\n",
+					kp->data.keynames[ofs], ofs);
+			input_report_key(kp->input_dev,
+					 kp->data.keymap[ofs], 0);
+		}
+	}
+
+	/* Update shadow copy */
+	for (i = 0; i < 3; i++)
+		kp->prev_keys[i] = kp->curr_keys[i];
+
+	input_sync(kp->input_dev);
+}
+
+static irqreturn_t keypad_irq_press(int irq, void *data)
+{
+	struct keypad_data *kp = (struct keypad_data *)data;
+	int i;
+
+	for (i = 0; i < 3; i++)
+		kp->curr_keys[i] = keypad_read(kp, pres[i]);
+	handle_change(kp);
+	keypad_write(kp, lock, 0); /* Allow hardware updates */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t keypad_irq_release(int irq, void *data)
+{
+	struct keypad_data *kp = (struct keypad_data *)data;
+	int i;
+
+	/* Hardware says all keys have been released */
+	for (i = 0; i < 3; i++)
+		kp->curr_keys[i] = 0;
+	handle_change(kp);
+	return IRQ_HANDLED;
+}
+
+static int tnetv107x_keypad_probe(struct platform_device *pdev)
+{
+	struct tnetv107x_keypad_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct keypad_data *kp;
+	int i, ret = 0;
+	u32 rev = 0;
+
+	ret = -EINVAL;
+	if (!pdata) {
+		dev_err(dev, "cannot find device data\n");
+		return ret;
+	}
+
+	ret = -ENOMEM;
+	kp = kzalloc(sizeof(struct keypad_data), GFP_KERNEL);
+	if (!kp) {
+		dev_err(dev, "cannot allocate device info\n");
+		return ret;
+	}
+
+	dev_set_drvdata(dev, kp);
+	kp->data = *pdata;
+	kp->dev = dev;
+
+	ret = -ENOMEM;
+	kp->input_dev = input_allocate_device();
+	if (!kp->input_dev) {
+		dev_err(dev, "cannot allocate input device\n");
+		goto error0;
+	}
+
+	ret = -ENODEV;
+	kp->irq_press   = platform_get_irq_byname(pdev, "press");
+	kp->irq_release = platform_get_irq_byname(pdev, "release");
+	if (kp->irq_press < 0 || kp->irq_release < 0) {
+		dev_err(dev, "cannot determine device interrupts\n");
+		goto error1;
+	}
+
+	ret = -ENODEV;
+	kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!kp->res) {
+		dev_err(dev, "cannot determine register area\n");
+		goto error1;
+	}
+
+	ret = -EINVAL;
+	if (!request_mem_region(kp->res->start, resource_size(kp->res),
+				pdev->name)) {
+		dev_err(dev, "cannot claim register memory\n");
+		goto error1;
+	}
+
+	ret = -ENOMEM;
+	kp->regs = ioremap(kp->res->start, resource_size(kp->res));
+	if (!kp->regs) {
+		dev_err(dev, "cannot map register memory\n");
+		goto error2;
+	}
+
+	ret = -EINVAL;
+	kp->clk = clk_get(dev, NULL);
+	if (!kp->clk) {
+		dev_err(dev, "cannot claim device clock\n");
+		goto error3;
+	}
+	clk_enable(kp->clk);
+
+	/* Initialize device registers */
+	keypad_write(kp, mode, 0);
+	keypad_write(kp, mask, ~((((1 << kp->data.rows)-1) << 9) |
+			   (((1 << kp->data.cols)-1))));
+	keypad_write(kp, pol, 0x3ffff);
+	keypad_write(kp, dclock, kp->data.debounce);
+	keypad_write(kp, rclock, 4*kp->data.debounce);
+	keypad_write(kp, stable_cnt, kp->data.stable);
+
+	/* Enable Input */
+	keypad_write(kp, in_en, 0);
+	mdelay(1);
+	keypad_write(kp, in_en, 1);
+
+	ret = request_irq(kp->irq_press, keypad_irq_press, 0,
+			  "keypad-press", kp);
+	if (ret < 0) {
+		dev_err(dev, "Could not allocate keypad press key irq\n");
+		goto error4;
+	}
+
+	ret = request_irq(kp->irq_release, keypad_irq_release, 0,
+			  "keypad-release", kp);
+	if (ret < 0) {
+		dev_err(dev, "Could not allocate keypad release key irq\n");
+		goto error5;
+	}
+
+	set_bit(EV_KEY, kp->input_dev->evbit);
+	for (i = 0; i < kp->data.keymap_size; i++)
+		set_bit(kp->data.keymap[i] & KEY_MAX, kp->input_dev->keybit);
+
+	kp->input_dev->name = "tnetv107x-keypad";
+	kp->input_dev->phys = "tnetv107x-keypad/input0";
+	kp->input_dev->dev.parent = &pdev->dev;
+	kp->input_dev->id.bustype = BUS_HOST;
+	kp->input_dev->id.vendor = 0x0001;
+
+	rev = keypad_read(kp, rev);
+	kp->input_dev->id.product = ((rev >>  8) & 0x07);
+	kp->input_dev->id.version = ((rev >> 16) & 0xfff);
+
+	kp->input_dev->keycode = kp->data.keymap;
+	kp->input_dev->keycodesize = sizeof(int);
+	kp->input_dev->keycodemax = kp->data.keymap_size;
+	ret = input_register_device(kp->input_dev);
+	if (ret < 0) {
+		dev_err(dev, "Could not register input device\n");
+		goto error6;
+	}
+
+	dev_info(dev, "registered keypad device\n");
+	return 0;
+
+error6:
+	free_irq(kp->irq_release, kp);
+error5:
+	free_irq(kp->irq_press, kp);
+error4:
+	clk_disable(kp->clk);
+	clk_put(kp->clk);
+error3:
+	iounmap(kp->regs);
+error2:
+	release_mem_region(kp->res->start, resource_size(kp->res));
+error1:
+	input_free_device(kp->input_dev);
+error0:
+	platform_set_drvdata(pdev, NULL);
+	kfree(kp);
+	return ret;
+}
+
+static int tnetv107x_keypad_remove(struct platform_device *pdev)
+{
+	struct keypad_data *kp = dev_get_drvdata(&pdev->dev);
+
+	if (kp) {
+		input_unregister_device(kp->input_dev);
+		free_irq(kp->irq_release, kp);
+		free_irq(kp->irq_press, kp);
+		clk_disable(kp->clk);
+		clk_put(kp->clk);
+		iounmap(kp->regs);
+		release_mem_region(kp->res->start, resource_size(kp->res));
+		input_free_device(kp->input_dev);
+		platform_set_drvdata(pdev, NULL);
+		kfree(kp);
+	}
+	return 0;
+}
+
+static int tnetv107x_keypad_suspend(struct platform_device *pdev,
+		pm_message_t state)
+{
+	/* Nothing yet */
+	return 0;
+}
+
+static int tnetv107x_keypad_resume(struct platform_device *pdev)
+{
+	/* Nothing yet */
+	return 0;
+}
+
+static struct platform_driver tnetv107x_keypad_driver = {
+	.probe		= tnetv107x_keypad_probe,
+	.remove		= tnetv107x_keypad_remove,
+	.suspend	= tnetv107x_keypad_suspend,
+	.resume		= tnetv107x_keypad_resume,
+	.driver.name	= "tnetv107x-keypad",
+};
+
+static int __init tnetv107x_keypad_init(void)
+{
+	return platform_driver_register(&tnetv107x_keypad_driver);
+}
+
+static void __exit tnetv107x_keypad_exit(void)
+{
+	platform_driver_unregister(&tnetv107x_keypad_driver);
+}
+
+module_init(tnetv107x_keypad_init);
+module_exit(tnetv107x_keypad_exit);
+
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_DESCRIPTION("TNETV107X Keypad Driver");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] davinci: add tnetv107x keypad platform device
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 1/7] davinci: define tnetv107x keypad platform data Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 4/7] davinci: add keypad config for tnetv107x evm board Cyril Chemparathy
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds a platform device definition for tnetv107x's keypad
controller.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 arch/arm/mach-davinci/devices-tnetv107x.c      |   30 ++++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/tnetv107x.h |    1 +
 2 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 2718a3a..086269f 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -33,6 +33,7 @@
 #define TNETV107X_WDOG_BASE			0x08086700
 #define TNETV107X_SDIO0_BASE			0x08088700
 #define TNETV107X_SDIO1_BASE			0x08088800
+#define TNETV107X_KEYPAD_BASE			0x08088a00
 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE		0x08200000
 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE	0x30000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE	0x40000000
@@ -298,6 +299,30 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data)
 	return platform_device_register(pdev);
 }
 
+static struct resource keypad_resources[] = {
+	{
+		.start	= TNETV107X_KEYPAD_BASE,
+		.end	= TNETV107X_KEYPAD_BASE + 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_TNETV107X_KEYPAD,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "press",
+	},
+	{
+		.start	= IRQ_TNETV107X_KEYPAD_FREE,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "release",
+	},
+};
+
+static struct platform_device keypad_device = {
+	.name		= "tnetv107x-keypad",
+	.num_resources	= ARRAY_SIZE(keypad_resources),
+	.resource	= keypad_resources,
+};
+
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
 	int i;
@@ -317,4 +342,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 	for (i = 0; i < 4; i++)
 		if (info->nand_config[i])
 			nand_init(i, info->nand_config[i]);
+
+	if (info->keypad_config) {
+		keypad_device.dev.platform_data = info->keypad_config;
+		platform_device_register(&keypad_device);
+	}
 }
diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
index 1ee3035..9f5350f 100644
--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
+++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
@@ -51,6 +51,7 @@ struct tnetv107x_device_info {
 	struct davinci_uart_config	*serial_config;
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
 	struct davinci_nand_pdata	*nand_config[4]; /* 4 chipsels */
+	struct tnetv107x_keypad_data	*keypad_config;
 };
 
 extern struct platform_device tnetv107x_wdt_device;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] davinci: add keypad config for tnetv107x evm board
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
                   ` (2 preceding siblings ...)
  2010-09-13 16:29 ` [PATCH 3/7] davinci: add tnetv107x keypad platform device Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 5/7] input: add driver for tnetv107x touchscreen controller Cyril Chemparathy
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds evm board specific keymap definitions and controller
configuration data for on-chip keypad controller on tnetv107x silicon.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 arch/arm/mach-davinci/board-tnetv107x-evm.c |   42 +++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index fe2a9d9..2fe7a3f 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/ratelimit.h>
+#include <linux/input.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <asm/mach/arch.h>
@@ -141,10 +142,51 @@ static struct davinci_uart_config serial_config __initconst = {
 	.enabled_uarts	= BIT(1),
 };
 
+static int keymap[] = {
+	/* row 0 */
+	KEY_NUMERIC_1, KEY_NUMERIC_2, KEY_NUMERIC_3, KEY_FN_F1, KEY_MENU,
+	/* row 1 */
+	KEY_NUMERIC_4, KEY_NUMERIC_5, KEY_NUMERIC_6, KEY_UP, KEY_FN_F2,
+	/* row 2 */
+	KEY_NUMERIC_7, KEY_NUMERIC_8, KEY_NUMERIC_9, KEY_LEFT, KEY_ENTER,
+	/* row 3 */
+	KEY_NUMERIC_STAR, KEY_NUMERIC_0, KEY_NUMERIC_POUND, KEY_DOWN, KEY_RIGHT,
+	/* row 4 */
+	KEY_FN_F3, KEY_FN_F4, KEY_MUTE, KEY_HOME, KEY_BACK,
+	/* row 5 */
+	KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_F1, KEY_F2, KEY_F3,
+};
+
+static const char *keynames[] = {
+	/* row 0 */
+	"1", "2", "3", "S1 (FN_F1)", "MENU",
+	/* row 1 */
+	"4", "5", "6", "UP", "S2 (FN_F2)",
+	/* row 2 */
+	"7", "8", "9", "LEFT", "ENTER",
+	/* row 3 */
+	"*", "0", "#", "DOWN", "RIGHT",
+	/* row 4 */
+	"SPEAKER (FN_F3)", "HEADSET (FN_F4)", "MUTE", "HOME", "BACK",
+	/* row 5 */
+	"VOL_DOWN", "VOL_UP", "F1", "F2", "F3",
+};
+
+static struct tnetv107x_keypad_data keypad_config = {
+	.keynames	= keynames,
+	.keymap		= keymap,
+	.keymap_size	= ARRAY_SIZE(keymap),
+	.rows		= 6,
+	.cols		= 5,
+	.debounce	= 0x400,
+	.stable		= 0x3,
+};
+
 static struct tnetv107x_device_info evm_device_info __initconst = {
 	.serial_config		= &serial_config,
 	.mmc_config[1]		= &mmc_config,	/* controller 1 */
 	.nand_config[0]		= &nand_config,	/* chip select 0 */
+	.keypad_config		= &keypad_config,
 };
 
 static __init void tnetv107x_evm_board_init(void)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] input: add driver for tnetv107x touchscreen controller
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
                   ` (3 preceding siblings ...)
  2010-09-13 16:29 ` [PATCH 4/7] davinci: add keypad config for tnetv107x evm board Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-14  1:27   ` Dmitry Torokhov
  2010-09-14  6:38   ` Datta, Shubhrajyoti
  2010-09-13 16:29 ` [PATCH 6/7] davinci: add tnetv107x touchscreen platform device Cyril Chemparathy
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds support for tnetv107x's on-chip touchscreen controller.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 drivers/input/touchscreen/Kconfig        |    6 +
 drivers/input/touchscreen/Makefile       |    1 +
 drivers/input/touchscreen/tnetv107x-ts.c |  481 ++++++++++++++++++++++++++++++
 3 files changed, 488 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0069d97..e56a170 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -638,4 +638,10 @@ config TOUCHSCREEN_STMPE
 	  To compile this driver as a module, choose M here: the
 	  module will be called stmpe-ts.
 
+config TOUCHSCREEN_TNETV107X
+	tristate "TI TNETV107X touchscreen support"
+	depends on ARCH_DAVINCI_TNETV107X
+	help
+	  Say Y here if you want to use the TNETV107X touchscreen.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 28217e1..55a7db9 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)	+= zylonite-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)	+= tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
new file mode 100644
index 0000000..a8543c5
--- /dev/null
+++ b/drivers/input/touchscreen/tnetv107x-ts.c
@@ -0,0 +1,481 @@
+/*
+ * Texas Instruments TNETV107X Touchscreen Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <mach/tnetv107x.h>
+
+/* Poll Rates */
+#define TSC_PENUP_POLL		(HZ / 5)
+
+/*
+ * The first and last samples of a touch interval are usually garbage and need
+ * to be filtered out with these devices.  The following definitions control
+ * the number of samples skipped.
+ */
+#define TSC_HEAD_SKIP		1
+#define TSC_TAIL_SKIP		1
+#define TSC_SKIP		(TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
+#define TSC_SAMPLES		(TSC_SKIP + 1)
+
+/* Register Offsets */
+struct tsc_regs {
+	u32	rev;
+	u32	tscm;
+	u32	bwcm;
+	u32	swc;
+	u32	adcchnl;
+	u32	adcdata;
+	u32	chval[4];
+};
+
+/* TSC Mode Configuration Register (tscm) bits */
+#define WMODE		BIT(0)
+#define TSKIND		BIT(1)
+#define ZMEASURE_EN	BIT(2)
+#define IDLE		BIT(3)
+#define TSC_EN		BIT(4)
+#define STOP		BIT(5)
+#define ONE_SHOT	BIT(6)
+#define SINGLE		BIT(7)
+#define AVG		BIT(8)
+#define AVGNUM(x)	(((x) & 0x03) <<  9)
+#define PVSTC(x)	(((x) & 0x07) << 11)
+#define PON		BIT(14)
+#define PONBG		BIT(15)
+#define AFERST		BIT(16)
+
+/* ADC DATA Capture Register bits */
+#define DATA_VALID	BIT(16)
+
+/* Register Access Macros */
+#define tsc_read(ts, reg)		__raw_readl(&(ts)->regs->reg)
+#define tsc_write(ts, reg, val)		__raw_writel(val, &(ts)->regs->reg);
+#define tsc_set_bits(ts, reg, val)	\
+	tsc_write(ts, reg, tsc_read(ts, reg) | (val))
+#define tsc_clr_bits(ts, reg, val)	\
+	tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
+
+struct sample {
+	int x, y, p;
+};
+
+struct tsc_data {
+	struct tnetv107x_tsc_data	data;
+	struct input_dev		*input_dev;
+	struct resource			*res;
+	struct tsc_regs __iomem		*regs;
+	struct timer_list		timer;
+	spinlock_t			lock;
+	struct clk			*clk;
+	struct device			*dev;
+	int				sample_count;
+	struct sample			samples[TSC_SAMPLES];
+	int				tsc_irq;
+	int				cal[TSC_CAL_SIZE];
+};
+
+/* default calibration that works for most evm boards */
+static int tscal_set;
+static int tscal[TSC_CAL_SIZE];
+module_param_array(tscal, int, &tscal_set, 0);
+
+static inline int
+tsc_read_sample(struct tsc_data *ts, struct sample* sample)
+{
+	int	x, y, z1, z2, t, p = 0;
+	u32	val;
+
+	val = tsc_read(ts, chval[0]);
+	if (val & DATA_VALID)
+		x = val & 0xffff;
+	else
+		return -EINVAL;
+
+	y  = tsc_read(ts, chval[1]) & 0xffff;
+	z1 = tsc_read(ts, chval[2]) & 0xffff;
+	z2 = tsc_read(ts, chval[3]) & 0xffff;
+
+	if (z1) {
+		t = ((600 * x) * (z2 - z1));
+		p = t / (u32) (z1 << 12);
+		if (p < 0)
+			p = 0;
+	}
+
+	sample->x  = (ts->cal[2] + ts->cal[0] * x + ts->cal[1] * y);
+	sample->x /= ts->cal[6];
+	sample->y  = (ts->cal[5] + ts->cal[3] * x + ts->cal[4] * y);
+	sample->y /= ts->cal[6];
+	sample->p  = p;
+
+	return 0;
+}
+
+static inline void tsc_report_up(struct tsc_data *ts)
+{
+	input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
+	input_report_key(ts->input_dev, BTN_TOUCH, 0);
+	input_sync(ts->input_dev);
+}
+
+static inline void tsc_report(struct tsc_data *ts, int x, int y, int p)
+{
+	input_report_abs(ts->input_dev, ABS_X, x);
+	input_report_abs(ts->input_dev, ABS_Y, y);
+	input_report_abs(ts->input_dev, ABS_PRESSURE, p);
+}
+
+static inline void tsc_report_down(struct tsc_data *ts, bool touch)
+{
+	if (touch)
+		input_report_key(ts->input_dev, BTN_TOUCH, 1);
+	input_sync(ts->input_dev);
+}
+
+static inline void tsc_poll(unsigned long data)
+{
+	struct tsc_data *ts = (struct tsc_data *)data;
+	unsigned long flags;
+	int i, val, x, y, p;
+
+	spin_lock_irqsave(&ts->lock, flags);
+
+	if (ts->sample_count >= TSC_SKIP) {
+		tsc_report_up(ts);
+	} else if (ts->sample_count > 0) {
+		/*
+		 * A touch event lasted less than our skip count.  Salvage and
+		 * report anyway.
+		 */
+		for (i = 0, val = 0; i < ts->sample_count; i++)
+			val += ts->samples[i].x;
+		x = val / ts->sample_count;
+
+		for (i = 0, val = 0; i < ts->sample_count; i++)
+			val += ts->samples[i].y;
+		y = val / ts->sample_count;
+
+		for (i = 0, val = 0; i < ts->sample_count; i++)
+			val += ts->samples[i].p;
+		p = val / ts->sample_count;
+
+		tsc_report(ts, x, y, p);
+		tsc_report_down(ts, true);
+	}
+
+	ts->sample_count = 0;
+
+	spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static irqreturn_t tsc_irq(int irq, void *dev_id)
+{
+	struct tsc_data *ts = (struct tsc_data *)dev_id;
+	struct sample *sample;
+	int index;
+
+	spin_lock(&ts->lock);
+
+	index = ts->sample_count % TSC_SAMPLES;
+	sample = &ts->samples[index];
+	if (tsc_read_sample(ts, sample) >= 0) {
+		++ts->sample_count;
+
+		if (ts->sample_count < TSC_SKIP)
+			goto done;
+
+		index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
+		sample = &ts->samples[index];
+
+		tsc_report(ts, sample->x, sample->y, sample->y);
+		tsc_report_down(ts, (ts->sample_count == TSC_SKIP));
+done:
+		mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
+	}
+
+	spin_unlock(&ts->lock);
+	return IRQ_HANDLED;
+}
+
+static ssize_t tsc_cal_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct tsc_data *ts = dev_get_drvdata(dev);
+	ssize_t len = 0;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		len += snprintf(buf+len, PAGE_SIZE-len, "%d ", ts->cal[i]);
+
+	len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", ts->cal[6]);
+
+	return len;
+}
+
+/*
+ * The calibration data format is identical to the contents of tslib's
+ * generated output
+ */
+static ssize_t tsc_cal_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct tsc_data *ts = dev_get_drvdata(dev);
+	int index = 0;
+	int cal[TSC_CAL_SIZE];
+	const char *cur = buf, *end = buf + count;
+	char *tmp;
+	unsigned long flags;
+
+	for (index = 0; index < TSC_CAL_SIZE; index++) {
+		while (isspace(*cur) && cur < end)
+			cur++;
+		if (cur >= end) {
+			dev_err(ts->dev, "premature end in calib data\n");
+			return -EINVAL;
+		}
+
+		if (isdigit(*cur) || *cur == '-') {
+			cal[index] = simple_strtol(cur, &tmp, 0);
+			cur = tmp;
+		}
+	}
+
+	spin_lock_irqsave(&ts->lock, flags);
+	memcpy(ts->cal, cal, sizeof(cal));
+	spin_unlock_irqrestore(&ts->lock, flags);
+
+	return count;
+}
+
+static struct device_attribute tsc_attr_cal =
+	__ATTR(tscal, S_IWUSR | S_IRUGO, tsc_cal_show, tsc_cal_store);
+
+static int tsc_probe(struct platform_device *pdev)
+{
+	struct tnetv107x_tsc_data *pdata = pdev->dev.platform_data;
+	struct tsc_data *ts;
+	int ret = 0, *cal;
+	u32 rev = 0, val = 0;
+	struct device *dev = &pdev->dev;
+
+	if (!pdata) {
+		dev_err(dev, "could not find platform data\n");
+		return -EINVAL;
+	}
+
+	ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
+	if (!ts) {
+		dev_err(dev, "cannot allocate device info\n");
+		return -ENOMEM;
+	}
+
+	ts->dev = dev;
+	ts->data = *pdata;
+	dev_set_drvdata(dev, ts);
+
+	cal = (tscal_set == TSC_CAL_SIZE) ? tscal : ts->data.calibration_data;
+	memcpy(ts->cal, cal, TSC_CAL_SIZE * sizeof(int));
+
+	ret = -ENOMEM;
+	ts->input_dev = input_allocate_device();
+	if (!ts->input_dev) {
+		dev_err(dev, "cannot allocate input device\n");
+		goto error0;
+	}
+
+	ret = -ENODEV;
+	ts->tsc_irq = platform_get_irq(pdev, 0);
+	if (ts->tsc_irq < 0) {
+		dev_err(dev, "cannot determine device interrupt\n");
+		goto error1;
+	}
+
+	ret = -ENODEV;
+	ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ts->res) {
+		dev_err(dev, "cannot determine register area\n");
+		goto error1;
+	}
+
+	ret = -EINVAL;
+	if (!request_mem_region(ts->res->start, resource_size(ts->res),
+				pdev->name)) {
+		dev_err(dev, "cannot claim register memory\n");
+		goto error1;
+	}
+
+	ret = -ENOMEM;
+	ts->regs = ioremap(ts->res->start, resource_size(ts->res));
+	if (!ts->regs) {
+		dev_err(dev, "cannot map register memory\n");
+		goto error2;
+	}
+
+	ret = -EINVAL;
+	ts->clk = clk_get(dev, NULL);
+	if (!ts->clk) {
+		dev_err(dev, "cannot claim device clock\n");
+		goto error3;
+	}
+	clk_enable(ts->clk);
+
+	spin_lock_init(&ts->lock);
+
+	init_timer(&ts->timer);
+	setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
+
+	/* Go to idle mode, before any initialization */
+	while ((tsc_read(ts, tscm) & IDLE) == 0)
+		barrier();
+
+	/* Configure the TSC Control register*/
+	val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
+	tsc_write(ts, tscm, val);
+
+	/* Bring TSC out of reset: Clear AFE reset bit */
+	val &= ~(AFERST);
+	tsc_write(ts, tscm, val);
+	udelay(10);
+
+	/* Configure all pins for hardware control*/
+	tsc_write(ts, bwcm, 0);
+
+	/* Finally enable the TSC */
+	tsc_set_bits(ts, tscm, TSC_EN);
+
+	ret = -EINVAL;
+	if (request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts)) {
+		dev_err(dev, "Could not allocate ts irq\n");
+		goto error4;
+	}
+
+	ret = device_create_file(ts->dev, &tsc_attr_cal);
+	if (ret < 0) {
+		dev_err(dev, "Could not create sysfs entry!\n");
+		goto error5;
+	}
+
+	rev = tsc_read(ts, rev);
+	ts->input_dev->name       = "tnetv107x-ts";
+	ts->input_dev->phys       = "tnetv107x-ts/input0";
+	ts->input_dev->id.bustype = BUS_HOST;
+	ts->input_dev->id.vendor  = 0x0001;
+	ts->input_dev->id.product = ((rev >>  8) & 0x07);
+	ts->input_dev->id.version = ((rev >> 16) & 0xfff);
+	ts->input_dev->dev.parent = &pdev->dev;
+
+	/* Declare capabilities */
+	set_bit(EV_KEY,       ts->input_dev->evbit);
+	set_bit(BTN_TOUCH,    ts->input_dev->keybit);
+	set_bit(EV_ABS,       ts->input_dev->evbit);
+	set_bit(ABS_X,        ts->input_dev->absbit);
+	set_bit(ABS_Y,        ts->input_dev->absbit);
+	set_bit(ABS_PRESSURE, ts->input_dev->absbit);
+
+	input_set_abs_params(ts->input_dev, ABS_X, 0, ts->data.xres, 5, 0);
+	input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->data.yres, 5, 0);
+	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
+
+	ret = input_register_device(ts->input_dev);
+	if (ret < 0)
+		goto error6;
+
+	return 0;
+
+error6:
+	device_remove_file(ts->dev, &tsc_attr_cal);
+error5:
+	free_irq(ts->tsc_irq, ts);
+error4:
+	clk_disable(ts->clk);
+	clk_put(ts->clk);
+error3:
+	iounmap(ts->regs);
+error2:
+	release_mem_region(ts->res->start, resource_size(ts->res));
+error1:
+	input_free_device(ts->input_dev);
+error0:
+	kfree(ts);
+	dev_set_drvdata(dev, NULL);
+	return ret;
+}
+
+static int tsc_remove(struct platform_device *pdev)
+{
+	struct tsc_data *ts = dev_get_drvdata(&pdev->dev);
+
+	if (!ts)
+		return 0;
+
+	tsc_clr_bits(ts, tscm, TSC_EN);
+	del_timer_sync(&ts->timer);
+	device_remove_file(ts->dev, &tsc_attr_cal);
+	free_irq(ts->tsc_irq, ts);
+	clk_disable(ts->clk);
+	clk_put(ts->clk);
+	iounmap(ts->regs);
+	release_mem_region(ts->res->start, resource_size(ts->res));
+	input_free_device(ts->input_dev);
+	kfree(ts);
+	dev_set_drvdata(&pdev->dev, NULL);
+	return 0;
+}
+
+static int tsc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	/* Nothing yet */
+	return 0;
+}
+
+static int tsc_resume(struct platform_device *pdev)
+{
+	/* Nothing yet */
+	return 0;
+}
+
+static struct platform_driver tsc_driver = {
+	.probe		= tsc_probe,
+	.remove		= tsc_remove,
+	.suspend	= tsc_suspend,
+	.resume		= tsc_resume,
+	.driver.name	= "tnetv107x-ts",
+};
+
+static int __init tsc_init(void)
+{
+	return platform_driver_register(&tsc_driver);
+}
+
+static void __exit tsc_exit(void)
+{
+	platform_driver_unregister(&tsc_driver);
+}
+
+module_init(tsc_init);
+module_exit(tsc_exit);
+
+MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] davinci: add tnetv107x touchscreen platform device
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
                   ` (4 preceding siblings ...)
  2010-09-13 16:29 ` [PATCH 5/7] input: add driver for tnetv107x touchscreen controller Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-13 16:29 ` [PATCH 7/7] davinci: add touchscreen config for tnetv107x evm board Cyril Chemparathy
  2010-09-16 17:53 ` [PATCH 0/7] add tnetv107x input drivers Kevin Hilman
  7 siblings, 0 replies; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds a platform device definition for tnetv107x's touchscreen
controller.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 arch/arm/mach-davinci/devices-tnetv107x.c      |   24 ++++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/tnetv107x.h |   13 +++++++++++++
 2 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 086269f..018ca13 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -31,6 +31,7 @@
 #define TNETV107X_TPTC0_BASE			0x01c10000
 #define TNETV107X_TPTC1_BASE			0x01c10400
 #define TNETV107X_WDOG_BASE			0x08086700
+#define TNETV107X_TSC_BASE			0x08088500
 #define TNETV107X_SDIO0_BASE			0x08088700
 #define TNETV107X_SDIO1_BASE			0x08088800
 #define TNETV107X_KEYPAD_BASE			0x08088a00
@@ -323,6 +324,24 @@ static struct platform_device keypad_device = {
 	.resource	= keypad_resources,
 };
 
+static struct resource tsc_resources[] = {
+	{
+		.start	= TNETV107X_TSC_BASE,
+		.end	= TNETV107X_TSC_BASE + 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_TNETV107X_TSC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tsc_device = {
+	.name		= "tnetv107x-ts",
+	.num_resources	= ARRAY_SIZE(tsc_resources),
+	.resource	= tsc_resources,
+};
+
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
 	int i;
@@ -347,4 +366,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 		keypad_device.dev.platform_data = info->keypad_config;
 		platform_device_register(&keypad_device);
 	}
+
+	if (info->tsc_config) {
+		tsc_device.dev.platform_data = info->tsc_config;
+		platform_device_register(&tsc_device);
+	}
 }
diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
index 9f5350f..7e33148 100644
--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
+++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
@@ -47,11 +47,24 @@ struct tnetv107x_keypad_data {
 	u32		stable;
 };
 
+struct tnetv107x_tsc_data {
+	int		xres, yres;
+
+	/*
+	 * Calibration info:
+	 *   out_x = (C0 * in_x + C1 * in_y + C2) / C6
+	 *   out_y = (C3 * in_x + C4 * in_y + C5) / C6
+	 */
+#define TSC_CAL_SIZE	7
+	int		calibration_data[TSC_CAL_SIZE];
+};
+
 struct tnetv107x_device_info {
 	struct davinci_uart_config	*serial_config;
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
 	struct davinci_nand_pdata	*nand_config[4]; /* 4 chipsels */
 	struct tnetv107x_keypad_data	*keypad_config;
+	struct tnetv107x_tsc_data	*tsc_config;
 };
 
 extern struct platform_device tnetv107x_wdt_device;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] davinci: add touchscreen config for tnetv107x evm board
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
                   ` (5 preceding siblings ...)
  2010-09-13 16:29 ` [PATCH 6/7] davinci: add tnetv107x touchscreen platform device Cyril Chemparathy
@ 2010-09-13 16:29 ` Cyril Chemparathy
  2010-09-16 17:53 ` [PATCH 0/7] add tnetv107x input drivers Kevin Hilman
  7 siblings, 0 replies; 15+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 16:29 UTC (permalink / raw)
  To: linux-input, davinci-linux-open-source; +Cc: Cyril Chemparathy

This patch adds evm board specific definitions (dimensions, default
calibration, etc.) for the on-chip keypad controller on tnetv107x silicon.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
---
 arch/arm/mach-davinci/board-tnetv107x-evm.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index 2fe7a3f..287c5ee 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -182,11 +182,20 @@ static struct tnetv107x_keypad_data keypad_config = {
 	.stable		= 0x3,
 };
 
+static struct tnetv107x_tsc_data tsc_config = {
+	.xres	= 800,
+	.yres	= 480,
+	.calibration_data = {
+		217, 14019, -2540712, 8690, -140, -1651470, 65536,
+	},
+};
+
 static struct tnetv107x_device_info evm_device_info __initconst = {
 	.serial_config		= &serial_config,
 	.mmc_config[1]		= &mmc_config,	/* controller 1 */
 	.nand_config[0]		= &nand_config,	/* chip select 0 */
 	.keypad_config		= &keypad_config,
+	.tsc_config		= &tsc_config,
 };
 
 static __init void tnetv107x_evm_board_init(void)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/7] davinci: define tnetv107x keypad platform data
  2010-09-13 16:29 ` [PATCH 1/7] davinci: define tnetv107x keypad platform data Cyril Chemparathy
@ 2010-09-14  1:26   ` Dmitry Torokhov
  0 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2010-09-14  1:26 UTC (permalink / raw)
  To: Cyril Chemparathy; +Cc: linux-input, davinci-linux-open-source

Hi Cyril,

On Mon, Sep 13, 2010 at 12:29:42PM -0400, Cyril Chemparathy wrote:
> This patch adds a definition for the platform data structure needed to
> configure the keypad controller on tnetv107x socs.
> 
> Since this controller is (so far) present only on tnetv107x devices, the data
> structure definition has been kept local to tnetv107x.
> 
> Signed-off-by: Cyril Chemparathy <cyril@ti.com>
> ---
>  arch/arm/mach-davinci/include/mach/tnetv107x.h |   10 ++++++++++
>  1 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
> index c720647..1ee3035 100644
> --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
> +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
> @@ -37,6 +37,16 @@
>  #include <mach/nand.h>
>  #include <mach/serial.h>
>  
> +struct tnetv107x_keypad_data {
> +	int		*keymap;
> +	const char	**keynames;
> +	int		keymap_size;
> +	int		rows;
> +	int		cols;
> +	u32		debounce;
> +	u32		stable;
> +};
> +

This should be folded into the next patch and probably split into a
separate header file. Also, please consider switching to interface in
linux/input/matrix_keymap.h

Thanks.

- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller
  2010-09-13 16:29 ` [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller Cyril Chemparathy
@ 2010-09-14  1:26   ` Dmitry Torokhov
  0 siblings, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2010-09-14  1:26 UTC (permalink / raw)
  To: Cyril Chemparathy; +Cc: linux-input, davinci-linux-open-source

On Mon, Sep 13, 2010 at 12:29:43PM -0400, Cyril Chemparathy wrote:
> This patch adds support for tnetv107x's on-chip keypad controller.
> 
> Signed-off-by: Cyril Chemparathy <cyril@ti.com>
> ---
>  drivers/input/keyboard/Kconfig            |    9 +
>  drivers/input/keyboard/Makefile           |    1 +
>  drivers/input/keyboard/tnetv107x-keypad.c |  324 +++++++++++++++++++++++++++++
>  3 files changed, 334 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
> 
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index 9cc488d..0ea8648 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -457,4 +457,13 @@ config KEYBOARD_W90P910
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called w90p910_keypad.
>  
> +config KEYBOARD_TNETV107X
> +	tristate "TI TNETV107X keypad support"
> +	depends on ARCH_DAVINCI_TNETV107X
> +	help
> +	  Say Y here if you want to use the TNETV107X keypad.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called tnetv107x-keypad.
> +
>  endif
> diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
> index 504b591..63261b0 100644
> --- a/drivers/input/keyboard/Makefile
> +++ b/drivers/input/keyboard/Makefile
> @@ -41,3 +41,4 @@ obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
>  obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
>  obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
>  obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
> +obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o

Please keep makefile and Kconfig sorted alphabetically please.

> diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
> new file mode 100644
> index 0000000..5039164
> --- /dev/null
> +++ b/drivers/input/keyboard/tnetv107x-keypad.c
> @@ -0,0 +1,324 @@
> +/*
> + * Texas Instruments TNETV107X Keypad Driver
> + *
> + * Copyright (C) 2010 Texas Instruments
> + *
> + * 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.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/input.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +
> +#include <mach/tnetv107x.h>
> +
> +#define KEYPAD_ROWS		9
> +#define KEYPAD_COLS		9
> +
> +struct keypad_regs {
> +	u32	rev;
> +	u32	mode;
> +	u32	mask;
> +	u32	pol;
> +	u32	dclock;
> +	u32	rclock;
> +	u32	stable_cnt;
> +	u32	in_en;
> +	u32	out;
> +	u32	out_en;
> +	u32	in;
> +	u32	lock;
> +	u32	pres[3];
> +};
> +
> +#define keypad_read(kp, reg)		__raw_readl(&(kp)->regs->reg)
> +#define keypad_write(kp, reg, val)	__raw_writel(val, &(kp)->regs->reg)
> +
> +struct keypad_data {
> +	struct tnetv107x_keypad_data	data;
> +	struct input_dev		*input_dev;
> +	struct resource			*res;
> +	struct keypad_regs __iomem	*regs;
> +	struct clk			*clk;
> +	struct device			*dev;
> +	u32				irq_press;
> +	u32				irq_release;
> +	u32				curr_keys[3];
> +	u32				prev_keys[3];
> +};
> +
> +static void handle_change(struct keypad_data *kp)
> +{
> +	int bit, i;
> +
> +	for (bit = 0; bit < (KEYPAD_ROWS * KEYPAD_COLS); bit++) {
> +		int idx		= bit / 32;
> +		u32 mask	= 1 << (bit % 32);
> +		u32 curr	= kp->curr_keys[idx] & mask;
> +		u32 prev	= kp->prev_keys[idx] & mask;
> +		int row		= bit / KEYPAD_COLS;
> +		int col		= bit % KEYPAD_COLS;
> +		int ofs		= row * kp->data.cols + col;
> +
> +		if (col >= kp->data.cols || row >= kp->data.rows)
> +			continue;
> +
> +		if (curr && !prev) {
> +			/* Report key press */
> +			if (kp->data.keynames && kp->data.keynames[ofs])
> +				dev_dbg(kp->dev, "%s (%d) pressed\n",
> +					kp->data.keynames[ofs], ofs);
> +			input_report_key(kp->input_dev,
> +					 kp->data.keymap[ofs], 1);
> +		} else if (!curr && prev) {
> +			/* Report key release */
> +			if (kp->data.keynames && kp->data.keynames[ofs])
> +				dev_dbg(kp->dev, "%s (%d) released\n",
> +					kp->data.keynames[ofs], ofs);
> +			input_report_key(kp->input_dev,
> +					 kp->data.keymap[ofs], 0);
> +		}

This is called xor.

Also, instead of printing key names just send EV_MSC/MSC_SCAN - much
more useful.

> +	}
> +
> +	/* Update shadow copy */
> +	for (i = 0; i < 3; i++)
> +		kp->prev_keys[i] = kp->curr_keys[i];

memcpy(kp->prev_keys, kp->curr_keys, sizeof(kp->prev_keys));

> +
> +	input_sync(kp->input_dev);
> +}
> +
> +static irqreturn_t keypad_irq_press(int irq, void *data)
> +{
> +	struct keypad_data *kp = (struct keypad_data *)data;
> +	int i;
> +
> +	for (i = 0; i < 3; i++)
> +		kp->curr_keys[i] = keypad_read(kp, pres[i]);
> +	handle_change(kp);
> +	keypad_write(kp, lock, 0); /* Allow hardware updates */
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t keypad_irq_release(int irq, void *data)
> +{
> +	struct keypad_data *kp = (struct keypad_data *)data;
> +	int i;
> +
> +	/* Hardware says all keys have been released */
> +	for (i = 0; i < 3; i++)
> +		kp->curr_keys[i] = 0;

	memset(kp->curr_keys, 0, sizeof(kp->curr_keys));

> +	handle_change(kp);
> +	return IRQ_HANDLED;
> +}
> +
> +static int tnetv107x_keypad_probe(struct platform_device *pdev)
> +{
> +	struct tnetv107x_keypad_data *pdata = pdev->dev.platform_data;

This should be const.

> +	struct device *dev = &pdev->dev;
> +	struct keypad_data *kp;
> +	int i, ret = 0;
> +	u32 rev = 0;
> +
> +	ret = -EINVAL;
> +	if (!pdata) {
> +		dev_err(dev, "cannot find device data\n");
> +		return ret;
> +	}

Please assign error code in the error branch. I also prefer variable
be called error if possible.

> +
> +	ret = -ENOMEM;
> +	kp = kzalloc(sizeof(struct keypad_data), GFP_KERNEL);
> +	if (!kp) {
> +		dev_err(dev, "cannot allocate device info\n");
> +		return ret;
> +	}
> +
> +	dev_set_drvdata(dev, kp);
> +	kp->data = *pdata;
> +	kp->dev = dev;
> +
> +	ret = -ENOMEM;
> +	kp->input_dev = input_allocate_device();
> +	if (!kp->input_dev) {
> +		dev_err(dev, "cannot allocate input device\n");
> +		goto error0;
> +	}
> +
> +	ret = -ENODEV;
> +	kp->irq_press   = platform_get_irq_byname(pdev, "press");
> +	kp->irq_release = platform_get_irq_byname(pdev, "release");
> +	if (kp->irq_press < 0 || kp->irq_release < 0) {
> +		dev_err(dev, "cannot determine device interrupts\n");
> +		goto error1;
> +	}
> +
> +	ret = -ENODEV;
> +	kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!kp->res) {
> +		dev_err(dev, "cannot determine register area\n");
> +		goto error1;
> +	}
> +
> +	ret = -EINVAL;
> +	if (!request_mem_region(kp->res->start, resource_size(kp->res),
> +				pdev->name)) {
> +		dev_err(dev, "cannot claim register memory\n");
> +		goto error1;
> +	}
> +
> +	ret = -ENOMEM;
> +	kp->regs = ioremap(kp->res->start, resource_size(kp->res));
> +	if (!kp->regs) {
> +		dev_err(dev, "cannot map register memory\n");
> +		goto error2;
> +	}
> +
> +	ret = -EINVAL;
> +	kp->clk = clk_get(dev, NULL);
> +	if (!kp->clk) {
> +		dev_err(dev, "cannot claim device clock\n");
> +		goto error3;
> +	}
> +	clk_enable(kp->clk);
> +
> +	/* Initialize device registers */
> +	keypad_write(kp, mode, 0);
> +	keypad_write(kp, mask, ~((((1 << kp->data.rows)-1) << 9) |
> +			   (((1 << kp->data.cols)-1))));
> +	keypad_write(kp, pol, 0x3ffff);
> +	keypad_write(kp, dclock, kp->data.debounce);
> +	keypad_write(kp, rclock, 4*kp->data.debounce);
> +	keypad_write(kp, stable_cnt, kp->data.stable);
> +
> +	/* Enable Input */
> +	keypad_write(kp, in_en, 0);
> +	mdelay(1);
> +	keypad_write(kp, in_en, 1);
> +
> +	ret = request_irq(kp->irq_press, keypad_irq_press, 0,
> +			  "keypad-press", kp);
> +	if (ret < 0) {
> +		dev_err(dev, "Could not allocate keypad press key irq\n");
> +		goto error4;
> +	}
> +
> +	ret = request_irq(kp->irq_release, keypad_irq_release, 0,
> +			  "keypad-release", kp);
> +	if (ret < 0) {
> +		dev_err(dev, "Could not allocate keypad release key irq\n");
> +		goto error5;
> +	}
> +
> +	set_bit(EV_KEY, kp->input_dev->evbit);
> +	for (i = 0; i < kp->data.keymap_size; i++)
> +		set_bit(kp->data.keymap[i] & KEY_MAX, kp->input_dev->keybit);
> +
> +	kp->input_dev->name = "tnetv107x-keypad";
> +	kp->input_dev->phys = "tnetv107x-keypad/input0";
> +	kp->input_dev->dev.parent = &pdev->dev;
> +	kp->input_dev->id.bustype = BUS_HOST;
> +	kp->input_dev->id.vendor = 0x0001;
> +
> +	rev = keypad_read(kp, rev);
> +	kp->input_dev->id.product = ((rev >>  8) & 0x07);
> +	kp->input_dev->id.version = ((rev >> 16) & 0xfff);
> +
> +	kp->input_dev->keycode = kp->data.keymap;
> +	kp->input_dev->keycodesize = sizeof(int);
> +	kp->input_dev->keycodemax = kp->data.keymap_size;

Since you allow changing data keymap should be moved into per-device
instance (platform data should be kept constant).

> +	ret = input_register_device(kp->input_dev);
> +	if (ret < 0) {
> +		dev_err(dev, "Could not register input device\n");
> +		goto error6;
> +	}
> +
> +	dev_info(dev, "registered keypad device\n");

Input core already emits message when new device is registered, should
be enough.

> +	return 0;
> +
> +error6:
> +	free_irq(kp->irq_release, kp);
> +error5:
> +	free_irq(kp->irq_press, kp);
> +error4:
> +	clk_disable(kp->clk);
> +	clk_put(kp->clk);
> +error3:
> +	iounmap(kp->regs);
> +error2:
> +	release_mem_region(kp->res->start, resource_size(kp->res));
> +error1:
> +	input_free_device(kp->input_dev);
> +error0:
> +	platform_set_drvdata(pdev, NULL);
> +	kfree(kp);
> +	return ret;
> +}
> +
> +static int tnetv107x_keypad_remove(struct platform_device *pdev)
> +{
> +	struct keypad_data *kp = dev_get_drvdata(&pdev->dev);

platform_get_drvdata();

> +
> +	if (kp) {

How kp can be NULL here?

> +		input_unregister_device(kp->input_dev);
> +		free_irq(kp->irq_release, kp);
> +		free_irq(kp->irq_press, kp);
> +		clk_disable(kp->clk);
> +		clk_put(kp->clk);
> +		iounmap(kp->regs);
> +		release_mem_region(kp->res->start, resource_size(kp->res));
> +		input_free_device(kp->input_dev);

No free after unregister.

> +		platform_set_drvdata(pdev, NULL);
> +		kfree(kp);
> +	}
> +	return 0;
> +}
> +
> +static int tnetv107x_keypad_suspend(struct platform_device *pdev,
> +		pm_message_t state)
> +{
> +	/* Nothing yet */
> +	return 0;
> +}
> +
> +static int tnetv107x_keypad_resume(struct platform_device *pdev)
> +{
> +	/* Nothing yet */
> +	return 0;
> +}

If there is nothing yet - drop them.

> +
> +static struct platform_driver tnetv107x_keypad_driver = {
> +	.probe		= tnetv107x_keypad_probe,
> +	.remove		= tnetv107x_keypad_remove,
> +	.suspend	= tnetv107x_keypad_suspend,
> +	.resume		= tnetv107x_keypad_resume,
> +	.driver.name	= "tnetv107x-keypad",

Please assign .owner = THIS_MODULE as well.

> +};
> +
> +static int __init tnetv107x_keypad_init(void)
> +{
> +	return platform_driver_register(&tnetv107x_keypad_driver);
> +}
> +
> +static void __exit tnetv107x_keypad_exit(void)
> +{
> +	platform_driver_unregister(&tnetv107x_keypad_driver);
> +}
> +
> +module_init(tnetv107x_keypad_init);
> +module_exit(tnetv107x_keypad_exit);
> +
> +MODULE_AUTHOR("Cyril Chemparathy");
> +MODULE_DESCRIPTION("TNETV107X Keypad Driver");
> +MODULE_LICENSE("GPL");


MODULE_ALIAS("platform: tnetv107x-keypad"); in case driver gets renamed.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] input: add driver for tnetv107x touchscreen controller
  2010-09-13 16:29 ` [PATCH 5/7] input: add driver for tnetv107x touchscreen controller Cyril Chemparathy
@ 2010-09-14  1:27   ` Dmitry Torokhov
  2010-09-14  6:38   ` Datta, Shubhrajyoti
  1 sibling, 0 replies; 15+ messages in thread
From: Dmitry Torokhov @ 2010-09-14  1:27 UTC (permalink / raw)
  To: Cyril Chemparathy; +Cc: linux-input, davinci-linux-open-source

On Mon, Sep 13, 2010 at 12:29:46PM -0400, Cyril Chemparathy wrote:
> This patch adds support for tnetv107x's on-chip touchscreen controller.
> 
> Signed-off-by: Cyril Chemparathy <cyril@ti.com>
> ---
>  drivers/input/touchscreen/Kconfig        |    6 +
>  drivers/input/touchscreen/Makefile       |    1 +
>  drivers/input/touchscreen/tnetv107x-ts.c |  481 ++++++++++++++++++++++++++++++
>  3 files changed, 488 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c
> 
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 0069d97..e56a170 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -638,4 +638,10 @@ config TOUCHSCREEN_STMPE
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called stmpe-ts.
>  
> +config TOUCHSCREEN_TNETV107X
> +	tristate "TI TNETV107X touchscreen support"
> +	depends on ARCH_DAVINCI_TNETV107X
> +	help
> +	  Say Y here if you want to use the TNETV107X touchscreen.
> +

To compile this driver as a module...

>  endif
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 28217e1..55a7db9 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -52,3 +52,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
>  obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)	+= zylonite-wm97xx.o
>  obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
>  obj-$(CONFIG_TOUCHSCREEN_TPS6507X)	+= tps6507x-ts.o
> +obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o

Alphabetical order please.

> diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
> new file mode 100644
> index 0000000..a8543c5
> --- /dev/null
> +++ b/drivers/input/touchscreen/tnetv107x-ts.c
> @@ -0,0 +1,481 @@
> +/*
> + * Texas Instruments TNETV107X Touchscreen Driver
> + *
> + * Copyright (C) 2010 Texas Instruments
> + *
> + * 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.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/input.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/ctype.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +
> +#include <mach/tnetv107x.h>
> +
> +/* Poll Rates */
> +#define TSC_PENUP_POLL		(HZ / 5)
> +
> +/*
> + * The first and last samples of a touch interval are usually garbage and need
> + * to be filtered out with these devices.  The following definitions control
> + * the number of samples skipped.
> + */
> +#define TSC_HEAD_SKIP		1
> +#define TSC_TAIL_SKIP		1
> +#define TSC_SKIP		(TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
> +#define TSC_SAMPLES		(TSC_SKIP + 1)
> +
> +/* Register Offsets */
> +struct tsc_regs {
> +	u32	rev;
> +	u32	tscm;
> +	u32	bwcm;
> +	u32	swc;
> +	u32	adcchnl;
> +	u32	adcdata;
> +	u32	chval[4];
> +};
> +
> +/* TSC Mode Configuration Register (tscm) bits */
> +#define WMODE		BIT(0)
> +#define TSKIND		BIT(1)
> +#define ZMEASURE_EN	BIT(2)
> +#define IDLE		BIT(3)
> +#define TSC_EN		BIT(4)
> +#define STOP		BIT(5)
> +#define ONE_SHOT	BIT(6)
> +#define SINGLE		BIT(7)
> +#define AVG		BIT(8)
> +#define AVGNUM(x)	(((x) & 0x03) <<  9)
> +#define PVSTC(x)	(((x) & 0x07) << 11)
> +#define PON		BIT(14)
> +#define PONBG		BIT(15)
> +#define AFERST		BIT(16)
> +
> +/* ADC DATA Capture Register bits */
> +#define DATA_VALID	BIT(16)
> +
> +/* Register Access Macros */
> +#define tsc_read(ts, reg)		__raw_readl(&(ts)->regs->reg)
> +#define tsc_write(ts, reg, val)		__raw_writel(val, &(ts)->regs->reg);
> +#define tsc_set_bits(ts, reg, val)	\
> +	tsc_write(ts, reg, tsc_read(ts, reg) | (val))
> +#define tsc_clr_bits(ts, reg, val)	\
> +	tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
> +
> +struct sample {
> +	int x, y, p;
> +};
> +
> +struct tsc_data {
> +	struct tnetv107x_tsc_data	data;
> +	struct input_dev		*input_dev;
> +	struct resource			*res;
> +	struct tsc_regs __iomem		*regs;
> +	struct timer_list		timer;
> +	spinlock_t			lock;
> +	struct clk			*clk;
> +	struct device			*dev;
> +	int				sample_count;
> +	struct sample			samples[TSC_SAMPLES];
> +	int				tsc_irq;
> +	int				cal[TSC_CAL_SIZE];
> +};
> +
> +/* default calibration that works for most evm boards */
> +static int tscal_set;
> +static int tscal[TSC_CAL_SIZE];
> +module_param_array(tscal, int, &tscal_set, 0);
> +
> +static inline int

Let compiler decide whether it should be inline or not. Same for the
rest.

> +tsc_read_sample(struct tsc_data *ts, struct sample* sample)
> +{
> +	int	x, y, z1, z2, t, p = 0;
> +	u32	val;
> +
> +	val = tsc_read(ts, chval[0]);
> +	if (val & DATA_VALID)
> +		x = val & 0xffff;
> +	else
> +		return -EINVAL;
> +
> +	y  = tsc_read(ts, chval[1]) & 0xffff;
> +	z1 = tsc_read(ts, chval[2]) & 0xffff;
> +	z2 = tsc_read(ts, chval[3]) & 0xffff;
> +
> +	if (z1) {
> +		t = ((600 * x) * (z2 - z1));
> +		p = t / (u32) (z1 << 12);
> +		if (p < 0)
> +			p = 0;
> +	}
> +
> +	sample->x  = (ts->cal[2] + ts->cal[0] * x + ts->cal[1] * y);
> +	sample->x /= ts->cal[6];
> +	sample->y  = (ts->cal[5] + ts->cal[3] * x + ts->cal[4] * y);
> +	sample->y /= ts->cal[6];
> +	sample->p  = p;
> +
> +	return 0;
> +}
> +
> +static inline void tsc_report_up(struct tsc_data *ts)
> +{
> +	input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
> +	input_report_key(ts->input_dev, BTN_TOUCH, 0);
> +	input_sync(ts->input_dev);
> +}
> +
> +static inline void tsc_report(struct tsc_data *ts, int x, int y, int p)
> +{
> +	input_report_abs(ts->input_dev, ABS_X, x);
> +	input_report_abs(ts->input_dev, ABS_Y, y);
> +	input_report_abs(ts->input_dev, ABS_PRESSURE, p);
> +}
> +
> +static inline void tsc_report_down(struct tsc_data *ts, bool touch)
> +{
> +	if (touch)
> +		input_report_key(ts->input_dev, BTN_TOUCH, 1);
> +	input_sync(ts->input_dev);
> +}
> +
> +static inline void tsc_poll(unsigned long data)
> +{
> +	struct tsc_data *ts = (struct tsc_data *)data;
> +	unsigned long flags;
> +	int i, val, x, y, p;
> +
> +	spin_lock_irqsave(&ts->lock, flags);
> +
> +	if (ts->sample_count >= TSC_SKIP) {
> +		tsc_report_up(ts);
> +	} else if (ts->sample_count > 0) {
> +		/*
> +		 * A touch event lasted less than our skip count.  Salvage and
> +		 * report anyway.
> +		 */
> +		for (i = 0, val = 0; i < ts->sample_count; i++)
> +			val += ts->samples[i].x;
> +		x = val / ts->sample_count;
> +
> +		for (i = 0, val = 0; i < ts->sample_count; i++)
> +			val += ts->samples[i].y;
> +		y = val / ts->sample_count;
> +
> +		for (i = 0, val = 0; i < ts->sample_count; i++)
> +			val += ts->samples[i].p;
> +		p = val / ts->sample_count;
> +
> +		tsc_report(ts, x, y, p);
> +		tsc_report_down(ts, true);
> +	}
> +
> +	ts->sample_count = 0;
> +
> +	spin_unlock_irqrestore(&ts->lock, flags);
> +}
> +
> +static irqreturn_t tsc_irq(int irq, void *dev_id)
> +{
> +	struct tsc_data *ts = (struct tsc_data *)dev_id;
> +	struct sample *sample;
> +	int index;
> +
> +	spin_lock(&ts->lock);
> +
> +	index = ts->sample_count % TSC_SAMPLES;
> +	sample = &ts->samples[index];
> +	if (tsc_read_sample(ts, sample) >= 0) {
> +		++ts->sample_count;
> +
> +		if (ts->sample_count < TSC_SKIP)
> +			goto done;
> +
> +		index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
> +		sample = &ts->samples[index];
> +
> +		tsc_report(ts, sample->x, sample->y, sample->y);
> +		tsc_report_down(ts, (ts->sample_count == TSC_SKIP));
> +done:
> +		mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
> +	}
> +
> +	spin_unlock(&ts->lock);
> +	return IRQ_HANDLED;
> +}
> +
> +static ssize_t tsc_cal_show(struct device *dev, struct device_attribute *attr,
> +			    char *buf)
> +{
> +	struct tsc_data *ts = dev_get_drvdata(dev);
> +	ssize_t len = 0;
> +	int i;
> +
> +	for (i = 0; i < 6; i++)
> +		len += snprintf(buf+len, PAGE_SIZE-len, "%d ", ts->cal[i]);
> +
> +	len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", ts->cal[6]);
> +
> +	return len;
> +}
> +
> +/*
> + * The calibration data format is identical to the contents of tslib's
> + * generated output
> + */
> +static ssize_t tsc_cal_store(struct device *dev, struct device_attribute *attr,
> +			     const char *buf, size_t count)
> +{
> +	struct tsc_data *ts = dev_get_drvdata(dev);
> +	int index = 0;
> +	int cal[TSC_CAL_SIZE];
> +	const char *cur = buf, *end = buf + count;
> +	char *tmp;
> +	unsigned long flags;
> +
> +	for (index = 0; index < TSC_CAL_SIZE; index++) {
> +		while (isspace(*cur) && cur < end)
> +			cur++;
> +		if (cur >= end) {
> +			dev_err(ts->dev, "premature end in calib data\n");
> +			return -EINVAL;
> +		}
> +
> +		if (isdigit(*cur) || *cur == '-') {
> +			cal[index] = simple_strtol(cur, &tmp, 0);
> +			cur = tmp;
> +		}
> +	}
> +
> +	spin_lock_irqsave(&ts->lock, flags);
> +	memcpy(ts->cal, cal, sizeof(cal));
> +	spin_unlock_irqrestore(&ts->lock, flags);
> +
> +	return count;


Calibration should be handled in userspace. Tslib soes it as far as I
know.

> +}
> +
> +static struct device_attribute tsc_attr_cal =
> +	__ATTR(tscal, S_IWUSR | S_IRUGO, tsc_cal_show, tsc_cal_store);
> +
> +static int tsc_probe(struct platform_device *pdev)
> +{
> +	struct tnetv107x_tsc_data *pdata = pdev->dev.platform_data;
> +	struct tsc_data *ts;
> +	int ret = 0, *cal;
> +	u32 rev = 0, val = 0;
> +	struct device *dev = &pdev->dev;
> +
> +	if (!pdata) {
> +		dev_err(dev, "could not find platform data\n");
> +		return -EINVAL;
> +	}
> +
> +	ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
> +	if (!ts) {
> +		dev_err(dev, "cannot allocate device info\n");
> +		return -ENOMEM;
> +	}
> +
> +	ts->dev = dev;
> +	ts->data = *pdata;
> +	dev_set_drvdata(dev, ts);
> +
> +	cal = (tscal_set == TSC_CAL_SIZE) ? tscal : ts->data.calibration_data;
> +	memcpy(ts->cal, cal, TSC_CAL_SIZE * sizeof(int));
> +
> +	ret = -ENOMEM;
> +	ts->input_dev = input_allocate_device();
> +	if (!ts->input_dev) {
> +		dev_err(dev, "cannot allocate input device\n");
> +		goto error0;
> +	}
> +
> +	ret = -ENODEV;
> +	ts->tsc_irq = platform_get_irq(pdev, 0);
> +	if (ts->tsc_irq < 0) {
> +		dev_err(dev, "cannot determine device interrupt\n");
> +		goto error1;
> +	}
> +
> +	ret = -ENODEV;
> +	ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!ts->res) {
> +		dev_err(dev, "cannot determine register area\n");
> +		goto error1;
> +	}
> +
> +	ret = -EINVAL;
> +	if (!request_mem_region(ts->res->start, resource_size(ts->res),
> +				pdev->name)) {
> +		dev_err(dev, "cannot claim register memory\n");
> +		goto error1;
> +	}
> +
> +	ret = -ENOMEM;
> +	ts->regs = ioremap(ts->res->start, resource_size(ts->res));
> +	if (!ts->regs) {
> +		dev_err(dev, "cannot map register memory\n");
> +		goto error2;
> +	}
> +
> +	ret = -EINVAL;
> +	ts->clk = clk_get(dev, NULL);
> +	if (!ts->clk) {
> +		dev_err(dev, "cannot claim device clock\n");
> +		goto error3;
> +	}
> +	clk_enable(ts->clk);
> +
> +	spin_lock_init(&ts->lock);
> +
> +	init_timer(&ts->timer);
> +	setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);

init_timer() is extra if you call setu_timer();

> +
> +	/* Go to idle mode, before any initialization */
> +	while ((tsc_read(ts, tscm) & IDLE) == 0)
> +		barrier();

Hm, I do not see how barrier() would help here...

> +
> +	/* Configure the TSC Control register*/
> +	val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
> +	tsc_write(ts, tscm, val);
> +
> +	/* Bring TSC out of reset: Clear AFE reset bit */
> +	val &= ~(AFERST);
> +	tsc_write(ts, tscm, val);
> +	udelay(10);
> +
> +	/* Configure all pins for hardware control*/
> +	tsc_write(ts, bwcm, 0);
> +
> +	/* Finally enable the TSC */
> +	tsc_set_bits(ts, tscm, TSC_EN);

Should it be in ->open() method?

> +
> +	ret = -EINVAL;
> +	if (request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts)) {
> +		dev_err(dev, "Could not allocate ts irq\n");
> +		goto error4;
> +	}
> +
> +	ret = device_create_file(ts->dev, &tsc_attr_cal);
> +	if (ret < 0) {
> +		dev_err(dev, "Could not create sysfs entry!\n");
> +		goto error5;
> +	}
> +
> +	rev = tsc_read(ts, rev);
> +	ts->input_dev->name       = "tnetv107x-ts";
> +	ts->input_dev->phys       = "tnetv107x-ts/input0";
> +	ts->input_dev->id.bustype = BUS_HOST;
> +	ts->input_dev->id.vendor  = 0x0001;
> +	ts->input_dev->id.product = ((rev >>  8) & 0x07);
> +	ts->input_dev->id.version = ((rev >> 16) & 0xfff);
> +	ts->input_dev->dev.parent = &pdev->dev;
> +
> +	/* Declare capabilities */
> +	set_bit(EV_KEY,       ts->input_dev->evbit);
> +	set_bit(BTN_TOUCH,    ts->input_dev->keybit);
> +	set_bit(EV_ABS,       ts->input_dev->evbit);
> +	set_bit(ABS_X,        ts->input_dev->absbit);
> +	set_bit(ABS_Y,        ts->input_dev->absbit);
> +	set_bit(ABS_PRESSURE, ts->input_dev->absbit);
> +
> +	input_set_abs_params(ts->input_dev, ABS_X, 0, ts->data.xres, 5, 0);
> +	input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->data.yres, 5, 0);
> +	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
> +
> +	ret = input_register_device(ts->input_dev);
> +	if (ret < 0)
> +		goto error6;
> +
> +	return 0;
> +
> +error6:
> +	device_remove_file(ts->dev, &tsc_attr_cal);
> +error5:
> +	free_irq(ts->tsc_irq, ts);
> +error4:
> +	clk_disable(ts->clk);
> +	clk_put(ts->clk);
> +error3:
> +	iounmap(ts->regs);
> +error2:
> +	release_mem_region(ts->res->start, resource_size(ts->res));
> +error1:
> +	input_free_device(ts->input_dev);
> +error0:
> +	kfree(ts);
> +	dev_set_drvdata(dev, NULL);
> +	return ret;
> +}
> +
> +static int tsc_remove(struct platform_device *pdev)
> +{
> +	struct tsc_data *ts = dev_get_drvdata(&pdev->dev);

platform_get_drvdata();

> +
> +	if (!ts)
> +		return 0;


Impossible.

> +
> +	tsc_clr_bits(ts, tscm, TSC_EN);

I think this should be in ->close().

> +	del_timer_sync(&ts->timer);
> +	device_remove_file(ts->dev, &tsc_attr_cal);
> +	free_irq(ts->tsc_irq, ts);
> +	clk_disable(ts->clk);
> +	clk_put(ts->clk);
> +	iounmap(ts->regs);
> +	release_mem_region(ts->res->start, resource_size(ts->res));
> +	input_free_device(ts->input_dev);

Should be input_unregister_device().


> +	kfree(ts);
> +	dev_set_drvdata(&pdev->dev, NULL);

platform_set_drvdata().

> +	return 0;
> +}
> +
> +static int tsc_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	/* Nothing yet */
> +	return 0;
> +}
> +
> +static int tsc_resume(struct platform_device *pdev)
> +{
> +	/* Nothing yet */
> +	return 0;
> +}
> +

Drop these.

> +static struct platform_driver tsc_driver = {
> +	.probe		= tsc_probe,
> +	.remove		= tsc_remove,
> +	.suspend	= tsc_suspend,
> +	.resume		= tsc_resume,
> +	.driver.name	= "tnetv107x-ts",

Please set up driver.owner.

> +};
> +
> +static int __init tsc_init(void)
> +{
> +	return platform_driver_register(&tsc_driver);
> +}
> +
> +static void __exit tsc_exit(void)
> +{
> +	platform_driver_unregister(&tsc_driver);
> +}
> +
> +module_init(tsc_init);
> +module_exit(tsc_exit);
> +
> +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
> +MODULE_LICENSE("GPL");

MODULE_AUTHOR() and MODULE_ALIAS().

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 5/7] input: add driver for tnetv107x touchscreen controller
  2010-09-13 16:29 ` [PATCH 5/7] input: add driver for tnetv107x touchscreen controller Cyril Chemparathy
  2010-09-14  1:27   ` Dmitry Torokhov
@ 2010-09-14  6:38   ` Datta, Shubhrajyoti
  1 sibling, 0 replies; 15+ messages in thread
From: Datta, Shubhrajyoti @ 2010-09-14  6:38 UTC (permalink / raw)
  To: Chemparathy, Cyril, linux-input,
	davinci-linux-open-source@linux.davincidsp.com


Hi Cyril,
Minor comments/doubts
> -----Original Message-----
> From: linux-input-owner@vger.kernel.org [mailto:linux-input-
> owner@vger.kernel.org] On Behalf Of Chemparathy, Cyril
> Sent: Monday, September 13, 2010 10:00 PM
> To: linux-input@vger.kernel.org; davinci-linux-open-
> source@linux.davincidsp.com
> Cc: Chemparathy, Cyril
> Subject: [PATCH 5/7] input: add driver for tnetv107x touchscreen
> controller
> 
> This patch adds support for tnetv107x's on-chip touchscreen controller.
> 
> Signed-off-by: Cyril Chemparathy <cyril@ti.com>
> ---
>  drivers/input/touchscreen/Kconfig        |    6 +
>  drivers/input/touchscreen/Makefile       |    1 +
>  drivers/input/touchscreen/tnetv107x-ts.c |  481


> +
> +static inline void tsc_report_up(struct tsc_data *ts)
> +{
> +	input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
> +	input_report_key(ts->input_dev, BTN_TOUCH, 0);
> +	input_sync(ts->input_dev);
> +}
> +
> +static inline void tsc_report(struct tsc_data *ts, int x, int y, int p)
> +{
> +	input_report_abs(ts->input_dev, ABS_X, x);
> +	input_report_abs(ts->input_dev, ABS_Y, y);
> +	input_report_abs(ts->input_dev, ABS_PRESSURE, p);

Did not understand why no sync here.

> +}
> +
> +static inline void tsc_report_down(struct tsc_data *ts, bool touch)
> +{
> +	if (touch)
> +		input_report_key(ts->input_dev, BTN_TOUCH, 1);

Even if you donot report you do a sync.

> +	input_sync(ts->input_dev);
> +}
> +
> +static inline void tsc_poll(unsigned long data)
> +{
> +	struct tsc_data *ts = (struct tsc_data *)data;
> +	unsigned long flags;
> +	int i, val, x, y, p;
> +
> +	spin_lock_irqsave(&ts->lock, flags);
> +
> +	if (ts->sample_count >= TSC_SKIP) {
> +		tsc_report_up(ts);
> +	} else if (ts->sample_count > 0) {
> +		/*
> +		 * A touch event lasted less than our skip count.  Salvage and
> +		 * report anyway.
> +		 */
> +		for (i = 0, val = 0; i < ts->sample_count; i++)
> +			val += ts->samples[i].x;
> +		x = val / ts->sample_count;
> +
> +		for (i = 0, val = 0; i < ts->sample_count; i++)
> +			val += ts->samples[i].y;
> +		y = val / ts->sample_count;
> +
> +		for (i = 0, val = 0; i < ts->sample_count; i++)
> +			val += ts->samples[i].p;
> +		p = val / ts->sample_count;
> +
> +		tsc_report(ts, x, y, p);
> +		tsc_report_down(ts, true);
> +	}
> +
> +	ts->sample_count = 0;
> +
> +	spin_unlock_irqrestore(&ts->lock, flags);
> +}
> +
> +static irqreturn_t tsc_irq(int irq, void *dev_id)
> +{
> +	struct tsc_data *ts = (struct tsc_data *)dev_id;
> +	struct sample *sample;
> +	int index;
> +
> +	spin_lock(&ts->lock);
> +
> +	index = ts->sample_count % TSC_SAMPLES;
> +	sample = &ts->samples[index];
> +	if (tsc_read_sample(ts, sample) >= 0) {
> +		++ts->sample_count;
> +
> +		if (ts->sample_count < TSC_SKIP)
> +			goto done;
> +
> +		index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
> +		sample = &ts->samples[index];
> +
> +		tsc_report(ts, sample->x, sample->y, sample->y);
> +		tsc_report_down(ts, (ts->sample_count == TSC_SKIP));
> +done:
> +		mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
> +	}
> +
> +	spin_unlock(&ts->lock);
> +	return IRQ_HANDLED;
> +}
> +
> +static ssize_t tsc_cal_show(struct device *dev, struct device_attribute
> *attr,
> +			    char *buf)
> +{
> +	struct tsc_data *ts = dev_get_drvdata(dev);
> +	ssize_t len = 0;
> +	int i;
> +
> +	for (i = 0; i < 6; i++)
> +		len += snprintf(buf+len, PAGE_SIZE-len, "%d ", ts->cal[i]);
> +
> +	len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", ts->cal[6]);
> +
> +	return len;
> +}
> +
> +/*
> + * The calibration data format is identical to the contents of tslib's
> + * generated output
> + */
> +static ssize_t tsc_cal_store(struct device *dev, struct device_attribute
> *attr,
> +			     const char *buf, size_t count)
> +{
> +	struct tsc_data *ts = dev_get_drvdata(dev);
> +	int index = 0;
> +	int cal[TSC_CAL_SIZE];
> +	const char *cur = buf, *end = buf + count;
> +	char *tmp;
> +	unsigned long flags;
> +
> +	for (index = 0; index < TSC_CAL_SIZE; index++) {
> +		while (isspace(*cur) && cur < end)
> +			cur++;
> +		if (cur >= end) {
> +			dev_err(ts->dev, "premature end in calib data\n");
> +			return -EINVAL;
> +		}
> +
> +		if (isdigit(*cur) || *cur == '-') {
> +			cal[index] = simple_strtol(cur, &tmp, 0);
> +			cur = tmp;
> +		}
> +	}
> +
> +	spin_lock_irqsave(&ts->lock, flags);
> +	memcpy(ts->cal, cal, sizeof(cal));
> +	spin_unlock_irqrestore(&ts->lock, flags);
> +
> +	return count;
> +}
> +
> +static struct device_attribute tsc_attr_cal =
> +	__ATTR(tscal, S_IWUSR | S_IRUGO, tsc_cal_show, tsc_cal_store);
> +
> +static int tsc_probe(struct platform_device *pdev)

May consider __devinit as this memory location may not be needed afterwards.

> +{
> +	struct tnetv107x_tsc_data *pdata = pdev->dev.platform_data;
> +	struct tsc_data *ts;
> +	int ret = 0, *cal;
> +	u32 rev = 0, val = 0;
> +	struct device *dev = &pdev->dev;
> +
> +	if (!pdata) {
> +		dev_err(dev, "could not find platform data\n");
> +		return -EINVAL;
> +	}
> +
> +	ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
> +	if (!ts) {
> +		dev_err(dev, "cannot allocate device info\n");
> +		return -ENOMEM;
> +	}
> +
> +	ts->dev = dev;
> +	ts->data = *pdata;
> +	dev_set_drvdata(dev, ts);
> +
> +	cal = (tscal_set == TSC_CAL_SIZE) ? tscal : ts-
> >data.calibration_data;
> +	memcpy(ts->cal, cal, TSC_CAL_SIZE * sizeof(int));
> +
> +	ret = -ENOMEM;
> +	ts->input_dev = input_allocate_device();
> +	if (!ts->input_dev) {
> +		dev_err(dev, "cannot allocate input device\n");
> +		goto error0;
> +	}
> +
> +	ret = -ENODEV;
> +	ts->tsc_irq = platform_get_irq(pdev, 0);
> +	if (ts->tsc_irq < 0) {
> +		dev_err(dev, "cannot determine device interrupt\n");
> +		goto error1;
> +	}
> +
> +	ret = -ENODEV;
> +	ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!ts->res) {
> +		dev_err(dev, "cannot determine register area\n");
> +		goto error1;
> +	}
> +
> +	ret = -EINVAL;
> +	if (!request_mem_region(ts->res->start, resource_size(ts->res),
> +				pdev->name)) {
> +		dev_err(dev, "cannot claim register memory\n");
> +		goto error1;
> +	}
> +
> +	ret = -ENOMEM;
> +	ts->regs = ioremap(ts->res->start, resource_size(ts->res));
> +	if (!ts->regs) {
> +		dev_err(dev, "cannot map register memory\n");
> +		goto error2;
> +	}
> +
> +	ret = -EINVAL;
> +	ts->clk = clk_get(dev, NULL);
> +	if (!ts->clk) {
> +		dev_err(dev, "cannot claim device clock\n");
> +		goto error3;
> +	}
> +	clk_enable(ts->clk);
> +
> +	spin_lock_init(&ts->lock);
> +
> +	init_timer(&ts->timer);
> +	setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
> +
> +	/* Go to idle mode, before any initialization */
> +	while ((tsc_read(ts, tscm) & IDLE) == 0)
> +		barrier();
> +
> +	/* Configure the TSC Control register*/
> +	val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
> +	tsc_write(ts, tscm, val);
> +
> +	/* Bring TSC out of reset: Clear AFE reset bit */
> +	val &= ~(AFERST);
> +	tsc_write(ts, tscm, val);
> +	udelay(10);
> +
> +	/* Configure all pins for hardware control*/
> +	tsc_write(ts, bwcm, 0);
> +
> +	/* Finally enable the TSC */
> +	tsc_set_bits(ts, tscm, TSC_EN);
> +
> +	ret = -EINVAL;
> +	if (request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts)) {
> +		dev_err(dev, "Could not allocate ts irq\n");
> +		goto error4;
> +	}
> +
> +	ret = device_create_file(ts->dev, &tsc_attr_cal);
> +	if (ret < 0) {
> +		dev_err(dev, "Could not create sysfs entry!\n");
> +		goto error5;
> +	}
> +
> +	rev = tsc_read(ts, rev);
> +	ts->input_dev->name       = "tnetv107x-ts";
> +	ts->input_dev->phys       = "tnetv107x-ts/input0";
> +	ts->input_dev->id.bustype = BUS_HOST;
> +	ts->input_dev->id.vendor  = 0x0001;
> +	ts->input_dev->id.product = ((rev >>  8) & 0x07);
> +	ts->input_dev->id.version = ((rev >> 16) & 0xfff);
> +	ts->input_dev->dev.parent = &pdev->dev;
> +
> +	/* Declare capabilities */
> +	set_bit(EV_KEY,       ts->input_dev->evbit);
> +	set_bit(BTN_TOUCH,    ts->input_dev->keybit);
> +	set_bit(EV_ABS,       ts->input_dev->evbit);
> +	set_bit(ABS_X,        ts->input_dev->absbit);
> +	set_bit(ABS_Y,        ts->input_dev->absbit);
> +	set_bit(ABS_PRESSURE, ts->input_dev->absbit);
> +
> +	input_set_abs_params(ts->input_dev, ABS_X, 0, ts->data.xres, 5, 0);
> +	input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->data.yres, 5, 0);
> +	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
> +
> +	ret = input_register_device(ts->input_dev);
> +	if (ret < 0)
> +		goto error6;
> +
> +	return 0;
> +
> +error6:
> +	device_remove_file(ts->dev, &tsc_attr_cal);
> +error5:
> +	free_irq(ts->tsc_irq, ts);
> +error4:
> +	clk_disable(ts->clk);
> +	clk_put(ts->clk);
> +error3:
> +	iounmap(ts->regs);
> +error2:
> +	release_mem_region(ts->res->start, resource_size(ts->res));
> +error1:
> +	input_free_device(ts->input_dev);
> +error0:
> +	kfree(ts);
> +	dev_set_drvdata(dev, NULL);
> +	return ret;
> +}
> +
> +static int tsc_remove(struct platform_device *pdev)
Same as probe.
> +{
> +	struct tsc_data *ts = dev_get_drvdata(&pdev->dev);
> +
> +	if (!ts)
> +		return 0;
> +
> +	tsc_clr_bits(ts, tscm, TSC_EN);
> +	del_timer_sync(&ts->timer);
> +	device_remove_file(ts->dev, &tsc_attr_cal);
> +	free_irq(ts->tsc_irq, ts);
> +	clk_disable(ts->clk);
> +	clk_put(ts->clk);
> +	iounmap(ts->regs);
> +	release_mem_region(ts->res->start, resource_size(ts->res));
> +	input_free_device(ts->input_dev);
> +	kfree(ts);
> +	dev_set_drvdata(&pdev->dev, NULL);
> +	return 0;
> +}
> +
> +static int tsc_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	/* Nothing yet */
> +	return 0;
> +}
> +
> +static int tsc_resume(struct platform_device *pdev)
> +{
> +	/* Nothing yet */
> +	return 0;
> +}
> +
> +static struct platform_driver tsc_driver = {
> +	.probe		= tsc_probe,
> +	.remove		= tsc_remove,
> +	.suspend	= tsc_suspend,
> +	.resume		= tsc_resume,
> +	.driver.name	= "tnetv107x-ts",
> +};
> +
> +static int __init tsc_init(void)
> +{
> +	return platform_driver_register(&tsc_driver);
> +}
> +
> +static void __exit tsc_exit(void)
> +{
> +	platform_driver_unregister(&tsc_driver);
> +}
> +
> +module_init(tsc_init);
> +module_exit(tsc_exit);
> +
> +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
> +MODULE_LICENSE("GPL");
> --
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] add tnetv107x input drivers
  2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
                   ` (6 preceding siblings ...)
  2010-09-13 16:29 ` [PATCH 7/7] davinci: add touchscreen config for tnetv107x evm board Cyril Chemparathy
@ 2010-09-16 17:53 ` Kevin Hilman
  2010-09-16 18:11   ` Dmitry Torokhov
  7 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2010-09-16 17:53 UTC (permalink / raw)
  To: Cyril Chemparathy, Dmitry Torokhov; +Cc: linux-input, davinci-linux-open-source

Cyril Chemparathy <cyril@ti.com> writes:

> Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip
> touchscreen and keypad controllers.  This patch series adds drivers for these
> controllers.

Dmitry,

With you're review/ack, I can merge these via the davinci tree so the
drivers can merge with the platform code that goes with them.  That way
we can avoid potential conflicts from other davinci changes touching the
same platform files.

Kevin

>
> Cyril Chemparathy (7):
>   davinci: define tnetv107x keypad platform data
>   input: add driver for tnetv107x on-chip keypad controller
>   davinci: add tnetv107x keypad platform device
>   davinci: add keypad config for tnetv107x evm board
>   input: add driver for tnetv107x touchscreen controller
>   davinci: add tnetv107x touchscreen platform device
>   davinci: add touchscreen config for tnetv107x evm board
>
>  arch/arm/mach-davinci/board-tnetv107x-evm.c    |   51 +++
>  arch/arm/mach-davinci/devices-tnetv107x.c      |   54 +++
>  arch/arm/mach-davinci/include/mach/tnetv107x.h |   24 ++
>  drivers/input/keyboard/Kconfig                 |    9 +
>  drivers/input/keyboard/Makefile                |    1 +
>  drivers/input/keyboard/tnetv107x-keypad.c      |  324 ++++++++++++++++
>  drivers/input/touchscreen/Kconfig              |    6 +
>  drivers/input/touchscreen/Makefile             |    1 +
>  drivers/input/touchscreen/tnetv107x-ts.c       |  481 ++++++++++++++++++++++++
>  9 files changed, 951 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
>  create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c
>
> _______________________________________________
> Davinci-linux-open-source mailing list
> Davinci-linux-open-source@linux.davincidsp.com
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] add tnetv107x input drivers
  2010-09-16 17:53 ` [PATCH 0/7] add tnetv107x input drivers Kevin Hilman
@ 2010-09-16 18:11   ` Dmitry Torokhov
  2010-09-16 18:29     ` Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry Torokhov @ 2010-09-16 18:11 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Cyril Chemparathy, linux-input, davinci-linux-open-source

On Thursday, September 16, 2010 10:53:56 am Kevin Hilman wrote:
> Cyril Chemparathy <cyril@ti.com> writes:
> > Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip
> > touchscreen and keypad controllers.  This patch series adds drivers for
> > these controllers.
> 
> Dmitry,
> 
> With you're review/ack, I can merge these via the davinci tree so the
> drivers can merge with the platform code that goes with them.  That way
> we can avoid potential conflicts from other davinci changes touching the
> same platform files.

Kevin,

I am OK with the drivers coming through your tree, however I am not yet
completely happy with the patches (as they were posted - their initial
version).

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] add tnetv107x input drivers
  2010-09-16 18:11   ` Dmitry Torokhov
@ 2010-09-16 18:29     ` Kevin Hilman
  0 siblings, 0 replies; 15+ messages in thread
From: Kevin Hilman @ 2010-09-16 18:29 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Cyril Chemparathy, linux-input, davinci-linux-open-source

Dmitry Torokhov <dmitry.torokhov@gmail.com> writes:

> On Thursday, September 16, 2010 10:53:56 am Kevin Hilman wrote:
>> Cyril Chemparathy <cyril@ti.com> writes:
>> > Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip
>> > touchscreen and keypad controllers.  This patch series adds drivers for
>> > these controllers.
>> 
>> Dmitry,
>> 
>> With you're review/ack, I can merge these via the davinci tree so the
>> drivers can merge with the platform code that goes with them.  That way
>> we can avoid potential conflicts from other davinci changes touching the
>> same platform files.
>
> Kevin,
>
> I am OK with the drivers coming through your tree, however I am not yet
> completely happy with the patches (as they were posted - their initial
> version).
>

Sure, I'll wait for your review and will not merge them without your
ack.

Thanks,

Kevin




^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2010-09-16 18:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-13 16:29 [PATCH 0/7] add tnetv107x input drivers Cyril Chemparathy
2010-09-13 16:29 ` [PATCH 1/7] davinci: define tnetv107x keypad platform data Cyril Chemparathy
2010-09-14  1:26   ` Dmitry Torokhov
2010-09-13 16:29 ` [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller Cyril Chemparathy
2010-09-14  1:26   ` Dmitry Torokhov
2010-09-13 16:29 ` [PATCH 3/7] davinci: add tnetv107x keypad platform device Cyril Chemparathy
2010-09-13 16:29 ` [PATCH 4/7] davinci: add keypad config for tnetv107x evm board Cyril Chemparathy
2010-09-13 16:29 ` [PATCH 5/7] input: add driver for tnetv107x touchscreen controller Cyril Chemparathy
2010-09-14  1:27   ` Dmitry Torokhov
2010-09-14  6:38   ` Datta, Shubhrajyoti
2010-09-13 16:29 ` [PATCH 6/7] davinci: add tnetv107x touchscreen platform device Cyril Chemparathy
2010-09-13 16:29 ` [PATCH 7/7] davinci: add touchscreen config for tnetv107x evm board Cyril Chemparathy
2010-09-16 17:53 ` [PATCH 0/7] add tnetv107x input drivers Kevin Hilman
2010-09-16 18:11   ` Dmitry Torokhov
2010-09-16 18:29     ` Kevin Hilman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.