diff options
Diffstat (limited to 'drivers/input/touchscreen/bu21013_ts.c')
| -rw-r--r-- | drivers/input/touchscreen/bu21013_ts.c | 125 | 
1 files changed, 99 insertions, 26 deletions
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 5c487d23f11..b9b5ddad665 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -14,6 +14,9 @@  #include <linux/slab.h>  #include <linux/regulator/consumer.h>  #include <linux/module.h> +#include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_gpio.h>  #define PEN_DOWN_INTR	0  #define MAX_FINGERS	2 @@ -148,11 +151,12 @@  struct bu21013_ts_data {  	struct i2c_client *client;  	wait_queue_head_t wait; -	bool touch_stopped;  	const struct bu21013_platform_device *chip;  	struct input_dev *in_dev; -	unsigned int intr_pin;  	struct regulator *regulator; +	unsigned int irq; +	unsigned int intr_pin; +	bool touch_stopped;  };  /** @@ -262,7 +266,7 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)  			return IRQ_NONE;  		} -		data->intr_pin = data->chip->irq_read_val(); +		data->intr_pin = gpio_get_value(data->chip->touch_pin);  		if (data->intr_pin == PEN_DOWN_INTR)  			wait_event_timeout(data->wait, data->touch_stopped,  					   msecs_to_jiffies(2)); @@ -418,8 +422,70 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)  {  	bu21013_data->touch_stopped = true;  	wake_up(&bu21013_data->wait); -	free_irq(bu21013_data->chip->irq, bu21013_data); +	free_irq(bu21013_data->irq, bu21013_data); +} + +/** + * bu21013_cs_disable() - deconfigures the touch panel controller + * @bu21013_data: device structure pointer + * + * This function is used to deconfigure the chip selection + * for touch panel controller. + */ +static void bu21013_cs_disable(struct bu21013_ts_data *bu21013_data) +{ +	int error; + +	error = gpio_direction_output(bu21013_data->chip->cs_pin, 0); +	if (error < 0) +		dev_warn(&bu21013_data->client->dev, +			 "%s: gpio direction failed, error: %d\n", +			 __func__, error); +	else +		gpio_set_value(bu21013_data->chip->cs_pin, 0); + +	gpio_free(bu21013_data->chip->cs_pin); +} + +#ifdef CONFIG_OF +static const struct bu21013_platform_device * +bu21013_parse_dt(struct device *dev) +{ +	struct device_node *np = dev->of_node; +	struct bu21013_platform_device *pdata; + +	if (!np) { +		dev_err(dev, "no device tree or platform data\n"); +		return ERR_PTR(-EINVAL); +	} + +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return ERR_PTR(-ENOMEM); + +	pdata->y_flip = pdata->x_flip = false; + +	pdata->x_flip = of_property_read_bool(np, "rohm,flip-x"); +	pdata->y_flip = of_property_read_bool(np, "rohm,flip-y"); + +	of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); +	of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); + +	pdata->touch_pin = of_get_named_gpio(np, "touch-gpio", 0); +	pdata->cs_pin = of_get_named_gpio(np, "reset-gpio", 0); + +	pdata->ext_clk = false; + +	return pdata;  } +#else +static inline const struct bu21013_platform_device * +bu21013_parse_dt(struct device *dev) +{ +	dev_err(dev, "no platform data available\n"); +	return ERR_PTR(-EINVAL); +} +#endif  /**   * bu21013_probe() - initializes the i2c-client touchscreen driver @@ -429,13 +495,13 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)   * This function used to initializes the i2c-client touchscreen   * driver and returns integer.   */ -static int __devinit bu21013_probe(struct i2c_client *client, -					const struct i2c_device_id *id) +static int bu21013_probe(struct i2c_client *client, +			 const struct i2c_device_id *id)  { +	const struct bu21013_platform_device *pdata = +					dev_get_platdata(&client->dev);  	struct bu21013_ts_data *bu21013_data;  	struct input_dev *in_dev; -	const struct bu21013_platform_device *pdata = -					client->dev.platform_data;  	int error;  	if (!i2c_check_functionality(client->adapter, @@ -445,7 +511,13 @@ static int __devinit bu21013_probe(struct i2c_client *client,  	}  	if (!pdata) { -		dev_err(&client->dev, "platform data not defined\n"); +		pdata = bu21013_parse_dt(&client->dev); +		if (IS_ERR(pdata)) +			return PTR_ERR(pdata); +	} + +	if (!gpio_is_valid(pdata->touch_pin)) { +		dev_err(&client->dev, "invalid touch_pin supplied\n");  		return -EINVAL;  	} @@ -460,8 +532,9 @@ static int __devinit bu21013_probe(struct i2c_client *client,  	bu21013_data->in_dev = in_dev;  	bu21013_data->chip = pdata;  	bu21013_data->client = client; +	bu21013_data->irq = gpio_to_irq(pdata->touch_pin); -	bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH"); +	bu21013_data->regulator = regulator_get(&client->dev, "avdd");  	if (IS_ERR(bu21013_data->regulator)) {  		dev_err(&client->dev, "regulator_get failed\n");  		error = PTR_ERR(bu21013_data->regulator); @@ -478,12 +551,11 @@ static int __devinit bu21013_probe(struct i2c_client *client,  	init_waitqueue_head(&bu21013_data->wait);  	/* configure the gpio pins */ -	if (pdata->cs_en) { -		error = pdata->cs_en(pdata->cs_pin); -		if (error < 0) { -			dev_err(&client->dev, "chip init failed\n"); -			goto err_disable_regulator; -		} +	error = gpio_request_one(pdata->cs_pin, GPIOF_OUT_INIT_HIGH, +				 "touchp_reset"); +	if (error < 0) { +		dev_err(&client->dev, "Unable to request gpio reset_pin\n"); +		goto err_disable_regulator;  	}  	/* configure the touch panel controller */ @@ -508,12 +580,13 @@ static int __devinit bu21013_probe(struct i2c_client *client,  						pdata->touch_y_max, 0, 0);  	input_set_drvdata(in_dev, bu21013_data); -	error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, +	error = request_threaded_irq(bu21013_data->irq, NULL, bu21013_gpio_irq,  				     IRQF_TRIGGER_FALLING | IRQF_SHARED |  					IRQF_ONESHOT,  				     DRIVER_TP, bu21013_data);  	if (error) { -		dev_err(&client->dev, "request irq %d failed\n", pdata->irq); +		dev_err(&client->dev, "request irq %d failed\n", +			bu21013_data->irq);  		goto err_cs_disable;  	} @@ -531,7 +604,7 @@ static int __devinit bu21013_probe(struct i2c_client *client,  err_free_irq:  	bu21013_free_irq(bu21013_data);  err_cs_disable: -	pdata->cs_dis(pdata->cs_pin); +	bu21013_cs_disable(bu21013_data);  err_disable_regulator:  	regulator_disable(bu21013_data->regulator);  err_put_regulator: @@ -549,13 +622,13 @@ err_free_mem:   * This function uses to remove the i2c-client   * touchscreen driver and returns integer.   */ -static int __devexit bu21013_remove(struct i2c_client *client) +static int bu21013_remove(struct i2c_client *client)  {  	struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);  	bu21013_free_irq(bu21013_data); -	bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); +	bu21013_cs_disable(bu21013_data);  	input_unregister_device(bu21013_data->in_dev); @@ -584,9 +657,9 @@ static int bu21013_suspend(struct device *dev)  	bu21013_data->touch_stopped = true;  	if (device_may_wakeup(&client->dev)) -		enable_irq_wake(bu21013_data->chip->irq); +		enable_irq_wake(bu21013_data->irq);  	else -		disable_irq(bu21013_data->chip->irq); +		disable_irq(bu21013_data->irq);  	regulator_disable(bu21013_data->regulator); @@ -621,9 +694,9 @@ static int bu21013_resume(struct device *dev)  	bu21013_data->touch_stopped = false;  	if (device_may_wakeup(&client->dev)) -		disable_irq_wake(bu21013_data->chip->irq); +		disable_irq_wake(bu21013_data->irq);  	else -		enable_irq(bu21013_data->chip->irq); +		enable_irq(bu21013_data->irq);  	return 0;  } @@ -649,7 +722,7 @@ static struct i2c_driver bu21013_driver = {  #endif  	},  	.probe		=	bu21013_probe, -	.remove		=	__devexit_p(bu21013_remove), +	.remove		=	bu21013_remove,  	.id_table	=	bu21013_id,  };  |