summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Waters <justin.waters@timesys.com>2008-09-15 16:48:31 -0400
committerJustin Waters <justin.waters@timesys.com>2008-09-16 10:22:17 -0400
commit39917c7cc0c971909a2023d5960bd7abbbb67e4b (patch)
tree116df826e3b25b6810ce8839bfe532f688b2ba9a
parent7dfe8145a9788da7dd0fc055f4fe0b22511eb357 (diff)
Cleanup mxc touchscreen driver
The mxc touchscreen driver, based on the Freescale Atlas Chip and i.MX chips, is a mess. This is my attempt to clean it up quite a bit, and I think it's a definite improvement. There are still issues on large displays near the higher X coordinates, but I believe this is a hardware issue. Signed-off-by: Justin Waters <justin.waters@timesys.com>
-rw-r--r--drivers/input/touchscreen/mxc_ts.c30
-rw-r--r--drivers/mxc/pmic/mc13783/pmic_adc.c154
-rw-r--r--drivers/mxc/pmic/mc13783/pmic_adc_defs.h20
-rw-r--r--include/asm-arm/arch-mxc/pmic_adc.h9
4 files changed, 74 insertions, 139 deletions
diff --git a/drivers/input/touchscreen/mxc_ts.c b/drivers/input/touchscreen/mxc_ts.c
index b346c21eec99..dce4c8c63ccd 100644
--- a/drivers/input/touchscreen/mxc_ts.c
+++ b/drivers/input/touchscreen/mxc_ts.c
@@ -49,14 +49,16 @@ static int ts_thread(void *arg)
while (input_ts_installed) {
try_to_freeze();
memset(&ts_sample, 0, sizeof(t_touch_screen));
- pmic_adc_get_touch_sample(&ts_sample, !wait);
-
- input_report_abs(mxc_inputdev, ABS_X, ts_sample.x_position);
- input_report_abs(mxc_inputdev, ABS_Y, ts_sample.y_position);
- input_report_abs(mxc_inputdev, ABS_PRESSURE,
- ts_sample.contact_resistance);
- input_sync(mxc_inputdev);
-
+ if (pmic_adc_get_touch_sample(&ts_sample, !wait) ==
+ PMIC_SUCCESS) {
+ input_report_abs(mxc_inputdev, ABS_X,
+ ts_sample.x_position);
+ input_report_abs(mxc_inputdev, ABS_Y,
+ ts_sample.y_position);
+ input_report_abs(mxc_inputdev, ABS_PRESSURE,
+ ts_sample.contact_resistance);
+ input_sync(mxc_inputdev);
+ }
wait = ts_sample.contact_resistance;
msleep(20);
}
@@ -76,7 +78,17 @@ static int __init mxc_ts_init(void)
mxc_inputdev->name = MXC_TS_NAME;
mxc_inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
mxc_inputdev->keybit[BIT_WORD(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- mxc_inputdev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+ input_set_abs_params(mxc_inputdev, ABS_X,
+ 0,
+ (1<<12)-1,
+ 0, 0);
+ input_set_abs_params(mxc_inputdev, ABS_Y,
+ 0,
+ (1<<12)-1,
+ 0, 0);
+ input_set_abs_params(mxc_inputdev, ABS_PRESSURE,
+ 0, 1, 0, 0);
+
input_register_device(mxc_inputdev);
input_ts_installed = 1;
diff --git a/drivers/mxc/pmic/mc13783/pmic_adc.c b/drivers/mxc/pmic/mc13783/pmic_adc.c
index 5f72f0d43d2a..208087660831 100644
--- a/drivers/mxc/pmic/mc13783/pmic_adc.c
+++ b/drivers/mxc/pmic/mc13783/pmic_adc.c
@@ -231,169 +231,112 @@ static int pmic_adc_filter(t_touch_screen * ts_curr)
{
unsigned int ydiff1, ydiff2, ydiff3, xdiff1, xdiff2, xdiff3;
unsigned int sample_sumx, sample_sumy;
- static unsigned int prev_x[FILTLEN], prev_y[FILTLEN];
- int index = 0;
+ static unsigned int prev_x, prev_y;
unsigned int y_curr, x_curr;
static int filt_count = 0;
- /* Added a variable filt_type to decide filtering at run-time */
- unsigned int filt_type = 0;
+ /* Reset the filter when contact is removed */
if (ts_curr->contact_resistance == 0) {
ts_curr->x_position = 0;
ts_curr->y_position = 0;
filt_count = 0;
+ prev_x = 0;
+ prev_y = 0;
return 0;
}
- ydiff1 = abs(ts_curr->y_position1 - ts_curr->y_position2);
- ydiff2 = abs(ts_curr->y_position2 - ts_curr->y_position3);
- ydiff3 = abs(ts_curr->y_position1 - ts_curr->y_position3);
- if ((ydiff1 > DELTA_Y_MAX) ||
- (ydiff2 > DELTA_Y_MAX) || (ydiff3 > DELTA_Y_MAX)) {
- pr_debug("pmic_adc_filter: Ret pos 1\n");
- return -1;
- }
-
+ /* Compute the differences between the samples */
xdiff1 = abs(ts_curr->x_position1 - ts_curr->x_position2);
xdiff2 = abs(ts_curr->x_position2 - ts_curr->x_position3);
xdiff3 = abs(ts_curr->x_position1 - ts_curr->x_position3);
- if ((xdiff1 > DELTA_X_MAX) ||
- (xdiff2 > DELTA_X_MAX) || (xdiff3 > DELTA_X_MAX)) {
- pr_debug("mc13783_adc_filter: Ret pos 2\n");
- return -1;
- }
- /* Compute two closer values among the three available Y readouts */
+ ydiff1 = abs(ts_curr->y_position1 - ts_curr->y_position2);
+ ydiff2 = abs(ts_curr->y_position2 - ts_curr->y_position3);
+ ydiff3 = abs(ts_curr->y_position1 - ts_curr->y_position3);
+ /*
+ * Compute two closer values among the three available Y
+ * readouts and use the average as the sample
+ */
if (ydiff1 < ydiff2) {
if (ydiff1 < ydiff3) {
- // Sample 0 & 1 closest together
+ // Sample 1 & 2 closest together
sample_sumy = ts_curr->y_position1 +
ts_curr->y_position2;
} else {
- // Sample 0 & 2 closest together
+ // Sample 1 & 3 closest together
sample_sumy = ts_curr->y_position1 +
ts_curr->y_position3;
}
} else {
if (ydiff2 < ydiff3) {
- // Sample 1 & 2 closest together
+ // Sample 2 & 3 closest together
sample_sumy = ts_curr->y_position2 +
ts_curr->y_position3;
} else {
- // Sample 0 & 2 closest together
+ // Sample 1 & 3 closest together
sample_sumy = ts_curr->y_position1 +
ts_curr->y_position3;
}
}
+ sample_sumy /= 2;
/*
* Compute two closer values among the three available X
- * readouts
+ * readouts and use the average as the sample
*/
if (xdiff1 < xdiff2) {
if (xdiff1 < xdiff3) {
- // Sample 0 & 1 closest together
+ // Sample 1 & 2 closest together
sample_sumx = ts_curr->x_position1 +
ts_curr->x_position2;
} else {
- // Sample 0 & 2 closest together
+ // Sample 1 & 3 closest together
sample_sumx = ts_curr->x_position1 +
ts_curr->x_position3;
}
} else {
if (xdiff2 < xdiff3) {
- // Sample 1 & 2 closest together
+ // Sample 2 & 3 closest together
sample_sumx = ts_curr->x_position2 +
ts_curr->x_position3;
} else {
- // Sample 0 & 2 closest together
+ // Sample 1 & 3 closest together
sample_sumx = ts_curr->x_position1 +
ts_curr->x_position3;
}
}
+ sample_sumx /= 2;
+
/*
- * Wait FILTER_MIN_DELAY number of samples to restart
- * filtering
+ * Current output is a simple low pass filter
+ * based on previous and current value.
*/
- if (filt_count < FILTER_MIN_DELAY) {
- /*
- * Current output is the average of the two closer
- * values and no filtering is used
- */
- y_curr = (sample_sumy / 2);
- x_curr = (sample_sumx / 2);
- ts_curr->y_position = y_curr;
- ts_curr->x_position = x_curr;
- filt_count++;
- } else {
- if (abs(sample_sumx - (prev_x[0] + prev_x[1])) >
- (DELTA_X_MAX * 16)) {
- pr_debug("pmic_adc_filter: : Ret pos 3\n");
- return -1;
- }
- if (abs(sample_sumy - (prev_y[0] + prev_y[1])) >
- (DELTA_Y_MAX * 16)) {
- return -1;
- }
- sample_sumy /= 2;
- sample_sumx /= 2;
- /* Use hard filtering if the sample difference < 10 */
- if ((abs(sample_sumy - prev_y[0]) > 10) ||
- (abs(sample_sumx - prev_x[0]) > 10)) {
- filt_type = 1;
- }
+ /* Y Filter */
+ y_curr = ((sample_sumy * 90) + (prev_y * 10))/100;
+ ts_curr->y_position = y_curr;
- /*
- * Current outputs are the average of three previous
- * values and the present readout
- */
- y_curr = sample_sumy;
- for (index = 0; index < FILTLEN; index++) {
- if (filt_type == 0) {
- y_curr = y_curr + (prev_y[index]);
- } else {
- y_curr = y_curr + (prev_y[index] / 3);
- }
- }
- if (filt_type == 0) {
- y_curr = y_curr >> 2;
- } else {
- y_curr = y_curr >> 1;
- }
- ts_curr->y_position = y_curr;
-
- x_curr = sample_sumx;
- for (index = 0; index < FILTLEN; index++) {
- if (filt_type == 0) {
- x_curr = x_curr + (prev_x[index]);
- } else {
- x_curr = x_curr + (prev_x[index] / 3);
- }
- }
- if (filt_type == 0) {
- x_curr = x_curr >> 2;
- } else {
- x_curr = x_curr >> 1;
- }
- ts_curr->x_position = x_curr;
-
- }
-
- /* Update previous X and Y values */
- for (index = (FILTLEN - 1); index > 0; index--) {
- prev_x[index] = prev_x[index - 1];
- prev_y[index] = prev_y[index - 1];
- }
+ /* X Filter */
+ x_curr = ((sample_sumx * 90) + (prev_x * 10))/100;
+ ts_curr->x_position = x_curr;
/*
- * Current output will be the most recent past for the
- * next sample
+ * Store current sample for next evaluation
*/
- prev_y[0] = y_curr;
- prev_x[0] = x_curr;
+ prev_y = y_curr;
+ prev_x = x_curr;
- return 0;
+ /*
+ * Wait FILTER_MIN_DELAY number of samples to restart
+ * filtering. This is used to seed the filter until it
+ * has enough samples to be stable.
+ */
+ if (filt_count < FILTER_MIN_DELAY) {
+ filt_count++;
+ return -1;
+ } else {
+ return 0;
+ }
}
/*!
@@ -687,7 +630,6 @@ PMIC_STATUS mc13783_adc_convert(t_adc_param * adc_param)
adc_param->ts_value.y_position3 = adc_param->value[5];
adc_param->ts_value.y_position = adc_param->value[5];
adc_param->ts_value.contact_resistance = adc_param->value[6];
-
}
/*if (adc_param->read_ts) {
@@ -936,8 +878,8 @@ PMIC_STATUS pmic_adc_get_touch_mode(t_touch_mode * touch_mode)
PMIC_STATUS pmic_adc_get_touch_sample(t_touch_screen * touch_sample, int wait)
{
mc13783_adc_read_ts(touch_sample, wait);
- pmic_adc_filter(touch_sample);
- return PMIC_SUCCESS;
+
+ return pmic_adc_filter(touch_sample);
}
/*!
diff --git a/drivers/mxc/pmic/mc13783/pmic_adc_defs.h b/drivers/mxc/pmic/mc13783/pmic_adc_defs.h
index 5278814d9c0a..eca1c8b59448 100644
--- a/drivers/mxc/pmic/mc13783/pmic_adc_defs.h
+++ b/drivers/mxc/pmic/mc13783/pmic_adc_defs.h
@@ -30,24 +30,14 @@
#define MAX_CHANNEL 7
-/*
- * Maximun allowed variation in the three X/Y co-ordinates acquired from
- * touch-screen
- */
-#define DELTA_Y_MAX 50
-#define DELTA_X_MAX 50
-
/* Upon clearing the filter, this is the delay in restarting the filter */
-#define FILTER_MIN_DELAY 4
-
-/* Length of X and Y Touch screen filters */
-#define FILTLEN 3
+#define FILTER_MIN_DELAY 2
-#define TS_X_MAX 1000
-#define TS_Y_MAX 1000
+#define TS_X_MAX 1024
+#define TS_Y_MAX 1024
-#define TS_X_MIN 80
-#define TS_Y_MIN 80
+#define TS_X_MIN 2
+#define TS_Y_MIN 2
#define MC13783_ADC0_TS_M_LSH 14
#define MC13783_ADC0_TS_M_WID 3
diff --git a/include/asm-arm/arch-mxc/pmic_adc.h b/include/asm-arm/arch-mxc/pmic_adc.h
index 30573861785c..02c05cfa3d75 100644
--- a/include/asm-arm/arch-mxc/pmic_adc.h
+++ b/include/asm-arm/arch-mxc/pmic_adc.h
@@ -100,15 +100,6 @@
*/
#define TOUCH_SCREEN_READ_UNINSTALL _IOWR('D',5, int)
-/*! @{ */
-/*!
- * @name Touch Screen minimum and maximum values
- */
-#define TS_X_MIN 80 /*! < Minimum X */
-#define TS_Y_MIN 80 /*! < Minimum Y */
-
-#define TS_X_MAX 1000 /*! < Maximum X */
-#define TS_Y_MAX 1000 /*! < Maximum Y */
/*! @} */
/*!
* This enumeration defines input channels for PMIC ADC