Re: [PATCH] Add support for touch screen on W90P910 ARM platform

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear Dmitry,

Thank you very much for your reviewing my patch.
According to your advice,I have re-modified this
ts driver and submitted it again.

I have run the patch through scripts/checkpatch.pl 
and make sure it does not complain. Thanks!

--
 drivers/input/touchscreen/Kconfig      |    6 
 drivers/input/touchscreen/Makefile     |    1 
 drivers/input/touchscreen/w90p910_ts.c |  279 +++++++++++++++++++++++
 3 files changed, 286 insertions(+)
---
patch text:

Add touchscreen drivers for w90p910 platform.

Signed-off-by: Wan ZongShun <mcuos.com@xxxxxxxxx>

diff -Npur linux-2.6.29/drivers/input/touchscreen/Kconfig linux-2.6.30/drivers/input/touchscreen/Kconfig
--- linux-2.6.29/drivers/input/touchscreen/Kconfig	2009-05-05 18:32:26.000000000 +0800
+++ linux-2.6.30/drivers/input/touchscreen/Kconfig	2009-05-09 07:33:32.000000000 +0800
@@ -466,4 +466,10 @@ config TOUCHSCREEN_TSC2007
 	  To compile this driver as a module, choose M here: the
 	  module will be called tsc2007.
 
+config TOUCHSCREEN_W90X900
+	tristate "W90P910 touchscreens"
+	depends on CPU_W90P910
+	help
+		Compile this driver to support W90P910 touchscreen.
+
 endif
