Commit 031bfed2 authored by Guy Shapiro's avatar Guy Shapiro Committed by Dmitry Torokhov

Input: imx6ul_tsc - add support for sample averaging

The i.MX6UL internal touchscreen controller contains an option to
average upon samples. This feature reduces noise from the produced
touch locations.

This patch adds sample averaging support to the imx6ul_tsc device
driver.
Signed-off-by: default avatarGuy Shapiro <guy.shapiro@mobi-wize.com>
Reviewed-by: default avatarFabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent ae3b4469
...@@ -17,6 +17,13 @@ Optional properties: ...@@ -17,6 +17,13 @@ Optional properties:
This value depends on the touch screen. This value depends on the touch screen.
- pre-charge-time: the touch screen need some time to precharge. - pre-charge-time: the touch screen need some time to precharge.
This value depends on the touch screen. This value depends on the touch screen.
- average-samples: Number of data samples which are averaged for each read.
Valid values 0-4
0 = 1 sample
1 = 4 samples
2 = 8 samples
3 = 16 samples
4 = 32 samples
Example: Example:
tsc: tsc@02040000 { tsc: tsc@02040000 {
...@@ -32,5 +39,6 @@ Example: ...@@ -32,5 +39,6 @@ Example:
xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
measure-delay-time = <0xfff>; measure-delay-time = <0xfff>;
pre-charge-time = <0xffff>; pre-charge-time = <0xffff>;
average-samples = <4>;
status = "okay"; status = "okay";
}; };
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
/* ADC configuration registers field define */ /* ADC configuration registers field define */
#define ADC_AIEN (0x1 << 7) #define ADC_AIEN (0x1 << 7)
#define ADC_CONV_DISABLE 0x1F #define ADC_CONV_DISABLE 0x1F
#define ADC_AVGE (0x1 << 5)
#define ADC_CAL (0x1 << 7) #define ADC_CAL (0x1 << 7)
#define ADC_CALF 0x2 #define ADC_CALF 0x2
#define ADC_12BIT_MODE (0x2 << 2) #define ADC_12BIT_MODE (0x2 << 2)
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
#define ADC_CLK_DIV_8 (0x03 << 5) #define ADC_CLK_DIV_8 (0x03 << 5)
#define ADC_SHORT_SAMPLE_MODE (0x0 << 4) #define ADC_SHORT_SAMPLE_MODE (0x0 << 4)
#define ADC_HARDWARE_TRIGGER (0x1 << 13) #define ADC_HARDWARE_TRIGGER (0x1 << 13)
#define ADC_AVGS_SHIFT 14
#define SELECT_CHANNEL_4 0x04 #define SELECT_CHANNEL_4 0x04
#define SELECT_CHANNEL_1 0x01 #define SELECT_CHANNEL_1 0x01
#define DISABLE_CONVERSION_INT (0x0 << 7) #define DISABLE_CONVERSION_INT (0x0 << 7)
...@@ -86,6 +88,7 @@ struct imx6ul_tsc { ...@@ -86,6 +88,7 @@ struct imx6ul_tsc {
int measure_delay_time; int measure_delay_time;
int pre_charge_time; int pre_charge_time;
int average_samples;
struct completion completion; struct completion completion;
}; };
...@@ -107,6 +110,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc) ...@@ -107,6 +110,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG); adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK; adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK;
adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE; adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
if (tsc->average_samples)
adc_cfg |= (tsc->average_samples - 1) << ADC_AVGS_SHIFT;
adc_cfg &= ~ADC_HARDWARE_TRIGGER; adc_cfg &= ~ADC_HARDWARE_TRIGGER;
writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG); writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
...@@ -118,6 +123,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc) ...@@ -118,6 +123,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
/* start ADC calibration */ /* start ADC calibration */
adc_gc = readl(tsc->adc_regs + REG_ADC_GC); adc_gc = readl(tsc->adc_regs + REG_ADC_GC);
adc_gc |= ADC_CAL; adc_gc |= ADC_CAL;
if (tsc->average_samples)
adc_gc |= ADC_AVGE;
writel(adc_gc, tsc->adc_regs + REG_ADC_GC); writel(adc_gc, tsc->adc_regs + REG_ADC_GC);
timeout = wait_for_completion_timeout timeout = wait_for_completion_timeout
...@@ -450,6 +457,17 @@ static int imx6ul_tsc_probe(struct platform_device *pdev) ...@@ -450,6 +457,17 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
if (err) if (err)
tsc->pre_charge_time = 0xfff; tsc->pre_charge_time = 0xfff;
err = of_property_read_u32(np, "average-samples",
&tsc->average_samples);
if (err)
tsc->average_samples = 0;
if (tsc->average_samples > 4) {
dev_err(&pdev->dev, "average-samples (%u) must be [0-4]\n",
tsc->average_samples);
return -EINVAL;
}
err = input_register_device(tsc->input); err = input_register_device(tsc->input);
if (err) { if (err) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment