From 39917c7cc0c971909a2023d5960bd7abbbb67e4b Mon Sep 17 00:00:00 2001 From: Justin Waters Date: Mon, 15 Sep 2008 16:48:31 -0400 Subject: 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 --- drivers/input/touchscreen/mxc_ts.c | 30 ++++-- drivers/mxc/pmic/mc13783/pmic_adc.c | 154 ++++++++++--------------------- drivers/mxc/pmic/mc13783/pmic_adc_defs.h | 20 +--- include/asm-arm/arch-mxc/pmic_adc.h | 9 -- 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 -- cgit v1.2.3