aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/s3c2410_ts.c
diff options
context:
space:
mode:
authorNelson Castillo <arhuaco@freaks-unidos.net>2009-03-10 12:04:05 +0000
committerAndy Green <agreen@octopus.localdomain>2009-03-10 12:04:05 +0000
commitbd88fa696f505a8a71484341e4fcde581b2d12a6 (patch)
treebca483a0c57848ca6d122907c42a0c7c04fbeb4a /drivers/input/touchscreen/s3c2410_ts.c
parent45aeeebf673b03329c423c2382a836ca878dd851 (diff)
Improve filter API and update filters
This patch turns upstream feedback into API modifications and code improvements. There will be more patches implementing upstream corrections but this one is the that will make most of the invasive changes and make the most important improvements to the API. Tested in a GTA02/rev06. The goals of this patch are: * Replace recursive calls with iteration. * General code improvements. * Make ts_filter_mean.c a reference for the rest of the filters. * Make the (almost)minimum number of changes to the other filters so that they compile and work, patches for cleaning these up will come next. * Filters should do what they were doing before. Some important changes: * Move "struct ts_filter tsf" in the private structures to force a crash (or break things) if we forget to remove an open-coded cast. * ts_filter.c/ts_filter.h ~ API modifications. * s3c2410_ts.c: ~ Use the new API. ~ Cleanups. * ts_filter_mean.c ~ Replace with a simple mean. ~ Use as a reference for the new API. ~ Move private structure from the .h to the .c. * ts_filter_group.c ~ Update to use the new API. * ts_filter_median.c ~ Update to use the new API. * ts_filter_linear.c ~ Remove functions that are no longer needed. Note: I might leave some TODOs and FIXMEs with this patch. Most of them will be removed shortly. Signed-off-by: Nelson Castillo <arhuaco@freaks-unidos.net>
Diffstat (limited to 'drivers/input/touchscreen/s3c2410_ts.c')
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c95
1 files changed, 38 insertions, 57 deletions
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 7d5b3debbb3..d63d4eab605 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -98,6 +98,7 @@ static char *s3c2410ts_name = "s3c2410 TouchScreen";
#define TS_RELEASE_TIMEOUT (HZ >> 7 ? HZ >> 7 : 1) /* 8ms (5ms if HZ is 200) */
#define TS_EVENT_FIFO_SIZE (2 << 6) /* must be a power of 2 */
+#define TS_COORDINATES_SIZE 2 /* just X and Y for us */
#define TS_STATE_STANDBY 0 /* initial state */
#define TS_STATE_PRESSED 1
@@ -110,8 +111,7 @@ static char *s3c2410ts_name = "s3c2410 TouchScreen";
struct s3c2410ts {
struct input_dev *dev;
- struct ts_filter *tsf[MAX_TS_FILTER_CHAIN];
- int coords[2]; /* just X and Y for us */
+ struct ts_filter **tsf;
int is_down;
int state;
struct kfifo *event_fifo;
@@ -232,15 +232,14 @@ static void event_send_timer_f(unsigned long data)
if (noop_counter++ >= 1) {
noop_counter = 0;
if (ts.state == TS_STATE_RELEASE_PENDING) {
- /* We delay the UP event for a
- * while to avoid jitter. If we get a DOWN
- * event we do not send it. */
-
+ /*
+ * We delay the UP event for a while to avoid jitter.
+ * If we get a DOWN event we do not send it.
+ */
ts_input_report(IE_UP, NULL);
ts.state = TS_STATE_STANDBY;
- if (ts.tsf[0])
- (ts.tsf[0]->api->clear)(ts.tsf[0]);
+ ts_filter_chain_clear(ts.tsf);
}
} else {
mod_timer(&event_send_timer, jiffies + TS_RELEASE_TIMEOUT);
@@ -288,42 +287,29 @@ static irqreturn_t stylus_action(int irq, void *dev_id)
{
int buf[3];
- /* grab the ADC results */
- ts.coords[0] = readl(base_addr + S3C2410_ADCDAT0) &
- S3C2410_ADCDAT0_XPDATA_MASK;
- ts.coords[1] = readl(base_addr + S3C2410_ADCDAT1) &
- S3C2410_ADCDAT1_YPDATA_MASK;
-
- if (ts.tsf[0]) { /* filtering is enabled, don't use raw directly */
- switch ((ts.tsf[0]->api->process)(ts.tsf[0], &ts.coords[0])) {
- case 0: /*
- * no real sample came out of processing yet,
- * get another raw result to feed it
- */
- s3c2410_ts_start_adc_conversion();
- return IRQ_HANDLED;
- case 1: /* filters are ready to deliver a sample */
- (ts.tsf[0]->api->scale)(ts.tsf[0], &ts.coords[0]);
- break;
- case -1:
- /* error in filters, ignore the event */
- (ts.tsf[0]->api->clear)(ts.tsf[0]);
- writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
- return IRQ_HANDLED;
- default:
- printk(KERN_ERR":stylus_action error\n");
- }
- }
+ /* 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;
- /* We use a buffer because want an atomic operation */
- buf[0] = 'P';
- buf[1] = ts.coords[0];
- buf[2] = ts.coords[1];
+ switch (ts_filter_chain_feed(ts.tsf, &buf[1])) {
+ case 0:
+ s3c2410_ts_start_adc_conversion();
+ return IRQ_HANDLED;
+ case -1:
+ /* Error. Ignore the event. */
+ ts_filter_chain_clear(ts.tsf);
+ writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
+ return IRQ_HANDLED;
+ default:
+ /* We have a point from the filters or no filtering enabled. */
+ buf[0] = 'P';
+ };
if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf,
sizeof(int) * 3) != sizeof(int) * 3))
- /* should not happen */
- printk(KERN_ERR":stylus_action error\n");
+ printk(KERN_ERR":stylus_action error\n"); /* happens => bug */
writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
mod_timer(&event_send_timer, jiffies + 1);
@@ -425,18 +411,14 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
}
/* create the filter chain set up for the 2 coordinates we produce */
- ret = ts_filter_create_chain(
- pdev, (struct ts_filter_api **)&info->filter_sequence,
- (void *)&info->filter_config, ts.tsf, ARRAY_SIZE(ts.coords));
- if (ret)
- dev_info(&pdev->dev, "%d filter(s) initialized\n", ret);
- else /* this is OK, just means there won't be any filtering */
- dev_info(&pdev->dev, "Unfiltered output selected\n");
-
- if (ts.tsf[0])
- (ts.tsf[0]->api->clear)(ts.tsf[0]);
- else
- dev_info(&pdev->dev, "No filtering\n");
+ ts.tsf = ts_filter_chain_create(
+ pdev, (struct ts_filter_api **)&info->filter_sequence,
+ (void *)&info->filter_config, TS_COORDINATES_SIZE);
+
+ if (!ts.tsf)
+ goto bail2;
+
+ ts_filter_chain_clear(ts.tsf);
/* Get irqs */
if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
@@ -455,7 +437,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
goto bail4;
}
- dev_info(&pdev->dev, "successfully loaded\n");
+ dev_info(&pdev->dev, "Successfully loaded\n");
/* All went ok, so register to the input system */
rc = input_register_device(ts.dev);
@@ -475,7 +457,7 @@ bail5:
bail4:
disable_irq(IRQ_ADC);
bail3:
- ts_filter_destroy_chain(pdev, ts.tsf);
+ ts_filter_chain_destroy(ts.tsf);
kfifo_free(ts.event_fifo);
bail2:
input_unregister_device(ts.dev);
@@ -502,7 +484,7 @@ static int s3c2410ts_remove(struct platform_device *pdev)
input_unregister_device(ts.dev);
iounmap(base_addr);
- ts_filter_destroy_chain(pdev, ts.tsf);
+ ts_filter_chain_destroy(ts.tsf);
kfifo_free(ts.event_fifo);
@@ -532,8 +514,7 @@ static int s3c2410ts_resume(struct platform_device *pdev)
clk_enable(adc_clock);
mdelay(1);
- if (ts.tsf[0])
- (ts.tsf[0]->api->clear)(ts.tsf[0]);
+ ts_filter_chain_clear(ts.tsf);
enable_irq(IRQ_ADC);
enable_irq(IRQ_TC);