From: Dmitry Torokhov Date: Wed, 30 Jun 2010 21:50:51 +0000 (-0700) Subject: Input: ad7879 - add open and close methods X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=14fbbc36d126d7ec7717144def386b9fc4c7fba2;p=linux-beck.git Input: ad7879 - add open and close methods Tested-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 85dfdd27df5a..81937b21e9d2 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -20,7 +20,7 @@ static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message) { struct ad7879 *ts = i2c_get_clientdata(client); - ad7879_disable(ts); + ad7879_suspend(ts); return 0; } @@ -29,7 +29,7 @@ static int ad7879_i2c_resume(struct i2c_client *client) { struct ad7879 *ts = i2c_get_clientdata(client); - ad7879_enable(ts); + ad7879_resume(ts); return 0; } diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 5d1e5a050332..9fa8e5de5ff9 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c @@ -25,7 +25,7 @@ static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message) { struct ad7879 *ts = spi_get_drvdata(spi); - ad7879_disable(ts); + ad7879_suspend(ts); return 0; } @@ -34,7 +34,7 @@ static int ad7879_spi_resume(struct spi_device *spi) { struct ad7879 *ts = spi_get_drvdata(spi); - ad7879_enable(ts); + ad7879_resume(ts); return 0; } diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 1de19691c4a3..fad65969cc72 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -112,10 +112,11 @@ struct ad7879 { struct timer_list timer; #ifdef CONFIG_GPIOLIB struct gpio_chip gc; + struct mutex mutex; #endif unsigned int irq; - struct mutex mutex; - bool disabled; /* P: mutex */ + bool disabled; /* P: input->mutex */ + bool suspended; /* P: input->mutex */ u16 conversion_data[AD7879_NR_SENSE]; char phys[32]; u8 first_conversion_delay; @@ -208,46 +209,91 @@ static irqreturn_t ad7879_irq(int irq, void *handle) return IRQ_HANDLED; } -static void ad7879_setup(struct ad7879 *ts) +static void __ad7879_enable(struct ad7879 *ts) { ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2); ad7879_write(ts, AD7879_REG_CTRL3, ts->cmd_crtl3); ad7879_write(ts, AD7879_REG_CTRL1, ts->cmd_crtl1); + + enable_irq(ts->irq); } -void ad7879_disable(struct ad7879 *ts) +static void __ad7879_disable(struct ad7879 *ts) { - mutex_lock(&ts->mutex); + disable_irq(ts->irq); - if (!ts->disabled) { + if (del_timer_sync(&ts->timer)) + ad7879_ts_event_release(ts); - ts->disabled = true; - disable_irq(ts->irq); + ad7879_write(ts, AD7879_REG_CTRL2, AD7879_PM(AD7879_PM_SHUTDOWN)); +} - if (del_timer_sync(&ts->timer)) - ad7879_ts_event_release(ts); - ad7879_write(ts, AD7879_REG_CTRL2, - AD7879_PM(AD7879_PM_SHUTDOWN)); - } +static int ad7879_open(struct input_dev *input) +{ + struct ad7879 *ts = input_get_drvdata(input); - mutex_unlock(&ts->mutex); + /* protected by input->mutex */ + if (!ts->disabled && !ts->suspended) + __ad7879_enable(ts); + + return 0; } -EXPORT_SYMBOL(ad7879_disable); -void ad7879_enable(struct ad7879 *ts) +static void ad7879_close(struct input_dev* input) { - mutex_lock(&ts->mutex); + struct ad7879 *ts = input_get_drvdata(input); + + /* protected by input->mutex */ + if (!ts->disabled && !ts->suspended) + __ad7879_disable(ts); +} + +void ad7879_suspend(struct ad7879 *ts) +{ + mutex_lock(&ts->input->mutex); + + if (!ts->suspended && !ts->disabled && ts->input->users) + __ad7879_disable(ts); + + ts->suspended = true; + + mutex_unlock(&ts->input->mutex); +} +EXPORT_SYMBOL(ad7879_suspend); + +void ad7879_resume(struct ad7879 *ts) +{ + mutex_lock(&ts->input->mutex); - if (ts->disabled) { - ad7879_setup(ts); - ts->disabled = false; - enable_irq(ts->irq); + if (ts->suspended && !ts->disabled && ts->input->users) + __ad7879_enable(ts); + + ts->suspended = false; + + mutex_unlock(&ts->input->mutex); +} +EXPORT_SYMBOL(ad7879_resume); + +static void ad7879_toggle(struct ad7879 *ts, bool disable) +{ + mutex_lock(&ts->input->mutex); + + if (!ts->suspended && ts->input->users != 0) { + + if (disable) { + if (ts->disabled) + __ad7879_enable(ts); + } else { + if (!ts->disabled) + __ad7879_disable(ts); + } } - mutex_unlock(&ts->mutex); + ts->disabled = disable; + + mutex_unlock(&ts->input->mutex); } -EXPORT_SYMBOL(ad7879_enable); static ssize_t ad7879_disable_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -269,10 +315,7 @@ static ssize_t ad7879_disable_store(struct device *dev, if (error) return error; - if (val) - ad7879_disable(ts); - else - ad7879_enable(ts); + ad7879_toggle(ts, val); return count; } @@ -355,6 +398,8 @@ static int ad7879_gpio_add(struct ad7879 *ts, { int ret = 0; + mutex_init(&ts->mutex); + if (pdata->gpio_export) { ts->gc.direction_input = ad7879_gpio_direction_input; ts->gc.direction_output = ad7879_gpio_direction_output; @@ -431,11 +476,9 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, ts->bops = bops; ts->dev = dev; ts->input = input_dev; + ts->irq = irq; setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); - mutex_init(&ts->mutex); - - ts->irq = irq; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; ts->pressure_max = pdata->pressure_max ? : ~0; @@ -453,6 +496,11 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, input_dev->dev.parent = dev; input_dev->id.bustype = bops->bustype; + input_dev->open = ad7879_open; + input_dev->close = ad7879_close; + + input_set_drvdata(input_dev, ts); + __set_bit(EV_ABS, input_dev->evbit); __set_bit(ABS_X, input_dev->absbit); __set_bit(ABS_Y, input_dev->absbit); @@ -502,8 +550,6 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, AD7879_ACQ(ts->acquisition_time) | AD7879_TMR(ts->pen_down_acc_interval); - ad7879_setup(ts); - err = request_threaded_irq(ts->irq, NULL, ad7879_irq, IRQF_TRIGGER_FALLING, dev_name(dev), ts); @@ -512,6 +558,8 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, goto err_free_mem; } + __ad7879_disable(ts); + err = sysfs_create_group(&dev->kobj, &ad7879_attr_group); if (err) goto err_free_irq; @@ -543,7 +591,6 @@ EXPORT_SYMBOL(ad7879_probe); void ad7879_remove(struct ad7879 *ts) { ad7879_gpio_remove(ts); - ad7879_disable(ts); sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group); free_irq(ts->irq, ts); input_unregister_device(ts->input); diff --git a/drivers/input/touchscreen/ad7879.h b/drivers/input/touchscreen/ad7879.h index 169f155db3b9..6b45a27236c7 100644 --- a/drivers/input/touchscreen/ad7879.h +++ b/drivers/input/touchscreen/ad7879.h @@ -21,8 +21,8 @@ struct ad7879_bus_ops { int (*write)(struct device *dev, u8 reg, u16 val); }; -void ad7879_disable(struct ad7879 *); -void ad7879_enable(struct ad7879 *); +void ad7879_suspend(struct ad7879 *); +void ad7879_resume(struct ad7879 *); struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, const struct ad7879_bus_ops *bops); void ad7879_remove(struct ad7879 *);