diff options
Diffstat (limited to 'drivers/input/touchscreen/eeti_ts.c')
| -rw-r--r-- | drivers/input/touchscreen/eeti_ts.c | 57 | 
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 9029bd3f34e..75f8b73010f 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -33,6 +33,7 @@  #include <linux/timer.h>  #include <linux/gpio.h>  #include <linux/input/eeti_ts.h> +#include <linux/slab.h>  static int flip_x;  module_param(flip_x, bool, 0644); @@ -123,14 +124,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static int eeti_ts_open(struct input_dev *dev) +static void eeti_ts_start(struct eeti_ts_priv *priv)  { -	struct eeti_ts_priv *priv = input_get_drvdata(dev); -  	enable_irq(priv->irq);  	/* Read the events once to arm the IRQ */  	eeti_ts_read(&priv->work); +} + +static void eeti_ts_stop(struct eeti_ts_priv *priv) +{ +	disable_irq(priv->irq); +	cancel_work_sync(&priv->work); +} + +static int eeti_ts_open(struct input_dev *dev) +{ +	struct eeti_ts_priv *priv = input_get_drvdata(dev); + +	eeti_ts_start(priv);  	return 0;  } @@ -139,8 +151,7 @@ static void eeti_ts_close(struct input_dev *dev)  {  	struct eeti_ts_priv *priv = input_get_drvdata(dev); -	disable_irq(priv->irq); -	cancel_work_sync(&priv->work); +	eeti_ts_stop(priv);  }  static int __devinit eeti_ts_probe(struct i2c_client *client, @@ -152,10 +163,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  	unsigned int irq_flags;  	int err = -ENOMEM; -	/* In contrast to what's described in the datasheet, there seems +	/* +	 * In contrast to what's described in the datasheet, there seems  	 * to be no way of probing the presence of that device using I2C  	 * commands. So we need to blindly believe it is there, and wait -	 * for interrupts to occur. */ +	 * for interrupts to occur. +	 */  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv) { @@ -211,9 +224,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  		goto err2;  	} -	/* Disable the irq for now. It will be enabled once the input device -	 * is opened. */ -	disable_irq(priv->irq); +	/* +	 * Disable the device for now. It will be enabled once the +	 * input device is opened. +	 */ +	eeti_ts_stop(priv);  	device_init_wakeup(&client->dev, 0);  	return 0; @@ -234,6 +249,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)  	struct eeti_ts_priv *priv = i2c_get_clientdata(client);  	free_irq(priv->irq, priv); +	/* +	 * eeti_ts_stop() leaves IRQ disabled. We need to re-enable it +	 * so that device still works if we reload the driver. +	 */ +	enable_irq(priv->irq); +  	input_unregister_device(priv->input);  	i2c_set_clientdata(client, NULL);  	kfree(priv); @@ -245,6 +266,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)  static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)  {  	struct eeti_ts_priv *priv = i2c_get_clientdata(client); +	struct input_dev *input_dev = priv->input; + +	mutex_lock(&input_dev->mutex); + +	if (input_dev->users) +		eeti_ts_stop(priv); + +	mutex_unlock(&input_dev->mutex);  	if (device_may_wakeup(&client->dev))  		enable_irq_wake(priv->irq); @@ -255,10 +284,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)  static int eeti_ts_resume(struct i2c_client *client)  {  	struct eeti_ts_priv *priv = i2c_get_clientdata(client); +	struct input_dev *input_dev = priv->input;  	if (device_may_wakeup(&client->dev))  		disable_irq_wake(priv->irq); +	mutex_lock(&input_dev->mutex); + +	if (input_dev->users) +		eeti_ts_start(priv); + +	mutex_unlock(&input_dev->mutex); +  	return 0;  }  #else  |