From 542ad4f8886b376dac9a4334bdb38f9c22a4d8da Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 25 Apr 2014 15:08:29 -0700 Subject: Input: gpio_keys - convert struct descriptions to kernel-doc This patch converts descriptions of the structures defined in linux/gpio_keys.h to follow kernel-doc format. There is no functional change. Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- include/linux/gpio_keys.h | 48 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index a7e977ff4abf..8b622468952c 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -3,29 +3,53 @@ struct device; +/** + * struct gpio_keys_button - configuration parameters + * @code: input event code (KEY_*, SW_*) + * @gpio: %-1 if this key does not support gpio + * @active_low: %true indicates that button is considered + * depressed when gpio is low + * @desc: label that will be attached to button's gpio + * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS) + * @wakeup: configure the button as a wake-up source + * @debounce_interval: debounce ticks interval in msecs + * @can_disable: %true indicates that userspace is allowed to + * disable button via sysfs + * @value: axis value for %EV_ABS + * @irq: Irq number in case of interrupt keys + */ struct gpio_keys_button { - /* Configuration parameters */ - unsigned int code; /* input event code (KEY_*, SW_*) */ - int gpio; /* -1 if this key does not support gpio */ + unsigned int code; + int gpio; int active_low; const char *desc; - unsigned int type; /* input event type (EV_KEY, EV_SW, EV_ABS) */ - int wakeup; /* configure the button as a wake-up source */ - int debounce_interval; /* debounce ticks interval in msecs */ + unsigned int type; + int wakeup; + int debounce_interval; bool can_disable; - int value; /* axis value for EV_ABS */ - unsigned int irq; /* Irq number in case of interrupt keys */ + int value; + unsigned int irq; }; +/** + * struct gpio_keys_platform_data - platform data for gpio_keys driver + * @buttons: pointer to array of &gpio_keys_button structures + * describing buttons attached to the device + * @nbuttons: number of elements in @buttons array + * @poll_interval: polling interval in msecs - for polling driver only + * @rep: enable input subsystem auto repeat + * @enable: platform hook for enabling the device + * @disable: platform hook for disabling the device + * @name: input device name + */ struct gpio_keys_platform_data { struct gpio_keys_button *buttons; int nbuttons; - unsigned int poll_interval; /* polling interval in msecs - - for polling driver only */ - unsigned int rep:1; /* enable input subsystem auto repeat */ + unsigned int poll_interval; + unsigned int rep:1; int (*enable)(struct device *dev); void (*disable)(struct device *dev); - const char *name; /* input device name */ + const char *name; }; #endif -- cgit v1.2.3-71-gd317 From bf1de9761c21f56d5b0c6a0acd3b792d801c61e6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 28 Apr 2014 10:49:51 -0700 Subject: Input: implement managed polled input devices Managed resources are becoming more and more popular in drivers. Let's implement managed polled input devices, to complement managed regular input devices. Similarly to managed regular input devices only one new call devm_input_allocate_polled_device() is added and the rest of APIs is modified to work with both managed and non-managed devices. Reviewed-by: David Herrmann Tested-by: Alexander Shiyan Signed-off-by: Dmitry Torokhov --- drivers/input/input-polldev.c | 118 +++++++++++++++++++++++++++++++++++++++++- include/linux/input-polldev.h | 3 ++ 2 files changed, 119 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 4b191908d5de..3664f81655ca 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -176,6 +176,91 @@ struct input_polled_dev *input_allocate_polled_device(void) } EXPORT_SYMBOL(input_allocate_polled_device); +struct input_polled_devres { + struct input_polled_dev *polldev; +}; + +static int devm_input_polldev_match(struct device *dev, void *res, void *data) +{ + struct input_polled_devres *devres = res; + + return devres->polldev == data; +} + +static void devm_input_polldev_release(struct device *dev, void *res) +{ + struct input_polled_devres *devres = res; + struct input_polled_dev *polldev = devres->polldev; + + dev_dbg(dev, "%s: dropping reference/freeing %s\n", + __func__, dev_name(&polldev->input->dev)); + + input_put_device(polldev->input); + kfree(polldev); +} + +static void devm_input_polldev_unregister(struct device *dev, void *res) +{ + struct input_polled_devres *devres = res; + struct input_polled_dev *polldev = devres->polldev; + + dev_dbg(dev, "%s: unregistering device %s\n", + __func__, dev_name(&polldev->input->dev)); + input_unregister_device(polldev->input); + + /* + * Note that we are still holding extra reference to the input + * device so it will stick around until devm_input_polldev_release() + * is called. + */ +} + +/** + * devm_input_allocate_polled_device - allocate managed polled device + * @dev: device owning the polled device being created + * + * Returns prepared &struct input_polled_dev or %NULL. + * + * Managed polled input devices do not need to be explicitly unregistered + * or freed as it will be done automatically when owner device unbinds + * from * its driver (or binding fails). Once such managed polled device + * is allocated, it is ready to be set up and registered in the same + * fashion as regular polled input devices (using + * input_register_polled_device() function). + * + * If you want to manually unregister and free such managed polled devices, + * it can be still done by calling input_unregister_polled_device() and + * input_free_polled_device(), although it is rarely needed. + * + * NOTE: the owner device is set up as parent of input device and users + * should not override it. + */ +struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev) +{ + struct input_polled_dev *polldev; + struct input_polled_devres *devres; + + devres = devres_alloc(devm_input_polldev_release, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return NULL; + + polldev = input_allocate_polled_device(); + if (!polldev) { + devres_free(devres); + return NULL; + } + + polldev->input->dev.parent = dev; + polldev->devres_managed = true; + + devres->polldev = polldev; + devres_add(dev, devres); + + return polldev; +} +EXPORT_SYMBOL(devm_input_allocate_polled_device); + /** * input_free_polled_device - free memory allocated for polled device * @dev: device to free @@ -186,7 +271,12 @@ EXPORT_SYMBOL(input_allocate_polled_device); void input_free_polled_device(struct input_polled_dev *dev) { if (dev) { - input_free_device(dev->input); + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->input->dev.parent, + devm_input_polldev_release, + devm_input_polldev_match, + dev)); + input_put_device(dev->input); kfree(dev); } } @@ -204,9 +294,19 @@ EXPORT_SYMBOL(input_free_polled_device); */ int input_register_polled_device(struct input_polled_dev *dev) { + struct input_polled_devres *devres = NULL; struct input_dev *input = dev->input; int error; + if (dev->devres_managed) { + devres = devres_alloc(devm_input_polldev_unregister, + sizeof(*devres), GFP_KERNEL); + if (!devres) + return -ENOMEM; + + devres->polldev = dev; + } + input_set_drvdata(input, dev); INIT_DELAYED_WORK(&dev->work, input_polled_device_work); @@ -221,8 +321,10 @@ int input_register_polled_device(struct input_polled_dev *dev) input->dev.groups = input_polldev_attribute_groups; error = input_register_device(input); - if (error) + if (error) { + devres_free(devres); return error; + } /* * Take extra reference to the underlying input device so @@ -233,6 +335,12 @@ int input_register_polled_device(struct input_polled_dev *dev) */ input_get_device(input); + if (dev->devres_managed) { + dev_dbg(input->dev.parent, "%s: registering %s with devres.\n", + __func__, dev_name(&input->dev)); + devres_add(input->dev.parent, devres); + } + return 0; } EXPORT_SYMBOL(input_register_polled_device); @@ -247,6 +355,12 @@ EXPORT_SYMBOL(input_register_polled_device); */ void input_unregister_polled_device(struct input_polled_dev *dev) { + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->input->dev.parent, + devm_input_polldev_unregister, + devm_input_polldev_match, + dev)); + input_unregister_device(dev->input); } EXPORT_SYMBOL(input_unregister_polled_device); diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h index ce0b72464eb8..2465182670db 100644 --- a/include/linux/input-polldev.h +++ b/include/linux/input-polldev.h @@ -48,9 +48,12 @@ struct input_polled_dev { /* private: */ struct delayed_work work; + + bool devres_managed; }; struct input_polled_dev *input_allocate_polled_device(void); +struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev); void input_free_polled_device(struct input_polled_dev *dev); int input_register_polled_device(struct input_polled_dev *dev); void input_unregister_polled_device(struct input_polled_dev *dev); -- cgit v1.2.3-71-gd317 From 3b36fbb01dc50f58e7803006f5a99683daf26c8c Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Sun, 18 May 2014 22:44:35 -0700 Subject: Input: pixcir_i2c_ts - initialize interrupt mode and power mode Introduce helper functions to configure power and interrupt registers. Default to IDLE mode on probe as device supports auto wakeup to ACVIE mode on detecting finger touch. Configure interrupt mode and polarity on start up. Power down on device closure or module removal. Signed-off-by: Roger Quadros Acked-by: Mugunthan V N Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 182 ++++++++++++++++++++++++++++-- include/linux/input/pixcir_ts.h | 42 +++++++ 2 files changed, 216 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 5d36243bdc79..6c6f6dacb858 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -29,7 +29,7 @@ struct pixcir_i2c_ts_data { struct i2c_client *client; struct input_dev *input; const struct pixcir_ts_platform_data *chip; - bool exiting; + bool running; }; static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) @@ -88,7 +88,7 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) { struct pixcir_i2c_ts_data *tsdata = dev_id; - while (!tsdata->exiting) { + while (tsdata->running) { pixcir_ts_poscheck(tsdata); if (tsdata->chip->attb_read_val()) @@ -100,6 +100,164 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, + enum pixcir_power_mode mode) +{ + struct device *dev = &ts->client->dev; + int ret; + + ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE); + if (ret < 0) { + dev_err(dev, "%s: can't read reg 0x%x : %d\n", + __func__, PIXCIR_REG_POWER_MODE, ret); + return ret; + } + + ret &= ~PIXCIR_POWER_MODE_MASK; + ret |= mode; + + /* Always AUTO_IDLE */ + ret |= PIXCIR_POWER_ALLOW_IDLE; + + ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret); + if (ret < 0) { + dev_err(dev, "%s: can't write reg 0x%x : %d\n", + __func__, PIXCIR_REG_POWER_MODE, ret); + return ret; + } + + return 0; +} + +/* + * Set the interrupt mode for the device i.e. ATTB line behaviour + * + * @polarity : 1 for active high, 0 for active low. + */ +static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, + enum pixcir_int_mode mode, bool polarity) +{ + struct device *dev = &ts->client->dev; + int ret; + + ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); + if (ret < 0) { + dev_err(dev, "%s: can't read reg 0x%x : %d\n", + __func__, PIXCIR_REG_INT_MODE, ret); + return ret; + } + + ret &= ~PIXCIR_INT_MODE_MASK; + ret |= mode; + + if (polarity) + ret |= PIXCIR_INT_POL_HIGH; + else + ret &= ~PIXCIR_INT_POL_HIGH; + + ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); + if (ret < 0) { + dev_err(dev, "%s: can't write reg 0x%x : %d\n", + __func__, PIXCIR_REG_INT_MODE, ret); + return ret; + } + + return 0; +} + +/* + * Enable/disable interrupt generation + */ +static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable) +{ + struct device *dev = &ts->client->dev; + int ret; + + ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); + if (ret < 0) { + dev_err(dev, "%s: can't read reg 0x%x : %d\n", + __func__, PIXCIR_REG_INT_MODE, ret); + return ret; + } + + if (enable) + ret |= PIXCIR_INT_ENABLE; + else + ret &= ~PIXCIR_INT_ENABLE; + + ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); + if (ret < 0) { + dev_err(dev, "%s: can't write reg 0x%x : %d\n", + __func__, PIXCIR_REG_INT_MODE, ret); + return ret; + } + + return 0; +} + +static int pixcir_start(struct pixcir_i2c_ts_data *ts) +{ + struct device *dev = &ts->client->dev; + int error; + + /* LEVEL_TOUCH interrupt with active low polarity */ + error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0); + if (error) { + dev_err(dev, "Failed to set interrupt mode: %d\n", error); + return error; + } + + ts->running = true; + mb(); /* Update status before IRQ can fire */ + + /* enable interrupt generation */ + error = pixcir_int_enable(ts, true); + if (error) { + dev_err(dev, "Failed to enable interrupt generation: %d\n", + error); + return error; + } + + return 0; +} + +static int pixcir_stop(struct pixcir_i2c_ts_data *ts) +{ + int error; + + /* Disable interrupt generation */ + error = pixcir_int_enable(ts, false); + if (error) { + dev_err(&ts->client->dev, + "Failed to disable interrupt generation: %d\n", + error); + return error; + } + + /* Exit ISR if running, no more report parsing */ + ts->running = false; + mb(); /* update status before we synchronize irq */ + + /* Wait till running ISR is complete */ + synchronize_irq(ts->client->irq); + + return 0; +} + +static int pixcir_input_open(struct input_dev *dev) +{ + struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev); + + return pixcir_start(ts); +} + +static void pixcir_input_close(struct input_dev *dev) +{ + struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev); + + pixcir_stop(ts); +} + #ifdef CONFIG_PM_SLEEP static int pixcir_i2c_ts_suspend(struct device *dev) { @@ -156,6 +314,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, input->name = client->name; input->id.bustype = BUS_I2C; + input->open = pixcir_input_open; + input->close = pixcir_input_close; input->dev.parent = &client->dev; __set_bit(EV_KEY, input->evbit); @@ -176,11 +336,22 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, return error; } + /* Always be in IDLE mode to save power, device supports auto wake */ + error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE); + if (error) { + dev_err(dev, "Failed to set IDLE mode\n"); + return error; + } + + /* Stop device till opened */ + error = pixcir_stop(tsdata); + if (error) + return error; + error = input_register_device(input); if (error) return error; - i2c_set_clientdata(client, tsdata); device_init_wakeup(&client->dev, 1); return 0; @@ -188,13 +359,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, static int pixcir_i2c_ts_remove(struct i2c_client *client) { - struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client); - device_init_wakeup(&client->dev, 0); - tsdata->exiting = true; - mb(); - return 0; } diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h index 7163d91c0373..7942804464d3 100644 --- a/include/linux/input/pixcir_ts.h +++ b/include/linux/input/pixcir_ts.h @@ -1,6 +1,48 @@ #ifndef _PIXCIR_I2C_TS_H #define _PIXCIR_I2C_TS_H +/* + * Register map + */ +#define PIXCIR_REG_POWER_MODE 51 +#define PIXCIR_REG_INT_MODE 52 + +/* + * Power modes: + * active: max scan speed + * idle: lower scan speed with automatic transition to active on touch + * halt: datasheet says sleep but this is more like halt as the chip + * clocks are cut and it can only be brought out of this mode + * using the RESET pin. + */ +enum pixcir_power_mode { + PIXCIR_POWER_ACTIVE, + PIXCIR_POWER_IDLE, + PIXCIR_POWER_HALT, +}; + +#define PIXCIR_POWER_MODE_MASK 0x03 +#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) + +/* + * Interrupt modes: + * periodical: interrupt is asserted periodicaly + * diff coordinates: interrupt is asserted when coordinates change + * level on touch: interrupt level asserted during touch + * pulse on touch: interrupt pulse asserted druing touch + * + */ +enum pixcir_int_mode { + PIXCIR_INT_PERIODICAL, + PIXCIR_INT_DIFF_COORD, + PIXCIR_INT_LEVEL_TOUCH, + PIXCIR_INT_PULSE_TOUCH, +}; + +#define PIXCIR_INT_MODE_MASK 0x03 +#define PIXCIR_INT_ENABLE (1UL << 3) +#define PIXCIR_INT_POL_HIGH (1UL << 2) + struct pixcir_ts_platform_data { int (*attb_read_val)(void); int x_max; -- cgit v1.2.3-71-gd317 From 0dfc8d41bfa091a61354eea73199a5af0eaae9c0 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Sun, 18 May 2014 22:46:43 -0700 Subject: Input: pixcir_i2c_ts - get rid of pdata->attb_read_val() Get rid of the attb_read_val() platform hook. Instead, read the ATTB gpio directly from the driver. Fail if valid ATTB gpio is not provided by patform data. Signed-off-by: Roger Quadros Acked-by: Mugunthan V N Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 16 +++++++++++++++- include/linux/input/pixcir_ts.h | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 6c6f6dacb858..f2c0ae18e24a 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -24,6 +24,7 @@ #include #include #include +#include struct pixcir_i2c_ts_data { struct i2c_client *client; @@ -87,11 +88,12 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) { struct pixcir_i2c_ts_data *tsdata = dev_id; + const struct pixcir_ts_platform_data *pdata = tsdata->chip; while (tsdata->running) { pixcir_ts_poscheck(tsdata); - if (tsdata->chip->attb_read_val()) + if (gpio_get_value(pdata->gpio_attb)) break; msleep(20); @@ -298,6 +300,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, return -EINVAL; } + if (!gpio_is_valid(pdata->gpio_attb)) { + dev_err(dev, "Invalid gpio_attb in pdata\n"); + return -EINVAL; + } + tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); if (!tsdata) return -ENOMEM; @@ -328,6 +335,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, input_set_drvdata(input, tsdata); + error = devm_gpio_request_one(dev, pdata->gpio_attb, + GPIOF_DIR_IN, "pixcir_i2c_attb"); + if (error) { + dev_err(dev, "Failed to request ATTB gpio\n"); + return error; + } + error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, tsdata); diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h index 7942804464d3..160cf353aa39 100644 --- a/include/linux/input/pixcir_ts.h +++ b/include/linux/input/pixcir_ts.h @@ -44,9 +44,9 @@ enum pixcir_int_mode { #define PIXCIR_INT_POL_HIGH (1UL << 2) struct pixcir_ts_platform_data { - int (*attb_read_val)(void); int x_max; int y_max; + int gpio_attb; /* GPIO connected to ATTB line */ }; #endif -- cgit v1.2.3-71-gd317 From 2cefdb1f0a27150755ef2730bafc58bf2ed16571 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Sun, 18 May 2014 22:59:20 -0700 Subject: Input: atmel_mxt_ts - remove unnecessary platform data It is not necessary to download these values to the maXTouch chip on every probe, since they are stored in NVRAM. It makes life difficult when tuning the device to keep them in sync with the config array/file, and requires a new kernel build for minor tweaks. These parameters only represent a tiny subset of the available configuration options, tracking all of these options in platform data would be a endless task. In addition, different versions of maXTouch chips may have these values in different places or may not even have them at all. Having these values also makes life more complex for device tree and other platforms where having to define a static configuration isn't helpful. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen Signed-off-by: Dmitry Torokhov --- arch/arm/mach-s5pv210/mach-goni.c | 5 ---- drivers/input/touchscreen/atmel_mxt_ts.c | 50 ------------------------------- drivers/platform/chrome/chromeos_laptop.c | 10 ------- include/linux/i2c/atmel_mxt_ts.h | 6 +--- 4 files changed, 1 insertion(+), 70 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index b41a38a75844..e549ecf0e5dc 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -239,13 +239,8 @@ static void __init goni_radio_init(void) /* TSP */ static struct mxt_platform_data qt602240_platform_data = { - .x_line = 17, - .y_line = 11, .x_size = 800, .y_size = 480, - .blen = 0x21, - .threshold = 0x28, - .voltage = 2800000, /* 2.8V */ .orient = MXT_DIAGONAL, .irqflags = IRQF_TRIGGER_FALLING, }; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index a70400754e92..7eb515caf215 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -685,54 +685,6 @@ static int mxt_make_highchg(struct mxt_data *data) return 0; } -static void mxt_handle_pdata(struct mxt_data *data) -{ - const struct mxt_platform_data *pdata = data->pdata; - u8 voltage; - - /* Set touchscreen lines */ - mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE, - pdata->x_line); - mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE, - pdata->y_line); - - /* Set touchscreen orient */ - mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT, - pdata->orient); - - /* Set touchscreen burst length */ - mxt_write_object(data, MXT_TOUCH_MULTI_T9, - MXT_TOUCH_BLEN, pdata->blen); - - /* Set touchscreen threshold */ - mxt_write_object(data, MXT_TOUCH_MULTI_T9, - MXT_TOUCH_TCHTHR, pdata->threshold); - - /* Set touchscreen resolution */ - mxt_write_object(data, MXT_TOUCH_MULTI_T9, - MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); - mxt_write_object(data, MXT_TOUCH_MULTI_T9, - MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); - mxt_write_object(data, MXT_TOUCH_MULTI_T9, - MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); - mxt_write_object(data, MXT_TOUCH_MULTI_T9, - MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); - - /* Set touchscreen voltage */ - if (pdata->voltage) { - if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { - voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / - MXT_VOLTAGE_STEP; - voltage = 0xff - voltage + 1; - } else - voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / - MXT_VOLTAGE_STEP; - - mxt_write_object(data, MXT_SPT_CTECONFIG_T28, - MXT_CTE_VOLTAGE, voltage); - } -} - static int mxt_get_info(struct mxt_data *data) { struct i2c_client *client = data->client; @@ -840,8 +792,6 @@ static int mxt_initialize(struct mxt_data *data) if (error) goto err_free_object_table; - mxt_handle_pdata(data); - /* Backup to memory */ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_BACKUPNV, diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 7f3aad0e115c..2559a0407c58 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -85,13 +85,8 @@ static struct i2c_board_info tsl2563_als_device = { }; static struct mxt_platform_data atmel_224s_tp_platform_data = { - .x_line = 18, - .y_line = 12, .x_size = 102*20, .y_size = 68*20, - .blen = 0x80, /* Gain setting is in upper 4 bits */ - .threshold = 0x32, - .voltage = 0, /* 3.3V */ .orient = MXT_VERTICAL_FLIP, .irqflags = IRQF_TRIGGER_FALLING, .is_tp = true, @@ -110,13 +105,8 @@ static struct i2c_board_info atmel_224s_tp_device = { }; static struct mxt_platform_data atmel_1664s_platform_data = { - .x_line = 32, - .y_line = 50, .x_size = 1700, .y_size = 2560, - .blen = 0x89, /* Gain setting is in upper 4 bits */ - .threshold = 0x28, - .voltage = 0, /* 3.3V */ .orient = MXT_ROTATED_90_COUNTER, .irqflags = IRQF_TRIGGER_FALLING, .is_tp = false, diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index 99e379b74398..eff0cdc08843 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -33,14 +33,10 @@ struct mxt_platform_data { const u8 *config; size_t config_length; - unsigned int x_line; - unsigned int y_line; unsigned int x_size; unsigned int y_size; - unsigned int blen; - unsigned int threshold; - unsigned int voltage; unsigned char orient; + unsigned long irqflags; bool is_tp; const unsigned int key_map[MXT_NUM_GPIO]; -- cgit v1.2.3-71-gd317 From fb5e4c3ee140b29e1935b4bbb19c319177bed231 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Sun, 18 May 2014 23:00:15 -0700 Subject: Input: atmel_mxt_ts - improve T19 GPIO keys handling * The mapping of the GPIO numbers into the T19 status byte varies between different maXTouch chips. Some have up to 7 GPIOs. Allowing a keycode array of up to 8 items is simpler and more generic. So replace #define with configurable number of keys which also allows the removal of is_tp. * Rename platform data parameters to include "t19" to prevent confusion with T15 key array. * Probe aborts early on when pdata is NULL, so no need to check. * Move "int i" to beginning of function (mixed declarations and code) * Use API calls rather than __set_bit() * Remove unused dev variable. Signed-off-by: Nick Dyer Acked-by: Yufeng Shen Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 44 ++++++++++++------------------- drivers/platform/chrome/chromeos_laptop.c | 17 +++++++----- include/linux/i2c/atmel_mxt_ts.h | 7 ++--- 3 files changed, 30 insertions(+), 38 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 7eb515caf215..65df362cf327 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -180,12 +180,6 @@ #define MXT_FWRESET_TIME 175 /* msec */ -/* MXT_SPT_GPIOPWM_T19 field */ -#define MXT_GPIO0_MASK 0x04 -#define MXT_GPIO1_MASK 0x08 -#define MXT_GPIO2_MASK 0x10 -#define MXT_GPIO3_MASK 0x20 - /* Command to unlock bootloader */ #define MXT_UNLOCK_CMD_MSB 0xaa #define MXT_UNLOCK_CMD_LSB 0xdc @@ -250,7 +244,6 @@ struct mxt_data { const struct mxt_platform_data *pdata; struct mxt_object *object_table; struct mxt_info info; - bool is_tp; unsigned int irq; unsigned int max_x; @@ -515,15 +508,16 @@ static int mxt_write_object(struct mxt_data *data, static void mxt_input_button(struct mxt_data *data, struct mxt_message *message) { struct input_dev *input = data->input_dev; + const struct mxt_platform_data *pdata = data->pdata; bool button; int i; /* Active-low switch */ - for (i = 0; i < MXT_NUM_GPIO; i++) { - if (data->pdata->key_map[i] == KEY_RESERVED) + for (i = 0; i < pdata->t19_num_keys; i++) { + if (pdata->t19_keymap[i] == KEY_RESERVED) continue; - button = !(message->message[0] & MXT_GPIO0_MASK << i); - input_report_key(input, data->pdata->key_map[i], button); + button = !(message->message[0] & (1 << i)); + input_report_key(input, pdata->t19_keymap[i], button); } } @@ -1084,6 +1078,8 @@ static int mxt_probe(struct i2c_client *client, struct input_dev *input_dev; int error; unsigned int num_mt_slots; + unsigned int mt_flags = 0; + int i; if (!pdata) return -EINVAL; @@ -1096,10 +1092,7 @@ static int mxt_probe(struct i2c_client *client, goto err_free_mem; } - data->is_tp = pdata && pdata->is_tp; - - input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" : - "Atmel maXTouch Touchscreen"; + input_dev->name = "Atmel maXTouch Touchscreen"; snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", client->adapter->nr, client->addr); @@ -1125,20 +1118,15 @@ static int mxt_probe(struct i2c_client *client, __set_bit(EV_KEY, input_dev->evbit); __set_bit(BTN_TOUCH, input_dev->keybit); - if (data->is_tp) { - int i; - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + if (pdata->t19_num_keys) { __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); - for (i = 0; i < MXT_NUM_GPIO; i++) - if (pdata->key_map[i] != KEY_RESERVED) - __set_bit(pdata->key_map[i], input_dev->keybit); + for (i = 0; i < pdata->t19_num_keys; i++) + if (pdata->t19_keymap[i] != KEY_RESERVED) + input_set_capability(input_dev, EV_KEY, + pdata->t19_keymap[i]); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); - __set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit); + mt_flags |= INPUT_MT_POINTER; input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); @@ -1146,6 +1134,8 @@ static int mxt_probe(struct i2c_client *client, MXT_PIXELS_PER_MM); input_abs_set_res(input_dev, ABS_MT_POSITION_Y, MXT_PIXELS_PER_MM); + + input_dev->name = "Atmel maXTouch Touchpad"; } /* For single touch */ @@ -1158,7 +1148,7 @@ static int mxt_probe(struct i2c_client *client, /* For multi touch */ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; - error = input_mt_init_slots(input_dev, num_mt_slots, 0); + error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); if (error) goto err_free_object; input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 2559a0407c58..8b7523ab62e5 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -84,16 +84,22 @@ static struct i2c_board_info tsl2563_als_device = { I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), }; +static int mxt_t19_keys[] = { + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + BTN_LEFT +}; + static struct mxt_platform_data atmel_224s_tp_platform_data = { .x_size = 102*20, .y_size = 68*20, .orient = MXT_VERTICAL_FLIP, .irqflags = IRQF_TRIGGER_FALLING, - .is_tp = true, - .key_map = { KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - BTN_LEFT }, + .t19_num_keys = ARRAY_SIZE(mxt_t19_keys), + .t19_keymap = mxt_t19_keys, .config = NULL, .config_length = 0, }; @@ -109,7 +115,6 @@ static struct mxt_platform_data atmel_1664s_platform_data = { .y_size = 2560, .orient = MXT_ROTATED_90_COUNTER, .irqflags = IRQF_TRIGGER_FALLING, - .is_tp = false, .config = NULL, .config_length = 0, }; diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index eff0cdc08843..d26080dc606c 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -15,9 +15,6 @@ #include -/* For key_map array */ -#define MXT_NUM_GPIO 4 - /* Orient */ #define MXT_NORMAL 0x0 #define MXT_DIAGONAL 0x1 @@ -38,8 +35,8 @@ struct mxt_platform_data { unsigned char orient; unsigned long irqflags; - bool is_tp; - const unsigned int key_map[MXT_NUM_GPIO]; + u8 t19_num_keys; + const unsigned int *t19_keymap; }; #endif /* __LINUX_ATMEL_MXT_TS_H */ -- cgit v1.2.3-71-gd317 From c3f78043d5aea39205a14c580babd87fbdcfa148 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Sun, 18 May 2014 23:04:46 -0700 Subject: Input: atmel_mxt_ts - implement CRC check for configuration data The configuration is stored in NVRAM on the maXTouch chip. When the device is reset it reports a CRC of the stored configuration values. Therefore it isn't necessary to send the configuration on each probe - we can check the CRC matches and avoid a timeconsuming backup/reset cycle. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 60 +++++++++++++++++++++++++++----- include/linux/i2c/atmel_mxt_ts.h | 1 + 2 files changed, 53 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 278f364ec6e1..61f9ef221d12 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -188,6 +188,7 @@ #define MXT_BACKUP_TIME 50 /* msec */ #define MXT_RESET_TIME 200 /* msec */ #define MXT_RESET_TIMEOUT 3000 /* msec */ +#define MXT_CRC_TIMEOUT 1000 /* msec */ #define MXT_FW_RESET_TIME 3000 /* msec */ #define MXT_FW_CHG_TIMEOUT 300 /* msec */ @@ -259,6 +260,7 @@ struct mxt_data { unsigned int max_x; unsigned int max_y; bool in_bootloader; + u32 config_crc; /* Cached parameters from object table */ u8 T6_reportid; @@ -272,6 +274,9 @@ struct mxt_data { /* for reset handling */ struct completion reset_completion; + + /* for config update handling */ + struct completion crc_completion; }; static size_t mxt_obj_size(const struct mxt_object *obj) @@ -636,7 +641,7 @@ static void mxt_input_touchevent(struct mxt_data *data, } } -static unsigned mxt_extract_T6_csum(const u8 *csum) +static u16 mxt_extract_T6_csum(const u8 *csum) { return csum[0] | (csum[1] << 8) | (csum[2] << 16); } @@ -654,6 +659,7 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data) struct device *dev = &data->client->dev; u8 reportid; bool update_input = false; + u32 crc; do { if (mxt_read_message(data, &message)) { @@ -665,9 +671,15 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data) if (reportid == data->T6_reportid) { u8 status = payload[0]; - unsigned csum = mxt_extract_T6_csum(&payload[1]); + + crc = mxt_extract_T6_csum(&payload[1]); + if (crc != data->config_crc) { + data->config_crc = crc; + complete(&data->crc_completion); + } + dev_dbg(dev, "Status: %02x Config Checksum: %06x\n", - status, csum); + status, data->config_crc); if (status & MXT_T6_STATUS_RESET) complete(&data->reset_completion); @@ -757,6 +769,24 @@ static int mxt_soft_reset(struct mxt_data *data) return 0; } +static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value) +{ + /* + * On failure, CRC is set to 0 and config will always be + * downloaded. + */ + data->config_crc = 0; + reinit_completion(&data->crc_completion); + + mxt_t6_command(data, cmd, value, true); + + /* + * Wait for crc message. On failure, CRC is set to 0 and config will + * always be downloaded. + */ + mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT); +} + static int mxt_check_reg_init(struct mxt_data *data) { const struct mxt_platform_data *pdata = data->pdata; @@ -771,6 +801,16 @@ static int mxt_check_reg_init(struct mxt_data *data) return 0; } + mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); + + if (data->config_crc == pdata->config_crc) { + dev_info(dev, "Config CRC 0x%06X: OK\n", data->config_crc); + return 0; + } + + dev_info(dev, "Config CRC 0x%06X: does not match 0x%06X\n", + data->config_crc, pdata->config_crc); + for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; @@ -790,6 +830,14 @@ static int mxt_check_reg_init(struct mxt_data *data) index += size; } + mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); + + ret = mxt_soft_reset(data); + if (ret) + return ret; + + dev_info(dev, "Config successfully updated\n"); + return 0; } @@ -929,11 +977,6 @@ static int mxt_initialize(struct mxt_data *data) goto err_free_object_table; } - error = mxt_t6_command(data, MXT_COMMAND_BACKUPNV, - MXT_BACKUP_VALUE, false); - if (!error) - mxt_soft_reset(data); - /* Update matrix size at info struct */ error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); if (error) @@ -1263,6 +1306,7 @@ static int mxt_probe(struct i2c_client *client, init_completion(&data->bl_completion); init_completion(&data->reset_completion); + init_completion(&data->crc_completion); mxt_calc_resolution(data); diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index d26080dc606c..9f92135b6620 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -29,6 +29,7 @@ struct mxt_platform_data { const u8 *config; size_t config_length; + u32 config_crc; unsigned int x_size; unsigned int y_size; -- cgit v1.2.3-71-gd317 From 61dc1abae64854c7cef543598b9e6f04886c4ebd Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Sun, 18 May 2014 23:16:49 -0700 Subject: Input: atmel_mxt_ts - read screen config from chip By reading the touchscreen configuration from the settings that the maXTouch chip is actually using, we can remove some platform data. The matrix size is not used for anything, and results in some rather confusing code to re-read it because it may change when configuration is downloaded, so don't print it out. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen Signed-off-by: Dmitry Torokhov --- arch/arm/mach-s5pv210/mach-goni.c | 3 - drivers/input/touchscreen/atmel_mxt_ts.c | 136 ++++++++++++++---------------- drivers/platform/chrome/chromeos_laptop.c | 6 -- include/linux/i2c/atmel_mxt_ts.h | 15 ---- 4 files changed, 65 insertions(+), 95 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index e549ecf0e5dc..bb9354f45e27 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -239,9 +239,6 @@ static void __init goni_radio_init(void) /* TSP */ static struct mxt_platform_data qt602240_platform_data = { - .x_size = 800, - .y_size = 480, - .orient = MXT_DIAGONAL, .irqflags = IRQF_TRIGGER_FALLING, }; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 7a9197a19f67..75493ca8e784 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -100,33 +100,16 @@ /* MXT_TOUCH_MULTI_T9 field */ #define MXT_TOUCH_CTRL 0 -#define MXT_TOUCH_XORIGIN 1 -#define MXT_TOUCH_YORIGIN 2 -#define MXT_TOUCH_XSIZE 3 -#define MXT_TOUCH_YSIZE 4 -#define MXT_TOUCH_BLEN 6 -#define MXT_TOUCH_TCHTHR 7 -#define MXT_TOUCH_TCHDI 8 -#define MXT_TOUCH_ORIENT 9 -#define MXT_TOUCH_MOVHYSTI 11 -#define MXT_TOUCH_MOVHYSTN 12 -#define MXT_TOUCH_NUMTOUCH 14 -#define MXT_TOUCH_MRGHYST 15 -#define MXT_TOUCH_MRGTHR 16 -#define MXT_TOUCH_AMPHYST 17 -#define MXT_TOUCH_XRANGE_LSB 18 -#define MXT_TOUCH_XRANGE_MSB 19 -#define MXT_TOUCH_YRANGE_LSB 20 -#define MXT_TOUCH_YRANGE_MSB 21 -#define MXT_TOUCH_XLOCLIP 22 -#define MXT_TOUCH_XHICLIP 23 -#define MXT_TOUCH_YLOCLIP 24 -#define MXT_TOUCH_YHICLIP 25 -#define MXT_TOUCH_XEDGECTRL 26 -#define MXT_TOUCH_XEDGEDIST 27 -#define MXT_TOUCH_YEDGECTRL 28 -#define MXT_TOUCH_YEDGEDIST 29 -#define MXT_TOUCH_JUMPLIMIT 30 +#define MXT_T9_ORIENT 9 +#define MXT_T9_RANGE 18 + +struct t9_range { + u16 x; + u16 y; +} __packed; + +/* Touch orient bits */ +#define MXT_XY_SWITCH (1 << 0) /* MXT_PROCI_GRIPFACE_T20 field */ #define MXT_GRIPFACE_CTRL 0 @@ -211,11 +194,6 @@ #define MXT_PRESS (1 << 6) #define MXT_DETECT (1 << 7) -/* Touch orient bits */ -#define MXT_XY_SWITCH (1 << 0) -#define MXT_X_INVERT (1 << 1) -#define MXT_Y_INVERT (1 << 2) - /* Touchscreen absolute values */ #define MXT_MAX_AREA 0xff @@ -580,11 +558,6 @@ static int __mxt_read_reg(struct i2c_client *client, return ret; } -static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) -{ - return __mxt_read_reg(client, reg, 1, val); -} - static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len, const void *val) { @@ -1029,12 +1002,59 @@ static void mxt_free_object_table(struct mxt_data *data) data->T19_reportid = 0; } +static int mxt_read_t9_resolution(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + int error; + struct t9_range range; + unsigned char orient; + struct mxt_object *object; + + object = mxt_get_object(data, MXT_TOUCH_MULTI_T9); + if (!object) + return -EINVAL; + + error = __mxt_read_reg(client, + object->start_address + MXT_T9_RANGE, + sizeof(range), &range); + if (error) + return error; + + le16_to_cpus(&range.x); + le16_to_cpus(&range.y); + + error = __mxt_read_reg(client, + object->start_address + MXT_T9_ORIENT, + 1, &orient); + if (error) + return error; + + /* Handle default values */ + if (range.x == 0) + range.x = 1023; + + if (range.y == 0) + range.y = 1023; + + if (orient & MXT_XY_SWITCH) { + data->max_x = range.y; + data->max_y = range.x; + } else { + data->max_x = range.x; + data->max_y = range.y; + } + + dev_dbg(&client->dev, + "Touchscreen size X%uY%u\n", data->max_x, data->max_y); + + return 0; +} + static int mxt_initialize(struct mxt_data *data) { struct i2c_client *client = data->client; struct mxt_info *info = &data->info; int error; - u8 val; error = mxt_get_info(data); if (error) @@ -1063,26 +1083,16 @@ static int mxt_initialize(struct mxt_data *data) goto err_free_object_table; } - /* Update matrix size at info struct */ - error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); - if (error) - goto err_free_object_table; - info->matrix_xsize = val; - - error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val); - if (error) + error = mxt_read_t9_resolution(data); + if (error) { + dev_err(&client->dev, "Failed to initialize T9 resolution\n"); goto err_free_object_table; - info->matrix_ysize = val; - - dev_info(&client->dev, - "Family: %u Variant: %u Firmware V%u.%u.%02X\n", - info->family_id, info->variant_id, info->version >> 4, - info->version & 0xf, info->build); + } dev_info(&client->dev, - "Matrix X Size: %u Matrix Y Size: %u Objects: %u\n", - info->matrix_xsize, info->matrix_ysize, - info->object_num); + "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", + info->family_id, info->variant_id, info->version >> 4, + info->version & 0xf, info->build, info->object_num); return 0; @@ -1091,20 +1101,6 @@ err_free_object_table: return error; } -static void mxt_calc_resolution(struct mxt_data *data) -{ - unsigned int max_x = data->pdata->x_size - 1; - unsigned int max_y = data->pdata->y_size - 1; - - if (data->pdata->orient & MXT_XY_SWITCH) { - data->max_x = max_y; - data->max_y = max_x; - } else { - data->max_x = max_x; - data->max_y = max_y; - } -} - /* Firmware Version is returned as Major.Minor.Build */ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1430,8 +1426,6 @@ static int mxt_probe(struct i2c_client *client, init_completion(&data->reset_completion); init_completion(&data->crc_completion); - mxt_calc_resolution(data); - error = mxt_initialize(data); if (error) goto err_free_mem; diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 8b7523ab62e5..7f1a2e2711bd 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -94,9 +94,6 @@ static int mxt_t19_keys[] = { }; static struct mxt_platform_data atmel_224s_tp_platform_data = { - .x_size = 102*20, - .y_size = 68*20, - .orient = MXT_VERTICAL_FLIP, .irqflags = IRQF_TRIGGER_FALLING, .t19_num_keys = ARRAY_SIZE(mxt_t19_keys), .t19_keymap = mxt_t19_keys, @@ -111,9 +108,6 @@ static struct i2c_board_info atmel_224s_tp_device = { }; static struct mxt_platform_data atmel_1664s_platform_data = { - .x_size = 1700, - .y_size = 2560, - .orient = MXT_ROTATED_90_COUNTER, .irqflags = IRQF_TRIGGER_FALLING, .config = NULL, .config_length = 0, diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index 9f92135b6620..3891dc1de21c 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -15,26 +15,11 @@ #include -/* Orient */ -#define MXT_NORMAL 0x0 -#define MXT_DIAGONAL 0x1 -#define MXT_HORIZONTAL_FLIP 0x2 -#define MXT_ROTATED_90_COUNTER 0x3 -#define MXT_VERTICAL_FLIP 0x4 -#define MXT_ROTATED_90 0x5 -#define MXT_ROTATED_180 0x6 -#define MXT_DIAGONAL_COUNTER 0x7 - /* The platform data for the Atmel maXTouch touchscreen driver */ struct mxt_platform_data { const u8 *config; size_t config_length; u32 config_crc; - - unsigned int x_size; - unsigned int y_size; - unsigned char orient; - unsigned long irqflags; u8 t19_num_keys; const unsigned int *t19_keymap; -- cgit v1.2.3-71-gd317 From b98abe52fa8e2a3797d3cc2db3d0e109f4549c03 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 28 May 2014 23:51:53 -0700 Subject: Input: add common DT binding for touchscreens Add common DT binding documentation for touchscreen devices and implement input_parse_touchscreen_of_params, which parses the common properties and configures the input device accordingly. The method currently does not interpret the axis inversion properties, since there is no matching flag in the generic linux input device. Reviewed-by: Pavel Machek Acked-by: Aaro Koskinen Signed-off-by: Sebastian Reichel Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/touchscreen.txt | 27 +++++++++++++ drivers/input/touchscreen/Kconfig | 4 ++ drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/of_touchscreen.c | 45 ++++++++++++++++++++++ include/linux/input/touchscreen.h | 22 +++++++++++ 5 files changed, 99 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt create mode 100644 drivers/input/touchscreen/of_touchscreen.c create mode 100644 include/linux/input/touchscreen.h (limited to 'include/linux') diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt new file mode 100644 index 000000000000..d8e06163c54e --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt @@ -0,0 +1,27 @@ +General Touchscreen Properties: + +Optional properties for Touchscreens: + - touchscreen-size-x : horizontal resolution of touchscreen + (in pixels) + - touchscreen-size-y : vertical resolution of touchscreen + (in pixels) + - touchscreen-max-pressure : maximum reported pressure (arbitrary range + dependent on the controller) + - touchscreen-fuzz-x : horizontal noise value of the absolute input + device (in pixels) + - touchscreen-fuzz-y : vertical noise value of the absolute input + device (in pixels) + - touchscreen-fuzz-pressure : pressure noise value of the absolute input + device (arbitrary range dependent on the + controller) + - touchscreen-inverted-x : X axis is inverted (boolean) + - touchscreen-inverted-y : Y axis is inverted (boolean) + +Deprecated properties for Touchscreens: + - x-size : deprecated name for touchscreen-size-x + - y-size : deprecated name for touchscreen-size-y + - moving-threshold : deprecated name for a combination of + touchscreen-fuzz-x and touchscreen-fuzz-y + - contact-threshold : deprecated name for touchscreen-fuzz-pressure + - x-invert : deprecated name for touchscreen-inverted-x + - y-invert : deprecated name for touchscreen-inverted-y diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 43389c097b02..8e07fe8505fd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -11,6 +11,10 @@ menuconfig INPUT_TOUCHSCREEN if INPUT_TOUCHSCREEN +config OF_TOUCHSCREEN + def_tristate INPUT + depends on INPUT && OF + config TOUCHSCREEN_88PM860X tristate "Marvell 88PM860x touchscreen" depends on MFD_88PM860X diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 71a97559ce68..4d479fb0a768 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -6,6 +6,7 @@ wm97xx-ts-y := wm97xx-core.o +obj-$(CONFIG_OF_TOUCHSCREEN) += of_touchscreen.o obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o diff --git a/drivers/input/touchscreen/of_touchscreen.c b/drivers/input/touchscreen/of_touchscreen.c new file mode 100644 index 000000000000..f8f9b84230b1 --- /dev/null +++ b/drivers/input/touchscreen/of_touchscreen.c @@ -0,0 +1,45 @@ +/* + * Generic DT helper functions for touchscreen devices + * + * Copyright (c) 2014 Sebastian Reichel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include + +/** + * touchscreen_parse_of_params - parse common touchscreen DT properties + * @dev: device that should be parsed + * + * This function parses common DT properties for touchscreens and setups the + * input device accordingly. The function keeps previously setuped default + * values if no value is specified via DT. + */ +void touchscreen_parse_of_params(struct input_dev *dev) +{ + struct device_node *np = dev->dev.parent->of_node; + struct input_absinfo *absinfo; + + input_alloc_absinfo(dev); + if (!dev->absinfo) + return; + + absinfo = &dev->absinfo[ABS_X]; + of_property_read_u32(np, "touchscreen-size-x", &absinfo->maximum); + of_property_read_u32(np, "touchscreen-fuzz-x", &absinfo->fuzz); + + absinfo = &dev->absinfo[ABS_Y]; + of_property_read_u32(np, "touchscreen-size-y", &absinfo->maximum); + of_property_read_u32(np, "touchscreen-fuzz-y", &absinfo->fuzz); + + absinfo = &dev->absinfo[ABS_PRESSURE]; + of_property_read_u32(np, "touchscreen-max-pressure", &absinfo->maximum); + of_property_read_u32(np, "touchscreen-fuzz-pressure", &absinfo->fuzz); +} +EXPORT_SYMBOL(touchscreen_parse_of_params); diff --git a/include/linux/input/touchscreen.h b/include/linux/input/touchscreen.h new file mode 100644 index 000000000000..08a5ef6e8f25 --- /dev/null +++ b/include/linux/input/touchscreen.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014 Sebastian Reichel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _TOUCHSCREEN_H +#define _TOUCHSCREEN_H + +#include + +#ifdef CONFIG_OF +void touchscreen_parse_of_params(struct input_dev *dev); +#else +static inline void touchscreen_parse_of_params(struct input_dev *dev) +{ +} +#endif + +#endif -- cgit v1.2.3-71-gd317 From 61721c88b8d85c9dc13bfeedf75dfc245f397c3c Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 29 May 2014 00:30:02 -0700 Subject: Input: omap-keypad - remove platform data support This is unused since all users (OMAP4/5) are DT only. Signed-off-by: Joachim Eastwood Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/keyboard/omap4-keypad.c | 32 ++++++------------------------ include/linux/platform_data/omap4-keypad.h | 13 ------------ 3 files changed, 7 insertions(+), 40 deletions(-) delete mode 100644 include/linux/platform_data/omap4-keypad.h (limited to 'include/linux') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 948a30304870..0f84f2346fe4 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -589,7 +589,7 @@ config KEYBOARD_OMAP config KEYBOARD_OMAP4 tristate "TI OMAP4+ keypad support" - depends on ARCH_OMAP2PLUS + depends on OF || ARCH_OMAP2PLUS select INPUT_MATRIXKMAP help Say Y here if you want to use the OMAP4+ keypad. diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 0400b3f2b4b9..024b7bdffe5b 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -28,11 +28,10 @@ #include #include #include +#include #include #include -#include - /* OMAP4 registers */ #define OMAP4_KBD_REVISION 0x00 #define OMAP4_KBD_SYSCONFIG 0x10 @@ -218,7 +217,6 @@ static void omap4_keypad_close(struct input_dev *input) pm_runtime_put_sync(input->dev.parent); } -#ifdef CONFIG_OF static int omap4_keypad_parse_dt(struct device *dev, struct omap4_keypad *keypad_data) { @@ -235,20 +233,9 @@ static int omap4_keypad_parse_dt(struct device *dev, return 0; } -#else -static inline int omap4_keypad_parse_dt(struct device *dev, - struct omap4_keypad *keypad_data) -{ - return -ENOSYS; -} -#endif static int omap4_keypad_probe(struct platform_device *pdev) { - const struct omap4_keypad_platform_data *pdata = - dev_get_platdata(&pdev->dev); - const struct matrix_keymap_data *keymap_data = - pdata ? pdata->keymap_data : NULL; struct omap4_keypad *keypad_data; struct input_dev *input_dev; struct resource *res; @@ -277,14 +264,9 @@ static int omap4_keypad_probe(struct platform_device *pdev) keypad_data->irq = irq; - if (pdata) { - keypad_data->rows = pdata->rows; - keypad_data->cols = pdata->cols; - } else { - error = omap4_keypad_parse_dt(&pdev->dev, keypad_data); - if (error) - return error; - } + error = omap4_keypad_parse_dt(&pdev->dev, keypad_data); + if (error) + return error; res = request_mem_region(res->start, resource_size(res), pdev->name); if (!res) { @@ -363,7 +345,7 @@ static int omap4_keypad_probe(struct platform_device *pdev) goto err_free_input; } - error = matrix_keypad_build_keymap(keymap_data, NULL, + error = matrix_keypad_build_keymap(NULL, NULL, keypad_data->rows, keypad_data->cols, keypad_data->keymap, input_dev); if (error) { @@ -434,13 +416,11 @@ static int omap4_keypad_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id omap_keypad_dt_match[] = { { .compatible = "ti,omap4-keypad" }, {}, }; MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); -#endif #ifdef CONFIG_PM_SLEEP static int omap4_keypad_suspend(struct device *dev) @@ -482,7 +462,7 @@ static struct platform_driver omap4_keypad_driver = { .name = "omap4-keypad", .owner = THIS_MODULE, .pm = &omap4_keypad_pm_ops, - .of_match_table = of_match_ptr(omap_keypad_dt_match), + .of_match_table = omap_keypad_dt_match, }, }; module_platform_driver(omap4_keypad_driver); diff --git a/include/linux/platform_data/omap4-keypad.h b/include/linux/platform_data/omap4-keypad.h deleted file mode 100644 index 4eef5fb05a17..000000000000 --- a/include/linux/platform_data/omap4-keypad.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __LINUX_INPUT_OMAP4_KEYPAD_H -#define __LINUX_INPUT_OMAP4_KEYPAD_H - -#include - -struct omap4_keypad_platform_data { - const struct matrix_keymap_data *keymap_data; - - u8 rows; - u8 cols; -}; - -#endif /* __LINUX_INPUT_OMAP4_KEYPAD_H */ -- cgit v1.2.3-71-gd317