diff -Npur linux-2.6.29/drivers/input/touchscreen/Makefile linux-2.6.30/drivers/input/touchscreen/Makefile
--- linux-2.6.29/drivers/input/touchscreen/Makefile	2009-05-05 18:32:26.000000000 +0800
+++ linux-2.6.30/drivers/input/touchscreen/Makefile	2009-05-09 07:34:12.000000000 +0800
@@ -37,3 +37,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)	+= wm9713.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)	+= zylonite-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
diff -Npur linux-2.6.29/drivers/input/touchscreen/w90p910_ts.c linux-2.6.30/drivers/input/touchscreen/w90p910_ts.c
--- linux-2.6.29/drivers/input/touchscreen/w90p910_ts.c	1970-01-01 08:00:00.000000000 +0800
+++ linux-2.6.30/drivers/input/touchscreen/w90p910_ts.c	2009-05-09 08:48:01.000000000 +0800
@@ -0,0 +1,279 @@
+/*
+ * linux/driver/input/w90x900_ts.c
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+
+#include <mach/hardware.h>
+
+/*adc state define*/
+#define NO_PRESS	0
+#define START_READX	1
+#define START_READY	2
+
+/*adc controller bit define*/
+#define ADC_DELAY	0xf00
+#define ADC_DOWN	0x01
+#define ADC_TSC_Y	(0x01<<8)
+#define ADC_TSC_X	(0x00<<8)
+#define TSC_FOURWIRE	(~(0x03<<1))
+#define ADC_CLK_EN	(0x01<<28)/*adc clock*/
+#define ADC_READ_CON	(0x01<<12)
+#define ADC_CONV	(0x01<<13)
+#define ADC_SEMIAUTO	(0x01<<14)
+#define ADC_WAITTRIG	(0x03<<14)
+#define ADC_RST1	(0x01<<16)
+#define ADC_RST0	(0x00<<16)
+#define ADC_EN		(0x01<<17)
+#define ADC_INT		(0x01<<18)
+#define WT_INT		(0x01<<20)
+#define ADC_INT_EN	(0x01<<21)
+#define LVD_INT_EN	(0x01<<22)
+#define WT_INT_EN	(0x01<<23)
+#define ADC_DIV		(0x04<<1)/*div=6*/
+
+static DEFINE_SPINLOCK(touch_lock);
+
+struct ts_event {
+	short pressure;
+	short x;
+	short y;
+};
+
+struct w90p910drv_ts {
+	struct input_dev *input;
+	struct timer_list timer;
+	struct ts_event tc;
+	unsigned int ts_state;
+	int irq_num;
+	int pendown;
+	int clocken;
+	void __iomem *ts_reg;
+};
+
+static void new_data(struct w90p910drv_ts *w90p910_ts)
+{
+	struct input_dev *dev = w90p910_ts->input;
+
+	input_report_abs(dev, ABS_X, w90p910_ts->tc.x);
+	input_report_abs(dev, ABS_Y, w90p910_ts->tc.y);
+	input_report_key(dev, BTN_TOUCH, w90p910_ts->pendown);
+	input_sync(dev);
+}
+
+static void w90p910_ts_interrupt(struct w90p910drv_ts *w90p910_ts, int isTimer)
+{
+	if ((__raw_readl(w90p910_ts->ts_reg)&WT_INT) && !w90p910_ts->ts_state) {
+		w90p910_ts->pendown = 1;
+		w90p910_ts->ts_state = START_READX;
+		__raw_writel(ADC_TSC_X, w90p910_ts->ts_reg+0x04);
+		__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+			ADC_SEMIAUTO|ADC_INT_EN|ADC_CONV)&0xFF6F7FFF,
+							w90p910_ts->ts_reg);
+	} else {
+		if (__raw_readl(w90p910_ts->ts_reg+0x04)&ADC_DOWN) {
+			__raw_writel(ADC_TSC_X, w90p910_ts->ts_reg+0x04);
+
+			__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+				ADC_SEMIAUTO|ADC_INT_EN|ADC_CONV)&0xFF7F7FFF,
+							w90p910_ts->ts_reg);
+			w90p910_ts->ts_state = START_READX;
+			w90p910_ts->pendown = 1;
+		} else {
+			__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+				ADC_WAITTRIG|WT_INT_EN)&0xFFCBFFFF,
+							w90p910_ts->ts_reg);
+			w90p910_ts->ts_state = NO_PRESS;
+			w90p910_ts->pendown = 0;
+		}
+	}
+
+	if ((__raw_readl(w90p910_ts->ts_reg)&ADC_INT) &&
+					w90p910_ts->ts_state == START_READX) {
+		w90p910_ts->ts_state = START_READY;
+		__raw_writel(ADC_TSC_Y, w90p910_ts->ts_reg+0x04);
+		__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+			ADC_SEMIAUTO|ADC_INT_EN|ADC_CONV)&0xFF7B7FFF,
+							w90p910_ts->ts_reg);
+	}
+
+	if ((__raw_readl(w90p910_ts->ts_reg)&ADC_INT) &&
+					w90p910_ts->ts_state == START_READY) {
+		new_data(w90p910_ts);
+		__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+				ADC_WAITTRIG)&0xFF5BFFFF, w90p910_ts->ts_reg);
+		mod_timer(&w90p910_ts->timer, jiffies + 4*HZ / 100);
+	}
+}
+
+static void w90p910_ts_timer(unsigned long data)
+{
+	struct w90p910drv_ts *w90p910_data = (struct w90p910drv_ts *) data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&touch_lock, flags);
+
+	w90p910_ts_interrupt(w90p910_data, 1);
+
+	spin_unlock_irqrestore(&touch_lock, flags);
+}
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id)
+{
+	struct w90p910drv_ts *w90p910_data = dev_id;
+
+	w90p910_ts_interrupt(w90p910_data, 0);
+	return IRQ_HANDLED;
+}
+
+static int __devinit w90x900ts_probe(struct platform_device *pdev)
+{
+	struct w90p910drv_ts *w90p910_ts;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
+	struct resource *res;
+
+	w90p910_ts = kzalloc(sizeof(struct w90p910drv_ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!w90p910_ts || !input_dev)
+		goto fail1;
+
+	platform_set_drvdata(pdev, w90p910_ts);
+
+	w90p910_ts->input = input_dev;
+
+	init_timer(&w90p910_ts->timer);
+	w90p910_ts->timer.data = (unsigned long) w90p910_ts;
+	w90p910_ts->timer.function = w90p910_ts_timer;
+
+	w90p910_ts->ts_state = NO_PRESS;
+	w90p910_ts->clocken = (int)W90X900_VA_CLKPWR;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENXIO;
+		goto fail1;
+	}
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				pdev->name)) {
+		err = -EBUSY;
+		goto fail1;
+	}
+
+	w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1);
+	if (!w90p910_ts->ts_reg) {
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	/* enable the ADC clock */
+	__raw_writel(__raw_readl(w90p910_ts->clocken)|ADC_CLK_EN,
+						w90p910_ts->clocken);
+
+	input_dev->name = "W90P910 TouchScreen";
+	input_dev->phys = "w90p910ts/event0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor 	= 0x0005;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->evbit[0] = BIT_MASK(EV_KEY)|
+				BIT_MASK(EV_ABS) | BIT_MASK(EV_SYN);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input_dev, ABS_X, 0, 0x400, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 0x400, 0, 0);
+
+	w90p910_ts->irq_num = platform_get_irq(pdev, 0);
+	if (request_irq(w90p910_ts->irq_num, ts_interrupt, IRQF_DISABLED,
+						"w90p910ts", w90p910_ts)) {
+		err = -EBUSY;
+		goto fail3;
+	}
+
+	err = input_register_device(w90p910_ts->input);
+	if (err)
+		goto fail4;
+
+	__raw_writel(ADC_RST1, w90p910_ts->ts_reg);
+	udelay(1000);
+	__raw_writel(ADC_RST0, w90p910_ts->ts_reg);
+	udelay(1000);
+
+	/* set delay and screen type */
+	__raw_writel(__raw_readl(w90p910_ts->ts_reg+0x04) & TSC_FOURWIRE,
+						(w90p910_ts->ts_reg+0x04));
+	__raw_writel(ADC_DELAY, (w90p910_ts->ts_reg+0x08));
+	/* waitting for trigger mode */
+	__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+		ADC_WAITTRIG|ADC_DIV|ADC_EN|WT_INT_EN) & 0xFFEBFF09,
+							w90p910_ts->ts_reg);
+	return 0;
+
+fail4:	free_irq(w90p910_ts->irq_num, w90p910_ts);
+fail3:	iounmap(w90p910_ts->ts_reg);
+fail2:	release_mem_region(res->start, res->end - res->start + 1);
+fail1:	input_free_device(input_dev);
+	kfree(w90p910_ts);
+	return err;
+}
+
+static int __devexit w90x900ts_remove(struct platform_device *pdev)
+{
+	struct w90p910drv_ts *w90p910_ts = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	free_irq(w90p910_ts->irq_num, w90p910_ts);
+	del_timer_sync(&w90p910_ts->timer);
+	iounmap(w90p910_ts->ts_reg);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	input_unregister_device(w90p910_ts->input);
+	kfree(w90p910_ts);
+
+	return 0;
+}
+
+static struct platform_driver w90x900ts_driver = {
+	.probe		= w90x900ts_probe,
+	.remove		= __devexit_p(w90x900ts_remove),
+	.driver		= {
+		.name	= "w90x900-ts",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init w90x900ts_init(void)
+{
+	return platform_driver_register(&w90x900ts_driver);
+}
+
+static void __exit w90x900ts_exit(void)
+{
+	platform_driver_unregister(&w90x900ts_driver);
+}
+
+module_init(w90x900ts_init);
+module_exit(w90x900ts_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@xxxxxxxxx>");
+MODULE_DESCRIPTION("w90p910 touch screen driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:w90p910-ts");
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux