aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/s3c2410_ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/s3c2410_ts.c')
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c136
1 files changed, 49 insertions, 87 deletions
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 23d7e28e460..760b13c7eb8 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -64,6 +64,7 @@
#include <mach/ts.h>
#include <mach/hardware.h>
#include <plat/regs-adc.h>
+#include <plat/adc.h>
#include "ts_filter_chain.h"
@@ -78,12 +79,6 @@
S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_XY_PST(3))
-#define AUTOPST (S3C2410_ADCTSC_YM_SEN | \
- S3C2410_ADCTSC_YP_SEN | \
- S3C2410_ADCTSC_XP_SEN | \
- S3C2410_ADCTSC_AUTO_PST | \
- S3C2410_ADCTSC_XY_PST(0))
-
#define DEBUG_LVL KERN_DEBUG
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
@@ -110,10 +105,12 @@ static char *s3c2410ts_name = "s3c2410 TouchScreen";
struct s3c2410ts {
struct input_dev *dev;
+ struct s3c_adc_client *adc_client;
struct ts_filter_chain *chain;
int is_down;
int state;
struct kfifo *event_fifo;
+ unsigned adc_selected;
};
static struct s3c2410ts ts;
@@ -132,12 +129,26 @@ static inline void s3c2410_ts_connect(void)
s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
}
+static void ts_adc_timer_f(unsigned long data);
+static struct timer_list ts_adc_timer = TIMER_INITIALIZER(ts_adc_timer_f, 0, 0);
+
+static void ts_adc_timer_f(unsigned long data)
+{
+ if (s3c_adc_start(ts.adc_client, 0, 1))
+ mod_timer(&ts_adc_timer, jiffies + 1);
+}
+
+void adc_selected_f(unsigned selected)
+{
+ ts.adc_selected = selected;
+}
+
static void s3c2410_ts_start_adc_conversion(void)
{
- writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
- base_addr + S3C2410_ADCTSC);
- writel(readl(base_addr + S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START,
- base_addr + S3C2410_ADCCON);
+ if (ts.adc_selected)
+ mod_timer(&ts_adc_timer, jiffies + 1);
+ else
+ ts_adc_timer_f(0);
}
/*
@@ -282,21 +293,25 @@ static irqreturn_t stylus_updown(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static irqreturn_t stylus_action(int irq, void *dev_id)
+static void stylus_adc_action(unsigned p0, unsigned p1, unsigned *conv_left)
{
int buf[3];
- /* Grab the ADC results. */
- buf[1] = readl(base_addr + S3C2410_ADCDAT0) &
- S3C2410_ADCDAT0_XPDATA_MASK;
- buf[2] = readl(base_addr + S3C2410_ADCDAT1) &
- S3C2410_ADCDAT1_YPDATA_MASK;
+ /* TODO: Do we really need this? */
+ if (p0 & S3C2410_ADCDAT0_AUTO_PST ||
+ p1 & S3C2410_ADCDAT1_AUTO_PST) {
+ *conv_left = 1;
+ return;
+ }
+
+ buf[1] = p0;
+ buf[2] = p1;
switch (ts_filter_chain_feed(ts.chain, &buf[1])) {
case 0:
/* The filter wants more points. */
- s3c2410_ts_start_adc_conversion();
- return IRQ_HANDLED;
+ *conv_left = 1;
+ return;
case 1:
/* We have a point from the filters or no filtering enabled. */
buf[0] = 'P';
@@ -309,7 +324,7 @@ static irqreturn_t stylus_action(int irq, void *dev_id)
/* Error. Ignore the event. */
ts_filter_chain_clear(ts.chain);
writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
- return IRQ_HANDLED;
+ return;
};
if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf,
@@ -319,11 +334,9 @@ static irqreturn_t stylus_action(int irq, void *dev_id)
writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
mod_timer(&event_send_timer, jiffies + 1);
- return IRQ_HANDLED;
+ return;
}
-static struct clk *adc_clock;
-
/*
* The functions for inserting/removing us as a module.
*/
@@ -349,17 +362,6 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
printk(DEBUG_LVL "Entering s3c2410ts_init\n");
#endif
- adc_clock = clk_get(NULL, "adc");
- if (!adc_clock) {
- dev_err(&pdev->dev, "failed to get adc clock source\n");
- return -ENOENT;
- }
- clk_enable(adc_clock);
-
-#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
- printk(DEBUG_LVL "got and enabled clock\n");
-#endif
-
base_addr = ioremap(S3C2410_PA_ADC,0x20);
if (base_addr == NULL) {
dev_err(&pdev->dev, "Failed to remap register block\n");
@@ -372,23 +374,22 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
if (!strcmp(pdev->name, "s3c2410-ts"))
s3c2410_ts_connect();
- if ((info->presc & 0xff) > 0)
- writel(S3C2410_ADCCON_PRSCEN |
- S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
- base_addr + S3C2410_ADCCON);
- else
- writel(0, base_addr+S3C2410_ADCCON);
-
- /* Initialise registers */
- if ((info->delay & 0xffff) > 0)
- writel(info->delay & 0xffff, base_addr + S3C2410_ADCDLY);
-
writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC);
/* Initialise input stuff */
memset(&ts, 0, sizeof(struct s3c2410ts));
- input_dev = input_allocate_device();
+ ts.adc_client =
+ s3c_adc_register(pdev, adc_selected_f, stylus_adc_action, 1);
+ if (!ts.adc_client) {
+ dev_err(&pdev->dev,
+ "Unable to register s3c2410_ts as s3_adc client\n");
+ iounmap(base_addr);
+ ret = -EIO;
+ goto bail0;
+ }
+
+ input_dev = input_allocate_device();
if (!input_dev) {
dev_err(&pdev->dev, "Unable to allocate the input device\n");
ret = -ENOMEM;
@@ -423,18 +424,10 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
ts_filter_chain_clear(ts.chain);
- /* Get irqs */
- if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
- "s3c2410_action", ts.dev)) {
- dev_err(&pdev->dev, "Could not allocate ts IRQ_ADC !\n");
- iounmap(base_addr);
- ret = -EIO;
- goto bail3;
- }
+ /* Get IRQ. */
if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
"s3c2410_action", ts.dev)) {
dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n");
- free_irq(IRQ_ADC, ts.dev);
iounmap(base_addr);
ret = -EIO;
goto bail4;
@@ -445,6 +438,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
/* All went ok, so register to the input system */
rc = input_register_device(ts.dev);
if (rc) {
+ dev_info(&pdev->dev, "Could not register input device\n");
ret = -EIO;
goto bail5;
}
@@ -453,13 +447,9 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
bail5:
free_irq(IRQ_TC, ts.dev);
- free_irq(IRQ_ADC, ts.dev);
- clk_disable(adc_clock);
iounmap(base_addr);
disable_irq(IRQ_TC);
bail4:
- disable_irq(IRQ_ADC);
-bail3:
ts_filter_chain_destroy(ts.chain);
kfifo_free(ts.event_fifo);
bail2:
@@ -473,17 +463,10 @@ bail0:
static int s3c2410ts_remove(struct platform_device *pdev)
{
- disable_irq(IRQ_ADC);
disable_irq(IRQ_TC);
free_irq(IRQ_TC,ts.dev);
- free_irq(IRQ_ADC,ts.dev);
-
- if (adc_clock) {
- clk_disable(adc_clock);
- clk_put(adc_clock);
- adc_clock = NULL;
- }
+ s3c_adc_release(ts.adc_client);
input_unregister_device(ts.dev);
iounmap(base_addr);
@@ -501,38 +484,17 @@ static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,
base_addr+S3C2410_ADCCON);
- disable_irq(IRQ_ADC);
disable_irq(IRQ_TC);
- clk_disable(adc_clock);
-
return 0;
}
static int s3c2410ts_resume(struct platform_device *pdev)
{
- struct s3c2410_ts_mach_info *info =
- ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
-
- clk_enable(adc_clock);
- mdelay(1);
-
ts_filter_chain_clear(ts.chain);
- enable_irq(IRQ_ADC);
enable_irq(IRQ_TC);
- if ((info->presc&0xff) > 0)
- writel(S3C2410_ADCCON_PRSCEN |
- S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
- base_addr+S3C2410_ADCCON);
- else
- writel(0,base_addr+S3C2410_ADCCON);
-
- /* Initialise registers */
- if ((info->delay & 0xffff) > 0)
- writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
-
writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
return 0;