X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Finput%2Ftouchscreen%2Fads7846.c;h=634f6f6b9b1349a27bcca9a056ca27a1b5151abc;hb=cc106eb35ed4abea675bce0d8fe40a46ff0b4a72;hp=ba9d38c3f412a7a1526f028f5cf2a2c8863f1ed8;hpb=c57c0a2a0d019aa8108f1155f99098ea7e7e1ab3;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index ba9d38c..634f6f6 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -27,15 +27,16 @@ #include #include #include +#include #include - /* * This code has been heavily tested on a Nokia 770, and lightly - * tested on other ads7846 devices (OSK/Mistral, Lubbock). + * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz). * TSC2046 is just newer ads7846 silicon. * Support for ads7843 tested on Atmel at91sam926x-EK. * Support for ads7845 has only been stubbed in. + * Support for Analog Devices AD7873 and AD7843 tested. * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These @@ -43,7 +44,7 @@ * have to maintain our own SW IRQ disabled status. This should be * removed as soon as the affected platform's IRQ handling is fixed. * - * app note sbaa036 talks in more detail about accurate sampling... + * App note sbaa036 talks in more detail about accurate sampling... * that ought to help in situations like LCDs inducing noise (which * can also be helped by using synch signals) and more generally. * This driver tries to utilize the measures described in the app @@ -86,6 +87,7 @@ struct ads7846 { char name[32]; struct spi_device *spi; + struct regulator *reg; #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) struct attribute_group *attr_group; @@ -566,10 +568,8 @@ static void ads7846_rx(void *ads) * once more the measurement */ if (packet->tc.ignore || Rt > ts->pressure_max) { -#ifdef VERBOSE - pr_debug("%s: ignored %d pressure %d\n", - dev_name(&ts->spi->dev), packet->tc.ignore, Rt); -#endif + dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n", + packet->tc.ignore, Rt); hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_MODE_REL); return; @@ -598,9 +598,7 @@ static void ads7846_rx(void *ads) if (!ts->pendown) { input_report_key(input, BTN_TOUCH, 1); ts->pendown = 1; -#ifdef VERBOSE - dev_dbg(&ts->spi->dev, "DOWN\n"); -#endif + dev_vdbg(&ts->spi->dev, "DOWN\n"); } if (ts->swap_xy) @@ -608,12 +606,10 @@ static void ads7846_rx(void *ads) input_report_abs(input, ABS_X, x); input_report_abs(input, ABS_Y, y); - input_report_abs(input, ABS_PRESSURE, Rt); + input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt); input_sync(input); -#ifdef VERBOSE - dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); -#endif + dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); } hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), @@ -723,9 +719,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) input_sync(input); ts->pendown = 0; -#ifdef VERBOSE - dev_dbg(&ts->spi->dev, "UP\n"); -#endif + dev_vdbg(&ts->spi->dev, "UP\n"); } /* measurement cycle ended */ @@ -797,6 +791,8 @@ static void ads7846_disable(struct ads7846 *ts) } } + regulator_disable(ts->reg); + /* we know the chip's in lowpower mode since we always * leave it that way after every request */ @@ -808,6 +804,8 @@ static void ads7846_enable(struct ads7846 *ts) if (!ts->disabled) return; + regulator_enable(ts->reg); + ts->disabled = 0; ts->irq_disabled = 0; enable_irq(ts->spi->irq); @@ -824,6 +822,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) spin_unlock_irq(&ts->lock); + if (device_may_wakeup(&ts->spi->dev)) + enable_irq_wake(ts->spi->irq); + return 0; } @@ -832,6 +833,9 @@ static int ads7846_resume(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + if (device_may_wakeup(&ts->spi->dev)) + disable_irq_wake(ts->spi->irq); + spin_lock_irq(&ts->lock); ts->is_suspended = 0; @@ -987,6 +991,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) vref = pdata->keep_vref_on; + if (ts->model == 7873) { + /* The AD7873 is almost identical to the ADS7846 + * keep VREF off during differential/ratiometric + * conversion modes + */ + ts->model = 7846; + vref = 0; + } + /* set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ @@ -1148,6 +1161,19 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->last_msg = m; + ts->reg = regulator_get(&spi->dev, "vcc"); + if (IS_ERR(ts->reg)) { + err = PTR_ERR(ts->reg); + dev_err(&spi->dev, "unable to get regulator: %ld\n", err); + goto err_free_gpio; + } + + err = regulator_enable(ts->reg); + if (err) { + dev_err(&spi->dev, "unable to enable regulator: %d\n", err); + goto err_put_regulator; + } + if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, spi->dev.driver->name, ts)) { dev_info(&spi->dev, @@ -1157,7 +1183,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) spi->dev.driver->name, ts); if (err) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; + goto err_disable_regulator; } } @@ -1181,6 +1207,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) if (err) goto err_remove_attr_group; + device_init_wakeup(&spi->dev, pdata->wakeup); + return 0; err_remove_attr_group: @@ -1189,6 +1217,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) ads784x_hwmon_unregister(spi, ts); err_free_irq: free_irq(spi->irq, ts); + err_disable_regulator: + regulator_disable(ts->reg); + err_put_regulator: + regulator_put(ts->reg); err_free_gpio: if (ts->gpio_pendown != -1) gpio_free(ts->gpio_pendown); @@ -1206,6 +1238,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + device_init_wakeup(&spi->dev, false); + ads784x_hwmon_unregister(spi, ts); input_unregister_device(ts->input); @@ -1217,6 +1251,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) /* suspend left the IRQ disabled */ enable_irq(ts->spi->irq); + regulator_disable(ts->reg); + regulator_put(ts->reg); + if (ts->gpio_pendown != -1) gpio_free(ts->gpio_pendown); @@ -1256,3 +1293,4 @@ module_exit(ads7846_exit); MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:ads7846");