From a9bce1b03c2199e66d36cda8aac675338bc074a7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:13:47 +0200 Subject: mfd: input: iio: ti_am335x_adc: use one structure for ti_tscadc_dev The mfd driver creates platform data for the child devices and it is the ti_tscadc_dev struct. This struct is copied for the two devices. The copy of the structure makes a common lock in this structure a little less usefull. Therefore the platform data is not a pointer to the structure and the same structure is used. While doing the change I noticed that the suspend/resume code assumes the wrong pointer for ti_tscadc_dev and this has been fixed as well. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 51e7b87827a4..16077d3d80ba 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -262,7 +262,7 @@ static int titsc_probe(struct platform_device *pdev) { struct titsc *ts_dev; struct input_dev *input_dev; - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); struct mfd_tscadc_board *pdata; int err; @@ -329,8 +329,8 @@ err_free_mem: static int titsc_remove(struct platform_device *pdev) { - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = platform_get_drvdata(pdev); + u32 steps; free_irq(ts_dev->irq, ts_dev); @@ -344,10 +344,11 @@ static int titsc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int titsc_suspend(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc_dev; unsigned int idle; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (device_may_wakeup(tscadc_dev->dev)) { idle = titsc_readl(ts_dev, REG_IRQENABLE); titsc_writel(ts_dev, REG_IRQENABLE, @@ -359,9 +360,10 @@ static int titsc_suspend(struct device *dev) static int titsc_resume(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc_dev; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (device_may_wakeup(tscadc_dev->dev)) { titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); -- cgit v1.2.3-59-g8ed1b From abeccee40320245a2a6a006dc8466a703cbd1d5e Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:05 +0000 Subject: input: ti_am33x_tsc: Step enable bits made configurable Current code has hard coded value written to step enable bits. Now the bits are updated based on how many steps are needed to be configured got from platform data. The user needs to take care not to exceed the count more than 16. While using ADC and TSC one should take care to set this parameter correctly. Sebastian added the common lock and moved the code, that manipulates the steps, from into the mfd module. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 20 ++++++++++++++++++-- drivers/input/touchscreen/ti_am335x_tsc.c | 12 ++++++++++-- drivers/mfd/ti_am335x_tscadc.c | 29 ++++++++++++++++++++++++++++- include/linux/mfd/ti_am335x_tscadc.h | 8 ++++++-- 4 files changed, 62 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 9db352e413e4..543b9c42ac5f 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -42,10 +42,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg, writel(val, adc->mfd_tscadc->tscadc_base + reg); } +static u32 get_adc_step_mask(struct tiadc_device *adc_dev) +{ + u32 step_en; + + step_en = ((1 << adc_dev->channels) - 1); + step_en <<= TOTAL_STEPS - adc_dev->channels + 1; + return step_en; +} + static void tiadc_step_config(struct tiadc_device *adc_dev) { unsigned int stepconfig; int i, channels = 0, steps; + u32 step_en; /* * There are 16 configurable steps and 8 analog input @@ -69,7 +79,8 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) STEPCONFIG_OPENDLY); channels++; } - tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); } static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) @@ -127,7 +138,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, if (i == chan->channel) *val = readx1 & 0xfff; } - tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB); + am335x_tsc_se_update(adc_dev->mfd_tscadc); return IIO_VAL_INT; } @@ -191,10 +202,15 @@ err_ret: static int tiadc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct tiadc_device *adc_dev = iio_priv(indio_dev); + u32 step_en; iio_device_unregister(indio_dev); tiadc_channels_remove(indio_dev); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); + iio_device_free(indio_dev); return 0; diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 16077d3d80ba..23d6a4dacc88 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -57,6 +57,7 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; + unsigned int stepenable = 0; int i, total_steps; /* Configure the Step registers */ @@ -128,7 +129,9 @@ static void titsc_step_config(struct titsc *ts_dev) titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), STEPCONFIG_OPENDLY); - titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + /* The steps1 … end and bit 0 for TS_Charge */ + stepenable = (1 << (total_steps + 2)) - 1; + am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); } static void titsc_read_coordinates(struct titsc *ts_dev, @@ -250,7 +253,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); - titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + am335x_tsc_se_update(ts_dev->mfd_tscadc); return IRQ_HANDLED; } @@ -334,6 +337,11 @@ static int titsc_remove(struct platform_device *pdev) free_irq(ts_dev->irq, ts_dev); + /* total steps followed by the enable mask */ + steps = 2 * ts_dev->steps_to_configure + 2; + steps = (1 << steps) - 1; + am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); + input_unregister_device(ts_dev->input); platform_set_drvdata(pdev, NULL); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 772ea2adb539..90ccfc07e16b 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -48,6 +48,32 @@ static const struct regmap_config tscadc_regmap_config = { .val_bits = 32, }; +void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc) +{ + tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_update); + +void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock(&tsadc->reg_lock); + tsadc->reg_se_cache |= val; + spin_unlock(&tsadc->reg_lock); + + am335x_tsc_se_update(tsadc); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_set); + +void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock(&tsadc->reg_lock); + tsadc->reg_se_cache &= ~val; + spin_unlock(&tsadc->reg_lock); + + am335x_tsc_se_update(tsadc); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); + static void tscadc_idle_config(struct ti_tscadc_dev *config) { unsigned int idleconfig; @@ -129,6 +155,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) goto ret; } + spin_lock_init(&tscadc->reg_lock); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -239,7 +266,7 @@ static int tscadc_resume(struct device *dev) CNTRLREG_STEPID | CNTRLREG_4WIRE; tscadc_writel(tscadc_dev, REG_CTRL, ctrl); tscadc_idle_config(tscadc_dev); - tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB); + am335x_tsc_se_update(tscadc_dev); restore = tscadc_readl(tscadc_dev, REG_CTRL); tscadc_writel(tscadc_dev, REG_CTRL, (restore | CNTRLREG_TSCSSENB)); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 8114e4e8b91b..4258627d076a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -46,8 +46,6 @@ /* Step Enable */ #define STEPENB_MASK (0x1FFFF << 0) #define STEPENB(val) ((val) << 0) -#define STPENB_STEPENB STEPENB(0x1FFFF) -#define STPENB_STEPENB_TC STEPENB(0x1FFF) /* IRQ enable */ #define IRQENB_HW_PEN BIT(0) @@ -141,6 +139,8 @@ struct ti_tscadc_dev { void __iomem *tscadc_base; int irq; struct mfd_cell cells[TSCADC_CELLS]; + u32 reg_se_cache; + spinlock_t reg_lock; /* tsc device */ struct titsc *tsc; @@ -156,4 +156,8 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) return *tscadc_dev; } +void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc); +void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val); +void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val); + #endif -- cgit v1.2.3-59-g8ed1b From bb76dc09ddfc135c6c5e8eb7d3c583bfa8bdd439 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:06 +0000 Subject: input: ti_am33x_tsc: Order of TSC wires, made configurable The current driver expected touchscreen input wires(XP,XN,YP,YN) to be connected in a particular order. Making changes to accept this as platform data. Sebastian reworked the original patch and removed a lot of the not required pieces. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 102 +++++++++++++++++++++++++----- include/linux/input/ti_am335x_tsc.h | 12 ++++ include/linux/mfd/ti_am335x_tscadc.h | 3 - 3 files changed, 98 insertions(+), 19 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 23d6a4dacc88..2bdd66cd76a7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -33,6 +33,13 @@ #define SEQ_SETTLE 275 #define MAX_12BIT ((1 << 12) - 1) +static const int config_pins[] = { + STEPCONFIG_XPP, + STEPCONFIG_XNN, + STEPCONFIG_YPP, + STEPCONFIG_YNN, +}; + struct titsc { struct input_dev *input; struct ti_tscadc_dev *mfd_tscadc; @@ -41,6 +48,9 @@ struct titsc { unsigned int x_plate_resistance; bool pen_down; int steps_to_configure; + u32 config_inp[4]; + u32 bit_xp, bit_xn, bit_yp, bit_yn; + u32 inp_xp, inp_xn, inp_yp, inp_yn; }; static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) @@ -54,6 +64,58 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, writel(val, tsc->mfd_tscadc->tscadc_base + reg); } +static int titsc_config_wires(struct titsc *ts_dev) +{ + u32 analog_line[4]; + u32 wire_order[4]; + int i, bit_cfg; + + for (i = 0; i < 4; i++) { + /* + * Get the order in which TSC wires are attached + * w.r.t. each of the analog input lines on the EVM. + */ + analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4; + wire_order[i] = ts_dev->config_inp[i] & 0x0F; + if (WARN_ON(analog_line[i] > 7)) + return -EINVAL; + if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins))) + return -EINVAL; + } + + for (i = 0; i < 4; i++) { + int an_line; + int wi_order; + + an_line = analog_line[i]; + wi_order = wire_order[i]; + bit_cfg = config_pins[wi_order]; + if (bit_cfg == 0) + return -EINVAL; + switch (wi_order) { + case 0: + ts_dev->bit_xp = bit_cfg; + ts_dev->inp_xp = an_line; + break; + + case 1: + ts_dev->bit_xn = bit_cfg; + ts_dev->inp_xn = an_line; + break; + + case 2: + ts_dev->bit_yp = bit_cfg; + ts_dev->inp_yp = an_line; + break; + case 3: + ts_dev->bit_yn = bit_cfg; + ts_dev->inp_yn = an_line; + break; + } + } + return 0; +} + static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; @@ -64,18 +126,18 @@ static void titsc_step_config(struct titsc *ts_dev) total_steps = 2 * ts_dev->steps_to_configure; config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_XPP; + STEPCONFIG_AVG_16 | ts_dev->bit_xp; switch (ts_dev->wires) { case 4: - config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; break; case 5: - config |= STEPCONFIG_YNN | - STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | - STEPCONFIG_YPP; + config |= ts_dev->bit_yn | + STEPCONFIG_INP_AN4 | ts_dev->bit_xn | + ts_dev->bit_yp; break; case 8: - config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; break; } @@ -86,18 +148,18 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_YNN | + STEPCONFIG_AVG_16 | ts_dev->bit_yn | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; switch (ts_dev->wires) { case 4: - config |= STEPCONFIG_YPP; + config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); break; case 5: - config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | - STEPCONFIG_XNP | STEPCONFIG_YPN; + config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | + ts_dev->bit_xn | ts_dev->bit_yp; break; case 8: - config |= STEPCONFIG_YPP; + config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); break; } @@ -108,9 +170,9 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; /* Charge step configuration */ - config = STEPCONFIG_XPP | STEPCONFIG_YNN | + config = ts_dev->bit_xp | ts_dev->bit_yn | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | - STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; + STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp); titsc_writel(ts_dev, REG_CHARGECONFIG, config); titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); @@ -118,13 +180,14 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; /* Configure to calculate pressure */ config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_YPP | - STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; + STEPCONFIG_AVG_16 | ts_dev->bit_yp | + ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | + STEPCONFIG_INP(ts_dev->inp_xp); titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), STEPCONFIG_OPENDLY); - config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; + config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), STEPCONFIG_OPENDLY); @@ -292,6 +355,8 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->wires = pdata->tsc_init->wires; ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; + memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, + sizeof(pdata->tsc_init->wire_config)); err = request_irq(ts_dev->irq, titsc_irq, 0, pdev->dev.driver->name, ts_dev); @@ -301,6 +366,11 @@ static int titsc_probe(struct platform_device *pdev) } titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); + err = titsc_config_wires(ts_dev); + if (err) { + dev_err(&pdev->dev, "wrong i/p wire configuration\n"); + goto err_free_irq; + } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h index 49269a2aa329..6a66b4d1ac2c 100644 --- a/include/linux/input/ti_am335x_tsc.h +++ b/include/linux/input/ti_am335x_tsc.h @@ -12,12 +12,24 @@ * A step configured to read a single * co-ordinate value, can be applied * more number of times for better results. + * @wire_config: Different EVM's could have a different order + * for connecting wires on touchscreen. + * We need to provide an 8 bit number where in + * the 1st four bits represent the analog lines + * and the next 4 bits represent positive/ + * negative terminal on that input line. + * Notations to represent the input lines and + * terminals resoectively is as follows: + * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + * XP = 0, XN = 1, YP = 2, YN = 3. + * */ struct tsc_data { int wires; int x_plate_resistance; int steps_to_configure; + int wire_config[10]; }; #endif diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 4258627d076a..e36ae4184917 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -71,8 +71,6 @@ #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8) #define STEPCONFIG_INP_MASK (0xF << 19) #define STEPCONFIG_INP(val) ((val) << 19) -#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2) -#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3) #define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4) #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8) #define STEPCONFIG_FIFO1 BIT(26) @@ -94,7 +92,6 @@ #define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1) #define STEPCHARGE_INP_MASK (0xF << 19) #define STEPCHARGE_INP(val) ((val) << 19) -#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1) #define STEPCHARGE_RFM_MASK (3 << 23) #define STEPCHARGE_RFM(val) ((val) << 23) #define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1) -- cgit v1.2.3-59-g8ed1b From af9c2fe3740fe8dac05eede8805d9aaa45972cb6 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:07 +0000 Subject: input: ti_am33x_tsc: remove unwanted fifo flush When touchscreen and ADC are used together, this unwanted fifo flush leads to loss of ADC data. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 2bdd66cd76a7..7b7de6035af7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -252,8 +252,6 @@ static irqreturn_t titsc_irq(int irq, void *dev) unsigned int x = 0, y = 0; unsigned int z1, z2, z; unsigned int fsm; - unsigned int fifo1count, fifo0count; - int i; status = titsc_readl(ts_dev, REG_IRQSTATUS); if (status & IRQENB_FIFO0THRES) { @@ -262,14 +260,6 @@ static irqreturn_t titsc_irq(int irq, void *dev) z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; - fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); - for (i = 0; i < fifo1count; i++) - titsc_readl(ts_dev, REG_FIFO1); - - fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); - for (i = 0; i < fifo0count; i++) - titsc_readl(ts_dev, REG_FIFO0); - if (ts_dev->pen_down && z1 != 0 && z2 != 0) { /* * Calculate pressure using formula -- cgit v1.2.3-59-g8ed1b From 0396310b0eba71595c1151ce7c8fde7a9f33f719 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:10 +0000 Subject: input: ti_am33x_tsc: Add DT support This patch adds DT support to touch driver. It also provides a binding document which is used by the MFD and IIO part of the device. This patch also renames steps_to_configure to coordinate_readouts because the original name misleads the purpose of the variable. Signed-off-by: Pantelis Antoniou Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- .../bindings/input/touchscreen/ti-tsc-adc.txt | 44 +++++++++ drivers/input/touchscreen/ti_am335x_tsc.c | 105 ++++++++++++++++----- drivers/mfd/ti_am335x_tscadc.c | 1 + 3 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt new file mode 100644 index 000000000000..491c97b78384 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt @@ -0,0 +1,44 @@ +* TI - TSC ADC (Touschscreen and analog digital converter) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Required properties: +- child "tsc" + ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen + support on the platform. + ti,x-plate-resistance: X plate resistance + ti,coordiante-readouts: The sequencer supports a total of 16 + programmable steps each step is used to + read a single coordinate. A single + readout is enough but multiple reads can + increase the quality. + A value of 5 means, 5 reads for X, 5 for + Y and 2 for Z (always). This utilises 12 + of the 16 software steps available. The + remaining 4 can be used by the ADC. + ti,wire-config: Different boards could have a different order for + connecting wires on touchscreen. We need to provide an + 8 bit number where in the 1st four bits represent the + analog lines and the next 4 bits represent positive/ + negative terminal on that input line. Notations to + represent the input lines and terminals resoectively + is as follows: + AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + XP = 0, XN = 1, YP = 2, YN = 3. +- child "adc" + ti,adc-channels: List of analog inputs available for ADC. + AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + +Example: + tscadc: tscadc@44e0d000 { + compatible = "ti,am3359-tscadc"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordiante-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + }; + + adc { + ti,adc-channels = <4 5 6 7>; + }; + } diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 7b7de6035af7..449c0fbbe1d6 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include @@ -47,7 +49,7 @@ struct titsc { unsigned int wires; unsigned int x_plate_resistance; bool pen_down; - int steps_to_configure; + int coordinate_readouts; u32 config_inp[4]; u32 bit_xp, bit_xn, bit_yp, bit_yn; u32 inp_xp, inp_xn, inp_yp, inp_yn; @@ -123,7 +125,7 @@ static void titsc_step_config(struct titsc *ts_dev) int i, total_steps; /* Configure the Step registers */ - total_steps = 2 * ts_dev->steps_to_configure; + total_steps = 2 * ts_dev->coordinate_readouts; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_xp; @@ -141,7 +143,7 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = 1; i <= ts_dev->steps_to_configure; i++) { + for (i = 1; i <= ts_dev->coordinate_readouts; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -163,7 +165,7 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { + for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -218,7 +220,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev, read = titsc_readl(ts_dev, REG_FIFO0); channel = read & 0xf0000; channel = channel >> 0x10; - if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { + if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) { read &= 0xfff; diff = abs(read - prev_val_x); if (diff < prev_diff_x) { @@ -231,8 +233,8 @@ static void titsc_read_coordinates(struct titsc *ts_dev, read = titsc_readl(ts_dev, REG_FIFO1); channel = read & 0xf0000; channel = channel >> 0x10; - if ((channel >= ts_dev->steps_to_configure) && - (channel < (2 * ts_dev->steps_to_configure - 1))) { + if ((channel >= ts_dev->coordinate_readouts) && + (channel < (2 * ts_dev->coordinate_readouts - 1))) { read &= 0xfff; diff = abs(read - prev_val_y); if (diff < prev_diff_y) { @@ -310,6 +312,59 @@ static irqreturn_t titsc_irq(int irq, void *dev) return IRQ_HANDLED; } +static int titsc_parse_dt(struct platform_device *pdev, + struct titsc *ts_dev) +{ + struct device_node *node = pdev->dev.of_node; + int err; + + if (!node) + return -EINVAL; + + err = of_property_read_u32(node, "ti,wires", &ts_dev->wires); + if (err < 0) + return err; + switch (ts_dev->wires) { + case 4: + case 5: + case 8: + break; + default: + return -EINVAL; + } + + err = of_property_read_u32(node, "ti,x-plate-resistance", + &ts_dev->x_plate_resistance); + if (err < 0) + return err; + + err = of_property_read_u32(node, "ti,coordiante-readouts", + &ts_dev->coordinate_readouts); + if (err < 0) + return err; + + return of_property_read_u32_array(node, "ti,wire-config", + ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp)); +} + +static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev, + struct titsc *ts_dev) +{ + struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data; + + if (!pdata) + return -EINVAL; + + ts_dev->wires = pdata->tsc_init->wires; + ts_dev->x_plate_resistance = + pdata->tsc_init->x_plate_resistance; + ts_dev->steps_to_configure = + pdata->tsc_init->steps_to_configure; + memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, + sizeof(pdata->tsc_init->wire_config)); + return 0; +} + /* * The functions for inserting/removing driver as a module. */ @@ -319,16 +374,8 @@ static int titsc_probe(struct platform_device *pdev) struct titsc *ts_dev; struct input_dev *input_dev; struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); - struct mfd_tscadc_board *pdata; int err; - pdata = tscadc_dev->dev->platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "Could not find platform data\n"); - return -EINVAL; - } - /* Allocate memory for device */ ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); input_dev = input_allocate_device(); @@ -342,11 +389,16 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->mfd_tscadc = tscadc_dev; ts_dev->input = input_dev; ts_dev->irq = tscadc_dev->irq; - ts_dev->wires = pdata->tsc_init->wires; - ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; - ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; - memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, - sizeof(pdata->tsc_init->wire_config)); + + if (tscadc_dev->dev->platform_data) + err = titsc_parse_pdata(tscadc_dev, ts_dev); + else + err = titsc_parse_dt(pdev, ts_dev); + + if (err) { + dev_err(&pdev->dev, "Could not find valid DT data.\n"); + goto err_free_mem; + } err = request_irq(ts_dev->irq, titsc_irq, 0, pdev->dev.driver->name, ts_dev); @@ -362,7 +414,7 @@ static int titsc_probe(struct platform_device *pdev) goto err_free_irq; } titsc_step_config(ts_dev); - titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); + titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts); input_dev->name = "ti-tsc"; input_dev->dev.parent = &pdev->dev; @@ -398,7 +450,7 @@ static int titsc_remove(struct platform_device *pdev) free_irq(ts_dev->irq, ts_dev); /* total steps followed by the enable mask */ - steps = 2 * ts_dev->steps_to_configure + 2; + steps = 2 * ts_dev->coordinate_readouts + 2; steps = (1 << steps) - 1; am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); @@ -439,7 +491,7 @@ static int titsc_resume(struct device *dev) } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, - ts_dev->steps_to_configure); + ts_dev->coordinate_readouts); return 0; } @@ -452,6 +504,12 @@ static const struct dev_pm_ops titsc_pm_ops = { #define TITSC_PM_OPS NULL #endif +static const struct of_device_id ti_tsc_dt_ids[] = { + { .compatible = "ti,am3359-tsc", }, + { } +}; +MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids); + static struct platform_driver ti_tsc_driver = { .probe = titsc_probe, .remove = titsc_remove, @@ -459,6 +517,7 @@ static struct platform_driver ti_tsc_driver = { .name = "tsc", .owner = THIS_MODULE, .pm = TITSC_PM_OPS, + .of_match_table = of_match_ptr(ti_tsc_dt_ids), }, }; module_platform_driver(ti_tsc_driver); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 90ccfc07e16b..f50976623a01 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -203,6 +203,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSC Cell */ cell = &tscadc->cells[TSC_CELL]; cell->name = "tsc"; + cell->of_compatible = "ti,am3359-tsc"; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); -- cgit v1.2.3-59-g8ed1b From b9194fdfa6e729b97ffc59ae00dc9d51c7ae314d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 21 May 2013 17:39:13 +0200 Subject: input: ti_am33x_tsc: remove platform_data support This patch removes access to platform data mfd_tscadc_board because the platform is DT only. Acked-by: Dmitry Torokhov Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 449c0fbbe1d6..a1db55d1a862 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -347,24 +346,6 @@ static int titsc_parse_dt(struct platform_device *pdev, ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp)); } -static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev, - struct titsc *ts_dev) -{ - struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data; - - if (!pdata) - return -EINVAL; - - ts_dev->wires = pdata->tsc_init->wires; - ts_dev->x_plate_resistance = - pdata->tsc_init->x_plate_resistance; - ts_dev->steps_to_configure = - pdata->tsc_init->steps_to_configure; - memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, - sizeof(pdata->tsc_init->wire_config)); - return 0; -} - /* * The functions for inserting/removing driver as a module. */ @@ -390,11 +371,7 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->input = input_dev; ts_dev->irq = tscadc_dev->irq; - if (tscadc_dev->dev->platform_data) - err = titsc_parse_pdata(tscadc_dev, ts_dev); - else - err = titsc_parse_dt(pdev, ts_dev); - + err = titsc_parse_dt(pdev, ts_dev); if (err) { dev_err(&pdev->dev, "Could not find valid DT data.\n"); goto err_free_mem; -- cgit v1.2.3-59-g8ed1b From 5f184e63c61f92ab499273e682bb8898e88209a8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 27 May 2013 17:08:28 +0200 Subject: mfd: input: ti_am335x_tsc: rename device from tsc to TI-am335x-tsc tsc is a very generic name. This patch adds a TI and HW prefix to it less generic. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 2 +- drivers/mfd/ti_am335x_tscadc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index a1db55d1a862..ff3215ddf9f5 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -491,7 +491,7 @@ static struct platform_driver ti_tsc_driver = { .probe = titsc_probe, .remove = titsc_remove, .driver = { - .name = "tsc", + .name = "TI-am335x-tsc", .owner = THIS_MODULE, .pm = TITSC_PM_OPS, .of_match_table = of_match_ptr(ti_tsc_dt_ids), diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index d05fcba6f13a..5fb8b1dace8e 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -213,7 +213,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (tsc_wires > 0) { tscadc->tsc_cell = tscadc->used_cells; cell = &tscadc->cells[tscadc->used_cells++]; - cell->name = "tsc"; + cell->name = "TI-am335x-tsc"; cell->of_compatible = "ti,am3359-tsc"; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); -- cgit v1.2.3-59-g8ed1b From 8c896308feae7fb2e8da4ae4c09fe2d2ca18ad7b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 29 May 2013 14:46:21 +0200 Subject: input: ti_am335x_adc: use only FIFO0 and clean up a little The driver programs a threshold of "coordinate_readouts" say 5. The REG_FIFO0THR registers says it should it be programmed to "threshold minus one". The driver does not expect just 5 coordinates but 5 * 2 + 2. Multiplied by two because 5 for X and 5 for Y and plus 2 because we have two Z. The whole thing kind of works because It reads the 5 coordinates for X and Y from FIFO0 and FIFO1 and the last element in each FIFO is ignored within the loop and read later. Nothing guaranties that FIFO1 is ready by the time it is read. In fact I could see that that FIFO1 reaturns for Y channels 8,9, 10, 12, 6 and for Y channel 7 for Z. The problem is that channel 7 and channel 12 got somehow mixed up. The other Problem is that FIFO1 is also used by the IIO part leading to wrong results if both (tsc & adc) are used. The patch tries to clean up the whole thing a little: - Remove the +1 and -1 in REG_STEPCONFIG, REG_STEPDELAY and its counter part in the for loop. This is just confusing. - Use only FIFO0 in TSC. The fifo has space for 64 entries so should be fine. - Read the whole FIFO in one function and check the channel. - in case we dawdle around, make sure we only read a multiple of our coordinate set. On the second interrupt we will cleanup the remaining enties. Acked-by: Dmitry Torokhov Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 2 +- drivers/input/touchscreen/ti_am335x_tsc.c | 78 ++++++++++++++++--------------- include/linux/mfd/ti_am335x_tscadc.h | 4 +- 3 files changed, 44 insertions(+), 40 deletions(-) (limited to 'drivers/input') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 4bec91e40bf7..307a7c07be47 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -75,7 +75,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; - for (i = (steps + 1); i <= TOTAL_STEPS; i++) { + for (i = steps; i < TOTAL_STEPS; i++) { tiadc_writel(adc_dev, REG_STEPCONFIG(i), stepconfig | STEPCONFIG_INP(channels)); tiadc_writel(adc_dev, REG_STEPDELAY(i), diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index ff3215ddf9f5..1bceb2591fc7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -120,11 +120,9 @@ static int titsc_config_wires(struct titsc *ts_dev) static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; - unsigned int stepenable = 0; - int i, total_steps; - - /* Configure the Step registers */ - total_steps = 2 * ts_dev->coordinate_readouts; + int i; + int end_step; + u32 stepenable; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_xp; @@ -142,7 +140,9 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = 1; i <= ts_dev->coordinate_readouts; i++) { + /* 1 … coordinate_readouts is for X */ + end_step = ts_dev->coordinate_readouts; + for (i = 0; i < end_step; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -150,7 +150,7 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_yn | - STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; + STEPCONFIG_INM_ADCREFM; switch (ts_dev->wires) { case 4: config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); @@ -164,12 +164,13 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) { + /* coordinate_readouts … coordinate_readouts * 2 is for Y */ + end_step = ts_dev->coordinate_readouts * 2; + for (i = ts_dev->coordinate_readouts; i < end_step; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } - config = 0; /* Charge step configuration */ config = ts_dev->bit_xp | ts_dev->bit_yn | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | @@ -178,35 +179,39 @@ static void titsc_step_config(struct titsc *ts_dev) titsc_writel(ts_dev, REG_CHARGECONFIG, config); titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); - config = 0; - /* Configure to calculate pressure */ + /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */ config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_yp | ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP(ts_dev->inp_xp); - titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); - titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), STEPCONFIG_OPENDLY); - config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; - titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); - titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), + end_step++; + config |= STEPCONFIG_INP(ts_dev->inp_yn); + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), STEPCONFIG_OPENDLY); /* The steps1 … end and bit 0 for TS_Charge */ - stepenable = (1 << (total_steps + 2)) - 1; + stepenable = (1 << (end_step + 2)) - 1; am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); } static void titsc_read_coordinates(struct titsc *ts_dev, - unsigned int *x, unsigned int *y) + u32 *x, u32 *y, u32 *z1, u32 *z2) { unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); unsigned int prev_val_x = ~0, prev_val_y = ~0; unsigned int prev_diff_x = ~0, prev_diff_y = ~0; unsigned int read, diff; unsigned int i, channel; + unsigned int creads = ts_dev->coordinate_readouts; + *z1 = *z2 = 0; + if (fifocount % (creads * 2 + 2)) + fifocount -= fifocount % (creads * 2 + 2); /* * Delta filter is used to remove large variations in sampled * values from ADC. The filter tries to predict where the next @@ -215,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev, * algorithm compares the difference with that of a present value, * if true the value is reported to the sub system. */ - for (i = 0; i < fifocount - 1; i++) { + for (i = 0; i < fifocount; i++) { read = titsc_readl(ts_dev, REG_FIFO0); - channel = read & 0xf0000; - channel = channel >> 0x10; - if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) { - read &= 0xfff; + + channel = (read & 0xf0000) >> 16; + read &= 0xfff; + if (channel < creads) { diff = abs(read - prev_val_x); if (diff < prev_diff_x) { prev_diff_x = diff; *x = read; } prev_val_x = read; - } - read = titsc_readl(ts_dev, REG_FIFO1); - channel = read & 0xf0000; - channel = channel >> 0x10; - if ((channel >= ts_dev->coordinate_readouts) && - (channel < (2 * ts_dev->coordinate_readouts - 1))) { - read &= 0xfff; + } else if (channel < creads * 2) { diff = abs(read - prev_val_y); if (diff < prev_diff_y) { prev_diff_y = diff; *y = read; } prev_val_y = read; + + } else if (channel < creads * 2 + 1) { + *z1 = read; + + } else if (channel < creads * 2 + 2) { + *z2 = read; } } } @@ -256,10 +261,8 @@ static irqreturn_t titsc_irq(int irq, void *dev) status = titsc_readl(ts_dev, REG_IRQSTATUS); if (status & IRQENB_FIFO0THRES) { - titsc_read_coordinates(ts_dev, &x, &y); - z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; - z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; + titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2); if (ts_dev->pen_down && z1 != 0 && z2 != 0) { /* @@ -267,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev) * Resistance(touch) = x plate resistance * * x postion/4096 * ((z2 / z1) - 1) */ - z = z2 - z1; + z = z1 - z2; z *= x; z *= ts_dev->x_plate_resistance; - z /= z1; + z /= z2; z = (z + 2047) >> 12; if (z <= MAX_12BIT) { @@ -391,7 +394,8 @@ static int titsc_probe(struct platform_device *pdev) goto err_free_irq; } titsc_step_config(ts_dev); - titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts); + titsc_writel(ts_dev, REG_FIFO0THR, + ts_dev->coordinate_readouts * 2 + 2 - 1); input_dev->name = "ti-tsc"; input_dev->dev.parent = &pdev->dev; @@ -468,7 +472,7 @@ static int titsc_resume(struct device *dev) } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, - ts_dev->coordinate_readouts); + ts_dev->coordinate_readouts * 2 + 2 - 1); return 0; } diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 533f200e6d0e..8d73fe29796a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -30,8 +30,8 @@ #define REG_IDLECONFIG 0x058 #define REG_CHARGECONFIG 0x05C #define REG_CHARGEDELAY 0x060 -#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) -#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) +#define REG_STEPCONFIG(n) (0x64 + ((n) * 8)) +#define REG_STEPDELAY(n) (0x68 + ((n) * 8)) #define REG_FIFO0CNT 0xE4 #define REG_FIFO0THR 0xE8 #define REG_FIFO1CNT 0xF0 -- cgit v1.2.3-59-g8ed1b From 00789e5deb0af08826bd0c602d21baa9016b54b5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:23:18 +0200 Subject: input: ti_am335x_tsc: ACK the HW_PEN irq in ISR The interrupt source IRQENB_HW_PEN is enabled in suspend and suposed to be used as a wake up source. Once this interrupt source is unmaksed, the devices ends up in ISR and never continues. This change ACKs the interrupt and disables it so the system does not freeze. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 1bceb2591fc7..2ba77039ab91 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -308,6 +308,12 @@ static irqreturn_t titsc_irq(int irq, void *dev) irqclr |= IRQENB_PENUP; } + if (status & IRQENB_HW_PEN) { + + titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); + titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); + } + titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); am335x_tsc_se_update(ts_dev->mfd_tscadc); -- cgit v1.2.3-59-g8ed1b From 9a28b8834c55f7315fb1a7c487f836472fd37bf9 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:30:00 +0200 Subject: input: ti_am335x_tsc: return IRQ_NONE if there was no IRQ for us The previous patch ("input/ti_am335x_tsc: ACK the HW_PEN irq in ISR") acked the interrupt so we don't freeze if we don't handle an enabled interrupt source. The interrupt core has a mechanism for this and to get it work one should only say that it handled an interrupt if it is actually the case. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 2ba77039ab91..0e9f02aeae6b 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -314,10 +314,12 @@ static irqreturn_t titsc_irq(int irq, void *dev) titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); } - titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); - - am335x_tsc_se_update(ts_dev->mfd_tscadc); - return IRQ_HANDLED; + if (irqclr) { + titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); + am335x_tsc_se_update(ts_dev->mfd_tscadc); + return IRQ_HANDLED; + } + return IRQ_NONE; } static int titsc_parse_dt(struct platform_device *pdev, -- cgit v1.2.3-59-g8ed1b