aboutsummaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorAndy Green <agreen@pads.home.warmcat.com>2008-11-22 09:05:43 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-22 09:05:43 +0000
commitb66aa08df846bbbbc41d21cd42052d4c96b84668 (patch)
tree9d796b023ac4c0e6dff0e317d499faf034595a18 /drivers/input
parentc08433d1b54a2cadc7061a2bd68fbf1a4d42fcca (diff)
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c102
-rw-r--r--drivers/input/touchscreen/ts_filter.c3
-rw-r--r--drivers/input/touchscreen/ts_filter_mean.c6
-rw-r--r--drivers/input/touchscreen/ts_filter_median.c3
4 files changed, 50 insertions, 64 deletions
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 8f0afc3e023..8e580a833e5 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -98,9 +98,10 @@ static char *s3c2410ts_name = "s3c2410 TouchScreen";
struct s3c2410ts {
struct input_dev *dev;
- int flag_first_touch_sent;
struct ts_filter *tsf[MAX_TS_FILTER_CHAIN];
int coords[2]; /* just X and Y for us */
+ int is_down;
+ int need_to_send_first_touch;
};
static struct s3c2410ts ts;
@@ -116,69 +117,58 @@ static inline void s3c2410_ts_connect(void)
s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
}
-static void touch_timer_fire(unsigned long data)
-{
- unsigned long data0;
- unsigned long data1;
- int updown;
-
- data0 = readl(base_addr + S3C2410_ADCDAT0);
- data1 = readl(base_addr + S3C2410_ADCDAT1);
+enum ts_input_event {IE_DOWN = 0, IE_UP, IE_UPDATE};
- updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
- (!(data1 & S3C2410_ADCDAT0_UPDOWN));
-
- // if we need to send an untouch event, but we haven't yet sent the
- // touch event (this happens if the touchscreen was tapped lightly),
- // send the touch event first
- if (!updown && !ts.flag_first_touch_sent) {
- if (ts.tsf[0])
- (ts.tsf[0]->api->scale)(ts.tsf[0], &ts.coords[0]);
+static void ts_input_report(int event)
+{
+ if (event == IE_DOWN || event == IE_UPDATE) {
input_report_abs(ts.dev, ABS_X, ts.coords[0]);
input_report_abs(ts.dev, ABS_Y, ts.coords[1]);
-
input_report_key(ts.dev, BTN_TOUCH, 1);
input_report_abs(ts.dev, ABS_PRESSURE, 1);
- input_sync(ts.dev);
- ts.flag_first_touch_sent = 1;
+ } else {
+ input_report_key(ts.dev, BTN_TOUCH, 0);
+ input_report_abs(ts.dev, ABS_PRESSURE, 0);
}
- if (updown) {
-
- if (ts.tsf[0])
- (ts.tsf[0]->api->scale)(ts.tsf[0], &ts.coords[0]);
+ input_sync(ts.dev);
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
- {
- struct timeval tv;
-
- do_gettimeofday(&tv);
- printk(DEBUG_LVL "T:%06d, X:%03ld, Y:%03ld\n",
- (int)tv.tv_usec, ts.coords[0], ts.coords[1]);
- }
+ {
+ static char *s[] = {"down", "up", "update"};
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ printk(DEBUG_LVL "T:%06d %6s (X:%03d, Y:%03d)\n",
+ (int)tv.tv_usec, s[event], ts.coords[0], ts.coords[1]);
+ }
#endif
+}
+static void touch_timer_fire(unsigned long data)
+{
+ if (ts.tsf[0])
+ (ts.tsf[0]->api->scale)(ts.tsf[0], &ts.coords[0]);
+
+ if (ts.need_to_send_first_touch) {
+ ts.need_to_send_first_touch = 0;
+ ts_input_report(IE_DOWN);
+ if (!ts.is_down) { /* Do we need this? I think so. */
+ ts_input_report(IE_UPDATE);
+ ts_input_report(IE_UP);
+ }
+ } else if (ts.is_down) {
+ ts_input_report(IE_UPDATE);
+ } else {
+ ts_input_report(IE_UP);
+ }
- input_report_abs(ts.dev, ABS_X, ts.coords[0]);
- input_report_abs(ts.dev, ABS_Y, ts.coords[1]);
-
- input_report_key(ts.dev, BTN_TOUCH, 1);
- input_report_abs(ts.dev, ABS_PRESSURE, 1);
- input_sync(ts.dev);
-
+ if (ts.is_down) {
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);
} else {
-
if (ts.tsf[0])
(ts.tsf[0]->api->clear)(ts.tsf[0]);
-
- input_report_key(ts.dev, BTN_TOUCH, 0);
- input_report_abs(ts.dev, ABS_PRESSURE, 0);
- input_sync(ts.dev);
- ts.flag_first_touch_sent = 0;
-
writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
}
}
@@ -190,20 +180,20 @@ static irqreturn_t stylus_updown(int irq, void *dev_id)
{
unsigned long data0;
unsigned long data1;
- int updown;
data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);
- updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
+ ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
(!(data1 & S3C2410_ADCDAT0_UPDOWN));
- /* TODO we should never get an interrupt with updown set while
- * the timer is running, but maybe we ought to verify that the
- * timer isn't running anyways. */
-
- if (updown)
- touch_timer_fire(0);
+ if (ts.is_down) {
+ ts.need_to_send_first_touch = 1;
+ 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);
+ }
return IRQ_HANDLED;
}
@@ -336,7 +326,9 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
else /* this is OK, just means there won't be any filtering */
dev_info(&pdev->dev, "Unfiltered output selected\n");
- if (!ts.tsf[0])
+ if (ts.tsf[0])
+ (ts.tsf[0]->api->clear)(ts.tsf[0]);
+ else
dev_info(&pdev->dev, "No filtering\n");
/* Get irqs */
diff --git a/drivers/input/touchscreen/ts_filter.c b/drivers/input/touchscreen/ts_filter.c
index f8b2b2f5846..4c650a5c66f 100644
--- a/drivers/input/touchscreen/ts_filter.c
+++ b/drivers/input/touchscreen/ts_filter.c
@@ -49,9 +49,12 @@ EXPORT_SYMBOL_GPL(ts_filter_create_chain);
void ts_filter_destroy_chain(struct ts_filter **list)
{
+ struct ts_filter **first;
+ first = list;
while (*list) {
((*list)->api->destroy)(*list);
list++;
}
+ *first = NULL;
}
EXPORT_SYMBOL_GPL(ts_filter_destroy_chain);
diff --git a/drivers/input/touchscreen/ts_filter_mean.c b/drivers/input/touchscreen/ts_filter_mean.c
index b589bee826f..2322432fc3f 100644
--- a/drivers/input/touchscreen/ts_filter_mean.c
+++ b/drivers/input/touchscreen/ts_filter_mean.c
@@ -94,12 +94,6 @@ static void ts_filter_mean_destroy(struct ts_filter *tsf)
{
struct ts_filter_mean *tsfs = (struct ts_filter_mean *)tsf;
- if (!tsf)
- return;
-
- if (tsf->next) /* chain */
- (tsf->next->api->destroy)(tsf->next);
-
kfree(tsfs->fifo[0]); /* first guy has pointer from kmalloc */
kfree(tsf);
}
diff --git a/drivers/input/touchscreen/ts_filter_median.c b/drivers/input/touchscreen/ts_filter_median.c
index fe1b35f110b..47970da3c6a 100644
--- a/drivers/input/touchscreen/ts_filter_median.c
+++ b/drivers/input/touchscreen/ts_filter_median.c
@@ -119,9 +119,6 @@ static void ts_filter_median_destroy(struct ts_filter *tsf)
{
struct ts_filter_median *tsfm = (struct ts_filter_median *)tsf;
- if (tsf->next) /* chain */
- (tsf->next->api->destroy)(tsf->next);
-
kfree(tsfm->sort[0]); /* first guy has pointer from kmalloc */
kfree(tsf);
}