aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/files-2.6.31/drivers/input/touchscreen/ts_filter_group.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/files-2.6.31/drivers/input/touchscreen/ts_filter_group.c')
-rw-r--r--target/linux/s3c24xx/files-2.6.31/drivers/input/touchscreen/ts_filter_group.c296
1 files changed, 0 insertions, 296 deletions
diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/input/touchscreen/ts_filter_group.c b/target/linux/s3c24xx/files-2.6.31/drivers/input/touchscreen/ts_filter_group.c
deleted file mode 100644
index f53f16dafd..0000000000
--- a/target/linux/s3c24xx/files-2.6.31/drivers/input/touchscreen/ts_filter_group.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Copyright (C) 2008,2009 by Openmoko, Inc.
- * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
- * All rights reserved.
- *
- *
- * This filter is useful to reject samples that are not reliable. We consider
- * that a sample is not reliable if it deviates form the Majority.
- *
- * 1) We collect S samples.
- *
- * 2) For each dimension:
- *
- * - We sort the points.
- * - Points that are "close enough" are considered to be in the same set.
- * - We choose the set with more elements. If more than "threshold"
- * points are in this set we use the first and the last point of the set
- * to define the valid range for this dimension [min, max], otherwise we
- * discard all the points and go to step 1.
- *
- * 3) We consider the unsorted S samples and try to feed them to the next
- * filter in the chain. If one of the points of each sample
- * is not in the allowed range for its dimension, we discard the sample.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sort.h>
-#include <linux/touchscreen/ts_filter_group.h>
-
-struct ts_filter_group {
- /* Private filter configuration. */
- struct ts_filter_group_configuration *config;
- /* Filter API. */
- struct ts_filter tsf;
-
- int N; /* How many samples we have. */
- int *samples[MAX_TS_FILTER_COORDS]; /* The samples: our input. */
-
- int *group_size; /* Used for temporal computations. */
- int *sorted_samples; /* Used for temporal computations. */
-
- int range_max[MAX_TS_FILTER_COORDS]; /* Max. computed ranges. */
- int range_min[MAX_TS_FILTER_COORDS]; /* Min. computed ranges. */
-
- int tries_left; /* We finish if we don't get enough samples. */
- int ready; /* If we are ready to deliver samples. */
- int result; /* Index of the point being returned. */
-};
-
-#define ts_filter_to_filter_group(f) \
- container_of(f, struct ts_filter_group, tsf)
-
-
-static void ts_filter_group_clear_internal(struct ts_filter_group *tsfg,
- int attempts)
-{
- tsfg->N = 0;
- tsfg->tries_left = attempts;
- tsfg->ready = 0;
- tsfg->result = 0;
-}
-
-static void ts_filter_group_clear(struct ts_filter *tsf)
-{
- struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
-
- ts_filter_group_clear_internal(tsfg, tsfg->config->attempts);
-}
-
-static struct ts_filter *ts_filter_group_create(
- struct platform_device *pdev,
- const struct ts_filter_configuration *conf,
- int count_coords)
-{
- struct ts_filter_group *tsfg;
- int i;
-
- tsfg = kzalloc(sizeof(struct ts_filter_group), GFP_KERNEL);
- if (!tsfg)
- return NULL;
-
- tsfg->config = container_of(conf,
- struct ts_filter_group_configuration,
- config);
- tsfg->tsf.count_coords = count_coords;
-
- BUG_ON(tsfg->config->attempts <= 0);
-
- tsfg->samples[0] = kmalloc((2 + count_coords) * sizeof(int) *
- tsfg->config->length, GFP_KERNEL);
- if (!tsfg->samples[0]) {
- kfree(tsfg);
- return NULL;
- }
- for (i = 1; i < count_coords; ++i)
- tsfg->samples[i] = tsfg->samples[0] + i * tsfg->config->length;
- tsfg->sorted_samples = tsfg->samples[0] + count_coords *
- tsfg->config->length;
- tsfg->group_size = tsfg->samples[0] + (1 + count_coords) *
- tsfg->config->length;
-
- ts_filter_group_clear_internal(tsfg, tsfg->config->attempts);
-
- dev_info(&pdev->dev, "Created Group filter len:%d coords:%d close:%d "
- "thresh:%d\n", tsfg->config->length, count_coords,
- tsfg->config->close_enough, tsfg->config->threshold);
-
- return &tsfg->tsf;
-}
-
-static void ts_filter_group_destroy(struct ts_filter *tsf)
-{
- struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
-
- kfree(tsfg->samples[0]); /* first guy has pointer from kmalloc */
- kfree(tsf);
-}
-
-static int int_cmp(const void *_a, const void *_b)
-{
- const int *a = _a;
- const int *b = _b;
-
- if (*a > *b)
- return 1;
- if (*a < *b)
- return -1;
- return 0;
-}
-
-static void ts_filter_group_prepare_next(struct ts_filter *tsf);
-
-static int ts_filter_group_process(struct ts_filter *tsf, int *coords)
-{
- struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
- int n;
- int i;
-
- BUG_ON(tsfg->N >= tsfg->config->length);
- BUG_ON(tsfg->ready);
-
- for (n = 0; n < tsf->count_coords; n++)
- tsfg->samples[n][tsfg->N] = coords[n];
-
- if (++tsfg->N < tsfg->config->length)
- return 0; /* We need more samples. */
-
- for (n = 0; n < tsfg->tsf.count_coords; n++) {
- int *v = tsfg->sorted_samples;
- int ngroups = 0;
- int best_size;
- int best_idx = 0;
- int idx = 0;
-
- memcpy(v, tsfg->samples[n], tsfg->N * sizeof(int));
- /*
- * FIXME: Remove this sort call. We already have the
- * algorithm for this modification. The filter will
- * need less points (about half) if there is not a
- * lot of noise. Right now we are doing a constant
- * amount of work no matter how much noise we are
- * dealing with.
- */
- sort(v, tsfg->N, sizeof(int), int_cmp, NULL);
-
- tsfg->group_size[0] = 1;
- for (i = 1; i < tsfg->N; ++i) {
- if (v[i] - v[i - 1] <= tsfg->config->close_enough)
- tsfg->group_size[ngroups]++;
- else
- tsfg->group_size[++ngroups] = 1;
- }
- ngroups++;
-
- best_size = tsfg->group_size[0];
- for (i = 1; i < ngroups; i++) {
- idx += tsfg->group_size[i - 1];
- if (best_size < tsfg->group_size[i]) {
- best_size = tsfg->group_size[i];
- best_idx = idx;
- }
- }
-
- if (best_size < tsfg->config->threshold) {
- /* This set is not good enough for us. */
- if (--tsfg->tries_left) {
- ts_filter_group_clear_internal
- (tsfg, tsfg->tries_left);
- /* No errors but we need more samples. */
- return 0;
- }
- return 1; /* We give up: error. */
- }
-
- tsfg->range_min[n] = v[best_idx];
- tsfg->range_max[n] = v[best_idx + best_size - 1];
- }
-
- ts_filter_group_prepare_next(tsf);
-
- return 0;
-}
-
-/*
- * This private function prepares a point that will be returned
- * in ts_filter_group_getpoint if it is available. It updates
- * the priv->ready state also.
- */
-static void ts_filter_group_prepare_next(struct ts_filter *tsf)
-{
- struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
- int n;
-
- while (priv->result < priv->N) {
- for (n = 0; n < priv->tsf.count_coords; ++n) {
- if (priv->samples[n][priv->result] <
- priv->range_min[n] ||
- priv->samples[n][priv->result] > priv->range_max[n])
- break;
- }
-
- if (n == priv->tsf.count_coords) /* Sample is OK. */
- break;
-
- priv->result++;
- }
-
- if (unlikely(priv->result >= priv->N)) { /* No sample to deliver. */
- ts_filter_group_clear_internal(priv, priv->config->attempts);
- priv->ready = 0;
- } else {
- priv->ready = 1;
- }
-}
-
-static int ts_filter_group_haspoint(struct ts_filter *tsf)
-{
- struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
-
- return priv->ready;
-}
-
-static void ts_filter_group_getpoint(struct ts_filter *tsf, int *point)
-{
- struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
- int n;
-
- BUG_ON(!priv->ready);
-
- for (n = 0; n < priv->tsf.count_coords; n++)
- point[n] = priv->samples[n][priv->result];
-
- priv->result++;
-
- /* This call will update priv->ready. */
- ts_filter_group_prepare_next(tsf);
-}
-
-/*
- * Get ready to process the next batch of points, forget
- * points we could have delivered.
- */
-static void ts_filter_group_scale(struct ts_filter *tsf, int *coords)
-{
- struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
-
- ts_filter_group_clear_internal(priv, priv->config->attempts);
-}
-
-const struct ts_filter_api ts_filter_group_api = {
- .create = ts_filter_group_create,
- .destroy = ts_filter_group_destroy,
- .clear = ts_filter_group_clear,
- .process = ts_filter_group_process,
- .haspoint = ts_filter_group_haspoint,
- .getpoint = ts_filter_group_getpoint,
- .scale = ts_filter_group_scale,
-};
-EXPORT_SYMBOL_GPL(ts_filter_group_api);
-