diff options
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/ad7877.c | 10 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/atmel-wm97xx.c | 12 | ||||
-rw-r--r-- | drivers/input/touchscreen/auo-pixcir-ts.c | 226 | ||||
-rw-r--r-- | drivers/input/touchscreen/edt-ft5x06.c | 3 | ||||
-rw-r--r-- | drivers/input/touchscreen/eeti_ts.c | 3 | ||||
-rw-r--r-- | drivers/input/touchscreen/mc13783_ts.c | 12 | ||||
-rw-r--r-- | drivers/input/touchscreen/st1232.c | 77 | ||||
-rw-r--r-- | drivers/input/touchscreen/wm9712.c | 28 | ||||
-rw-r--r-- | drivers/input/touchscreen/wm97xx-core.c | 11 |
10 files changed, 235 insertions, 151 deletions
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 23fa829b8..f3a174a 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -273,7 +273,7 @@ static int ad7877_write(struct spi_device *spi, u16 reg, u16 val) static int ad7877_read_adc(struct spi_device *spi, unsigned command) { - struct ad7877 *ts = dev_get_drvdata(&spi->dev); + struct ad7877 *ts = spi_get_drvdata(spi); struct ser_req *req; int status; int sample; @@ -720,7 +720,7 @@ static int ad7877_probe(struct spi_device *spi) goto err_free_mem; } - dev_set_drvdata(&spi->dev, ts); + spi_set_drvdata(spi, ts); ts->spi = spi; ts->input = input_dev; @@ -806,13 +806,13 @@ err_free_irq: err_free_mem: input_free_device(input_dev); kfree(ts); - dev_set_drvdata(&spi->dev, NULL); + spi_set_drvdata(spi, NULL); return err; } static int ad7877_remove(struct spi_device *spi) { - struct ad7877 *ts = dev_get_drvdata(&spi->dev); + struct ad7877 *ts = spi_get_drvdata(spi); sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); @@ -823,7 +823,7 @@ static int ad7877_remove(struct spi_device *spi) kfree(ts); dev_dbg(&spi->dev, "unregistered touchscreen\n"); - dev_set_drvdata(&spi->dev, NULL); + spi_set_drvdata(spi, NULL); return 0; } diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 434c3df..84ccf14 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1245,7 +1245,7 @@ static int ads7846_probe(struct spi_device *spi) goto err_free_mem; } - dev_set_drvdata(&spi->dev, ts); + spi_set_drvdata(spi, ts); ts->packet = packet; ts->spi = spi; @@ -1397,7 +1397,7 @@ static int ads7846_probe(struct spi_device *spi) static int ads7846_remove(struct spi_device *spi) { - struct ads7846 *ts = dev_get_drvdata(&spi->dev); + struct ads7846 *ts = spi_get_drvdata(spi); device_init_wakeup(&spi->dev, false); diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index c5c2dbb..2c1e46b 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c @@ -432,17 +432,7 @@ static struct platform_driver atmel_wm97xx_driver = { }, }; -static int __init atmel_wm97xx_init(void) -{ - return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe); -} -module_init(atmel_wm97xx_init); - -static void __exit atmel_wm97xx_exit(void) -{ - platform_driver_unregister(&atmel_wm97xx_driver); -} -module_exit(atmel_wm97xx_exit); +module_platform_driver_probe(atmel_wm97xx_driver, atmel_wm97xx_probe); MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32"); diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index c6e19a9..d3f9f6b 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -31,6 +31,8 @@ #include <linux/delay.h> #include <linux/gpio.h> #include <linux/input/auo-pixcir-ts.h> +#include <linux/of.h> +#include <linux/of_gpio.h> /* * Coordinate calculation: @@ -111,6 +113,7 @@ struct auo_pixcir_ts { struct i2c_client *client; struct input_dev *input; + const struct auo_pixcir_ts_platdata *pdata; char phys[32]; /* special handling for touch_indicate interupt mode */ @@ -132,7 +135,7 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, struct auo_point_t *point) { struct i2c_client *client = ts->client; - const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + const struct auo_pixcir_ts_platdata *pdata = ts->pdata; uint8_t raw_coord[8]; uint8_t raw_area[4]; int i, ret; @@ -178,8 +181,7 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) { struct auo_pixcir_ts *ts = dev_id; - struct i2c_client *client = ts->client; - const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + const struct auo_pixcir_ts_platdata *pdata = ts->pdata; struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; int i; int ret; @@ -290,7 +292,7 @@ static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, int int_setting) { struct i2c_client *client = ts->client; - struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + const struct auo_pixcir_ts_platdata *pdata = ts->pdata; int ret; ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); @@ -479,53 +481,105 @@ unlock: } #endif -static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend, - auo_pixcir_resume); +static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, + auo_pixcir_suspend, auo_pixcir_resume); + +#ifdef CONFIG_OF +static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev) +{ + struct auo_pixcir_ts_platdata *pdata; + struct device_node *np = dev->of_node; + + if (!np) + return ERR_PTR(-ENOENT); + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "failed to allocate platform data\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->gpio_int = of_get_gpio(np, 0); + if (!gpio_is_valid(pdata->gpio_int)) { + dev_err(dev, "failed to get interrupt gpio\n"); + return ERR_PTR(-EINVAL); + } + + pdata->gpio_rst = of_get_gpio(np, 1); + if (!gpio_is_valid(pdata->gpio_rst)) { + dev_err(dev, "failed to get reset gpio\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(np, "x-size", &pdata->x_max)) { + dev_err(dev, "failed to get x-size property\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(np, "y-size", &pdata->y_max)) { + dev_err(dev, "failed to get y-size property\n"); + return ERR_PTR(-EINVAL); + } + + /* default to asserting the interrupt when the screen is touched */ + pdata->int_setting = AUO_PIXCIR_INT_TOUCH_IND; + + return pdata; +} +#else +static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif + +static void auo_pixcir_reset(void *data) +{ + struct auo_pixcir_ts *ts = data; + + gpio_set_value(ts->pdata->gpio_rst, 0); +} static int auo_pixcir_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { - const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + const struct auo_pixcir_ts_platdata *pdata; struct auo_pixcir_ts *ts; struct input_dev *input_dev; - int ret; - - if (!pdata) - return -EINVAL; + int version; + int error; + + pdata = dev_get_platdata(&client->dev); + if (!pdata) { + pdata = auo_pixcir_parse_dt(&client->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } - ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL); + ts = devm_kzalloc(&client->dev, + sizeof(struct auo_pixcir_ts), GFP_KERNEL); if (!ts) return -ENOMEM; - ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int"); - if (ret) { - dev_err(&client->dev, "request of gpio %d failed, %d\n", - pdata->gpio_int, ret); - goto err_gpio_int; + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) { + dev_err(&client->dev, "could not allocate input device\n"); + return -ENOMEM; } - if (pdata->init_hw) - pdata->init_hw(client); - + ts->pdata = pdata; ts->client = client; + ts->input = input_dev; ts->touch_ind_mode = 0; + ts->stopped = true; init_waitqueue_head(&ts->wait); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); - input_dev = input_allocate_device(); - if (!input_dev) { - dev_err(&client->dev, "could not allocate input device\n"); - goto err_input_alloc; - } - - ts->input = input_dev; - input_dev->name = "AUO-Pixcir touchscreen"; input_dev->phys = ts->phys; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; input_dev->open = auo_pixcir_input_open; input_dev->close = auo_pixcir_input_close; @@ -550,70 +604,70 @@ static int auo_pixcir_probe(struct i2c_client *client, AUO_PIXCIR_MAX_AREA, 0, 0); input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); - ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); - if (ret < 0) - goto err_fw_vers; - dev_info(&client->dev, "firmware version 0x%X\n", ret); - - ret = auo_pixcir_int_config(ts, pdata->int_setting); - if (ret) - goto err_fw_vers; - input_set_drvdata(ts->input, ts); - ts->stopped = true; - ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - input_dev->name, ts); - if (ret) { - dev_err(&client->dev, "irq %d requested failed\n", client->irq); - goto err_fw_vers; + error = devm_gpio_request_one(&client->dev, pdata->gpio_int, + GPIOF_DIR_IN, "auo_pixcir_ts_int"); + if (error) { + dev_err(&client->dev, "request of gpio %d failed, %d\n", + pdata->gpio_int, error); + return error; } - /* stop device and put it into deep sleep until it is opened */ - ret = auo_pixcir_stop(ts); - if (ret < 0) - goto err_input_register; - - ret = input_register_device(input_dev); - if (ret) { - dev_err(&client->dev, "could not register input device\n"); - goto err_input_register; + error = devm_gpio_request_one(&client->dev, pdata->gpio_rst, + GPIOF_DIR_OUT | GPIOF_INIT_HIGH, + "auo_pixcir_ts_rst"); + if (error) { + dev_err(&client->dev, "request of gpio %d failed, %d\n", + pdata->gpio_rst, error); + return error; } - i2c_set_clientdata(client, ts); - - return 0; + error = devm_add_action(&client->dev, auo_pixcir_reset, ts); + if (error) { + auo_pixcir_reset(ts); + dev_err(&client->dev, "failed to register reset action, %d\n", + error); + return error; + } -err_input_register: - free_irq(client->irq, ts); -err_fw_vers: - input_free_device(input_dev); -err_input_alloc: - if (pdata->exit_hw) - pdata->exit_hw(client); - gpio_free(pdata->gpio_int); -err_gpio_int: - kfree(ts); + msleep(200); - return ret; -} - -static int auo_pixcir_remove(struct i2c_client *client) -{ - struct auo_pixcir_ts *ts = i2c_get_clientdata(client); - const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; + version = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); + if (version < 0) { + error = version; + return error; + } - free_irq(client->irq, ts); + dev_info(&client->dev, "firmware version 0x%X\n", version); - input_unregister_device(ts->input); + error = auo_pixcir_int_config(ts, pdata->int_setting); + if (error) + return error; - if (pdata->exit_hw) - pdata->exit_hw(client); + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, auo_pixcir_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + input_dev->name, ts); + if (error) { + dev_err(&client->dev, "irq %d requested failed, %d\n", + client->irq, error); + return error; + } - gpio_free(pdata->gpio_int); + /* stop device and put it into deep sleep until it is opened */ + error = auo_pixcir_stop(ts); + if (error) + return error; + + error = input_register_device(input_dev); + if (error) { + dev_err(&client->dev, "could not register input device, %d\n", + error); + return error; + } - kfree(ts); + i2c_set_clientdata(client, ts); return 0; } @@ -624,14 +678,22 @@ static const struct i2c_device_id auo_pixcir_idtable[] = { }; MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); +#ifdef CONFIG_OF +static struct of_device_id auo_pixcir_ts_dt_idtable[] = { + { .compatible = "auo,auo_pixcir_ts" }, + {}, +}; +MODULE_DEVICE_TABLE(of, auo_pixcir_ts_dt_idtable); +#endif + static struct i2c_driver auo_pixcir_driver = { .driver = { .owner = THIS_MODULE, .name = "auo_pixcir_ts", .pm = &auo_pixcir_pm_ops, + .of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable), }, .probe = auo_pixcir_probe, - .remove = auo_pixcir_remove, .id_table = auo_pixcir_idtable, }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index a917015..83fa1b1 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -440,8 +440,7 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) return -EIO; } - if (tsdata->raw_buffer) - kfree(tsdata->raw_buffer); + kfree(tsdata->raw_buffer); tsdata->raw_buffer = NULL; /* restore parameters */ diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 55255a9..8fe5086 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -206,8 +206,7 @@ static int eeti_ts_probe(struct i2c_client *client, if (err < 0) goto err1; - if (pdata) - priv->irq_active_high = pdata->irq_active_high; + priv->irq_active_high = pdata->irq_active_high; irq_flags = priv->irq_active_high ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index 02103b6..89308fe 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c @@ -250,17 +250,7 @@ static struct platform_driver mc13783_ts_driver = { }, }; -static int __init mc13783_ts_init(void) -{ - return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe); -} -module_init(mc13783_ts_init); - -static void __exit mc13783_ts_exit(void) -{ - platform_driver_unregister(&mc13783_ts_driver); -} -module_exit(mc13783_ts_exit); +module_platform_driver_probe(mc13783_ts_driver, mc13783_ts_probe); MODULE_DESCRIPTION("MC13783 input touchscreen driver"); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index d9d05e2..1740a24 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -19,13 +19,16 @@ */ #include <linux/delay.h> +#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/of_gpio.h> #include <linux/pm_qos.h> #include <linux/slab.h> #include <linux/types.h> +#include <linux/platform_data/st1232_pdata.h> #define ST1232_TS_NAME "st1232-ts" @@ -48,6 +51,7 @@ struct st1232_ts_data { struct input_dev *input_dev; struct st1232_ts_finger finger[MAX_FINGERS]; struct dev_pm_qos_request low_latency_req; + int reset_gpio; }; static int st1232_ts_read_data(struct st1232_ts_data *ts) @@ -139,10 +143,17 @@ end: return IRQ_HANDLED; } +static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron) +{ + if (gpio_is_valid(ts->reset_gpio)) + gpio_direction_output(ts->reset_gpio, poweron); +} + static int st1232_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct st1232_ts_data *ts; + struct st1232_pdata *pdata = client->dev.platform_data; struct input_dev *input_dev; int error; @@ -156,17 +167,36 @@ static int st1232_ts_probe(struct i2c_client *client, return -EINVAL; } + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; - ts = kzalloc(sizeof(struct st1232_ts_data), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - error = -ENOMEM; - goto err_free_mem; - } + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) + return -ENOMEM; ts->client = client; ts->input_dev = input_dev; + if (pdata) + ts->reset_gpio = pdata->reset_gpio; + else if (client->dev.of_node) + ts->reset_gpio = of_get_gpio(client->dev.of_node, 0); + else + ts->reset_gpio = -ENODEV; + + if (gpio_is_valid(ts->reset_gpio)) { + error = devm_gpio_request(&client->dev, ts->reset_gpio, NULL); + if (error) { + dev_err(&client->dev, + "Unable to request GPIO pin %d.\n", + ts->reset_gpio); + return error; + } + } + + st1232_ts_power(ts, true); + input_dev->name = "st1232-touchscreen"; input_dev->id.bustype = BUS_I2C; input_dev->dev.parent = &client->dev; @@ -179,31 +209,26 @@ static int st1232_ts_probe(struct i2c_client *client, input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0); - error = request_threaded_irq(client->irq, NULL, st1232_ts_irq_handler, - IRQF_ONESHOT, client->name, ts); + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, st1232_ts_irq_handler, + IRQF_ONESHOT, + client->name, ts); if (error) { dev_err(&client->dev, "Failed to register interrupt\n"); - goto err_free_mem; + return error; } error = input_register_device(ts->input_dev); if (error) { dev_err(&client->dev, "Unable to register %s input device\n", input_dev->name); - goto err_free_irq; + return error; } i2c_set_clientdata(client, ts); device_init_wakeup(&client->dev, 1); return 0; - -err_free_irq: - free_irq(client->irq, ts); -err_free_mem: - input_free_device(input_dev); - kfree(ts); - return error; } static int st1232_ts_remove(struct i2c_client *client) @@ -211,9 +236,7 @@ static int st1232_ts_remove(struct i2c_client *client) struct st1232_ts_data *ts = i2c_get_clientdata(client); device_init_wakeup(&client->dev, 0); - free_irq(client->irq, ts); - input_unregister_device(ts->input_dev); - kfree(ts); + st1232_ts_power(ts, false); return 0; } @@ -222,11 +245,14 @@ static int st1232_ts_remove(struct i2c_client *client) static int st1232_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + struct st1232_ts_data *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) + if (device_may_wakeup(&client->dev)) { enable_irq_wake(client->irq); - else + } else { disable_irq(client->irq); + st1232_ts_power(ts, false); + } return 0; } @@ -234,11 +260,14 @@ static int st1232_ts_suspend(struct device *dev) static int st1232_ts_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + struct st1232_ts_data *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) + if (device_may_wakeup(&client->dev)) { disable_irq_wake(client->irq); - else + } else { + st1232_ts_power(ts, true); enable_irq(client->irq); + } return 0; } diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 6e743e3..16b5211 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -162,14 +162,14 @@ static void wm9712_phy_init(struct wm97xx *wm) if (rpu) { dig2 &= 0xffc0; dig2 |= WM9712_RPU(rpu); - dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms", + dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms\n", 64000 / rpu); } /* WM9712 five wire */ if (five_wire) { dig2 |= WM9712_45W; - dev_dbg(wm->dev, "setting 5-wire touchscreen mode."); + dev_dbg(wm->dev, "setting 5-wire touchscreen mode.\n"); if (pil) { dev_warn(wm->dev, "pressure measurement is not " @@ -182,21 +182,21 @@ static void wm9712_phy_init(struct wm97xx *wm) if (pil == 2) { dig2 |= WM9712_PIL; dev_dbg(wm->dev, - "setting pressure measurement current to 400uA."); + "setting pressure measurement current to 400uA.\n"); } else if (pil) dev_dbg(wm->dev, - "setting pressure measurement current to 200uA."); + "setting pressure measurement current to 200uA.\n"); if (!pil) pressure = 0; /* polling mode sample settling delay */ if (delay < 0 || delay > 15) { - dev_dbg(wm->dev, "supplied delay out of range."); + dev_dbg(wm->dev, "supplied delay out of range.\n"); delay = 4; } dig1 &= 0xff0f; dig1 |= WM97XX_DELAY(delay); - dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.", + dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.\n", delay_table[delay]); /* mask */ @@ -285,7 +285,7 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) if (is_pden(wm)) wm->pen_probably_down = 0; else - dev_dbg(wm->dev, "adc sample timeout"); + dev_dbg(wm->dev, "adc sample timeout\n"); return RC_PENUP; } @@ -295,15 +295,19 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) /* check we have correct sample */ if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) { - dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x", + dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x\n", adcsel & WM97XX_ADCSEL_MASK, *sample & WM97XX_ADCSEL_MASK); - return RC_PENUP; + return RC_AGAIN; } if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) { - wm->pen_probably_down = 0; - return RC_PENUP; + /* Sometimes it reads a wrong value the first time. */ + *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); + if (!(*sample & WM97XX_PEN_DOWN)) { + wm->pen_probably_down = 0; + return RC_PENUP; + } } return RC_VALID; @@ -345,7 +349,7 @@ static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data) if (is_pden(wm)) wm->pen_probably_down = 0; else - dev_dbg(wm->dev, "adc sample timeout"); + dev_dbg(wm->dev, "adc sample timeout\n"); return RC_PENUP; } diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 5dbe73a..7e45c9f 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -442,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); @@ -455,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; } |