diff options
Diffstat (limited to 'drivers/input/touchscreen/wm97xx-core.c')
| -rw-r--r-- | drivers/input/touchscreen/wm97xx-core.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index f944918466e..d0ef91fc87d 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -48,6 +48,7 @@ #include <linux/wm97xx.h> #include <linux/uaccess.h> #include <linux/io.h> +#include <linux/slab.h> #define TS_NAME "wm97xx" #define WM_CORE_VERSION "1.00" @@ -124,6 +125,8 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel) { int power_adc = 0, auxval; u16 power = 0; + int rc = 0; + int timeout = 0; /* get codec */ mutex_lock(&wm->codec_mutex); @@ -142,7 +145,9 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel) /* Turn polling mode on to read AUX ADC */ wm->pen_probably_down = 1; - wm->codec->poll_sample(wm, adcsel, &auxval); + + while (rc != RC_VALID && timeout++ < 5) + rc = wm->codec->poll_sample(wm, adcsel, &auxval); if (power_adc) wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000); @@ -151,8 +156,15 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel) wm->pen_probably_down = 0; + if (timeout >= 5) { + dev_err(wm->dev, + "timeout reading auxadc %d, disabling digitiser\n", + adcsel); + wm->codec->dig_enable(wm, false); + } + mutex_unlock(&wm->codec_mutex); - return auxval & 0xfff; + return (rc == RC_VALID ? auxval & 0xfff : -EBUSY); } EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc); @@ -199,7 +211,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, mutex_lock(&wm->codec_mutex); reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS); - if (status & WM97XX_GPIO_HIGH) + if (status == WM97XX_GPIO_HIGH) reg |= gpio; else reg &= ~gpio; @@ -323,7 +335,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) */ if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) { if (wm->pen_is_down && !pen_was_down) { - /* Data is not availiable immediately on pen down */ + /* Data is not available immediately on pen down */ queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1); } @@ -342,7 +354,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) * Codec PENDOWN irq handler * * We have to disable the codec interrupt in the handler because it - * can take upto 1ms to clear the interrupt source. We schedule a task + * can take up to 1ms to clear the interrupt source. We schedule a task * in a work queue to do the actual interaction with the chip. The * interrupt is then enabled again in the slow handler when the source * has been cleared. @@ -430,6 +442,16 @@ static int wm97xx_read_samples(struct wm97xx *wm) "pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n", data.x >> 12, data.x & 0xfff, data.y >> 12, data.y & 0xfff, data.p >> 12, data.p & 0xfff); + + if (abs_x[0] > (data.x & 0xfff) || + abs_x[1] < (data.x & 0xfff) || + abs_y[0] > (data.y & 0xfff) || + abs_y[1] < (data.y & 0xfff)) { + dev_dbg(wm->dev, "Measurement out of range, dropping it\n"); + rc = RC_AGAIN; + goto out; + } + input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff); @@ -443,6 +465,7 @@ static int wm97xx_read_samples(struct wm97xx *wm) wm->ts_reader_interval = wm->ts_reader_min_interval; } +out: mutex_unlock(&wm->codec_mutex); return rc; } @@ -561,7 +584,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev) static int wm97xx_probe(struct device *dev) { struct wm97xx *wm; - struct wm97xx_pdata *pdata = dev->platform_data; + struct wm97xx_pdata *pdata = dev_get_platdata(dev); int ret = 0, id = 0; wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL); @@ -683,8 +706,7 @@ static int wm97xx_probe(struct device *dev) touch_reg_err: platform_device_put(wm->touch_dev); touch_err: - platform_device_unregister(wm->battery_dev); - wm->battery_dev = NULL; + platform_device_del(wm->battery_dev); batt_reg_err: platform_device_put(wm->battery_dev); batt_err: |
