aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/wm97xx-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/wm97xx-core.c')
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c38
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: