@@ -38,7 +38,6 @@
#include <plat/adc.h>
#include <plat/regs-adc.h>
-
#include <mach/regs-gpio.h>
#include <mach/ts.h>
@@ -73,7 +72,7 @@
* @count: The number of samples collected.
* @shift: The log2 of the maximum count to read in one go.
*/
-struct s3c2410ts {
+struct s3c2410_ts {
struct s3c_adc_client *client;
struct device *dev;
struct input_dev *input;
@@ -86,7 +85,7 @@ struct s3c2410ts {
int shift;
};
-static struct s3c2410ts ts;
+static struct s3c2410_ts ts;
/**
* s3c2410_ts_connect - configure gpio for s3c2410 systems
@@ -95,7 +94,7 @@ static struct s3c2410ts ts;
* connected to the device (later systems such as the S3C2440 integrate
* these into the device).
*/
-static inline void s3c2410_ts_connect(void)
+static void s3c2410_ts_connect(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
@@ -104,88 +103,57 @@ static inline void s3c2410_ts_connect(void)
}
/**
- * get_down - return the down state of the pen
- * @data0: The data read from ADCDAT0 register.
- * @data1: The data read from ADCDAT1 register.
- *
- * Return non-zero if both readings show that the pen is down.
+ * s3c2410_ts_check_pen_down - return the down state of the pen
*/
-static inline bool get_down(unsigned long data0, unsigned long data1)
+static bool s3c24xx_ts_check_pen_down(void)
{
+ unsigned long data0 = readl(ts.io + S3C2410_ADCDAT0);
+ unsigned long data1 = readl(ts.io + S3C2410_ADCDAT1);
+
/* returns true if both data values show stylus down */
- return (!(data0 & S3C2410_ADCDAT0_UPDOWN) &&
- !(data1 & S3C2410_ADCDAT0_UPDOWN));
+ return !((data0 | data1) & S3C2410_ADCDAT0_UPDOWN);
}
-static void touch_timer_fire(unsigned long data)
+static void s3c24xx_ts_report_state(bool pen_is_down)
{
- unsigned long data0;
- unsigned long data1;
- bool down;
-
- data0 = readl(ts.io + S3C2410_ADCDAT0);
- data1 = readl(ts.io + S3C2410_ADCDAT1);
-
- down = get_down(data0, data1);
-
- if (down) {
- if (ts.count == (1 << ts.shift)) {
- ts.xp >>= ts.shift;
- ts.yp >>= ts.shift;
-
- dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n",
- __func__, ts.xp, ts.yp, ts.count);
+ if (pen_is_down) {
+ ts.xp >>= ts.shift;
+ ts.yp >>= ts.shift;
- input_report_abs(ts.input, ABS_X, ts.xp);
- input_report_abs(ts.input, ABS_Y, ts.yp);
+ dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n",
+ __func__, ts.xp, ts.yp, ts.count);
- input_report_key(ts.input, BTN_TOUCH, 1);
- input_sync(ts.input);
+ input_report_abs(ts.input, ABS_X, ts.xp);
+ input_report_abs(ts.input, ABS_Y, ts.yp);
- ts.xp = 0;
- ts.yp = 0;
- ts.count = 0;
- }
-
- s3c_adc_start(ts.client, 0, 1 << ts.shift);
+ input_report_key(ts.input, BTN_TOUCH, 1);
} else {
- ts.xp = 0;
- ts.yp = 0;
- ts.count = 0;
-
input_report_key(ts.input, BTN_TOUCH, 0);
- input_sync(ts.input);
-
- writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
}
+
+ input_sync(ts.input);
+
}
-static DEFINE_TIMER(touch_timer, touch_timer_fire, 0, 0);
+static void s3c24xx_ts_schedule_read(void)
+{
+ ts.xp = ts.yp = 0;
+ ts.count = 0;
+
+ s3c_adc_start(ts.client, 0, 1 << ts.shift);
+}
/**
- * stylus_irq - touchscreen stylus event interrupt
+ * s3c24xx_ts_stylus_irq - touchscreen stylus event interrupt
* @irq: The interrupt number
* @dev_id: The device ID.
*
* Called when the IRQ_TC is fired for a pen up or down event.
*/
-static irqreturn_t stylus_irq(int irq, void *dev_id)
+static irqreturn_t s3c24xx_ts_stylus_irq(int irq, void *dev_id)
{
- unsigned long data0;
- unsigned long data1;
- bool down;
-
- data0 = readl(ts.io + S3C2410_ADCDAT0);
- data1 = readl(ts.io + S3C2410_ADCDAT1);
-
- down = get_down(data0, data1);
-
- /* TODO we should never get an interrupt with down set while
- * the timer is running, but maybe we ought to verify that the
- * timer isn't running anyways. */
-
- if (down)
- s3c_adc_start(ts.client, 0, 1 << ts.shift);
+ if (s3c24xx_ts_check_pen_down())
+ s3c24xx_ts_schedule_read();
else
dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count);
@@ -231,12 +199,26 @@ static void s3c24xx_ts_conversion(struct s3c_adc_client *client,
*/
static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select)
{
+ bool pen_is_down;
+
if (select) {
+ /*
+ * Prepare for the next sample.
+ */
writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
ts.io + S3C2410_ADCTSC);
} else {
- mod_timer(&touch_timer, jiffies+1);
- writel(WAIT4INT | INT_UP, ts.io + S3C2410_ADCTSC);
+ /*
+ * Conversion is complete, we have desired number of samples.
+ */
+ pen_is_down = s3c24xx_ts_check_pen_down();
+
+ s3c24xx_ts_report_state(pen_is_down);
+
+ if (pen_is_down)
+ s3c24xx_ts_schedule_read();
+ else
+ writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
}
}
@@ -247,7 +229,7 @@ static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select)
* Initialise, find and allocate any resources we need to run and then
* register with the ADC and input systems.
*/
-static int __devinit s3c2410ts_probe(struct platform_device *pdev)
+static int __devinit s3c24xx_ts_probe(struct platform_device *pdev)
{
struct s3c2410_ts_mach_info *info;
struct device *dev = &pdev->dev;
@@ -256,7 +238,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
int ret = -EINVAL;
/* Initialise input stuff */
- memset(&ts, 0, sizeof(struct s3c2410ts));
+ memset(&ts, 0, sizeof(struct s3c2410_ts));
ts.dev = dev;
@@ -313,8 +295,6 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
if ((info->delay & 0xffff) > 0)
writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY);
- writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
-
input_dev = input_allocate_device();
if (!input_dev) {
dev_err(dev, "Unable to allocate the input device !!\n");
@@ -333,17 +313,18 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
ts.input->id.vendor = 0xDEAD;
ts.input->id.product = 0xBEEF;
ts.input->id.version = 0x0102;
+ ts.input->dev.parent = &pdev->dev;
ts.shift = info->oversampling_shift;
- ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,
+ ret = request_irq(ts.irq_tc, s3c24xx_ts_stylus_irq, IRQF_DISABLED,
"s3c2410_ts_pen", ts.input);
if (ret) {
dev_err(dev, "cannot get TC interrupt\n");
goto err_inputdev;
}
- dev_info(dev, "driver attached, registering input device\n");
+ dev_dbg(dev, "driver attached, registering input device\n");
/* All went ok, so register to the input system */
ret = input_register_device(ts.input);
@@ -353,16 +334,17 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
goto err_tcirq;
}
+ writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
+
return 0;
err_tcirq:
free_irq(ts.irq_tc, ts.input);
err_inputdev:
- input_unregister_device(ts.input);
+ input_free_device(ts.input);
err_iomap:
iounmap(ts.io);
err_clk:
- del_timer_sync(&touch_timer);
clk_put(ts.clock);
return ret;
}
@@ -373,10 +355,9 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
*
* Free up our state ready to be removed.
*/
-static int __devexit s3c2410ts_remove(struct platform_device *pdev)
+static int __devexit s3c24xx_ts_remove(struct platform_device *pdev)
{
free_irq(ts.irq_tc, ts.input);
- del_timer_sync(&touch_timer);
clk_disable(ts.clock);
clk_put(ts.clock);
@@ -388,7 +369,7 @@ static int __devexit s3c2410ts_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int s3c2410ts_suspend(struct device *dev)
+static int s3c24xx_ts_suspend(struct device *dev)
{
writel(TSC_SLEEP, ts.io + S3C2410_ADCTSC);
disable_irq(ts.irq_tc);
@@ -397,7 +378,7 @@ static int s3c2410ts_suspend(struct device *dev)
return 0;
}
-static int s3c2410ts_resume(struct device *dev)
+static int s3c24xx_ts_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c2410_ts_mach_info *info = pdev->dev.platform_data;
@@ -414,44 +395,44 @@ static int s3c2410ts_resume(struct device *dev)
return 0;
}
-static struct dev_pm_ops s3c_ts_pmops = {
- .suspend = s3c2410ts_suspend,
- .resume = s3c2410ts_resume,
+static struct dev_pm_ops s3c24xx_ts_pmops = {
+ .suspend = s3c24xx_ts_suspend,
+ .resume = s3c24xx_ts_resume,
};
#endif
-static struct platform_device_id s3cts_driver_ids[] = {
+static struct platform_device_id s3c24xx_ts_driver_ids[] = {
{ "s3c2410-ts", 0 },
{ "s3c2440-ts", 1 },
{ }
};
-MODULE_DEVICE_TABLE(platform, s3cts_driver_ids);
+MODULE_DEVICE_TABLE(platform, s3c24xx_ts_driver_ids);
-static struct platform_driver s3c_ts_driver = {
+static struct platform_driver s3c24xx_ts_driver = {
.driver = {
.name = "s3c24xx-ts",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
- .pm = &s3c_ts_pmops,
+ .pm = &s3c24xx_ts_pmops,
#endif
},
- .id_table = s3cts_driver_ids,
- .probe = s3c2410ts_probe,
- .remove = __devexit_p(s3c2410ts_remove),
+ .id_table = s3c24xx_ts_driver_ids,
+ .probe = s3c24xx_ts_probe,
+ .remove = __devexit_p(s3c24xx_ts_remove),
};
-static int __init s3c2410ts_init(void)
+static int __init s3c24xx_ts_init(void)
{
- return platform_driver_register(&s3c_ts_driver);
+ return platform_driver_register(&s3c24xx_ts_driver);
}
-static void __exit s3c2410ts_exit(void)
+static void __exit s3c24xx_ts_exit(void)
{
- platform_driver_unregister(&s3c_ts_driver);
+ platform_driver_unregister(&s3c24xx_ts_driver);
}
-module_init(s3c2410ts_init);
-module_exit(s3c2410ts_exit);
+module_init(s3c24xx_ts_init);
+module_exit(s3c24xx_ts_exit);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, "
"Ben Dooks <ben@simtec.co.uk>, "