From: Wan ZongShun <mcuos.com@gmail.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org, mcuos.com@gmail.com
Subject: Re: [PATCH] Add support for touch screen on W90P910 ARM platform
Date: Mon, 11 May 2009 11:58:59 +0800 [thread overview]
Message-ID: <4A07A283.5080804@gmail.com> (raw)
In-Reply-To: <200905101315.45564.dmitry.torokhov@gmail.com>
Dear Dmitry,
Modifying the magic constants to use #defines form,but I forget to re-patch it in previous patch,
so i re-submit this patch again.
about you doubt:
if ((__raw_readl(w90p910_ts->ts_reg)&ADC_INT) &&
w90p910_ts->state == CAN_READY) {
w90p910_report_event(w90p910_ts);
__raw_writel((__raw_readl(w90p910_ts->ts_reg)|
ADC_WAITTRIG)&(~ADC_INT|~WT_INT_EN|~ADC_INT_EN),
w90p910_ts->ts_reg);
mod_timer(&w90p910_ts->timer, jiffies +
msecs_to_jiffies(40));
}
When changing to wait trigger mode(ADC_WAITTRIG),I have to close wait trigger(WT_INT) and ADC interrupt(ADC_INT), and start the timer to execute timer function,if pen still keep down,then opening the ADC interrupt again,so that it can continue to get values of X and
Y,but if pen keep up,opening wait trigger interrupt and closing ADC interrupt,so that we can wait the next pen in down.
MY PATCH text:
Add touchscreen drivers for w90p910 platform.
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
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-01 12:28:54.000000000 +0800
+++ linux-2.6.30/drivers/input/touchscreen/Kconfig 2009-05-10 14:47:07.000000000 +0800
@@ -466,4 +466,11 @@ config TOUCHSCREEN_TSC2007
To compile this driver as a module, choose M here: the
module will be called tsc2007.
+config TOUCHSCREEN_W90X900
+ tristate "W90P910 touchscreen driver"
+ depends on CPU_W90P910
+ help
+ To compile this driver as a module, choose M here: the
+ module will be called w90p910-ts.
+
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-01 12:28:54.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-11 11:12:48.000000000 +0800
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * 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 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)/*adc int status*/
+#define WT_INT (0x01 << 20)/*wait trig int status*/
+#define ADC_INT_EN (0x01 << 21)/*enable ADC_INT irq*/
+#define LVD_INT_EN (0x01 << 22)
+#define WT_INT_EN (0x01 << 23)/*enable WT_INT irq*/
+#define ADC_DIV (0x04 << 1)/*div=6*/
+
+/*adc state define*/
+enum ts_state { NO_PRESS, CAN_READX, CAN_READY };
+
+struct w90p910drv_ts {
+ struct input_dev *input;
+ struct timer_list timer;
+ int irq_num;
+ int pendown;
+ int clocken;
+ void __iomem *ts_reg;
+ short x;
+ short y;
+ spinlock_t lock;
+ enum ts_state state;
+};
+
+static void w90p910_report_event(struct w90p910drv_ts *w90p910_ts)
+{
+ struct input_dev *dev = w90p910_ts->input;
+
+ w90p910_ts->x = __raw_readl(w90p910_ts->ts_reg+0x0c);
+ w90p910_ts->y = __raw_readl(w90p910_ts->ts_reg+0x10);
+
+ input_report_abs(dev, ABS_X, w90p910_ts->x);
+ input_report_abs(dev, ABS_Y, w90p910_ts->y);
+ input_report_key(dev, BTN_TOUCH, w90p910_ts->pendown);
+ input_sync(dev);
+}
+
+static void w90p910_ts_interrupt(struct w90p910drv_ts *w90p910_ts)
+{
+ if ((__raw_readl(w90p910_ts->ts_reg)&WT_INT) &&
+ w90p910_ts->state == NO_PRESS) {
+ w90p910_ts->pendown = 1;
+ __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)&(~WT_INT|~WT_INT_EN),
+ w90p910_ts->ts_reg);
+ w90p910_ts->state = CAN_READX;
+ } 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)&(~WT_INT_EN),
+ w90p910_ts->ts_reg);
+ w90p910_ts->pendown = 1;
+ w90p910_ts->state = CAN_READX;
+ } else {
+ __raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+ ADC_WAITTRIG|WT_INT_EN)&(~ADC_INT_EN|
+ ~WT_INT|~ADC_INT), w90p910_ts->ts_reg);
+ w90p910_ts->pendown = 0;
+ w90p910_ts->state = NO_PRESS;
+ }
+ }
+
+ if ((__raw_readl(w90p910_ts->ts_reg)&ADC_INT) &&
+ w90p910_ts->state == CAN_READX) {
+ __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)&(~ADC_INT|~WT_INT_EN),
+ w90p910_ts->ts_reg);
+ w90p910_ts->state = CAN_READY;
+ }
+
+ if ((__raw_readl(w90p910_ts->ts_reg)&ADC_INT) &&
+ w90p910_ts->state == CAN_READY) {
+ w90p910_report_event(w90p910_ts);
+ __raw_writel((__raw_readl(w90p910_ts->ts_reg)|
+ ADC_WAITTRIG)&(~ADC_INT|~WT_INT_EN|~ADC_INT_EN),
+ w90p910_ts->ts_reg);
+ mod_timer(&w90p910_ts->timer, jiffies +
+ msecs_to_jiffies(40));
+ }
+}
+
+static void w90p910_ts_timer(unsigned long data)
+{
+ struct w90p910drv_ts *w90p910_data = (struct w90p910drv_ts *) data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&w90p910_data->lock, flags);
+
+ w90p910_ts_interrupt(w90p910_data);
+
+ spin_unlock_irqrestore(&w90p910_data->lock, flags);
+}
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id)
+{
+ struct w90p910drv_ts *w90p910_data = dev_id;
+
+ w90p910_ts_interrupt(w90p910_data);
+ 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;
+ w90p910_ts->state = NO_PRESS;
+ w90p910_ts->clocken = (int)W90X900_VA_CLKPWR;
+ spin_lock_init(&w90p910_ts->lock);
+ setup_timer(&w90p910_ts->timer, w90p910_ts_timer,
+ (unsigned long)w90p910_ts);
+
+ 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);
+ msleep(1);
+ __raw_writel(ADC_RST0, w90p910_ts->ts_reg);
+ msleep(1);
+
+ /* 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), 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@gmail.com>");
+MODULE_DESCRIPTION("w90p910 touch screen driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:w90p910-ts");
next prev parent reply other threads:[~2009-05-11 3:59 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-27 15:03 [PATCH] Add support for touch screen on W90P910 ARM platform Wan ZongShun
2009-05-08 3:41 ` Dmitry Torokhov
2009-05-09 1:30 ` Wan ZongShun
2009-05-09 19:54 ` Dmitry Torokhov
2009-05-10 10:35 ` Wan ZongShun
2009-05-10 20:15 ` Dmitry Torokhov
2009-05-11 3:58 ` Wan ZongShun [this message]
2009-05-12 1:07 ` Wan ZongShun
[not found] ` <e68bb3470905172007i47a5435x7b87383323a1cf1a@mail.gmail.com>
[not found] ` <200905181600.07651.dmitry.torokhov@gmail.com>
[not found] ` <e68bb3470905182054g6d9dba05kabc6c588d35b3548@mail.gmail.com>
[not found] ` <20090527141220.GA18589@dtor-d630.eng.vmware.com>
[not found] ` <4A24C0A4.3040704@gmail.com>
[not found] ` <20090602092031.GA2647@dtor-d630.eng.vmware.com>
2009-06-02 11:13 ` Wan ZongShun
2009-06-02 13:57 ` Dmitry Torokhov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A07A283.5080804@gmail.com \
--to=mcuos.com@gmail.com \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).