diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 13:20:36 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 13:20:36 -0800 |
commit | 86a0b4255e84563739d137ad374af6c7215bb3ff (patch) | |
tree | be80eb7559564cafc5531dea421fa65e8e5e4c43 /drivers/input | |
parent | 531d2644f3b10098dadb25b2c26cf19ec0330f90 (diff) | |
parent | e291c116f60f3c1ca98090f0f8e7c77e658562fb (diff) |
Merge tag 'input-for-v6.2-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
- a new driver for Cypress Generation 5 touchscreens
- a new driver for Hynitron cstxxx touchscreens
- a new driver for Himax hx83112b touchscreen
- I2C input devices have been converted to use i2c's probe_new()
- a large number of input devices are now using
DEFINE_SIMPLE_DEV_PM_OPS and pm_sleep_ptr() and no longer use
__maybe_unused annotations
- improvements to msg2638 touchscreen driver to also support msg2138
- conversion of several input deevine bindings to yaml/DT schema
- changes to select touch drivers to move handling of wake irqs to the
PM core
- other assorted fixes and improvements.
* tag 'input-for-v6.2-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (165 commits)
Input: elants_i2c - delay longer with reset asserted
dt-bindings: input: Convert ti,drv260x to DT schema
dt-bindings: input: gpio-beeper: Convert to yaml schema
Input: pxspad - fix unused data warning when force feedback not enabled
Input: lpc32xx - allow building with COMPILE_TEST
Input: nomadik-ske-keypad - allow building with COMPILE_TEST
Input: pxa27xx-keypad - allow build with COMPILE_TEST
Input: spear-keyboard - improve build coverage using COMPILE_TEST
Input: tegra-kbc - allow build with COMPILE_TEST
Input: tegra-kbc - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: tca6416-keypad - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: tc3589x - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: st-keyscan - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: sh-keysc - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: qt1070 - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: pxa27x_keypad - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: pmic8xxx-keypad - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: nomadik-ske-keypad - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: mcs-touchkey - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
Input: max7359-keypad - switch to DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr()
...
Diffstat (limited to 'drivers/input')
108 files changed, 2594 insertions, 645 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index ebb2b7f0f8ff..783961df3626 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -21,6 +21,7 @@ #include <linux/seq_file.h> #include <linux/poll.h> #include <linux/device.h> +#include <linux/kstrtox.h> #include <linux/mutex.h> #include <linux/rcupdate.h> #include "input-compat.h" @@ -1465,7 +1466,7 @@ static ssize_t inhibited_store(struct device *dev, ssize_t rv; bool inhibited; - if (strtobool(buf, &inhibited)) + if (kstrtobool(buf, &inhibited)) return -EINVAL; if (inhibited) diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 9dcf3f51f2dd..04ca3d1c2816 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -46,6 +46,7 @@ config JOYSTICK_A3D config JOYSTICK_ADC tristate "Simple joystick connected over ADC" depends on IIO + select IIO_BUFFER select IIO_BUFFER_CB help Say Y here if you have a simple joystick connected over ADC. diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index 2beda29021a3..3b88f0b49e01 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -212,8 +212,7 @@ static int as5011_configure_chip(struct as5011_device *as5011, return 0; } -static int as5011_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int as5011_probe(struct i2c_client *client) { const struct as5011_platform_data *plat_data; struct as5011_device *as5011; @@ -349,7 +348,7 @@ static struct i2c_driver as5011_driver = { .driver = { .name = "as5011", }, - .probe = as5011_probe, + .probe_new = as5011_probe, .remove = as5011_remove, .id_table = as5011_id, }; diff --git a/drivers/input/joystick/psxpad-spi.c b/drivers/input/joystick/psxpad-spi.c index a32656064f39..de734a927b4d 100644 --- a/drivers/input/joystick/psxpad-spi.c +++ b/drivers/input/joystick/psxpad-spi.c @@ -44,6 +44,8 @@ static const u8 PSX_CMD_POLL[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +#ifdef CONFIG_JOYSTICK_PSXPAD_SPI_FF /* 0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 */ static const u8 PSX_CMD_ENTER_CFG[] = { 0x80, 0xC2, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -56,6 +58,7 @@ static const u8 PSX_CMD_EXIT_CFG[] = { static const u8 PSX_CMD_ENABLE_MOTOR[] = { 0x80, 0xB2, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF }; +#endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */ struct psxpad { struct spi_device *spi; @@ -371,7 +374,7 @@ static int psxpad_spi_probe(struct spi_device *spi) return 0; } -static int __maybe_unused psxpad_spi_suspend(struct device *dev) +static int psxpad_spi_suspend(struct device *dev) { struct spi_device *spi = to_spi_device(dev); struct psxpad *pad = spi_get_drvdata(spi); @@ -381,7 +384,7 @@ static int __maybe_unused psxpad_spi_suspend(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL); +static DEFINE_SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL); static const struct spi_device_id psxpad_spi_id[] = { { "psxpad-spi", 0 }, @@ -392,7 +395,7 @@ MODULE_DEVICE_TABLE(spi, psxpad_spi_id); static struct spi_driver psxpad_spi_driver = { .driver = { .name = "psxpad-spi", - .pm = &psxpad_spi_pm, + .pm = pm_sleep_ptr(&psxpad_spi_pm), }, .id_table = psxpad_spi_id, .probe = psxpad_spi_probe, diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 00292118b79b..84490915ae4d 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -390,7 +390,7 @@ config KEYBOARD_LOCOMO config KEYBOARD_LPC32XX tristate "LPC32XX matrix key scanner support" - depends on ARCH_LPC32XX && OF + depends on (ARCH_LPC32XX && OF) || COMPILE_TEST select INPUT_MATRIXKMAP help Say Y here if you want to use NXP LPC32XX SoC key scanner interface, @@ -487,7 +487,7 @@ config KEYBOARD_NEWTON config KEYBOARD_NOMADIK tristate "ST-Ericsson Nomadik SKE keyboard" - depends on (ARCH_NOMADIK || ARCH_U8500) + depends on (ARCH_NOMADIK || ARCH_U8500 || COMPILE_TEST) select INPUT_MATRIXKMAP help Say Y here if you want to use a keypad provided on the SKE controller @@ -508,7 +508,7 @@ config KEYBOARD_NSPIRE config KEYBOARD_TEGRA tristate "NVIDIA Tegra internal matrix keyboard controller support" - depends on ARCH_TEGRA && OF + depends on (ARCH_TEGRA && OF) || COMPILE_TEST select INPUT_MATRIXKMAP help Say Y here if you want to use a matrix keyboard connected directly @@ -542,7 +542,7 @@ config KEYBOARD_PINEPHONE config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" - depends on PXA27x || PXA3xx || ARCH_MMP + depends on PXA27x || PXA3xx || ARCH_MMP || COMPILE_TEST select INPUT_MATRIXKMAP help Enable support for PXA27x/PXA3xx keypad controller. @@ -709,7 +709,7 @@ config KEYBOARD_OMAP4 config KEYBOARD_SPEAR tristate "ST SPEAR keyboard support" - depends on PLAT_SPEAR + depends on PLAT_SPEAR || COMPILE_TEST select INPUT_MATRIXKMAP help Say Y here if you want to use the SPEAR keyboard. diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 7cd83c8e7110..72ae5ce72956 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -718,8 +718,7 @@ static void adp5588_disable_regulator(void *reg) regulator_disable(reg); } -static int adp5588_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adp5588_probe(struct i2c_client *client) { struct adp5588_kpad *kpad; struct input_dev *input; @@ -867,7 +866,7 @@ static struct i2c_driver adp5588_driver = { .of_match_table = adp5588_of_match, .pm = pm_sleep_ptr(&adp5588_dev_pm_ops), }, - .probe = adp5588_probe, + .probe_new = adp5588_probe, .remove = adp5588_remove, .id_table = adp5588_id, }; diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index bdd264459a97..38d7073863a8 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -942,9 +942,9 @@ static void adp5589_clear_config(void *data) adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); } -static int adp5589_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adp5589_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct adp5589_kpad *kpad; const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(&client->dev); @@ -1016,7 +1016,7 @@ static int adp5589_probe(struct i2c_client *client, return 0; } -static int __maybe_unused adp5589_suspend(struct device *dev) +static int adp5589_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct adp5589_kpad *kpad = i2c_get_clientdata(client); @@ -1027,7 +1027,7 @@ static int __maybe_unused adp5589_suspend(struct device *dev) return 0; } -static int __maybe_unused adp5589_resume(struct device *dev) +static int adp5589_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct adp5589_kpad *kpad = i2c_get_clientdata(client); @@ -1038,7 +1038,7 @@ static int __maybe_unused adp5589_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume); static const struct i2c_device_id adp5589_id[] = { {"adp5589-keys", ADP5589}, @@ -1052,9 +1052,9 @@ MODULE_DEVICE_TABLE(i2c, adp5589_id); static struct i2c_driver adp5589_driver = { .driver = { .name = KBUILD_MODNAME, - .pm = &adp5589_dev_pm_ops, + .pm = pm_sleep_ptr(&adp5589_dev_pm_ops), }, - .probe = adp5589_probe, + .probe_new = adp5589_probe, .id_table = adp5589_id, }; diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 7c85343cd32f..79afd0386e3f 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -321,9 +321,9 @@ static int cap11xx_init_leds(struct device *dev, } #endif -static int cap11xx_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) +static int cap11xx_i2c_probe(struct i2c_client *i2c_client) { + const struct i2c_device_id *id = i2c_client_get_device_id(i2c_client); struct device *dev = &i2c_client->dev; struct cap11xx_priv *priv; struct device_node *node; @@ -503,7 +503,7 @@ static struct i2c_driver cap11xx_i2c_driver = { .of_match_table = cap11xx_dt_ids, }, .id_table = cap11xx_i2c_ids, - .probe = cap11xx_i2c_probe, + .probe_new = cap11xx_i2c_probe, }; module_i2c_driver(cap11xx_i2c_driver); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index c14136b733a9..6f435125ec03 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -415,7 +415,7 @@ static int cros_ec_keyb_query_switches(struct cros_ec_keyb *ckdev) * * Returns 0 if no error or -error upon error. */ -static __maybe_unused int cros_ec_keyb_resume(struct device *dev) +static int cros_ec_keyb_resume(struct device *dev) { struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); @@ -760,7 +760,7 @@ static const struct of_device_id cros_ec_keyb_of_match[] = { MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match); #endif -static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume); static struct platform_driver cros_ec_keyb_driver = { .probe = cros_ec_keyb_probe, @@ -769,7 +769,7 @@ static struct platform_driver cros_ec_keyb_driver = { .name = "cros-ec-keyb", .of_match_table = of_match_ptr(cros_ec_keyb_of_match), .acpi_match_table = ACPI_PTR(cros_ec_keyb_acpi_match), - .pm = &cros_ec_keyb_pm_ops, + .pm = pm_sleep_ptr(&cros_ec_keyb_pm_ops), }, }; diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c index 9a23eed6a4f4..686388f40317 100644 --- a/drivers/input/keyboard/cypress-sf.c +++ b/drivers/input/keyboard/cypress-sf.c @@ -168,7 +168,7 @@ static int cypress_sf_probe(struct i2c_client *client) return 0; }; -static int __maybe_unused cypress_sf_suspend(struct device *dev) +static int cypress_sf_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct cypress_sf_data *touchkey = i2c_get_clientdata(client); @@ -187,7 +187,7 @@ static int __maybe_unused cypress_sf_suspend(struct device *dev) return 0; } -static int __maybe_unused cypress_sf_resume(struct device *dev) +static int cypress_sf_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct cypress_sf_data *touchkey = i2c_get_clientdata(client); @@ -205,8 +205,8 @@ static int __maybe_unused cypress_sf_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops, - cypress_sf_suspend, cypress_sf_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops, + cypress_sf_suspend, cypress_sf_resume); static struct i2c_device_id cypress_sf_id_table[] = { { CYPRESS_SF_DEV_NAME, 0 }, @@ -225,7 +225,7 @@ MODULE_DEVICE_TABLE(of, cypress_sf_of_match); static struct i2c_driver cypress_sf_driver = { .driver = { .name = CYPRESS_SF_DEV_NAME, - .pm = &cypress_sf_pm_ops, + .pm = pm_sleep_ptr(&cypress_sf_pm_ops), .of_match_table = of_match_ptr(cypress_sf_of_match), }, .id_table = cypress_sf_id_table, diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c index a69dcc3bd30c..ddba2bc861da 100644 --- a/drivers/input/keyboard/dlink-dir685-touchkeys.c +++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c @@ -59,12 +59,11 @@ static irqreturn_t dir685_tk_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int dir685_tk_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int dir685_tk_probe(struct i2c_client *client) { - struct dir685_touchkeys *tk; + static const u8 bl_data[] = { 0xa7, 0x40 }; struct device *dev = &client->dev; - u8 bl_data[] = { 0xa7, 0x40 }; + struct dir685_touchkeys *tk; int err; int i; @@ -146,7 +145,7 @@ static struct i2c_driver dir685_tk_i2c_driver = { .name = "dlink-dir685-touchkeys", .of_match_table = of_match_ptr(dir685_tk_of_match), }, - .probe = dir685_tk_probe, + .probe_new = dir685_tk_probe, .id_table = dir685_tk_id, }; module_i2c_driver(dir685_tk_i2c_driver); diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index f5bf7524722a..55075addcac2 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -178,7 +178,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev) } -static int __maybe_unused ep93xx_keypad_suspend(struct device *dev) +static int ep93xx_keypad_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); @@ -196,7 +196,7 @@ static int __maybe_unused ep93xx_keypad_suspend(struct device *dev) return 0; } -static int __maybe_unused ep93xx_keypad_resume(struct device *dev) +static int ep93xx_keypad_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); @@ -217,8 +217,8 @@ static int __maybe_unused ep93xx_keypad_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, - ep93xx_keypad_suspend, ep93xx_keypad_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, + ep93xx_keypad_suspend, ep93xx_keypad_resume); static void ep93xx_keypad_release_gpio_action(void *_pdev) { @@ -318,7 +318,7 @@ static int ep93xx_keypad_remove(struct platform_device *pdev) static struct platform_driver ep93xx_keypad_driver = { .driver = { .name = "ep93xx-keypad", - .pm = &ep93xx_keypad_pm_ops, + .pm = pm_sleep_ptr(&ep93xx_keypad_pm_ops), }, .probe = ep93xx_keypad_probe, .remove = ep93xx_keypad_remove, diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a5dc4ab87fa1..5496482a38c1 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -992,7 +992,7 @@ gpio_keys_disable_wakeup(struct gpio_keys_drvdata *ddata) } } -static int __maybe_unused gpio_keys_suspend(struct device *dev) +static int gpio_keys_suspend(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct input_dev *input = ddata->input; @@ -1012,7 +1012,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev) return 0; } -static int __maybe_unused gpio_keys_resume(struct device *dev) +static int gpio_keys_resume(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct input_dev *input = ddata->input; @@ -1034,7 +1034,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); static void gpio_keys_shutdown(struct platform_device *pdev) { @@ -1050,7 +1050,7 @@ static struct platform_driver gpio_keys_device_driver = { .shutdown = gpio_keys_shutdown, .driver = { .name = "gpio-keys", - .pm = &gpio_keys_pm_ops, + .pm = pm_sleep_ptr(&gpio_keys_pm_ops), .of_match_table = gpio_keys_of_match, .dev_groups = gpio_keys_groups, } diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c index 13a66a8e3411..7b509bce2b33 100644 --- a/drivers/input/keyboard/ipaq-micro-keys.c +++ b/drivers/input/keyboard/ipaq-micro-keys.c @@ -124,7 +124,7 @@ static int micro_key_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused micro_key_suspend(struct device *dev) +static int micro_key_suspend(struct device *dev) { struct ipaq_micro_keys *keys = dev_get_drvdata(dev); @@ -133,7 +133,7 @@ static int __maybe_unused micro_key_suspend(struct device *dev) return 0; } -static int __maybe_unused micro_key_resume(struct device *dev) +static int micro_key_resume(struct device *dev) { struct ipaq_micro_keys *keys = dev_get_drvdata(dev); struct input_dev *input = keys->input; @@ -148,13 +148,13 @@ static int __maybe_unused micro_key_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(micro_key_dev_pm_ops, - micro_key_suspend, micro_key_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(micro_key_dev_pm_ops, + micro_key_suspend, micro_key_resume); static struct platform_driver micro_key_device_driver = { .driver = { .name = "ipaq-micro-keys", - .pm = µ_key_dev_pm_ops, + .pm = pm_sleep_ptr(µ_key_dev_pm_ops), }, .probe = micro_key_probe, }; diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 407dd2ad6302..5df4d5a7ed9e 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -615,8 +615,7 @@ static ssize_t lm8323_set_disable(struct device *dev, } static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable); -static int lm8323_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lm8323_probe(struct i2c_client *client) { struct lm8323_platform_data *pdata = dev_get_platdata(&client->dev); struct input_dev *idev; @@ -771,7 +770,6 @@ static void lm8323_remove(struct i2c_client *client) kfree(lm); } -#ifdef CONFIG_PM_SLEEP /* * We don't need to explicitly suspend the chip, as it already switches off * when there's no activity. @@ -815,9 +813,8 @@ static int lm8323_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume); static const struct i2c_device_id lm8323_id[] = { { "lm8323", 0 }, @@ -827,9 +824,9 @@ static const struct i2c_device_id lm8323_id[] = { static struct i2c_driver lm8323_i2c_driver = { .driver = { .name = "lm8323", - .pm = &lm8323_pm_ops, + .pm = pm_sleep_ptr(&lm8323_pm_ops), }, - .probe = lm8323_probe, + .probe_new = lm8323_probe, .remove = lm8323_remove, .id_table = lm8323_id, }; diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 3052cd6dedac..7457c3220f90 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -125,8 +125,7 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int lm8333_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lm8333_probe(struct i2c_client *client) { const struct lm8333_platform_data *pdata = dev_get_platdata(&client->dev); @@ -219,7 +218,7 @@ static struct i2c_driver lm8333_driver = { .driver = { .name = "lm8333", }, - .probe = lm8333_probe, + .probe_new = lm8333_probe, .remove = lm8333_remove, .id_table = lm8333_id, }; diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index 943aeeb0de79..911e1181cd6f 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -264,7 +264,6 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int lpc32xx_kscan_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -302,10 +301,9 @@ static int lpc32xx_kscan_resume(struct device *dev) mutex_unlock(&input->mutex); return retval; } -#endif -static SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend, - lpc32xx_kscan_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend, + lpc32xx_kscan_resume); static const struct of_device_id lpc32xx_kscan_match[] = { { .compatible = "nxp,lpc3220-key" }, @@ -317,7 +315,7 @@ static struct platform_driver lpc32xx_kscan_driver = { .probe = lpc32xx_kscan_probe, .driver = { .name = DRV_NAME, - .pm = &lpc32xx_kscan_pm_ops, + .pm = pm_sleep_ptr(&lpc32xx_kscan_pm_ops), .of_match_table = lpc32xx_kscan_match, } }; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 7dd3f3eda834..203310727d88 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -127,6 +127,9 @@ static void matrix_keypad_scan(struct work_struct *work) memset(new_state, 0, sizeof(new_state)); + for (row = 0; row < pdata->num_row_gpios; row++) + gpio_direction_input(pdata->row_gpios[row]); + /* assert each column and read the row status out */ for (col = 0; col < pdata->num_col_gpios; col++) { @@ -227,7 +230,6 @@ static void matrix_keypad_stop(struct input_dev *dev) disable_row_irqs(keypad); } -#ifdef CONFIG_PM_SLEEP static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) { const struct matrix_keypad_platform_data *pdata = keypad->pdata; @@ -296,10 +298,9 @@ static int matrix_keypad_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, - matrix_keypad_suspend, matrix_keypad_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, + matrix_keypad_suspend, matrix_keypad_resume); static int matrix_keypad_init_gpio(struct platform_device *pdev, struct matrix_keypad *keypad) @@ -574,7 +575,7 @@ static struct platform_driver matrix_keypad_driver = { .remove = matrix_keypad_remove, .driver = { .name = "matrix-keypad", - .pm = &matrix_keypad_pm_ops, + .pm = pm_sleep_ptr(&matrix_keypad_pm_ops), .of_match_table = of_match_ptr(matrix_keypad_dt_match), }, }; diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 62ce93462955..b363749d02e2 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -155,8 +155,7 @@ static void max7359_initialize(struct i2c_client *client) max7359_fall_deepsleep(client); } -static int max7359_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max7359_probe(struct i2c_client *client) { const struct matrix_keymap_data *keymap_data = dev_get_platdata(&client->dev); @@ -243,7 +242,6 @@ static int max7359_probe(struct i2c_client *client, return 0; } -#ifdef CONFIG_PM_SLEEP static int max7359_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -268,9 +266,8 @@ static int max7359_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume); static const struct i2c_device_id max7359_ids[] = { { "max7359", 0 }, @@ -281,9 +278,9 @@ MODULE_DEVICE_TABLE(i2c, max7359_ids); static struct i2c_driver max7359_i2c_driver = { .driver = { .name = "max7359", - .pm = &max7359_pm, + .pm = pm_sleep_ptr(&max7359_pm), }, - .probe = max7359_probe, + .probe_new = max7359_probe, .id_table = max7359_ids, }; diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index ac1637a3389e..d414e19e4559 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -92,9 +92,9 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int mcs_touchkey_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mcs_touchkey_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct mcs_platform_data *pdata; struct mcs_touchkey_data *data; struct input_dev *input_dev; @@ -213,7 +213,6 @@ static void mcs_touchkey_shutdown(struct i2c_client *client) data->poweron(false); } -#ifdef CONFIG_PM_SLEEP static int mcs_touchkey_suspend(struct device *dev) { struct mcs_touchkey_data *data = dev_get_drvdata(dev); @@ -243,10 +242,9 @@ static int mcs_touchkey_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, - mcs_touchkey_suspend, mcs_touchkey_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, + mcs_touchkey_suspend, mcs_touchkey_resume); static const struct i2c_device_id mcs_touchkey_id[] = { { "mcs5000_touchkey", MCS5000_TOUCHKEY }, @@ -258,9 +256,9 @@ MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id); static struct i2c_driver mcs_touchkey_driver = { .driver = { .name = "mcs_touchkey", - .pm = &mcs_touchkey_pm_ops, + .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops), }, - .probe = mcs_touchkey_probe, + .probe_new = mcs_touchkey_probe, .remove = mcs_touchkey_remove, .shutdown = mcs_touchkey_shutdown, .id_table = mcs_touchkey_id, diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 230ab3d50b9e..74ad353462a3 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -230,8 +230,7 @@ err_i2c_write: return ret; } -static int mpr_touchkey_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mpr_touchkey_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct regulator *vdd_supply; @@ -341,7 +340,7 @@ static int mpr_touchkey_probe(struct i2c_client *client, return 0; } -static int __maybe_unused mpr_suspend(struct device *dev) +static int mpr_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -353,7 +352,7 @@ static int __maybe_unused mpr_suspend(struct device *dev) return 0; } -static int __maybe_unused mpr_resume(struct device *dev) +static int mpr_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client); @@ -367,7 +366,7 @@ static int __maybe_unused mpr_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume); static const struct i2c_device_id mpr121_id[] = { { "mpr121_touchkey", 0 }, @@ -386,11 +385,11 @@ MODULE_DEVICE_TABLE(of, mpr121_touchkey_dt_match_table); static struct i2c_driver mpr_touchkey_driver = { .driver = { .name = "mpr121", - .pm = &mpr121_touchkey_pm_ops, + .pm = pm_sleep_ptr(&mpr121_touchkey_pm_ops), .of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table), }, .id_table = mpr121_id, - .probe = mpr_touchkey_probe, + .probe_new = mpr_touchkey_probe, }; module_i2c_driver(mpr_touchkey_driver); diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c index 9b34da0ec260..3d4ffa25e3df 100644 --- a/drivers/input/keyboard/mtk-pmic-keys.c +++ b/drivers/input/keyboard/mtk-pmic-keys.c @@ -231,7 +231,7 @@ static int mtk_pmic_key_setup(struct mtk_pmic_keys *keys, return 0; } -static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev) +static int mtk_pmic_keys_suspend(struct device *dev) { struct mtk_pmic_keys *keys = dev_get_drvdata(dev); int index; @@ -247,7 +247,7 @@ static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev) return 0; } -static int __maybe_unused mtk_pmic_keys_resume(struct device *dev) +static int mtk_pmic_keys_resume(struct device *dev) { struct mtk_pmic_keys *keys = dev_get_drvdata(dev); int index; @@ -263,8 +263,8 @@ static int __maybe_unused mtk_pmic_keys_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend, - mtk_pmic_keys_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend, + mtk_pmic_keys_resume); static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = { { @@ -387,7 +387,7 @@ static struct platform_driver pmic_keys_pdrv = { .driver = { .name = "mtk-pmic-keys", .of_match_table = of_mtk_pmic_keys_match_tbl, - .pm = &mtk_pmic_keys_pm_ops, + .pm = pm_sleep_ptr(&mtk_pmic_keys_pm_ops), }, }; diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 0d55a95347f1..970f2a671c2e 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -388,7 +388,6 @@ static int ske_keypad_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int ske_keypad_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -416,15 +415,14 @@ static int ske_keypad_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops, - ske_keypad_suspend, ske_keypad_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops, + ske_keypad_suspend, ske_keypad_resume); static struct platform_driver ske_keypad_driver = { .driver = { .name = "nmk-ske-keypad", - .pm = &ske_keypad_dev_pm_ops, + .pm = pm_sleep_ptr(&ske_keypad_dev_pm_ops), }, .remove = ske_keypad_remove, }; diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 4766c5048ce2..26a005f9ace3 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -621,7 +621,6 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int pmic8xxx_kp_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -661,10 +660,9 @@ static int pmic8xxx_kp_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, - pmic8xxx_kp_suspend, pmic8xxx_kp_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, + pmic8xxx_kp_suspend, pmic8xxx_kp_resume); static const struct of_device_id pm8xxx_match_table[] = { { .compatible = "qcom,pm8058-keypad" }, @@ -677,7 +675,7 @@ static struct platform_driver pmic8xxx_kp_driver = { .probe = pmic8xxx_kp_probe, .driver = { .name = "pm8xxx-keypad", - .pm = &pm8xxx_kp_pm_ops, + .pm = pm_sleep_ptr(&pm8xxx_kp_pm_ops), .of_match_table = pm8xxx_match_table, }, }; diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index a7f8257c8a02..871f858d0ba7 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -660,7 +660,6 @@ static void pxa27x_keypad_close(struct input_dev *dev) clk_disable_unprepare(keypad->clk); } -#ifdef CONFIG_PM_SLEEP static int pxa27x_keypad_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -706,10 +705,9 @@ static int pxa27x_keypad_resume(struct device *dev) return ret; } -#endif -static SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops, - pxa27x_keypad_suspend, pxa27x_keypad_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops, + pxa27x_keypad_suspend, pxa27x_keypad_resume); static int pxa27x_keypad_probe(struct platform_device *pdev) @@ -830,7 +828,7 @@ static struct platform_driver pxa27x_keypad_driver = { .driver = { .name = "pxa27x-keypad", .of_match_table = of_match_ptr(pxa27x_keypad_dt_match), - .pm = &pxa27x_keypad_pm_ops, + .pm = pm_sleep_ptr(&pxa27x_keypad_pm_ops), }, }; module_platform_driver(pxa27x_keypad_driver); diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c index 403060d05c3b..317fe2b1f827 100644 --- a/drivers/input/keyboard/qt1050.c +++ b/drivers/input/keyboard/qt1050.c @@ -547,7 +547,7 @@ static int qt1050_probe(struct i2c_client *client) return 0; } -static int __maybe_unused qt1050_suspend(struct device *dev) +static int qt1050_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct qt1050_priv *ts = i2c_get_clientdata(client); @@ -563,7 +563,7 @@ static int __maybe_unused qt1050_suspend(struct device *dev) device_may_wakeup(dev) ? 125 : 0); } -static int __maybe_unused qt1050_resume(struct device *dev) +static int qt1050_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct qt1050_priv *ts = i2c_get_clientdata(client); @@ -574,7 +574,7 @@ static int __maybe_unused qt1050_resume(struct device *dev) return regmap_write(ts->regmap, QT1050_LPMODE, 2); } -static SIMPLE_DEV_PM_OPS(qt1050_pm_ops, qt1050_suspend, qt1050_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(qt1050_pm_ops, qt1050_suspend, qt1050_resume); static const struct of_device_id __maybe_unused qt1050_of_match[] = { { .compatible = "microchip,qt1050", }, @@ -586,7 +586,7 @@ static struct i2c_driver qt1050_driver = { .driver = { .name = "qt1050", .of_match_table = of_match_ptr(qt1050_of_match), - .pm = &qt1050_pm_ops, + .pm = pm_sleep_ptr(&qt1050_pm_ops), }, .probe_new = qt1050_probe, }; diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index 9fcce18b1d65..fabb50bde844 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -126,8 +126,7 @@ static irqreturn_t qt1070_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int qt1070_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int qt1070_probe(struct i2c_client *client) { struct qt1070_data *data; struct input_dev *input; @@ -227,7 +226,6 @@ static void qt1070_remove(struct i2c_client *client) kfree(data); } -#ifdef CONFIG_PM_SLEEP static int qt1070_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -249,9 +247,8 @@ static int qt1070_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume); static const struct i2c_device_id qt1070_id[] = { { "qt1070", 0 }, @@ -271,10 +268,10 @@ static struct i2c_driver qt1070_driver = { .driver = { .name = "qt1070", .of_match_table = of_match_ptr(qt1070_of_match), - .pm = &qt1070_pm_ops, + .pm = pm_sleep_ptr(&qt1070_pm_ops), }, .id_table = qt1070_id, - .probe = qt1070_probe, + .probe_new = qt1070_probe, .remove = qt1070_remove, }; diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 382b1519218c..04d2ee6ff577 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -338,8 +338,7 @@ static bool qt2160_identify(struct i2c_client *client) return true; } -static int qt2160_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int qt2160_probe(struct i2c_client *client) { struct qt2160_data *qt2160; struct input_dev *input; @@ -461,7 +460,7 @@ static struct i2c_driver qt2160_driver = { }, .id_table = qt2160_idtable, - .probe = qt2160_probe, + .probe_new = qt2160_probe, .remove = qt2160_remove, }; diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index c155adebf96e..2c00320f739f 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -283,7 +283,6 @@ static int sh_keysc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int sh_keysc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -316,17 +315,16 @@ static int sh_keysc_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops, - sh_keysc_suspend, sh_keysc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops, + sh_keysc_suspend, sh_keysc_resume); static struct platform_driver sh_keysc_device_driver = { .probe = sh_keysc_probe, .remove = sh_keysc_remove, .driver = { .name = "sh_keysc", - .pm = &sh_keysc_dev_pm_ops, + .pm = pm_sleep_ptr(&sh_keysc_dev_pm_ops), } }; module_platform_driver(sh_keysc_device_driver); diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 9838c79cb288..4bb7c533147c 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -284,7 +284,7 @@ static int spear_kbd_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused spear_kbd_suspend(struct device *dev) +static int spear_kbd_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spear_kbd *kbd = platform_get_drvdata(pdev); @@ -337,7 +337,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev) return 0; } -static int __maybe_unused spear_kbd_resume(struct device *dev) +static int spear_kbd_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct spear_kbd *kbd = platform_get_drvdata(pdev); @@ -364,7 +364,8 @@ static int __maybe_unused spear_kbd_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, + spear_kbd_suspend, spear_kbd_resume); #ifdef CONFIG_OF static const struct of_device_id spear_kbd_id_table[] = { @@ -379,7 +380,7 @@ static struct platform_driver spear_kbd_driver = { .remove = spear_kbd_remove, .driver = { .name = "keyboard", - .pm = &spear_kbd_pm_ops, + .pm = pm_sleep_ptr(&spear_kbd_pm_ops), .of_match_table = of_match_ptr(spear_kbd_id_table), }, }; diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c index a62bb8fff88c..13735a5e8391 100644 --- a/drivers/input/keyboard/st-keyscan.c +++ b/drivers/input/keyboard/st-keyscan.c @@ -212,7 +212,6 @@ static int keyscan_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int keyscan_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -247,9 +246,9 @@ static int keyscan_resume(struct device *dev) mutex_unlock(&input->mutex); return retval; } -#endif -static SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, keyscan_suspend, keyscan_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, + keyscan_suspend, keyscan_resume); static const struct of_device_id keyscan_of_match[] = { { .compatible = "st,sti-keyscan" }, @@ -261,7 +260,7 @@ static struct platform_driver keyscan_device_driver = { .probe = keyscan_probe, .driver = { .name = "st-keyscan", - .pm = &keyscan_dev_pm_ops, + .pm = pm_sleep_ptr(&keyscan_dev_pm_ops), .of_match_table = of_match_ptr(keyscan_of_match), } }; diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 7bf97285e30c..2c6c53290cc0 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c @@ -9,6 +9,7 @@ #include <linux/slab.h> #include <linux/input.h> #include <linux/interrupt.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/input/matrix_keypad.h> #include <linux/mfd/stmpe.h> diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 78e55318ccd6..b0d86621c60a 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -455,7 +455,6 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int tc3589x_keypad_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -492,15 +491,14 @@ static int tc3589x_keypad_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, - tc3589x_keypad_suspend, tc3589x_keypad_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, + tc3589x_keypad_suspend, tc3589x_keypad_resume); static struct platform_driver tc3589x_keypad_driver = { .driver = { .name = "tc3589x-keypad", - .pm = &tc3589x_keypad_dev_pm_ops, + .pm = pm_sleep_ptr(&tc3589x_keypad_dev_pm_ops), }, .probe = tc3589x_keypad_probe, }; diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index afcdfbb002ff..673b905af6fe 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -194,9 +194,9 @@ static int tca6416_setup_registers(struct tca6416_keypad_chip *chip) return 0; } -static int tca6416_keypad_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tca6416_keypad_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct tca6416_keys_platform_data *pdata; struct tca6416_keypad_chip *chip; struct input_dev *input; @@ -320,7 +320,6 @@ static void tca6416_keypad_remove(struct i2c_client *client) kfree(chip); } -#ifdef CONFIG_PM_SLEEP static int tca6416_keypad_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -342,17 +341,16 @@ static int tca6416_keypad_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops, - tca6416_keypad_suspend, tca6416_keypad_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops, + tca6416_keypad_suspend, tca6416_keypad_resume); static struct i2c_driver tca6416_keypad_driver = { .driver = { .name = "tca6416-keypad", - .pm = &tca6416_keypad_dev_pm_ops, + .pm = pm_sleep_ptr(&tca6416_keypad_dev_pm_ops), }, - .probe = tca6416_keypad_probe, + .probe_new = tca6416_keypad_probe, .remove = tca6416_keypad_remove, .id_table = tca6416_id, }; diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 3bbd7e652533..3d7492f38337 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -259,8 +259,7 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data, return error; } -static int tca8418_keypad_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tca8418_keypad_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct tca8418_keypad *keypad_data; @@ -371,7 +370,7 @@ static struct i2c_driver tca8418_keypad_driver = { .name = "tca8418_keypad", .of_match_table = tca8418_dt_ids, }, - .probe = tca8418_keypad_probe, + .probe_new = tca8418_keypad_probe, .id_table = tca8418_id, }; diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 570fe18c0ce9..1eba06bcf27a 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -713,7 +713,6 @@ static int tegra_kbc_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable) { u32 val; @@ -802,15 +801,15 @@ static int tegra_kbc_resume(struct device *dev) return err; } -#endif -static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, + tegra_kbc_suspend, tegra_kbc_resume); static struct platform_driver tegra_kbc_driver = { .probe = tegra_kbc_probe, .driver = { .name = "tegra-kbc", - .pm = &tegra_kbc_pm_ops, + .pm = pm_sleep_ptr(&tegra_kbc_pm_ops), .of_match_table = tegra_kbc_of_match, }, }; diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c index 632cd6c1c8d4..6627e65f06e5 100644 --- a/drivers/input/keyboard/tm2-touchkey.c +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -181,8 +181,7 @@ out: return IRQ_HANDLED; } -static int tm2_touchkey_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tm2_touchkey_probe(struct i2c_client *client) { struct device_node *np = client->dev.of_node; struct tm2_touchkey_data *touchkey; @@ -298,7 +297,7 @@ static int tm2_touchkey_probe(struct i2c_client *client, return 0; } -static int __maybe_unused tm2_touchkey_suspend(struct device *dev) +static int tm2_touchkey_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client); @@ -309,7 +308,7 @@ static int __maybe_unused tm2_touchkey_suspend(struct device *dev) return 0; } -static int __maybe_unused tm2_touchkey_resume(struct device *dev) +static int tm2_touchkey_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client); @@ -324,8 +323,8 @@ static int __maybe_unused tm2_touchkey_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops, - tm2_touchkey_suspend, tm2_touchkey_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops, + tm2_touchkey_suspend, tm2_touchkey_resume); static const struct i2c_device_id tm2_touchkey_id_table[] = { { TM2_TOUCHKEY_DEV_NAME, 0 }, @@ -354,10 +353,10 @@ MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match); static struct i2c_driver tm2_touchkey_driver = { .driver = { .name = TM2_TOUCHKEY_DEV_NAME, - .pm = &tm2_touchkey_pm_ops, + .pm = pm_sleep_ptr(&tm2_touchkey_pm_ops), .of_match_table = of_match_ptr(tm2_touchkey_of_match), }, - .probe = tm2_touchkey_probe, + .probe_new = tm2_touchkey_probe, .id_table = tm2_touchkey_id_table, }; module_i2c_driver(tm2_touchkey_driver); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 9f088900f863..f3cf189c419b 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -107,7 +107,7 @@ config INPUT_ATC260X_ONKEY config INPUT_ATMEL_CAPTOUCH tristate "Atmel Capacitive Touch Button Driver" - depends on OF || COMPILE_TEST + depends on OF depends on I2C help Say Y here if an Atmel Capacitive Touch Button device which @@ -330,7 +330,7 @@ config INPUT_CPCAP_PWRBUTTON config INPUT_WISTRON_BTNS tristate "x86 Wistron laptop button interface" - depends on X86_32 + depends on X86_32 && !UML select INPUT_SPARSEKMAP select NEW_LEDS select LEDS_CLASS diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index efeef135007a..5ef518a50e63 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -69,8 +69,7 @@ static int ad714x_i2c_read(struct ad714x_chip *chip, return 0; } -static int ad714x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ad714x_i2c_probe(struct i2c_client *client) { struct ad714x_chip *chip; @@ -99,7 +98,7 @@ static struct i2c_driver ad714x_i2c_driver = { .name = "ad714x_captouch", .pm = &ad714x_i2c_pm, }, - .probe = ad714x_i2c_probe, + .probe_new = ad714x_i2c_probe, .id_table = ad714x_id, }; diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 5be636aaa94f..a8ceea36d80a 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -74,8 +74,7 @@ static const struct adxl34x_bus_ops adxl34x_i2c_bops = { .read_block = adxl34x_i2c_read_block, }; -static int adxl34x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adxl34x_i2c_probe(struct i2c_client *client) { struct adxl34x *ac; int error; @@ -159,7 +158,7 @@ static struct i2c_driver adxl34x_driver = { .pm = &adxl34x_i2c_pm, .of_match_table = adxl34x_of_id, }, - .probe = adxl34x_i2c_probe, + .probe_new = adxl34x_i2c_probe, .remove = adxl34x_i2c_remove, .id_table = adxl34x_id, }; diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 7276657ad7ca..f42d3219cdcc 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -120,8 +120,7 @@ static int mail_led_set(struct led_classdev *led, return i2c_smbus_write_word_data(ap->client, 0x10, led_bits); } -static int apanel_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int apanel_probe(struct i2c_client *client) { struct apanel *ap; struct input_dev *idev; @@ -202,7 +201,7 @@ static struct i2c_driver apanel_driver = { .driver = { .name = APANEL, }, - .probe = apanel_probe, + .probe_new = apanel_probe, .shutdown = apanel_shutdown, .id_table = apanel_id, }; diff --git a/drivers/input/misc/atmel_captouch.c b/drivers/input/misc/atmel_captouch.c index 051aded6815a..d9704b174d3a 100644 --- a/drivers/input/misc/atmel_captouch.c +++ b/drivers/input/misc/atmel_captouch.c @@ -161,8 +161,7 @@ out: /* * Probe function to setup the device, input system and interrupt */ -static int atmel_captouch_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int atmel_captouch_probe(struct i2c_client *client) { struct atmel_captouch_device *capdev; struct device *dev = &client->dev; @@ -249,7 +248,6 @@ static int atmel_captouch_probe(struct i2c_client *client, return 0; } -#ifdef CONFIG_OF static const struct of_device_id atmel_captouch_of_id[] = { { .compatible = "atmel,captouch", @@ -257,7 +255,6 @@ static const struct of_device_id atmel_captouch_of_id[] = { { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_captouch_of_id); -#endif static const struct i2c_device_id atmel_captouch_id[] = { { "atmel_captouch", 0 }, @@ -266,11 +263,11 @@ static const struct i2c_device_id atmel_captouch_id[] = { MODULE_DEVICE_TABLE(i2c, atmel_captouch_id); static struct i2c_driver atmel_captouch_driver = { - .probe = atmel_captouch_probe, + .probe_new = atmel_captouch_probe, .id_table = atmel_captouch_id, .driver = { .name = "atmel_captouch", - .of_match_table = of_match_ptr(atmel_captouch_of_id), + .of_match_table = atmel_captouch_of_id, }, }; module_i2c_driver(atmel_captouch_driver); diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 84fe394da7a6..3f9da5c3cb53 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -414,8 +414,7 @@ static int bma150_initialize(struct bma150_data *bma150, return bma150_set_mode(bma150, BMA150_MODE_SLEEP); } -static int bma150_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int bma150_probe(struct i2c_client *client) { const struct bma150_platform_data *pdata = dev_get_platdata(&client->dev); @@ -552,7 +551,7 @@ static struct i2c_driver bma150_driver = { }, .class = I2C_CLASS_HWMON, .id_table = bma150_id, - .probe = bma150_probe, + .probe_new = bma150_probe, .remove = bma150_remove, }; diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c index 3b23210c46b7..75442c1230b1 100644 --- a/drivers/input/misc/cma3000_d0x_i2c.c +++ b/drivers/input/misc/cma3000_d0x_i2c.c @@ -44,8 +44,7 @@ static const struct cma3000_bus_ops cma3000_i2c_bops = { .write = cma3000_i2c_set, }; -static int cma3000_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cma3000_i2c_probe(struct i2c_client *client) { struct cma3000_accl_data *data; @@ -100,7 +99,7 @@ static const struct i2c_device_id cma3000_i2c_id[] = { MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id); static struct i2c_driver cma3000_i2c_driver = { - .probe = cma3000_i2c_probe, + .probe_new = cma3000_i2c_probe, .remove = cma3000_i2c_remove, .id_table = cma3000_i2c_id, .driver = { diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c index b08610d6e575..dcdea33b1a8f 100644 --- a/drivers/input/misc/da7280.c +++ b/drivers/input/misc/da7280.c @@ -1140,8 +1140,7 @@ out_err: return error; } -static int da7280_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int da7280_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct da7280_haptic *haptics; @@ -1322,7 +1321,7 @@ static struct i2c_driver da7280_driver = { .of_match_table = of_match_ptr(da7280_of_match), .pm = &da7280_pm_ops, }, - .probe = da7280_probe, + .probe_new = da7280_probe, .id_table = da7280_i2c_id, }; module_i2c_driver(da7280_driver); diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 0efe56f49aa9..3a51ee5e935a 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -457,8 +457,7 @@ static const struct regmap_config drv260x_regmap_config = { .cache_type = REGCACHE_NONE, }; -static int drv260x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int drv260x_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct drv260x_data *haptics; @@ -654,7 +653,7 @@ static const struct of_device_id drv260x_of_match[] = { MODULE_DEVICE_TABLE(of, drv260x_of_match); static struct i2c_driver drv260x_driver = { - .probe = drv260x_probe, + .probe_new = drv260x_probe, .driver = { .name = "drv260x-haptics", .of_match_table = drv260x_of_match, diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c index 21913e8085d7..c2a2ff980c06 100644 --- a/drivers/input/misc/drv2665.c +++ b/drivers/input/misc/drv2665.c @@ -156,8 +156,7 @@ static const struct regmap_config drv2665_regmap_config = { .cache_type = REGCACHE_NONE, }; -static int drv2665_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int drv2665_probe(struct i2c_client *client) { struct drv2665_data *haptics; int error; @@ -298,7 +297,7 @@ MODULE_DEVICE_TABLE(of, drv2665_of_match); #endif static struct i2c_driver drv2665_driver = { - .probe = drv2665_probe, + .probe_new = drv2665_probe, .driver = { .name = "drv2665-haptics", .of_match_table = of_match_ptr(drv2665_of_match), diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c index 3f67b9b010bf..da7ac63dce4c 100644 --- a/drivers/input/misc/drv2667.c +++ b/drivers/input/misc/drv2667.c @@ -333,8 +333,7 @@ static const struct regmap_config drv2667_regmap_config = { .cache_type = REGCACHE_NONE, }; -static int drv2667_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int drv2667_probe(struct i2c_client *client) { struct drv2667_data *haptics; int error; @@ -475,7 +474,7 @@ MODULE_DEVICE_TABLE(of, drv2667_of_match); #endif static struct i2c_driver drv2667_driver = { - .probe = drv2667_probe, + .probe_new = drv2667_probe, .driver = { .name = "drv2667-haptics", .of_match_table = of_match_ptr(drv2667_of_match), diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c index a8fba0054719..3969ffc1bc8d 100644 --- a/drivers/input/misc/ibm-panel.c +++ b/drivers/input/misc/ibm-panel.c @@ -119,8 +119,7 @@ static int ibm_panel_i2c_slave_cb(struct i2c_client *client, return 0; } -static int ibm_panel_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ibm_panel_probe(struct i2c_client *client) { struct ibm_panel *panel; int i; @@ -190,7 +189,7 @@ static struct i2c_driver ibm_panel_driver = { .name = DEVICE_NAME, .of_match_table = ibm_panel_match, }, - .probe = ibm_panel_probe, + .probe_new = ibm_panel_probe, .remove = ibm_panel_remove, }; module_i2c_driver(ibm_panel_driver); diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index ddb863bf63ee..e47ab6c1177f 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -86,7 +86,9 @@ enum iqs7222_reg_key_id { IQS7222_REG_KEY_TOUCH, IQS7222_REG_KEY_DEBOUNCE, IQS7222_REG_KEY_TAP, + IQS7222_REG_KEY_TAP_LEGACY, IQS7222_REG_KEY_AXIAL, + IQS7222_REG_KEY_AXIAL_LEGACY, IQS7222_REG_KEY_WHEEL, IQS7222_REG_KEY_NO_WHEEL, IQS7222_REG_KEY_RESERVED @@ -105,14 +107,14 @@ enum iqs7222_reg_grp_id { IQS7222_NUM_REG_GRPS }; -static const char * const iqs7222_reg_grp_names[] = { +static const char * const iqs7222_reg_grp_names[IQS7222_NUM_REG_GRPS] = { [IQS7222_REG_GRP_CYCLE] = "cycle", [IQS7222_REG_GRP_CHAN] = "channel", [IQS7222_REG_GRP_SLDR] = "slider", [IQS7222_REG_GRP_GPIO] = "gpio", }; -static const unsigned int iqs7222_max_cols[] = { +static const unsigned int iqs7222_max_cols[IQS7222_NUM_REG_GRPS] = { [IQS7222_REG_GRP_STAT] = IQS7222_MAX_COLS_STAT, [IQS7222_REG_GRP_CYCLE] = IQS7222_MAX_COLS_CYCLE, [IQS7222_REG_GRP_GLBL] = IQS7222_MAX_COLS_GLBL, @@ -202,6 +204,7 @@ struct iqs7222_dev_desc { int allow_offset; int event_offset; int comms_offset; + bool legacy_gesture; struct iqs7222_reg_grp_desc reg_grps[IQS7222_NUM_REG_GRPS]; }; @@ -209,12 +212,70 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { { .prod_num = IQS7222_PROD_NUM_A, .fw_major = 1, + .fw_minor = 13, + .sldr_res = U8_MAX * 16, + .touch_link = 1768, + .allow_offset = 9, + .event_offset = 10, + .comms_offset = 12, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 8, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 7, + .num_col = 3, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8700, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 12, + .num_col = 3, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xA000, + .num_row = 12, + .num_col = 6, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xAC00, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SLDR] = { + .base = 0xB000, + .num_row = 2, + .num_col = 11, + }, + [IQS7222_REG_GRP_GPIO] = { + .base = 0xC000, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 13, + }, + }, + }, + { + .prod_num = IQS7222_PROD_NUM_A, + .fw_major = 1, .fw_minor = 12, .sldr_res = U8_MAX * 16, .touch_link = 1768, .allow_offset = 9, .event_offset = 10, .comms_offset = 12, + .legacy_gesture = true, .reg_grps = { [IQS7222_REG_GRP_STAT] = { .base = IQS7222_SYS_STATUS, @@ -874,6 +935,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .reg_offset = 9, .reg_shift = 8, .reg_width = 8, + .val_pitch = 16, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_TAP_LEGACY, + .reg_offset = 9, + .reg_shift = 8, + .reg_width = 8, .val_pitch = 4, .label = "maximum gesture time", }, @@ -884,6 +955,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .reg_offset = 9, .reg_shift = 3, .reg_width = 5, + .val_pitch = 16, + .label = "minimum gesture time", + }, + { + .name = "azoteq,gesture-min-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_TAP_LEGACY, + .reg_offset = 9, + .reg_shift = 3, + .reg_width = 5, .val_pitch = 4, .label = "minimum gesture time", }, @@ -898,12 +979,32 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .label = "gesture distance", }, { + .name = "azoteq,gesture-dist", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY, + .reg_offset = 10, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 16, + .label = "gesture distance", + }, + { .name = "azoteq,gesture-max-ms", .reg_grp = IQS7222_REG_GRP_SLDR, .reg_key = IQS7222_REG_KEY_AXIAL, .reg_offset = 10, .reg_shift = 0, .reg_width = 8, + .val_pitch = 16, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY, + .reg_offset = 10, + .reg_shift = 0, + .reg_width = 8, .val_pitch = 4, .label = "maximum gesture time", }, @@ -1567,56 +1668,17 @@ static int iqs7222_gpio_select(struct iqs7222_private *iqs7222, } static int iqs7222_parse_props(struct iqs7222_private *iqs7222, - struct fwnode_handle **child_node, - int child_index, + struct fwnode_handle *reg_grp_node, + int reg_grp_index, enum iqs7222_reg_grp_id reg_grp, enum iqs7222_reg_key_id reg_key) { - u16 *setup = iqs7222_setup(iqs7222, reg_grp, child_index); + u16 *setup = iqs7222_setup(iqs7222, reg_grp, reg_grp_index); struct i2c_client *client = iqs7222->client; - struct fwnode_handle *reg_grp_node; - char reg_grp_name[16]; int i; - switch (reg_grp) { - case IQS7222_REG_GRP_CYCLE: - case IQS7222_REG_GRP_CHAN: - case IQS7222_REG_GRP_SLDR: - case IQS7222_REG_GRP_GPIO: - case IQS7222_REG_GRP_BTN: - /* - * These groups derive a child node and return it to the caller - * for additional group-specific processing. In some cases, the - * child node may have already been derived. - */ - reg_grp_node = *child_node; - if (reg_grp_node) - break; - - snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d", - iqs7222_reg_grp_names[reg_grp], child_index); - - reg_grp_node = device_get_named_child_node(&client->dev, - reg_grp_name); - if (!reg_grp_node) - return 0; - - *child_node = reg_grp_node; - break; - - case IQS7222_REG_GRP_GLBL: - case IQS7222_REG_GRP_FILT: - case IQS7222_REG_GRP_SYS: - /* - * These groups are not organized beneath a child node, nor are - * they subject to any additional processing by the caller. - */ - reg_grp_node = dev_fwnode(&client->dev); - break; - - default: - return -EINVAL; - } + if (!setup) + return 0; for (i = 0; i < ARRAY_SIZE(iqs7222_props); i++) { const char *name = iqs7222_props[i].name; @@ -1686,11 +1748,66 @@ static int iqs7222_parse_props(struct iqs7222_private *iqs7222, return 0; } -static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) +static int iqs7222_parse_event(struct iqs7222_private *iqs7222, + struct fwnode_handle *event_node, + int reg_grp_index, + enum iqs7222_reg_grp_id reg_grp, + enum iqs7222_reg_key_id reg_key, + u16 event_enable, u16 event_link, + unsigned int *event_type, + unsigned int *event_code) +{ + struct i2c_client *client = iqs7222->client; + int error; + + error = iqs7222_parse_props(iqs7222, event_node, reg_grp_index, + reg_grp, reg_key); + if (error) + return error; + + error = iqs7222_gpio_select(iqs7222, event_node, event_enable, + event_link); + if (error) + return error; + + error = fwnode_property_read_u32(event_node, "linux,code", event_code); + if (error == -EINVAL) { + return 0; + } else if (error) { + dev_err(&client->dev, "Failed to read %s code: %d\n", + fwnode_get_name(event_node), error); + return error; + } + + if (!event_type) { + input_set_capability(iqs7222->keypad, EV_KEY, *event_code); + return 0; + } + + error = fwnode_property_read_u32(event_node, "linux,input-type", + event_type); + if (error == -EINVAL) { + *event_type = EV_KEY; + } else if (error) { + dev_err(&client->dev, "Failed to read %s input type: %d\n", + fwnode_get_name(event_node), error); + return error; + } else if (*event_type != EV_KEY && *event_type != EV_SW) { + dev_err(&client->dev, "Invalid %s input type: %d\n", + fwnode_get_name(event_node), *event_type); + return -EINVAL; + } + + input_set_capability(iqs7222->keypad, *event_type, *event_code); + + return 0; +} + +static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, + struct fwnode_handle *cycle_node, int cycle_index) { u16 *cycle_setup = iqs7222->cycle_setup[cycle_index]; struct i2c_client *client = iqs7222->client; - struct fwnode_handle *cycle_node = NULL; unsigned int pins[9]; int error, count, i; @@ -1698,17 +1815,7 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) * Each channel shares a cycle with one other channel; the mapping of * channels to cycles is fixed. Properties defined for a cycle impact * both channels tied to the cycle. - */ - error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index, - IQS7222_REG_GRP_CYCLE, - IQS7222_REG_KEY_NONE); - if (error) - return error; - - if (!cycle_node) - return 0; - - /* + * * Unlike channels which are restricted to a select range of CRx pins * based on channel number, any cycle can claim any of the device's 9 * CTx pins (CTx0-8). @@ -1750,11 +1857,11 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) return 0; } -static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) +static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, + struct fwnode_handle *chan_node, int chan_index) { const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; struct i2c_client *client = iqs7222->client; - struct fwnode_handle *chan_node = NULL; int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; int ext_chan = rounddown(num_chan, 10); int error, i; @@ -1762,15 +1869,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) u16 *sys_setup = iqs7222->sys_setup; unsigned int val; - error = iqs7222_parse_props(iqs7222, &chan_node, chan_index, - IQS7222_REG_GRP_CHAN, - IQS7222_REG_KEY_NONE); - if (error) - return error; - - if (!chan_node) - return 0; - if (dev_desc->allow_offset && fwnode_property_present(chan_node, "azoteq,ulp-allow")) sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index); @@ -1810,8 +1908,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW; chan_setup[4] = val * 42 + 1048; - if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight", - &val)) { + error = fwnode_property_read_u32(chan_node, "azoteq,ref-weight", + &val); + if (!error) { if (val > U16_MAX) { dev_err(&client->dev, "Invalid %s reference weight: %u\n", @@ -1820,6 +1919,11 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) } chan_setup[5] = val; + } else if (error != -EINVAL) { + dev_err(&client->dev, + "Failed to read %s reference weight: %d\n", + fwnode_get_name(chan_node), error); + return error; } /* @@ -1892,21 +1996,10 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) if (!event_node) continue; - error = iqs7222_parse_props(iqs7222, &event_node, chan_index, - IQS7222_REG_GRP_BTN, - iqs7222_kp_events[i].reg_key); - if (error) - return error; - - error = iqs7222_gpio_select(iqs7222, event_node, - BIT(chan_index), - dev_desc->touch_link - (i ? 0 : 2)); - if (error) - return error; - - if (!fwnode_property_read_u32(event_node, - "azoteq,timeout-press-ms", - &val)) { + error = fwnode_property_read_u32(event_node, + "azoteq,timeout-press-ms", + &val); + if (!error) { /* * The IQS7222B employs a global pair of press timeout * registers as opposed to channel-specific registers. @@ -1919,57 +2012,31 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) if (val > U8_MAX * 500) { dev_err(&client->dev, "Invalid %s press timeout: %u\n", - fwnode_get_name(chan_node), val); + fwnode_get_name(event_node), val); + fwnode_handle_put(event_node); return -EINVAL; } *setup &= ~(U8_MAX << i * 8); *setup |= (val / 500 << i * 8); - } - - error = fwnode_property_read_u32(event_node, "linux,code", - &val); - if (error) { - dev_err(&client->dev, "Failed to read %s code: %d\n", - fwnode_get_name(chan_node), error); + } else if (error != -EINVAL) { + dev_err(&client->dev, + "Failed to read %s press timeout: %d\n", + fwnode_get_name(event_node), error); + fwnode_handle_put(event_node); return error; } - iqs7222->kp_code[chan_index][i] = val; - iqs7222->kp_type[chan_index][i] = EV_KEY; - - if (fwnode_property_present(event_node, "linux,input-type")) { - error = fwnode_property_read_u32(event_node, - "linux,input-type", - &val); - if (error) { - dev_err(&client->dev, - "Failed to read %s input type: %d\n", - fwnode_get_name(chan_node), error); - return error; - } - - if (val != EV_KEY && val != EV_SW) { - dev_err(&client->dev, - "Invalid %s input type: %u\n", - fwnode_get_name(chan_node), val); - return -EINVAL; - } - - iqs7222->kp_type[chan_index][i] = val; - } - - /* - * Reference channels can opt out of event reporting by using - * KEY_RESERVED in place of a true key or switch code. - */ - if (iqs7222->kp_type[chan_index][i] == EV_KEY && - iqs7222->kp_code[chan_index][i] == KEY_RESERVED) - continue; - - input_set_capability(iqs7222->keypad, - iqs7222->kp_type[chan_index][i], - iqs7222->kp_code[chan_index][i]); + error = iqs7222_parse_event(iqs7222, event_node, chan_index, + IQS7222_REG_GRP_BTN, + iqs7222_kp_events[i].reg_key, + BIT(chan_index), + dev_desc->touch_link - (i ? 0 : 2), + &iqs7222->kp_type[chan_index][i], + &iqs7222->kp_code[chan_index][i]); + fwnode_handle_put(event_node); + if (error) + return error; if (!dev_desc->event_offset) continue; @@ -1981,16 +2048,16 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) * The following call handles a special pair of properties that apply * to a channel node, but reside within the button (event) group. */ - return iqs7222_parse_props(iqs7222, &chan_node, chan_index, + return iqs7222_parse_props(iqs7222, chan_node, chan_index, IQS7222_REG_GRP_BTN, IQS7222_REG_KEY_DEBOUNCE); } -static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) +static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, + struct fwnode_handle *sldr_node, int sldr_index) { const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; struct i2c_client *client = iqs7222->client; - struct fwnode_handle *sldr_node = NULL; int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; int ext_chan = rounddown(num_chan, 10); int count, error, reg_offset, i; @@ -1998,15 +2065,6 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) u16 *sldr_setup = iqs7222->sldr_setup[sldr_index]; unsigned int chan_sel[4], val; - error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, - IQS7222_REG_GRP_SLDR, - IQS7222_REG_KEY_NONE); - if (error) - return error; - - if (!sldr_node) - return 0; - /* * Each slider can be spread across 3 to 4 channels. It is possible to * select only 2 channels, but doing so prevents the slider from using @@ -2065,8 +2123,9 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) if (fwnode_property_present(sldr_node, "azoteq,use-prox")) sldr_setup[4 + reg_offset] -= 2; - if (!fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val)) { - if (!val || val > dev_desc->sldr_res) { + error = fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val); + if (!error) { + if (val > dev_desc->sldr_res) { dev_err(&client->dev, "Invalid %s size: %u\n", fwnode_get_name(sldr_node), val); return -EINVAL; @@ -2079,9 +2138,21 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) sldr_setup[2] |= (val / 16 << IQS7222_SLDR_SETUP_2_RES_SHIFT); } + } else if (error != -EINVAL) { + dev_err(&client->dev, "Failed to read %s size: %d\n", + fwnode_get_name(sldr_node), error); + return error; } - if (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) { + if (!(reg_offset ? sldr_setup[3] + : sldr_setup[2] & IQS7222_SLDR_SETUP_2_RES_MASK)) { + dev_err(&client->dev, "Undefined %s size\n", + fwnode_get_name(sldr_node)); + return -EINVAL; + } + + error = fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val); + if (!error) { if (val > (reg_offset ? U16_MAX : U8_MAX * 4)) { dev_err(&client->dev, "Invalid %s top speed: %u\n", fwnode_get_name(sldr_node), val); @@ -2094,9 +2165,14 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) sldr_setup[2] &= ~IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK; sldr_setup[2] |= (val / 4); } + } else if (error != -EINVAL) { + dev_err(&client->dev, "Failed to read %s top speed: %d\n", + fwnode_get_name(sldr_node), error); + return error; } - if (!fwnode_property_read_u32(sldr_node, "linux,axis", &val)) { + error = fwnode_property_read_u32(sldr_node, "linux,axis", &val); + if (!error) { u16 sldr_max = sldr_setup[3] - 1; if (!reg_offset) { @@ -2110,6 +2186,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) input_set_abs_params(iqs7222->keypad, val, 0, sldr_max, 0, 0); iqs7222->sl_axis[sldr_index] = val; + } else if (error != -EINVAL) { + dev_err(&client->dev, "Failed to read %s axis: %d\n", + fwnode_get_name(sldr_node), error); + return error; } if (dev_desc->wheel_enable) { @@ -2130,46 +2210,47 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) { const char *event_name = iqs7222_sl_events[i].name; struct fwnode_handle *event_node; + enum iqs7222_reg_key_id reg_key; event_node = fwnode_get_named_child_node(sldr_node, event_name); if (!event_node) continue; - error = iqs7222_parse_props(iqs7222, &event_node, sldr_index, - IQS7222_REG_GRP_SLDR, - reg_offset ? - IQS7222_REG_KEY_RESERVED : - iqs7222_sl_events[i].reg_key); - if (error) - return error; + /* + * Depending on the device, gestures are either offered using + * one of two timing resolutions, or are not supported at all. + */ + if (reg_offset) + reg_key = IQS7222_REG_KEY_RESERVED; + else if (dev_desc->legacy_gesture && + iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_TAP) + reg_key = IQS7222_REG_KEY_TAP_LEGACY; + else if (dev_desc->legacy_gesture && + iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_AXIAL) + reg_key = IQS7222_REG_KEY_AXIAL_LEGACY; + else + reg_key = iqs7222_sl_events[i].reg_key; /* * The press/release event does not expose a direct GPIO link, * but one can be emulated by tying each of the participating * channels to the same GPIO. */ - error = iqs7222_gpio_select(iqs7222, event_node, + error = iqs7222_parse_event(iqs7222, event_node, sldr_index, + IQS7222_REG_GRP_SLDR, reg_key, i ? iqs7222_sl_events[i].enable : sldr_setup[3 + reg_offset], i ? 1568 + sldr_index * 30 - : sldr_setup[4 + reg_offset]); + : sldr_setup[4 + reg_offset], + NULL, + &iqs7222->sl_code[sldr_index][i]); + fwnode_handle_put(event_node); if (error) return error; if (!reg_offset) sldr_setup[9] |= iqs7222_sl_events[i].enable; - error = fwnode_property_read_u32(event_node, "linux,code", - &val); - if (error) { - dev_err(&client->dev, "Failed to read %s code: %d\n", - fwnode_get_name(sldr_node), error); - return error; - } - - iqs7222->sl_code[sldr_index][i] = val; - input_set_capability(iqs7222->keypad, EV_KEY, val); - if (!dev_desc->event_offset) continue; @@ -2190,19 +2271,63 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) * The following call handles a special pair of properties that shift * to make room for a wheel enable control in the case of IQS7222C. */ - return iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, + return iqs7222_parse_props(iqs7222, sldr_node, sldr_index, IQS7222_REG_GRP_SLDR, dev_desc->wheel_enable ? IQS7222_REG_KEY_WHEEL : IQS7222_REG_KEY_NO_WHEEL); } +static int (*iqs7222_parse_extra[IQS7222_NUM_REG_GRPS]) + (struct iqs7222_private *iqs7222, + struct fwnode_handle *reg_grp_node, + int reg_grp_index) = { + [IQS7222_REG_GRP_CYCLE] = iqs7222_parse_cycle, + [IQS7222_REG_GRP_CHAN] = iqs7222_parse_chan, + [IQS7222_REG_GRP_SLDR] = iqs7222_parse_sldr, +}; + +static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222, + enum iqs7222_reg_grp_id reg_grp, + int reg_grp_index) +{ + struct i2c_client *client = iqs7222->client; + struct fwnode_handle *reg_grp_node; + int error; + + if (iqs7222_reg_grp_names[reg_grp]) { + char reg_grp_name[16]; + + snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d", + iqs7222_reg_grp_names[reg_grp], reg_grp_index); + + reg_grp_node = device_get_named_child_node(&client->dev, + reg_grp_name); + } else { + reg_grp_node = fwnode_handle_get(dev_fwnode(&client->dev)); + } + + if (!reg_grp_node) + return 0; + + error = iqs7222_parse_props(iqs7222, reg_grp_node, reg_grp_index, + reg_grp, IQS7222_REG_KEY_NONE); + + if (!error && iqs7222_parse_extra[reg_grp]) + error = iqs7222_parse_extra[reg_grp](iqs7222, reg_grp_node, + reg_grp_index); + + fwnode_handle_put(reg_grp_node); + + return error; +} + static int iqs7222_parse_all(struct iqs7222_private *iqs7222) { const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; const struct iqs7222_reg_grp_desc *reg_grps = dev_desc->reg_grps; u16 *sys_setup = iqs7222->sys_setup; - int error, i; + int error, i, j; if (dev_desc->allow_offset) sys_setup[dev_desc->allow_offset] = U16_MAX; @@ -2210,32 +2335,13 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222) if (dev_desc->event_offset) sys_setup[dev_desc->event_offset] = IQS7222_EVENT_MASK_ATI; - for (i = 0; i < reg_grps[IQS7222_REG_GRP_CYCLE].num_row; i++) { - error = iqs7222_parse_cycle(iqs7222, i); - if (error) - return error; - } - - error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_GLBL, - IQS7222_REG_KEY_NONE); - if (error) - return error; - for (i = 0; i < reg_grps[IQS7222_REG_GRP_GPIO].num_row; i++) { - struct fwnode_handle *gpio_node = NULL; u16 *gpio_setup = iqs7222->gpio_setup[i]; - int j; gpio_setup[0] &= ~IQS7222_GPIO_SETUP_0_GPIO_EN; gpio_setup[1] = 0; gpio_setup[2] = 0; - error = iqs7222_parse_props(iqs7222, &gpio_node, i, - IQS7222_REG_GRP_GPIO, - IQS7222_REG_KEY_NONE); - if (error) - return error; - if (reg_grps[IQS7222_REG_GRP_GPIO].num_row == 1) continue; @@ -2258,29 +2364,21 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222) chan_setup[5] = 0; } - for (i = 0; i < reg_grps[IQS7222_REG_GRP_CHAN].num_row; i++) { - error = iqs7222_parse_chan(iqs7222, i); - if (error) - return error; - } - - error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_FILT, - IQS7222_REG_KEY_NONE); - if (error) - return error; - for (i = 0; i < reg_grps[IQS7222_REG_GRP_SLDR].num_row; i++) { u16 *sldr_setup = iqs7222->sldr_setup[i]; sldr_setup[0] &= ~IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK; + } - error = iqs7222_parse_sldr(iqs7222, i); - if (error) - return error; + for (i = 0; i < IQS7222_NUM_REG_GRPS; i++) { + for (j = 0; j < reg_grps[i].num_row; j++) { + error = iqs7222_parse_reg_grp(iqs7222, i, j); + if (error) + return error; + } } - return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS, - IQS7222_REG_KEY_NONE); + return 0; } static int iqs7222_report(struct iqs7222_private *iqs7222) diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index bbb81617c2b2..7e73e6e0730f 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -385,8 +385,7 @@ out: return retval; } -static int kxtj9_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int kxtj9_probe(struct i2c_client *client) { const struct kxtj9_platform_data *pdata = dev_get_platdata(&client->dev); @@ -539,7 +538,7 @@ static struct i2c_driver kxtj9_driver = { .name = NAME, .pm = &kxtj9_pm_ops, }, - .probe = kxtj9_probe, + .probe_new = kxtj9_probe, .id_table = kxtj9_id, }; diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index cd5e99ec1d3c..99cbc5ee89d1 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -278,8 +278,7 @@ static int max8997_haptic_probe(struct platform_device *pdev) break; case MAX8997_EXTERNAL_MODE: - chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, - "max8997-haptic"); + chip->pwm = pwm_get(&pdev->dev, NULL); if (IS_ERR(chip->pwm)) { error = PTR_ERR(chip->pwm); dev_err(&pdev->dev, @@ -344,7 +343,7 @@ err_put_regulator: regulator_put(chip->regulator); err_free_pwm: if (chip->mode == MAX8997_EXTERNAL_MODE) - pwm_free(chip->pwm); + pwm_put(chip->pwm); err_free_mem: input_free_device(input_dev); kfree(chip); @@ -360,7 +359,7 @@ static int max8997_haptic_remove(struct platform_device *pdev) regulator_put(chip->regulator); if (chip->mode == MAX8997_EXTERNAL_MODE) - pwm_free(chip->pwm); + pwm_put(chip->pwm); kfree(chip); diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 1b5a5e19230a..b12152536976 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -146,8 +146,7 @@ static void mma8450_close(struct input_dev *input) /* * I2C init/probing/exit functions */ -static int mma8450_probe(struct i2c_client *c, - const struct i2c_device_id *id) +static int mma8450_probe(struct i2c_client *c) { struct input_dev *input; int err; @@ -203,7 +202,7 @@ static struct i2c_driver mma8450_driver = { .name = MMA8450_DRV_NAME, .of_match_table = mma8450_dt_ids, }, - .probe = mma8450_probe, + .probe_new = mma8450_probe, .id_table = mma8450_id, }; diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index cfd6640e4f82..fd1ff3f1cd92 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -80,7 +80,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int pcf8574_kp_probe(struct i2c_client *client) { int i, ret; struct input_dev *idev; @@ -209,7 +209,7 @@ static struct i2c_driver pcf8574_kp_driver = { .pm = &pcf8574_kp_pm_ops, #endif }, - .probe = pcf8574_kp_probe, + .probe_new = pcf8574_kp_probe, .remove = pcf8574_kp_remove, .id_table = pcf8574_kp_id, }; diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 77cc653edca2..7e88a6ec7989 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1244,8 +1244,7 @@ static void cyapa_disable_regulator(void *data) regulator_disable(cyapa->vcc); } -static int cyapa_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) +static int cyapa_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct cyapa *cyapa; @@ -1490,7 +1489,7 @@ static struct i2c_driver cyapa_driver = { .of_match_table = of_match_ptr(cyapa_of_match), }, - .probe = cyapa_probe, + .probe_new = cyapa_probe, .id_table = cyapa_id_table, }; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d4eb59b55bf1..76729ada1582 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -33,6 +33,7 @@ #include <linux/jiffies.h> #include <linux/completion.h> #include <linux/of.h> +#include <linux/pm_wakeirq.h> #include <linux/property.h> #include <linux/regulator/consumer.h> #include <asm/unaligned.h> @@ -86,8 +87,6 @@ struct elan_tp_data { u16 fw_page_size; u32 fw_signature_address; - bool irq_wake; - u8 min_baseline; u8 max_baseline; bool baseline_ready; @@ -1188,8 +1187,7 @@ static void elan_disable_regulator(void *_data) regulator_disable(data->vcc); } -static int elan_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) +static int elan_probe(struct i2c_client *client) { const struct elan_transport_ops *transport_ops; struct device *dev = &client->dev; @@ -1327,13 +1325,6 @@ static int elan_probe(struct i2c_client *client, } } - /* - * Systems using device tree should set up wakeup via DTS, - * the rest will configure device as wakeup source by default. - */ - if (!dev->of_node) - device_init_wakeup(dev, true); - return 0; } @@ -1356,8 +1347,6 @@ static int __maybe_unused elan_suspend(struct device *dev) if (device_may_wakeup(dev)) { ret = elan_sleep(data); - /* Enable wake from IRQ */ - data->irq_wake = (enable_irq_wake(client->irq) == 0); } else { ret = elan_set_power(data, false); if (ret) @@ -1388,9 +1377,6 @@ static int __maybe_unused elan_resume(struct device *dev) dev_err(dev, "error %d enabling regulator\n", error); goto err; } - } else if (data->irq_wake) { - disable_irq_wake(client->irq); - data->irq_wake = false; } error = elan_set_power(data, true); @@ -1438,7 +1424,7 @@ static struct i2c_driver elan_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .dev_groups = elan_sysfs_groups, }, - .probe = elan_probe, + .probe_new = elan_probe, .id_table = elan_id, }; diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 987ee67a1045..6487c8c60d5e 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -521,8 +521,7 @@ static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *clien return touch; } -static int synaptics_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) +static int synaptics_i2c_probe(struct i2c_client *client) { int ret; struct synaptics_i2c *touch; @@ -651,7 +650,7 @@ static struct i2c_driver synaptics_i2c_driver = { .pm = &synaptics_i2c_pm, }, - .probe = synaptics_i2c_probe, + .probe_new = synaptics_i2c_probe, .remove = synaptics_i2c_remove, .id_table = synaptics_i2c_id_table, diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c index 50305fcfbef5..f2b75c6d3224 100644 --- a/drivers/input/rmi4/rmi_i2c.c +++ b/drivers/input/rmi4/rmi_i2c.c @@ -198,8 +198,7 @@ static void rmi_i2c_unregister_transport(void *data) rmi_unregister_transport_device(&rmi_i2c->xport); } -static int rmi_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int rmi_i2c_probe(struct i2c_client *client) { struct rmi_device_platform_data *pdata; struct rmi_device_platform_data *client_pdata = @@ -383,7 +382,7 @@ static struct i2c_driver rmi_i2c_driver = { .of_match_table = of_match_ptr(rmi_i2c_of_match), }, .id_table = rmi_id, - .probe = rmi_i2c_probe, + .probe_new = rmi_i2c_probe, }; module_i2c_driver(rmi_i2c_driver); diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c index c130468541b7..8a9ee2bd7402 100644 --- a/drivers/input/rmi4/rmi_smbus.c +++ b/drivers/input/rmi4/rmi_smbus.c @@ -268,8 +268,7 @@ static const struct rmi_transport_ops rmi_smb_ops = { .reset = rmi_smb_reset, }; -static int rmi_smb_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int rmi_smb_probe(struct i2c_client *client) { struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); struct rmi_smb_xport *rmi_smb; @@ -420,7 +419,7 @@ static struct i2c_driver rmi_smb_driver = { .pm = &rmi_smb_pm, }, .id_table = rmi_id, - .probe = rmi_smb_probe, + .probe_new = rmi_smb_probe, .remove = rmi_smb_remove, }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index dc90a3ea51ee..68d99a112e14 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -284,6 +284,22 @@ config TOUCHSCREEN_CYTTSP4_SPI To compile this driver as a module, choose M here: the module will be called cyttsp4_spi. +config TOUCHSCREEN_CYTTSP5 + tristate "Cypress TrueTouch Gen5 Touchscreen Driver" + depends on I2C + select REGMAP_I2C + select CRC_ITU_T + help + Driver for Parade TrueTouch Standard Product Generation 5 + touchscreen controllers. I2C bus interface support only. + + Say Y here if you have a Cypress Gen5 touchscreen. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called cyttsp5. + config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X @@ -422,6 +438,18 @@ config TOUCHSCREEN_HYCON_HY46XX To compile this driver as a module, choose M here: the module will be called hycon-hy46xx. +config TOUCHSCREEN_HYNITRON_CSTXXX + tristate "Hynitron touchscreen support" + depends on I2C + help + Say Y here if you have a touchscreen using a Hynitron + touchscreen controller. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called hynitron-cstxxx. + config TOUCHSCREEN_ILI210X tristate "Ilitek ILI210X based touchscreen" depends on I2C @@ -1241,7 +1269,7 @@ config TOUCHSCREEN_STMFTS config TOUCHSCREEN_STMPE tristate "STMicroelectronics STMPE touchscreens" depends on MFD_STMPE - depends on (OF || COMPILE_TEST) + depends on OF help Say Y here if you want support for STMicroelectronics STMPE touchscreen controllers. @@ -1379,4 +1407,16 @@ config TOUCHSCREEN_ZINITIX To compile this driver as a module, choose M here: the module will be called zinitix. +config TOUCHSCREEN_HIMAX_HX83112B + tristate "Himax hx83112b touchscreen driver" + depends on I2C + select REGMAP_I2C + help + Say Y here to enable support for Himax hx83112b touchscreens. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called himax_hx83112b. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 557f84fd2075..4968c370479a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o +obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o @@ -47,6 +48,7 @@ obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_ts.o obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o +obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o obj-$(CONFIG_TOUCHSCREEN_IMAGIS) += imagis.o @@ -116,3 +118,4 @@ obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW) += raspberrypi-ts.o obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 0f20a1fdcdba..dd8f31737bb8 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -23,8 +23,7 @@ static const struct regmap_config ad7879_i2c_regmap_config = { .max_register = 15, }; -static int ad7879_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ad7879_i2c_probe(struct i2c_client *client) { struct regmap *regmap; @@ -63,7 +62,7 @@ static struct i2c_driver ad7879_i2c_driver = { .pm = &ad7879_pm_ops, .of_match_table = of_match_ptr(ad7879_i2c_dt_ids), }, - .probe = ad7879_i2c_probe, + .probe_new = ad7879_i2c_probe, .id_table = ad7879_id, }; diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index dc6a85362a40..25bcc677e98b 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -87,8 +87,7 @@ static void ar1021_i2c_close(struct input_dev *dev) disable_irq(client->irq); } -static int ar1021_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ar1021_i2c_probe(struct i2c_client *client) { struct ar1021_i2c *ar1021; struct input_dev *input; @@ -182,7 +181,7 @@ static struct i2c_driver ar1021_i2c_driver = { .of_match_table = ar1021_i2c_of_match, }, - .probe = ar1021_i2c_probe, + .probe_new = ar1021_i2c_probe, .id_table = ar1021_i2c_id, }; module_i2c_driver(ar1021_i2c_driver); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index ccecd1441f0b..39ef2664b852 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3129,7 +3129,7 @@ static const struct dmi_system_id chromebook_T9_suspend_dmi[] = { { } }; -static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int mxt_probe(struct i2c_client *client) { struct mxt_data *data; int error; @@ -3377,7 +3377,7 @@ static struct i2c_driver mxt_driver = { .acpi_match_table = ACPI_PTR(mxt_acpi_id), .pm = &mxt_pm_ops, }, - .probe = mxt_probe, + .probe_new = mxt_probe, .remove = mxt_remove, .id_table = mxt_id, }; diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 2deae5a6823a..a4a1d58aeeac 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -482,8 +482,7 @@ static void auo_pixcir_reset(void *data) gpiod_set_value_cansleep(ts->gpio_rst, 1); } -static int auo_pixcir_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int auo_pixcir_probe(struct i2c_client *client) { struct auo_pixcir_ts *ts; struct input_dev *input_dev; @@ -637,7 +636,7 @@ static struct i2c_driver auo_pixcir_driver = { .pm = &auo_pixcir_pm_ops, .of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable), }, - .probe = auo_pixcir_probe, + .probe_new = auo_pixcir_probe, .id_table = auo_pixcir_idtable, }; diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 34f422e246ef..5a4dbd39a372 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -404,8 +404,7 @@ static void bu21013_disable_chip(void *_ts) gpiod_set_value(ts->cs_gpiod, 0); } -static int bu21013_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int bu21013_probe(struct i2c_client *client) { struct bu21013_ts *ts; struct input_dev *in_dev; @@ -618,7 +617,7 @@ static struct i2c_driver bu21013_driver = { .name = DRIVER_TP, .pm = &bu21013_dev_pm_ops, }, - .probe = bu21013_probe, + .probe_new = bu21013_probe, .remove = bu21013_remove, .id_table = bu21013_id, }; diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c index 392950aa7856..215f4dc5105d 100644 --- a/drivers/input/touchscreen/bu21029_ts.c +++ b/drivers/input/touchscreen/bu21029_ts.c @@ -331,8 +331,7 @@ static void bu21029_stop_chip(struct input_dev *dev) regulator_disable(bu21029->vdd); } -static int bu21029_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int bu21029_probe(struct i2c_client *client) { struct bu21029_ts_data *bu21029; struct input_dev *in_dev; @@ -475,7 +474,7 @@ static struct i2c_driver bu21029_driver = { .pm = &bu21029_pm_ops, }, .id_table = bu21029_ids, - .probe = bu21029_probe, + .probe_new = bu21029_probe, }; module_i2c_driver(bu21029_driver); diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c index f2fb41fb031e..f6769e4bd4f2 100644 --- a/drivers/input/touchscreen/chipone_icn8318.c +++ b/drivers/input/touchscreen/chipone_icn8318.c @@ -176,8 +176,7 @@ static int icn8318_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(icn8318_pm_ops, icn8318_suspend, icn8318_resume); -static int icn8318_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int icn8318_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct icn8318_data *data; @@ -267,7 +266,7 @@ static struct i2c_driver icn8318_driver = { .pm = &icn8318_pm_ops, .of_match_table = icn8318_of_match, }, - .probe = icn8318_probe, + .probe_new = icn8318_probe, .id_table = icn8318_i2c_id, }; diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c index a9be29139cbf..3a91d948b7f6 100644 --- a/drivers/input/touchscreen/cy8ctma140.c +++ b/drivers/input/touchscreen/cy8ctma140.c @@ -198,8 +198,7 @@ static void cy8ctma140_power_off_action(void *d) cy8ctma140_power_down(ts); } -static int cy8ctma140_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cy8ctma140_probe(struct i2c_client *client) { struct cy8ctma140 *ts; struct input_dev *input; @@ -344,7 +343,7 @@ static struct i2c_driver cy8ctma140_driver = { .of_match_table = cy8ctma140_of_match, }, .id_table = cy8ctma140_idtable, - .probe = cy8ctma140_probe, + .probe_new = cy8ctma140_probe, }; module_i2c_driver(cy8ctma140_driver); diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 495ef156cf43..7c2b7309dbaf 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -168,8 +168,7 @@ static void cy8ctmg110_shut_off(void *_ts) cy8ctmg110_power(ts, false); } -static int cy8ctmg110_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cy8ctmg110_probe(struct i2c_client *client) { struct cy8ctmg110 *ts; struct input_dev *input_dev; @@ -279,7 +278,7 @@ static struct i2c_driver cy8ctmg110_driver = { .pm = &cy8ctmg110_pm, }, .id_table = cy8ctmg110_idtable, - .probe = cy8ctmg110_probe, + .probe_new = cy8ctmg110_probe, }; module_i2c_driver(cy8ctmg110_driver); diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c index 28ae7c15397a..c260bab0c62c 100644 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ b/drivers/input/touchscreen/cyttsp4_i2c.c @@ -27,8 +27,7 @@ static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = { .read = cyttsp_i2c_read_block_data, }; -static int cyttsp4_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cyttsp4_i2c_probe(struct i2c_client *client) { struct cyttsp4 *ts; @@ -61,7 +60,7 @@ static struct i2c_driver cyttsp4_i2c_driver = { .name = CYTTSP4_I2C_NAME, .pm = &cyttsp4_pm_ops, }, - .probe = cyttsp4_i2c_probe, + .probe_new = cyttsp4_i2c_probe, .remove = cyttsp4_i2c_remove, .id_table = cyttsp4_i2c_id, }; diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c new file mode 100644 index 000000000000..4a23d6231382 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp5.c @@ -0,0 +1,900 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Parade TrueTouch(TM) Standard Product V5 Module. + * + * Copyright (C) 2015 Parade Technologies + * Copyright (C) 2012-2015 Cypress Semiconductor + * Copyright (C) 2018 Bootlin + * + * Authors: Mylène Josserand <mylene.josserand@bootlin.com> + * Alistair Francis <alistair@alistair23.me> + */ + +#include <linux/crc-itu-t.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/input/mt.h> +#include <linux/input/touchscreen.h> +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <asm/unaligned.h> + +#define CYTTSP5_NAME "cyttsp5" +#define CY_I2C_DATA_SIZE (2 * 256) +#define HID_VERSION 0x0100 +#define CY_MAX_INPUT 512 +#define CYTTSP5_PREALLOCATED_CMD_BUFFER 32 +#define CY_BITS_PER_BTN 1 +#define CY_NUM_BTN_EVENT_ID GENMASK(CY_BITS_PER_BTN, 0) + +#define MAX_AREA 255 +#define HID_OUTPUT_BL_SOP 0x1 +#define HID_OUTPUT_BL_EOP 0x17 +#define HID_OUTPUT_BL_LAUNCH_APP 0x3B +#define HID_OUTPUT_BL_LAUNCH_APP_SIZE 11 +#define HID_OUTPUT_GET_SYSINFO 0x2 +#define HID_OUTPUT_GET_SYSINFO_SIZE 5 +#define HID_OUTPUT_MAX_CMD_SIZE 12 + +#define HID_DESC_REG 0x1 +#define HID_INPUT_REG 0x3 +#define HID_OUTPUT_REG 0x4 + +#define REPORT_ID_TOUCH 0x1 +#define REPORT_ID_BTN 0x3 +#define REPORT_SIZE_5 5 +#define REPORT_SIZE_8 8 +#define REPORT_SIZE_16 16 + +/* Touch reports offsets */ +/* Header offsets */ +#define TOUCH_REPORT_DESC_HDR_CONTACTCOUNT 16 +/* Record offsets */ +#define TOUCH_REPORT_DESC_CONTACTID 8 +#define TOUCH_REPORT_DESC_X 16 +#define TOUCH_REPORT_DESC_Y 32 +#define TOUCH_REPORT_DESC_P 48 +#define TOUCH_REPORT_DESC_MAJ 56 +#define TOUCH_REPORT_DESC_MIN 64 + +/* HID */ +#define HID_TOUCH_REPORT_ID 0x1 +#define HID_BTN_REPORT_ID 0x3 +#define HID_APP_RESPONSE_REPORT_ID 0x1F +#define HID_APP_OUTPUT_REPORT_ID 0x2F +#define HID_BL_RESPONSE_REPORT_ID 0x30 +#define HID_BL_OUTPUT_REPORT_ID 0x40 + +#define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2 +#define HID_OUTPUT_RESPONSE_CMD_OFFSET 4 +#define HID_OUTPUT_RESPONSE_CMD_MASK GENMASK(6, 0) + +#define HID_SYSINFO_SENSING_OFFSET 33 +#define HID_SYSINFO_BTN_OFFSET 48 +#define HID_SYSINFO_BTN_MASK GENMASK(7, 0) +#define HID_SYSINFO_MAX_BTN 8 + +#define CY_HID_OUTPUT_TIMEOUT_MS 200 +#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000 +#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 4000 + +/* maximum number of concurrent tracks */ +#define TOUCH_REPORT_SIZE 10 +#define TOUCH_INPUT_HEADER_SIZE 7 +#define BTN_REPORT_SIZE 9 +#define BTN_INPUT_HEADER_SIZE 5 + +#define MAX_CY_TCH_T_IDS 32 + +/* All usage pages for Touch Report */ +#define TOUCH_REPORT_USAGE_PG_X 0x00010030 +#define TOUCH_REPORT_USAGE_PG_Y 0x00010031 +#define TOUCH_REPORT_USAGE_PG_P 0x000D0030 +#define TOUCH_REPORT_USAGE_PG_CONTACTID 0x000D0051 +#define TOUCH_REPORT_USAGE_PG_CONTACTCOUNT 0x000D0054 +#define TOUCH_REPORT_USAGE_PG_MAJ 0xFF010062 +#define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063 +#define TOUCH_COL_USAGE_PG 0x000D0022 + +/* System Information interface definitions */ +struct cyttsp5_sensing_conf_data_dev { + u8 electrodes_x; + u8 electrodes_y; + __le16 len_x; + __le16 len_y; + __le16 res_x; + __le16 res_y; + __le16 max_z; + u8 origin_x; + u8 origin_y; + u8 btn; + u8 scan_mode; + u8 max_num_of_tch_per_refresh_cycle; +} __packed; + +struct cyttsp5_sensing_conf_data { + u16 res_x; + u16 res_y; + u16 max_z; + u16 len_x; + u16 len_y; + u8 origin_x; + u8 origin_y; + u8 max_tch; +}; + +enum cyttsp5_tch_abs { /* for ordering within the extracted touch data array */ + CY_TCH_X, /* X */ + CY_TCH_Y, /* Y */ + CY_TCH_P, /* P (Z) */ + CY_TCH_T, /* TOUCH ID */ + CY_TCH_MAJ, /* TOUCH_MAJOR */ + CY_TCH_MIN, /* TOUCH_MINOR */ + CY_TCH_NUM_ABS +}; + +struct cyttsp5_tch_abs_params { + size_t ofs; /* abs byte offset */ + size_t size; /* size in bits */ + size_t min; /* min value */ + size_t max; /* max value */ + size_t bofs; /* bit offset */ +}; + +struct cyttsp5_touch { + int abs[CY_TCH_NUM_ABS]; +}; + +struct cyttsp5_sysinfo { + struct cyttsp5_sensing_conf_data sensing_conf_data; + int num_btns; + struct cyttsp5_tch_abs_params tch_hdr; + struct cyttsp5_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; + u32 key_code[HID_SYSINFO_MAX_BTN]; +}; + +struct cyttsp5_hid_desc { + __le16 hid_desc_len; + u8 packet_id; + u8 reserved_byte; + __le16 bcd_version; + __le16 report_desc_len; + __le16 report_desc_register; + __le16 input_register; + __le16 max_input_len; + __le16 output_register; + __le16 max_output_len; + __le16 command_register; + __le16 data_register; + __le16 vendor_id; + __le16 product_id; + __le16 version_id; + u8 reserved[4]; +} __packed; + +struct cyttsp5 { + struct device *dev; + struct completion cmd_done; + struct cyttsp5_sysinfo sysinfo; + struct cyttsp5_hid_desc hid_desc; + u8 cmd_buf[CYTTSP5_PREALLOCATED_CMD_BUFFER]; + u8 input_buf[CY_MAX_INPUT]; + u8 response_buf[CY_MAX_INPUT]; + struct gpio_desc *reset_gpio; + struct input_dev *input; + char phys[NAME_MAX]; + int num_prv_rec; + struct regmap *regmap; + struct touchscreen_properties prop; + struct regulator *vdd; +}; + +/* + * For what is understood in the datasheet, the register does not + * matter. For consistency, use the Input Register address + * but it does mean anything to the device. The important data + * to send is the I2C address + */ +static int cyttsp5_read(struct cyttsp5 *ts, u8 *buf, u32 max) +{ + int error; + u32 size; + u8 temp[2]; + + /* Read the frame to retrieve the size */ + error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, temp, sizeof(temp)); + if (error) + return error; + + size = get_unaligned_le16(temp); + if (!size || size == 2) + return 0; + + if (size > max) + return -EINVAL; + + /* Get the real value */ + return regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, size); +} + +static int cyttsp5_write(struct cyttsp5 *ts, unsigned int reg, u8 *data, + size_t size) +{ + u8 cmd[HID_OUTPUT_MAX_CMD_SIZE]; + + if (size + 1 > HID_OUTPUT_MAX_CMD_SIZE) + return -E2BIG; + + /* High bytes of register address needed as first byte of cmd */ + cmd[0] = (reg >> 8) & 0xFF; + + /* Copy the rest of the data */ + if (data) + memcpy(&cmd[1], data, size); + + /* + * The hardware wants to receive a frame with the address register + * contained in the first two bytes. As the regmap_write function + * add the register adresse in the frame, we use the low byte as + * first frame byte for the address register and the first + * data byte is the high register + left of the cmd to send + */ + return regmap_bulk_write(ts->regmap, reg & 0xFF, cmd, size + 1); +} + +static void cyttsp5_get_touch_axis(int *axis, int size, int max, u8 *xy_data, + int bofs) +{ + int nbyte; + + for (nbyte = 0, *axis = 0; nbyte < size; nbyte++) + *axis += ((xy_data[nbyte] >> bofs) << (nbyte * 8)); + + *axis &= max - 1; +} + +static void cyttsp5_get_touch_record(struct cyttsp5 *ts, + struct cyttsp5_touch *touch, u8 *xy_data) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + enum cyttsp5_tch_abs abs; + + for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) + cyttsp5_get_touch_axis(&touch->abs[abs], + si->tch_abs[abs].size, + si->tch_abs[abs].max, + xy_data + si->tch_abs[abs].ofs, + si->tch_abs[abs].bofs); +} + +static void cyttsp5_get_mt_touches(struct cyttsp5 *ts, + struct cyttsp5_touch *tch, int num_cur_tch) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int i, t = 0, offset = 0; + DECLARE_BITMAP(ids, MAX_CY_TCH_T_IDS); + u8 *tch_addr; + int tmp; + + bitmap_zero(ids, MAX_CY_TCH_T_IDS); + memset(tch->abs, 0, sizeof(tch->abs)); + + switch (ts->input_buf[2]) { + case HID_TOUCH_REPORT_ID: + offset = TOUCH_INPUT_HEADER_SIZE; + break; + case HID_BTN_REPORT_ID: + offset = BTN_INPUT_HEADER_SIZE; + break; + } + + for (i = 0; i < num_cur_tch; i++) { + tch_addr = ts->input_buf + offset + (i * TOUCH_REPORT_SIZE); + cyttsp5_get_touch_record(ts, tch, tch_addr); + + /* Convert MAJOR/MINOR from mm to resolution */ + tmp = tch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x; + tch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x; + tmp = tch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x; + tch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x; + + t = tch->abs[CY_TCH_T]; + input_mt_slot(ts->input, t); + input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); + __set_bit(t, ids); + + /* position and pressure fields */ + touchscreen_report_pos(ts->input, &ts->prop, + tch->abs[CY_TCH_X], tch->abs[CY_TCH_Y], + true); + input_report_abs(ts->input, ABS_MT_PRESSURE, + tch->abs[CY_TCH_P]); + + /* Get the extended touch fields */ + input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, + tch->abs[CY_TCH_MAJ]); + input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, + tch->abs[CY_TCH_MIN]); + } + + ts->num_prv_rec = num_cur_tch; +} + +static int cyttsp5_mt_attention(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int max_tch = si->sensing_conf_data.max_tch; + struct cyttsp5_touch tch; + int num_cur_tch; + + cyttsp5_get_touch_axis(&num_cur_tch, si->tch_hdr.size, + si->tch_hdr.max, + ts->input_buf + 3 + si->tch_hdr.ofs, + si->tch_hdr.bofs); + + if (num_cur_tch > max_tch) { + dev_err(dev, "Num touch err detected (n=%d)\n", num_cur_tch); + num_cur_tch = max_tch; + } + + if (num_cur_tch == 0 && ts->num_prv_rec == 0) + return 0; + + /* extract xy_data for all currently reported touches */ + if (num_cur_tch) + cyttsp5_get_mt_touches(ts, &tch, num_cur_tch); + + input_mt_sync_frame(ts->input); + input_sync(ts->input); + + return 0; +} + +static int cyttsp5_setup_input_device(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int max_x, max_y, max_p; + int max_x_tmp, max_y_tmp; + int error; + + max_x_tmp = si->sensing_conf_data.res_x; + max_y_tmp = si->sensing_conf_data.res_y; + max_x = max_x_tmp - 1; + max_y = max_y_tmp - 1; + max_p = si->sensing_conf_data.max_z; + + input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, max_x, 0, 0); + input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); + input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, max_p, 0, 0); + + input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0); + input_set_abs_params(ts->input, ABS_MT_TOUCH_MINOR, 0, MAX_AREA, 0, 0); + + error = input_mt_init_slots(ts->input, si->tch_abs[CY_TCH_T].max, + INPUT_MT_DROP_UNUSED | INPUT_MT_DIRECT); + if (error) + return error; + + error = input_register_device(ts->input); + if (error) { + dev_err(dev, "failed to register input device: %d\n", error); + return error; + } + + return error; +} + +static int cyttsp5_parse_dt_key_code(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + + if (!si->num_btns) + return 0; + + /* Initialize the button to RESERVED */ + memset32(si->key_code, KEY_RESERVED, si->num_btns); + + return device_property_read_u32_array(dev, "linux,keycodes", + si->key_code, si->num_btns); +} + +static int cyttsp5_btn_attention(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int cur_btn, offset = 0; + int cur_btn_state; + + switch (ts->input_buf[2]) { + case HID_TOUCH_REPORT_ID: + offset = TOUCH_INPUT_HEADER_SIZE; + break; + case HID_BTN_REPORT_ID: + offset = BTN_INPUT_HEADER_SIZE; + break; + } + + if (ts->input_buf[2] != HID_BTN_REPORT_ID) + return 0; + + /* extract button press/release touch information */ + for (cur_btn = 0; cur_btn < si->num_btns; cur_btn++) { + /* Get current button state */ + cur_btn_state = (ts->input_buf[offset] >> (cur_btn * CY_BITS_PER_BTN)) + & CY_NUM_BTN_EVENT_ID; + + input_report_key(ts->input, si->key_code[cur_btn], + cur_btn_state); + input_sync(ts->input); + } + + return 0; +} + +static int cyttsp5_validate_cmd_response(struct cyttsp5 *ts, u8 code) +{ + u16 size, crc; + u8 status, report_id; + int command_code; + + size = get_unaligned_le16(&ts->response_buf[0]); + if (!size) + return 0; + + report_id = ts->response_buf[HID_OUTPUT_RESPONSE_REPORT_OFFSET]; + + switch (report_id) { + case HID_BL_RESPONSE_REPORT_ID: + if (ts->response_buf[4] != HID_OUTPUT_BL_SOP) { + dev_err(ts->dev, "HID output response, wrong SOP\n"); + return -EPROTO; + } + + if (ts->response_buf[size - 1] != HID_OUTPUT_BL_EOP) { + dev_err(ts->dev, "HID output response, wrong EOP\n"); + return -EPROTO; + } + + crc = crc_itu_t(0xFFFF, &ts->response_buf[4], size - 7); + if (get_unaligned_le16(&ts->response_buf[size - 3]) != crc) { + dev_err(ts->dev, + "HID output response, wrong CRC 0x%X\n", + crc); + return -EPROTO; + } + + status = ts->response_buf[5]; + if (status) { + dev_err(ts->dev, "HID output response, ERROR:%d\n", + status); + return -EPROTO; + } + break; + + case HID_APP_RESPONSE_REPORT_ID: + command_code = ts->response_buf[HID_OUTPUT_RESPONSE_CMD_OFFSET] + & HID_OUTPUT_RESPONSE_CMD_MASK; + if (command_code != code) { + dev_err(ts->dev, + "HID output response, wrong command_code:%X\n", + command_code); + return -EPROTO; + } + break; + } + + return 0; +} + +static void cyttsp5_si_get_btn_data(struct cyttsp5 *ts) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + unsigned int btns = ts->response_buf[HID_SYSINFO_BTN_OFFSET] & + HID_SYSINFO_BTN_MASK; + + si->num_btns = hweight8(btns); +} + +static int cyttsp5_get_sysinfo_regs(struct cyttsp5 *ts) +{ + struct cyttsp5_sensing_conf_data *scd = &ts->sysinfo.sensing_conf_data; + struct cyttsp5_sensing_conf_data_dev *scd_dev = + (struct cyttsp5_sensing_conf_data_dev *) + &ts->response_buf[HID_SYSINFO_SENSING_OFFSET]; + + cyttsp5_si_get_btn_data(ts); + + scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle; + scd->res_x = get_unaligned_le16(&scd_dev->res_x); + scd->res_y = get_unaligned_le16(&scd_dev->res_y); + scd->max_z = get_unaligned_le16(&scd_dev->max_z); + scd->len_x = get_unaligned_le16(&scd_dev->len_x); + scd->len_y = get_unaligned_le16(&scd_dev->len_y); + + return 0; +} + +static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts) +{ + int rc; + u8 cmd[HID_OUTPUT_GET_SYSINFO_SIZE]; + + /* HI bytes of Output register address */ + put_unaligned_le16(HID_OUTPUT_GET_SYSINFO_SIZE, cmd); + cmd[2] = HID_APP_OUTPUT_REPORT_ID; + cmd[3] = 0x0; /* Reserved */ + cmd[4] = HID_OUTPUT_GET_SYSINFO; + + rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd, + HID_OUTPUT_GET_SYSINFO_SIZE); + if (rc) { + dev_err(ts->dev, "Failed to write command %d", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS)); + if (rc <= 0) { + dev_err(ts->dev, "HID output cmd execution timed out\n"); + rc = -ETIMEDOUT; + return rc; + } + + rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_GET_SYSINFO); + if (rc) { + dev_err(ts->dev, "Validation of the response failed\n"); + return rc; + } + + return cyttsp5_get_sysinfo_regs(ts); +} + +static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts) +{ + int rc; + u8 cmd[HID_OUTPUT_BL_LAUNCH_APP]; + u16 crc; + + put_unaligned_le16(HID_OUTPUT_BL_LAUNCH_APP_SIZE, cmd); + cmd[2] = HID_BL_OUTPUT_REPORT_ID; + cmd[3] = 0x0; /* Reserved */ + cmd[4] = HID_OUTPUT_BL_SOP; + cmd[5] = HID_OUTPUT_BL_LAUNCH_APP; + put_unaligned_le16(0x00, &cmd[6]); + crc = crc_itu_t(0xFFFF, &cmd[4], 4); + put_unaligned_le16(crc, &cmd[8]); + cmd[10] = HID_OUTPUT_BL_EOP; + + rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd, + HID_OUTPUT_BL_LAUNCH_APP_SIZE); + if (rc) { + dev_err(ts->dev, "Failed to write command %d", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_OUTPUT_TIMEOUT_MS)); + if (rc <= 0) { + dev_err(ts->dev, "HID output cmd execution timed out\n"); + rc = -ETIMEDOUT; + return rc; + } + + rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_BL_LAUNCH_APP); + if (rc) { + dev_err(ts->dev, "Validation of the response failed\n"); + return rc; + } + + return 0; +} + +static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts, + struct cyttsp5_hid_desc *desc) +{ + struct device *dev = ts->dev; + __le16 hid_desc_register = cpu_to_le16(HID_DESC_REG); + int rc; + u8 cmd[2]; + + /* Set HID descriptor register */ + memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register)); + + rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0); + if (rc) { + dev_err(dev, "Failed to get HID descriptor, rc=%d\n", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS)); + if (rc <= 0) { + dev_err(ts->dev, "HID get descriptor timed out\n"); + rc = -ETIMEDOUT; + return rc; + } + + memcpy(desc, ts->response_buf, sizeof(*desc)); + + /* Check HID descriptor length and version */ + if (le16_to_cpu(desc->hid_desc_len) != sizeof(*desc) || + le16_to_cpu(desc->bcd_version) != HID_VERSION) { + dev_err(dev, "Unsupported HID version\n"); + return -ENODEV; + } + + return 0; +} + +static int fill_tch_abs(struct cyttsp5_tch_abs_params *tch_abs, int report_size, + int offset) +{ + tch_abs->ofs = offset / 8; + tch_abs->size = report_size / 8; + if (report_size % 8) + tch_abs->size += 1; + tch_abs->min = 0; + tch_abs->max = 1 << report_size; + tch_abs->bofs = offset - (tch_abs->ofs << 3); + + return 0; +} + +static irqreturn_t cyttsp5_handle_irq(int irq, void *handle) +{ + struct cyttsp5 *ts = handle; + int report_id; + int size; + int error; + + error = cyttsp5_read(ts, ts->input_buf, CY_MAX_INPUT); + if (error) + return IRQ_HANDLED; + + size = get_unaligned_le16(&ts->input_buf[0]); + if (size == 0) { + /* reset */ + report_id = 0; + size = 2; + } else { + report_id = ts->input_buf[2]; + } + + switch (report_id) { + case HID_TOUCH_REPORT_ID: + cyttsp5_mt_attention(ts->dev); + break; + case HID_BTN_REPORT_ID: + cyttsp5_btn_attention(ts->dev); + break; + default: + /* It is not an input but a command response */ + memcpy(ts->response_buf, ts->input_buf, size); + complete(&ts->cmd_done); + } + + return IRQ_HANDLED; +} + +static int cyttsp5_deassert_int(struct cyttsp5 *ts) +{ + u16 size; + u8 buf[2]; + int error; + + error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, sizeof(buf)); + if (error < 0) + return error; + + size = get_unaligned_le16(&buf[0]); + if (size == 2 || size == 0) + return 0; + + return -EINVAL; +} + +static int cyttsp5_fill_all_touch(struct cyttsp5 *ts) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + + fill_tch_abs(&si->tch_abs[CY_TCH_X], REPORT_SIZE_16, + TOUCH_REPORT_DESC_X); + fill_tch_abs(&si->tch_abs[CY_TCH_Y], REPORT_SIZE_16, + TOUCH_REPORT_DESC_Y); + fill_tch_abs(&si->tch_abs[CY_TCH_P], REPORT_SIZE_8, + TOUCH_REPORT_DESC_P); + fill_tch_abs(&si->tch_abs[CY_TCH_T], REPORT_SIZE_5, + TOUCH_REPORT_DESC_CONTACTID); + fill_tch_abs(&si->tch_hdr, REPORT_SIZE_5, + TOUCH_REPORT_DESC_HDR_CONTACTCOUNT); + fill_tch_abs(&si->tch_abs[CY_TCH_MAJ], REPORT_SIZE_8, + TOUCH_REPORT_DESC_MAJ); + fill_tch_abs(&si->tch_abs[CY_TCH_MIN], REPORT_SIZE_8, + TOUCH_REPORT_DESC_MIN); + + return 0; +} + +static int cyttsp5_startup(struct cyttsp5 *ts) +{ + int error; + + error = cyttsp5_deassert_int(ts); + if (error) { + dev_err(ts->dev, "Error on deassert int r=%d\n", error); + return -ENODEV; + } + + /* + * Launch the application as the device starts in bootloader mode + * because of a power-on-reset + */ + error = cyttsp5_hid_output_bl_launch_app(ts); + if (error < 0) { + dev_err(ts->dev, "Error on launch app r=%d\n", error); + return error; + } + + error = cyttsp5_get_hid_descriptor(ts, &ts->hid_desc); + if (error < 0) { + dev_err(ts->dev, "Error on getting HID descriptor r=%d\n", error); + return error; + } + + error = cyttsp5_fill_all_touch(ts); + if (error < 0) { + dev_err(ts->dev, "Error on report descriptor r=%d\n", error); + return error; + } + + error = cyttsp5_hid_output_get_sysinfo(ts); + if (error) { + dev_err(ts->dev, "Error on getting sysinfo r=%d\n", error); + return error; + } + + return error; +} + +static void cyttsp5_cleanup(void *data) +{ + struct cyttsp5 *ts = data; + + regulator_disable(ts->vdd); +} + +static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name) +{ + struct cyttsp5 *ts; + struct cyttsp5_sysinfo *si; + int error, i; + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + /* Initialize device info */ + ts->regmap = regmap; + ts->dev = dev; + si = &ts->sysinfo; + dev_set_drvdata(dev, ts); + + init_completion(&ts->cmd_done); + + /* Power up the device */ + ts->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(ts->vdd)) { + error = PTR_ERR(ts->vdd); + return error; + } + + error = devm_add_action_or_reset(dev, cyttsp5_cleanup, ts); + if (error) + return error; + + error = regulator_enable(ts->vdd); + if (error) + return error; + + ts->input = devm_input_allocate_device(dev); + if (!ts->input) { + dev_err(dev, "Error, failed to allocate input device\n"); + return -ENODEV; + } + + ts->input->name = "cyttsp5"; + scnprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); + ts->input->phys = ts->phys; + input_set_drvdata(ts->input, ts); + + /* Reset the gpio to be in a reset state */ + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) { + error = PTR_ERR(ts->reset_gpio); + dev_err(dev, "Failed to request reset gpio, error %d\n", error); + return error; + } + gpiod_set_value_cansleep(ts->reset_gpio, 0); + + /* Need a delay to have device up */ + msleep(20); + + error = devm_request_threaded_irq(dev, irq, NULL, cyttsp5_handle_irq, + IRQF_ONESHOT, name, ts); + if (error) { + dev_err(dev, "unable to request IRQ\n"); + return error; + } + + error = cyttsp5_startup(ts); + if (error) { + dev_err(ts->dev, "Fail initial startup r=%d\n", error); + return error; + } + + error = cyttsp5_parse_dt_key_code(dev); + if (error < 0) { + dev_err(ts->dev, "Error while parsing dts %d\n", error); + return error; + } + + touchscreen_parse_properties(ts->input, true, &ts->prop); + + __set_bit(EV_KEY, ts->input->evbit); + for (i = 0; i < si->num_btns; i++) + __set_bit(si->key_code[i], ts->input->keybit); + + return cyttsp5_setup_input_device(dev); +} + +static int cyttsp5_i2c_probe(struct i2c_client *client) +{ + struct regmap *regmap; + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + }; + + regmap = devm_regmap_init_i2c(client, &config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "regmap allocation failed: %ld\n", + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return cyttsp5_probe(&client->dev, regmap, client->irq, client->name); +} + +static const struct of_device_id cyttsp5_of_match[] = { + { .compatible = "cypress,tt21000", }, + { } +}; +MODULE_DEVICE_TABLE(of, cyttsp5_of_match); + +static const struct i2c_device_id cyttsp5_i2c_id[] = { + { CYTTSP5_NAME, 0, }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id); + +static struct i2c_driver cyttsp5_i2c_driver = { + .driver = { + .name = CYTTSP5_NAME, + .of_match_table = cyttsp5_of_match, + }, + .probe_new = cyttsp5_i2c_probe, + .id_table = cyttsp5_i2c_id, +}; +module_i2c_driver(cyttsp5_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Touchscreen driver for Cypress TrueTouch Gen 5 Product"); +MODULE_AUTHOR("Mylène Josserand <mylene.josserand@bootlin.com>"); diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 4c8473d327ab..0155a1626adf 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -28,8 +28,7 @@ static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { .read = cyttsp_i2c_read_block_data, }; -static int cyttsp_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cyttsp_i2c_probe(struct i2c_client *client) { struct cyttsp *ts; @@ -67,7 +66,7 @@ static struct i2c_driver cyttsp_i2c_driver = { .pm = &cyttsp_pm_ops, .of_match_table = cyttsp_of_i2c_match, }, - .probe = cyttsp_i2c_probe, + .probe_new = cyttsp_i2c_probe, .id_table = cyttsp_i2c_id, }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 9ac1378610bc..ddd0f1f62458 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -1131,9 +1131,9 @@ static void edt_ft5x06_disable_regulators(void *arg) regulator_disable(data->iovcc); } -static int edt_ft5x06_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int edt_ft5x06_ts_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct edt_i2c_chip_data *chip_data; struct edt_ft5x06_ts_data *tsdata; u8 buf[2] = { 0xfc, 0x00 }; @@ -1504,7 +1504,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .id_table = edt_ft5x06_ts_id, - .probe = edt_ft5x06_ts_probe, + .probe_new = edt_ft5x06_ts_probe, .remove = edt_ft5x06_ts_remove, }; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index a639ba7e56ea..c8ab03f49227 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -158,8 +158,7 @@ static void eeti_ts_close(struct input_dev *dev) eeti_ts_stop(eeti); } -static int eeti_ts_probe(struct i2c_client *client, - const struct i2c_device_id *idp) +static int eeti_ts_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct eeti_ts *eeti; @@ -292,7 +291,7 @@ static struct i2c_driver eeti_ts_driver = { .pm = &eeti_ts_pm, .of_match_table = of_match_ptr(of_eeti_ts_match), }, - .probe = eeti_ts_probe, + .probe_new = eeti_ts_probe, .id_table = eeti_ts_id, }; diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 83ac8c128192..742d47a75ac1 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -14,17 +14,17 @@ - auto idle mode support */ +#include <linux/err.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/irq.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/bitops.h> #include <linux/input/mt.h> -#include <linux/of_gpio.h> /* * Mouse Mode: some panel may configure the controller to mouse mode, @@ -119,32 +119,26 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) /* wake up controller by an falling edge of interrupt gpio. */ static int egalax_wake_up_device(struct i2c_client *client) { - struct device_node *np = client->dev.of_node; - int gpio; + struct gpio_desc *gpio; int ret; - if (!np) - return -ENODEV; - - gpio = of_get_named_gpio(np, "wakeup-gpios", 0); - if (!gpio_is_valid(gpio)) - return -ENODEV; - - ret = gpio_request(gpio, "egalax_irq"); - if (ret < 0) { - dev_err(&client->dev, - "request gpio failed, cannot wake up controller: %d\n", - ret); + /* wake up controller via an falling edge on IRQ gpio. */ + gpio = gpiod_get(&client->dev, "wakeup", GPIOD_OUT_HIGH); + ret = PTR_ERR_OR_ZERO(gpio); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(&client->dev, + "failed to request wakeup gpio, cannot wake up controller: %d\n", + ret); return ret; } - /* wake up controller via an falling edge on IRQ gpio. */ - gpio_direction_output(gpio, 0); - gpio_set_value(gpio, 1); + /* release the line */ + gpiod_set_value_cansleep(gpio, 0); - /* controller should be waken up, return irq. */ - gpio_direction_input(gpio); - gpio_free(gpio); + /* controller should be woken up, return irq. */ + gpiod_direction_input(gpio); + gpiod_put(gpio); return 0; } @@ -161,8 +155,7 @@ static int egalax_firmware_version(struct i2c_client *client) return 0; } -static int egalax_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int egalax_ts_probe(struct i2c_client *client) { struct egalax_ts *ts; struct input_dev *input_dev; @@ -185,10 +178,8 @@ static int egalax_ts_probe(struct i2c_client *client, /* controller may be in sleep, wake it up. */ error = egalax_wake_up_device(client); - if (error) { - dev_err(&client->dev, "Failed to wake up the controller\n"); + if (error) return error; - } error = egalax_firmware_version(client); if (error < 0) { @@ -211,10 +202,9 @@ static int egalax_ts_probe(struct i2c_client *client, ABS_MT_POSITION_Y, 0, EGALAX_MAX_Y, 0, 0); input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0); - error = devm_request_threaded_irq(&client->dev, client->irq, NULL, - egalax_ts_interrupt, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "egalax_ts", ts); + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, egalax_ts_interrupt, + IRQF_ONESHOT, "egalax_ts", ts); if (error < 0) { dev_err(&client->dev, "Failed to register interrupt\n"); return error; @@ -273,7 +263,7 @@ static struct i2c_driver egalax_ts_driver = { .of_match_table = egalax_ts_dt_ids, }, .id_table = egalax_ts_id, - .probe = egalax_ts_probe, + .probe_new = egalax_ts_probe, }; module_i2c_driver(egalax_ts_driver); diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c index 2d01a8cbfcc6..328841eaa1b7 100644 --- a/drivers/input/touchscreen/ektf2127.c +++ b/drivers/input/touchscreen/ektf2127.c @@ -244,8 +244,7 @@ static int ektf2127_query_dimension(struct i2c_client *client, bool width) return (((buf[3] & 0xf0) << 4) | buf[2]) - 1; } -static int ektf2127_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ektf2127_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct ektf2127_ts *ts; @@ -352,7 +351,7 @@ static struct i2c_driver ektf2127_driver = { .pm = &ektf2127_pm_ops, .of_match_table = of_match_ptr(ektf2127_of_match), }, - .probe = ektf2127_probe, + .probe_new = ektf2127_probe, .id_table = ektf2127_i2c_id, }; module_i2c_driver(ektf2127_driver); diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 879a4d984c90..5452b50f8a77 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -36,6 +36,7 @@ #include <linux/input/touchscreen.h> #include <linux/acpi.h> #include <linux/of.h> +#include <linux/pm_wakeirq.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <linux/uuid.h> @@ -114,7 +115,7 @@ /* calibration timeout definition */ #define ELAN_CALI_TIMEOUT_MSEC 12000 -#define ELAN_POWERON_DELAY_USEC 500 +#define ELAN_POWERON_DELAY_USEC 5000 #define ELAN_RESET_DELAY_MSEC 20 /* FW boot code version */ @@ -180,7 +181,6 @@ struct elants_data { u8 cmd_resp[HEADER_SIZE]; struct completion cmd_done; - bool wake_irq_enabled; bool keep_power_in_suspend; /* Must be last to be used for DMA operations */ @@ -1329,14 +1329,12 @@ static int elants_i2c_power_on(struct elants_data *ts) if (IS_ERR_OR_NULL(ts->reset_gpio)) return 0; - gpiod_set_value_cansleep(ts->reset_gpio, 1); - error = regulator_enable(ts->vcc33); if (error) { dev_err(&ts->client->dev, "failed to enable vcc33 regulator: %d\n", error); - goto release_reset_gpio; + return error; } error = regulator_enable(ts->vccio); @@ -1345,19 +1343,16 @@ static int elants_i2c_power_on(struct elants_data *ts) "failed to enable vccio regulator: %d\n", error); regulator_disable(ts->vcc33); - goto release_reset_gpio; + return error; } /* * We need to wait a bit after powering on controller before * we are allowed to release reset GPIO. */ - udelay(ELAN_POWERON_DELAY_USEC); + usleep_range(ELAN_POWERON_DELAY_USEC, ELAN_POWERON_DELAY_USEC + 100); -release_reset_gpio: gpiod_set_value_cansleep(ts->reset_gpio, 0); - if (error) - return error; msleep(ELAN_RESET_DELAY_MSEC); @@ -1462,7 +1457,7 @@ static int elants_i2c_probe(struct i2c_client *client) return error; } - ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW); + ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ts->reset_gpio)) { error = PTR_ERR(ts->reset_gpio); @@ -1567,13 +1562,6 @@ static int elants_i2c_probe(struct i2c_client *client) return error; } - /* - * Systems using device tree should set up wakeup via DTS, - * the rest will configure device as wakeup source by default. - */ - if (!client->dev.of_node) - device_init_wakeup(&client->dev, true); - error = devm_device_add_group(&client->dev, &elants_attribute_group); if (error) { dev_err(&client->dev, "failed to create sysfs attributes: %d\n", @@ -1605,7 +1593,7 @@ static int __maybe_unused elants_i2c_suspend(struct device *dev) * The device will automatically enter idle mode * that has reduced power consumption. */ - ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0); + return 0; } else if (ts->keep_power_in_suspend) { for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { error = elants_i2c_send(client, set_sleep_cmd, @@ -1634,8 +1622,6 @@ static int __maybe_unused elants_i2c_resume(struct device *dev) int error; if (device_may_wakeup(dev)) { - if (ts->wake_irq_enabled) - disable_irq_wake(client->irq); elants_i2c_sw_reset(client); } else if (ts->keep_power_in_suspend) { for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index c281e49826c2..8a0a8078de8f 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -1282,8 +1282,7 @@ static void goodix_disable_regulators(void *arg) regulator_disable(ts->avdd28); } -static int goodix_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int goodix_ts_probe(struct i2c_client *client) { struct goodix_ts_data *ts; const char *cfg_name; @@ -1537,7 +1536,7 @@ MODULE_DEVICE_TABLE(of, goodix_of_match); #endif static struct i2c_driver goodix_ts_driver = { - .probe = goodix_ts_probe, + .probe_new = goodix_ts_probe, .remove = goodix_ts_remove, .id_table = goodix_ts_id, .driver = { diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index e9547ee29756..ff4bb4c14898 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -997,8 +997,7 @@ static const struct regmap_config hideep_regmap_config = { .max_register = 0xffff, }; -static int hideep_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int hideep_probe(struct i2c_client *client) { struct hideep_ts *ts; int error; @@ -1112,7 +1111,7 @@ static struct i2c_driver hideep_driver = { .pm = &hideep_pm_ops, }, .id_table = hideep_i2c_id, - .probe = hideep_probe, + .probe_new = hideep_probe, }; module_i2c_driver(hideep_driver); diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c new file mode 100644 index 000000000000..e96150d80a48 --- /dev/null +++ b/drivers/input/touchscreen/himax_hx83112b.c @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Himax hx83112b touchscreens + * + * Copyright (C) 2022 Job Noorman <job@noorman.info> + * + * This code is based on "Himax Android Driver Sample Code for QCT platform": + * + * Copyright (C) 2017 Himax Corporation. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/input/touchscreen.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/regmap.h> + +#define HIMAX_ID_83112B 0x83112b + +#define HIMAX_MAX_POINTS 10 + +#define HIMAX_REG_CFG_SET_ADDR 0x00 +#define HIMAX_REG_CFG_INIT_READ 0x0c +#define HIMAX_REG_CFG_READ_VALUE 0x08 +#define HIMAX_REG_READ_EVENT 0x30 + +#define HIMAX_CFG_PRODUCT_ID 0x900000d0 + +#define HIMAX_INVALID_COORD 0xffff + +struct himax_event_point { + __be16 x; + __be16 y; +} __packed; + +struct himax_event { + struct himax_event_point points[HIMAX_MAX_POINTS]; + u8 majors[HIMAX_MAX_POINTS]; + u8 pad0[2]; + u8 num_points; + u8 pad1[2]; + u8 checksum_fix; +} __packed; + +static_assert(sizeof(struct himax_event) == 56); + +struct himax_ts_data { + struct gpio_desc *gpiod_rst; + struct input_dev *input_dev; + struct i2c_client *client; + struct regmap *regmap; + struct touchscreen_properties props; +}; + +static const struct regmap_config himax_regmap_config = { + .reg_bits = 8, + .val_bits = 32, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static int himax_read_config(struct himax_ts_data *ts, u32 address, u32 *dst) +{ + int error; + + error = regmap_write(ts->regmap, HIMAX_REG_CFG_SET_ADDR, address); + if (error) + return error; + + error = regmap_write(ts->regmap, HIMAX_REG_CFG_INIT_READ, 0x0); + if (error) + return error; + + error = regmap_read(ts->regmap, HIMAX_REG_CFG_READ_VALUE, dst); + if (error) + return error; + + return 0; +} + +static void himax_reset(struct himax_ts_data *ts) +{ + gpiod_set_value_cansleep(ts->gpiod_rst, 1); + + /* Delay copied from downstream driver */ + msleep(20); + gpiod_set_value_cansleep(ts->gpiod_rst, 0); + + /* + * The downstream driver doesn't contain this delay but is seems safer + * to include it. The range is just a guess that seems to work well. + */ + usleep_range(1000, 1100); +} + +static int himax_read_product_id(struct himax_ts_data *ts, u32 *product_id) +{ + int error; + + error = himax_read_config(ts, HIMAX_CFG_PRODUCT_ID, product_id); + if (error) + return error; + + *product_id >>= 8; + return 0; +} + +static int himax_check_product_id(struct himax_ts_data *ts) +{ + int error; + u32 product_id; + + error = himax_read_product_id(ts, &product_id); + if (error) + return error; + + dev_dbg(&ts->client->dev, "Product id: %x\n", product_id); + + switch (product_id) { + case HIMAX_ID_83112B: + return 0; + + default: + dev_err(&ts->client->dev, + "Unknown product id: %x\n", product_id); + return -EINVAL; + } +} + +static int himax_input_register(struct himax_ts_data *ts) +{ + int error; + + ts->input_dev = devm_input_allocate_device(&ts->client->dev); + if (!ts->input_dev) { + dev_err(&ts->client->dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + ts->input_dev->name = "Himax Touchscreen"; + + input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_Y); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 200, 0, 0); + + touchscreen_parse_properties(ts->input_dev, true, &ts->props); + + error = input_mt_init_slots(ts->input_dev, HIMAX_MAX_POINTS, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(&ts->client->dev, + "Failed to initialize MT slots: %d\n", error); + return error; + } + + error = input_register_device(ts->input_dev); + if (error) { + dev_err(&ts->client->dev, + "Failed to register input device: %d\n", error); + return error; + } + + return 0; +} + +static u8 himax_event_get_num_points(const struct himax_event *event) +{ + if (event->num_points == 0xff) + return 0; + else + return event->num_points & 0x0f; +} + +static bool himax_process_event_point(struct himax_ts_data *ts, + const struct himax_event *event, + int point_index) +{ + const struct himax_event_point *point = &event->points[point_index]; + u16 x = be16_to_cpu(point->x); + u16 y = be16_to_cpu(point->y); + u8 w = event->majors[point_index]; + + if (x == HIMAX_INVALID_COORD || y == HIMAX_INVALID_COORD) + return false; + + input_mt_slot(ts->input_dev, point_index); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); + touchscreen_report_pos(ts->input_dev, &ts->props, x, y, true); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); + return true; +} + +static void himax_process_event(struct himax_ts_data *ts, + const struct himax_event *event) +{ + int i; + int num_points_left = himax_event_get_num_points(event); + + for (i = 0; i < HIMAX_MAX_POINTS && num_points_left > 0; i++) { + if (himax_process_event_point(ts, event, i)) + num_points_left--; + } + + input_mt_sync_frame(ts->input_dev); + input_sync(ts->input_dev); +} + +static bool himax_verify_checksum(struct himax_ts_data *ts, + const struct himax_event *event) +{ + u8 *data = (u8 *)event; + int i; + u16 checksum = 0; + + for (i = 0; i < sizeof(*event); i++) + checksum += data[i]; + + if ((checksum & 0x00ff) != 0) { + dev_err(&ts->client->dev, "Wrong event checksum: %04x\n", + checksum); + return false; + } + + return true; +} + +static int himax_handle_input(struct himax_ts_data *ts) +{ + int error; + struct himax_event event; + + error = regmap_raw_read(ts->regmap, HIMAX_REG_READ_EVENT, &event, + sizeof(event)); + if (error) { + dev_err(&ts->client->dev, "Failed to read input event: %d\n", + error); + return error; + } + + /* + * Only process the current event when it has a valid checksum but + * don't consider it a fatal error when it doesn't. + */ + if (himax_verify_checksum(ts, &event)) + himax_process_event(ts, &event); + + return 0; +} + +static irqreturn_t himax_irq_handler(int irq, void *dev_id) +{ + int error; + struct himax_ts_data *ts = dev_id; + + error = himax_handle_input(ts); + if (error) + return IRQ_NONE; + + return IRQ_HANDLED; +} + +static int himax_probe(struct i2c_client *client) +{ + int error; + struct device *dev = &client->dev; + struct himax_ts_data *ts; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(dev, "I2C check functionality failed\n"); + return -ENXIO; + } + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + i2c_set_clientdata(client, ts); + ts->client = client; + + ts->regmap = devm_regmap_init_i2c(client, &himax_regmap_config); + error = PTR_ERR_OR_ZERO(ts->regmap); + if (error) { + dev_err(dev, "Failed to initialize regmap: %d\n", error); + return error; + } + + ts->gpiod_rst = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + error = PTR_ERR_OR_ZERO(ts->gpiod_rst); + if (error) { + dev_err(dev, "Failed to get reset GPIO: %d\n", error); + return error; + } + + himax_reset(ts); + + error = himax_check_product_id(ts); + if (error) + return error; + + error = himax_input_register(ts); + if (error) + return error; + + error = devm_request_threaded_irq(dev, client->irq, NULL, + himax_irq_handler, IRQF_ONESHOT, + client->name, ts); + if (error) + return error; + + return 0; +} + +static int himax_suspend(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + disable_irq(ts->client->irq); + return 0; +} + +static int himax_resume(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + enable_irq(ts->client->irq); + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(himax_pm_ops, himax_suspend, himax_resume); + +static const struct i2c_device_id himax_ts_id[] = { + { "hx83112b", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, himax_ts_id); + +#ifdef CONFIG_OF +static const struct of_device_id himax_of_match[] = { + { .compatible = "himax,hx83112b" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, himax_of_match); +#endif + +static struct i2c_driver himax_ts_driver = { + .probe_new = himax_probe, + .id_table = himax_ts_id, + .driver = { + .name = "Himax-hx83112b-TS", + .of_match_table = of_match_ptr(himax_of_match), + .pm = pm_sleep_ptr(&himax_pm_ops), + }, +}; +module_i2c_driver(himax_ts_driver); + +MODULE_AUTHOR("Job Noorman <job@noorman.info>"); +MODULE_DESCRIPTION("Himax hx83112b touchscreen driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/hycon-hy46xx.c b/drivers/input/touchscreen/hycon-hy46xx.c index 891d0430083e..8f4989aba9a4 100644 --- a/drivers/input/touchscreen/hycon-hy46xx.c +++ b/drivers/input/touchscreen/hycon-hy46xx.c @@ -439,8 +439,7 @@ static void hycon_hy46xx_disable_regulator(void *arg) regulator_disable(data->vcc); } -static int hycon_hy46xx_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int hycon_hy46xx_probe(struct i2c_client *client) { struct hycon_hy46xx_data *tsdata; struct input_dev *input; @@ -581,7 +580,7 @@ static struct i2c_driver hycon_hy46xx_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .id_table = hycon_hy46xx_id, - .probe = hycon_hy46xx_probe, + .probe_new = hycon_hy46xx_probe, }; module_i2c_driver(hycon_hy46xx_driver); diff --git a/drivers/input/touchscreen/hynitron_cstxxx.c b/drivers/input/touchscreen/hynitron_cstxxx.c new file mode 100644 index 000000000000..e86c85addb38 --- /dev/null +++ b/drivers/input/touchscreen/hynitron_cstxxx.c @@ -0,0 +1,498 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Hynitron cstxxx Touchscreen + * + * Copyright (c) 2022 Chris Morgan <macromorgan@hotmail.com> + * + * This code is based on hynitron_core.c authored by Hynitron. + * Note that no datasheet was available, so much of these registers + * are undocumented. This is essentially a cleaned-up version of the + * vendor driver with support removed for hardware I cannot test and + * device-specific functions replated with generic functions wherever + * possible. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/input/touchscreen.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/property.h> +#include <asm/unaligned.h> + +/* Per chip data */ +struct hynitron_ts_chip_data { + unsigned int max_touch_num; + u32 ic_chkcode; + int (*firmware_info)(struct i2c_client *client); + int (*bootloader_enter)(struct i2c_client *client); + int (*init_input)(struct i2c_client *client); + void (*report_touch)(struct i2c_client *client); +}; + +/* Data generic to all (supported and non-supported) controllers. */ +struct hynitron_ts_data { + const struct hynitron_ts_chip_data *chip; + struct i2c_client *client; + struct input_dev *input_dev; + struct touchscreen_properties prop; + struct gpio_desc *reset_gpio; +}; + +/* + * Since I have no datasheet, these values are guessed and/or assumed + * based on observation and testing. + */ +#define CST3XX_FIRMWARE_INFO_START_CMD 0x01d1 +#define CST3XX_FIRMWARE_INFO_END_CMD 0x09d1 +#define CST3XX_FIRMWARE_CHK_CODE_REG 0xfcd1 +#define CST3XX_FIRMWARE_VERSION_REG 0x08d2 +#define CST3XX_FIRMWARE_VER_INVALID_VAL 0xa5a5a5a5 + +#define CST3XX_BOOTLDR_PROG_CMD 0xaa01a0 +#define CST3XX_BOOTLDR_PROG_CHK_REG 0x02a0 +#define CST3XX_BOOTLDR_CHK_VAL 0xac + +#define CST3XX_TOUCH_DATA_PART_REG 0x00d0 +#define CST3XX_TOUCH_DATA_FULL_REG 0x07d0 +#define CST3XX_TOUCH_DATA_CHK_VAL 0xab +#define CST3XX_TOUCH_DATA_TOUCH_VAL 0x03 +#define CST3XX_TOUCH_DATA_STOP_CMD 0xab00d0 +#define CST3XX_TOUCH_COUNT_MASK GENMASK(6, 0) + + +/* + * Hard coded reset delay value of 20ms not IC dependent in + * vendor driver. + */ +static void hyn_reset_proc(struct i2c_client *client, int delay) +{ + struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); + + gpiod_set_value_cansleep(ts_data->reset_gpio, 1); + msleep(20); + gpiod_set_value_cansleep(ts_data->reset_gpio, 0); + if (delay) + fsleep(delay * 1000); +} + +static irqreturn_t hyn_interrupt_handler(int irq, void *dev_id) +{ + struct i2c_client *client = dev_id; + struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); + + ts_data->chip->report_touch(client); + + return IRQ_HANDLED; +} + +/* + * The vendor driver would retry twice before failing to read or write + * to the i2c device. + */ + +static int cst3xx_i2c_write(struct i2c_client *client, + unsigned char *buf, int len) +{ + int ret; + int retries = 0; + + while (retries < 2) { + ret = i2c_master_send(client, buf, len); + if (ret == len) + return 0; + if (ret <= 0) + retries++; + else + break; + } + + return ret < 0 ? ret : -EIO; +} + +static int cst3xx_i2c_read_register(struct i2c_client *client, u16 reg, + u8 *val, u16 len) +{ + __le16 buf = cpu_to_le16(reg); + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = (u8 *)&buf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = len, + .buf = val, + } + }; + int err; + int ret; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret == ARRAY_SIZE(msgs)) + return 0; + + err = ret < 0 ? ret : -EIO; + dev_err(&client->dev, "Error reading %d bytes from 0x%04x: %d (%d)\n", + len, reg, err, ret); + + return err; +} + +static int cst3xx_firmware_info(struct i2c_client *client) +{ + struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); + int err; + u32 tmp; + unsigned char buf[4]; + + /* + * Tests suggest this command needed to read firmware regs. + */ + put_unaligned_le16(CST3XX_FIRMWARE_INFO_START_CMD, buf); + err = cst3xx_i2c_write(client, buf, 2); + if (err) + return err; + + usleep_range(10000, 11000); + + /* + * Read register for check-code to determine if device detected + * correctly. + */ + err = cst3xx_i2c_read_register(client, CST3XX_FIRMWARE_CHK_CODE_REG, + buf, 4); + if (err) + return err; + + tmp = get_unaligned_le32(buf); + if ((tmp & 0xffff0000) != ts_data->chip->ic_chkcode) { + dev_err(&client->dev, "%s ic mismatch, chkcode is %u\n", + __func__, tmp); + return -ENODEV; + } + + usleep_range(10000, 11000); + + /* Read firmware version and test if firmware missing. */ + err = cst3xx_i2c_read_register(client, CST3XX_FIRMWARE_VERSION_REG, + buf, 4); + if (err) + return err; + + tmp = get_unaligned_le32(buf); + if (tmp == CST3XX_FIRMWARE_VER_INVALID_VAL) { + dev_err(&client->dev, "Device firmware missing\n"); + return -ENODEV; + } + + /* + * Tests suggest cmd required to exit reading firmware regs. + */ + put_unaligned_le16(CST3XX_FIRMWARE_INFO_END_CMD, buf); + err = cst3xx_i2c_write(client, buf, 2); + if (err) + return err; + + usleep_range(5000, 6000); + + return 0; +} + +static int cst3xx_bootloader_enter(struct i2c_client *client) +{ + int err; + u8 retry; + u32 tmp = 0; + unsigned char buf[3]; + + for (retry = 0; retry < 5; retry++) { + hyn_reset_proc(client, (7 + retry)); + /* set cmd to enter program mode */ + put_unaligned_le24(CST3XX_BOOTLDR_PROG_CMD, buf); + err = cst3xx_i2c_write(client, buf, 3); + if (err) + continue; + + usleep_range(2000, 2500); + + /* check whether in program mode */ + err = cst3xx_i2c_read_register(client, + CST3XX_BOOTLDR_PROG_CHK_REG, + buf, 1); + if (err) + continue; + + tmp = get_unaligned(buf); + if (tmp == CST3XX_BOOTLDR_CHK_VAL) + break; + } + + if (tmp != CST3XX_BOOTLDR_CHK_VAL) { + dev_err(&client->dev, "%s unable to enter bootloader mode\n", + __func__); + return -ENODEV; + } + + hyn_reset_proc(client, 40); + + return 0; +} + +static void cst3xx_report_contact(struct hynitron_ts_data *ts_data, + u8 id, unsigned int x, unsigned int y, u8 w) +{ + input_mt_slot(ts_data->input_dev, id); + input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, 1); + touchscreen_report_pos(ts_data->input_dev, &ts_data->prop, x, y, true); + input_report_abs(ts_data->input_dev, ABS_MT_TOUCH_MAJOR, w); +} + +static int cst3xx_finish_touch_read(struct i2c_client *client) +{ + unsigned char buf[3]; + int err; + + put_unaligned_le24(CST3XX_TOUCH_DATA_STOP_CMD, buf); + err = cst3xx_i2c_write(client, buf, 3); + if (err) { + dev_err(&client->dev, + "send read touch info ending failed: %d\n", err); + return err; + } + + return 0; +} + +/* + * Handle events from IRQ. Note that for cst3xx it appears that IRQ + * fires continuously while touched, otherwise once every 1500ms + * when not touched (assume touchscreen waking up periodically). + * Note buffer is sized for 5 fingers, if more needed buffer must + * be increased. The buffer contains 5 bytes for each touch point, + * a touch count byte, a check byte, and then a second check byte after + * all other touch points. + * + * For example 1 touch would look like this: + * touch1[5]:touch_count[1]:chk_byte[1] + * + * 3 touches would look like this: + * touch1[5]:touch_count[1]:chk_byte[1]:touch2[5]:touch3[5]:chk_byte[1] + */ +static void cst3xx_touch_report(struct i2c_client *client) +{ + struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); + u8 buf[28]; + u8 finger_id, sw, w; + unsigned int x, y; + unsigned int touch_cnt, end_byte; + unsigned int idx = 0; + unsigned int i; + int err; + + /* Read and validate the first bits of input data. */ + err = cst3xx_i2c_read_register(client, CST3XX_TOUCH_DATA_PART_REG, + buf, 28); + if (err || + buf[6] != CST3XX_TOUCH_DATA_CHK_VAL || + buf[0] == CST3XX_TOUCH_DATA_CHK_VAL) { + dev_err(&client->dev, "cst3xx touch read failure\n"); + return; + } + + /* Report to the device we're done reading the touch data. */ + err = cst3xx_finish_touch_read(client); + if (err) + return; + + touch_cnt = buf[5] & CST3XX_TOUCH_COUNT_MASK; + /* + * Check the check bit of the last touch slot. The check bit is + * always present after touch point 1 for valid data, and then + * appears as the last byte after all other touch data. + */ + if (touch_cnt > 1) { + end_byte = touch_cnt * 5 + 2; + if (buf[end_byte] != CST3XX_TOUCH_DATA_CHK_VAL) { + dev_err(&client->dev, "cst3xx touch read failure\n"); + return; + } + } + + /* Parse through the buffer to capture touch data. */ + for (i = 0; i < touch_cnt; i++) { + x = ((buf[idx + 1] << 4) | ((buf[idx + 3] >> 4) & 0x0f)); + y = ((buf[idx + 2] << 4) | (buf[idx + 3] & 0x0f)); + w = (buf[idx + 4] >> 3); + sw = (buf[idx] & 0x0f) >> 1; + finger_id = (buf[idx] >> 4) & 0x0f; + + /* Sanity check we don't have more fingers than we expect */ + if (ts_data->chip->max_touch_num < finger_id) { + dev_err(&client->dev, "cst3xx touch read failure\n"); + break; + } + + /* sw value of 0 means no touch, 0x03 means touch */ + if (sw == CST3XX_TOUCH_DATA_TOUCH_VAL) + cst3xx_report_contact(ts_data, finger_id, x, y, w); + + idx += 5; + + /* Skip the 2 bytes between point 1 and point 2 */ + if (i == 0) + idx += 2; + } + + input_mt_sync_frame(ts_data->input_dev); + input_sync(ts_data->input_dev); +} + +static int cst3xx_input_dev_int(struct i2c_client *client) +{ + struct hynitron_ts_data *ts_data = i2c_get_clientdata(client); + int err; + + ts_data->input_dev = devm_input_allocate_device(&client->dev); + if (!ts_data->input_dev) { + dev_err(&client->dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + ts_data->input_dev->name = "Hynitron cst3xx Touchscreen"; + ts_data->input_dev->phys = "input/ts"; + ts_data->input_dev->id.bustype = BUS_I2C; + + input_set_drvdata(ts_data->input_dev, ts_data); + + input_set_capability(ts_data->input_dev, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(ts_data->input_dev, EV_ABS, ABS_MT_POSITION_Y); + input_set_abs_params(ts_data->input_dev, ABS_MT_TOUCH_MAJOR, + 0, 255, 0, 0); + + touchscreen_parse_properties(ts_data->input_dev, true, &ts_data->prop); + + if (!ts_data->prop.max_x || !ts_data->prop.max_y) { + dev_err(&client->dev, + "Invalid x/y (%d, %d), using defaults\n", + ts_data->prop.max_x, ts_data->prop.max_y); + ts_data->prop.max_x = 1152; + ts_data->prop.max_y = 1920; + input_abs_set_max(ts_data->input_dev, + ABS_MT_POSITION_X, ts_data->prop.max_x); + input_abs_set_max(ts_data->input_dev, + ABS_MT_POSITION_Y, ts_data->prop.max_y); + } + + err = input_mt_init_slots(ts_data->input_dev, + ts_data->chip->max_touch_num, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (err) { + dev_err(&client->dev, + "Failed to initialize input slots: %d\n", err); + return err; + } + + err = input_register_device(ts_data->input_dev); + if (err) { + dev_err(&client->dev, + "Input device registration failed: %d\n", err); + return err; + } + + return 0; +} + +static int hyn_probe(struct i2c_client *client) +{ + struct hynitron_ts_data *ts_data; + int err; + + ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL); + if (!ts_data) + return -ENOMEM; + + ts_data->client = client; + i2c_set_clientdata(client, ts_data); + + ts_data->chip = device_get_match_data(&client->dev); + if (!ts_data->chip) + return -EINVAL; + + ts_data->reset_gpio = devm_gpiod_get(&client->dev, + "reset", GPIOD_OUT_LOW); + err = PTR_ERR_OR_ZERO(ts_data->reset_gpio); + if (err) { + dev_err(&client->dev, "request reset gpio failed: %d\n", err); + return err; + } + + hyn_reset_proc(client, 60); + + err = ts_data->chip->bootloader_enter(client); + if (err < 0) + return err; + + err = ts_data->chip->init_input(client); + if (err < 0) + return err; + + err = ts_data->chip->firmware_info(client); + if (err < 0) + return err; + + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, hyn_interrupt_handler, + IRQF_ONESHOT, + "Hynitron Touch Int", client); + if (err) { + dev_err(&client->dev, "failed to request IRQ: %d\n", err); + return err; + } + + return 0; +} + +static const struct hynitron_ts_chip_data cst3xx_data = { + .max_touch_num = 5, + .ic_chkcode = 0xcaca0000, + .firmware_info = &cst3xx_firmware_info, + .bootloader_enter = &cst3xx_bootloader_enter, + .init_input = &cst3xx_input_dev_int, + .report_touch = &cst3xx_touch_report, +}; + +static const struct i2c_device_id hyn_tpd_id[] = { + { .name = "hynitron_ts", 0 }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(i2c, hyn_tpd_id); + +static const struct of_device_id hyn_dt_match[] = { + { .compatible = "hynitron,cst340", .data = &cst3xx_data }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, hyn_dt_match); + +static struct i2c_driver hynitron_i2c_driver = { + .driver = { + .name = "Hynitron-TS", + .of_match_table = hyn_dt_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .id_table = hyn_tpd_id, + .probe_new = hyn_probe, +}; + +module_i2c_driver(hynitron_i2c_driver); + +MODULE_AUTHOR("Chris Morgan"); +MODULE_DESCRIPTION("Hynitron Touchscreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index e9bd36adbe47..4897fafa4204 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -913,9 +913,9 @@ static void ili210x_stop(void *data) priv->stop = true; } -static int ili210x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ili210x_i2c_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device *dev = &client->dev; const struct ili2xxx_chip *chip; struct ili210x *priv; @@ -1043,7 +1043,7 @@ static struct i2c_driver ili210x_ts_driver = { .of_match_table = ili210x_dt_ids, }, .id_table = ili210x_i2c_id, - .probe = ili210x_i2c_probe, + .probe_new = ili210x_i2c_probe, }; module_i2c_driver(ili210x_ts_driver); diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c index c5d259c76adc..e6ade3775a8a 100644 --- a/drivers/input/touchscreen/ilitek_ts_i2c.c +++ b/drivers/input/touchscreen/ilitek_ts_i2c.c @@ -542,8 +542,7 @@ static struct attribute_group ilitek_attrs_group = { .attrs = ilitek_sysfs_attrs, }; -static int ilitek_ts_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ilitek_ts_i2c_probe(struct i2c_client *client) { struct ilitek_ts_data *ts; struct device *dev = &client->dev; @@ -680,7 +679,7 @@ static struct i2c_driver ilitek_ts_i2c_driver = { .of_match_table = of_match_ptr(ilitek_ts_i2c_match), .acpi_match_table = ACPI_PTR(ilitekts_acpi_id), }, - .probe = ilitek_ts_i2c_probe, + .probe_new = ilitek_ts_i2c_probe, .id_table = ilitek_ts_i2c_id, }; module_i2c_driver(ilitek_ts_i2c_driver); diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c index 34c4cca57d13..dc3137a34f35 100644 --- a/drivers/input/touchscreen/iqs5xx.c +++ b/drivers/input/touchscreen/iqs5xx.c @@ -1019,8 +1019,7 @@ static int __maybe_unused iqs5xx_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(iqs5xx_pm, iqs5xx_suspend, iqs5xx_resume); -static int iqs5xx_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int iqs5xx_probe(struct i2c_client *client) { struct iqs5xx_private *iqs5xx; int error; @@ -1094,7 +1093,7 @@ static struct i2c_driver iqs5xx_i2c_driver = { .pm = &iqs5xx_pm, }, .id_table = iqs5xx_id, - .probe = iqs5xx_probe, + .probe_new = iqs5xx_probe, }; module_i2c_driver(iqs5xx_i2c_driver); diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index f15713aaebc2..461023fd6a09 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -168,8 +168,7 @@ static void max11801_ts_phy_init(struct max11801_data *data) max11801_write_reg(client, OP_MODE_CONF_REG, 0x36); } -static int max11801_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max11801_ts_probe(struct i2c_client *client) { struct max11801_data *data; struct input_dev *input_dev; @@ -231,7 +230,7 @@ static struct i2c_driver max11801_ts_driver = { .of_match_table = max11801_ts_dt_ids, }, .id_table = max11801_ts_id, - .probe = max11801_ts_probe, + .probe_new = max11801_ts_probe, }; module_i2c_driver(max11801_ts_driver); diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 5376d8f740ab..ea9517cad695 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -180,8 +180,7 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data, OP_MODE_ACTIVE | REPORT_RATE_80); } -static int mcs5000_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mcs5000_ts_probe(struct i2c_client *client) { const struct mcs_platform_data *pdata; struct mcs5000_ts_data *data; @@ -272,7 +271,7 @@ static const struct i2c_device_id mcs5000_ts_id[] = { MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); static struct i2c_driver mcs5000_ts_driver = { - .probe = mcs5000_ts_probe, + .probe_new = mcs5000_ts_probe, .driver = { .name = "mcs5000_ts", .pm = &mcs5000_ts_pm, diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 83f4be05e27b..4ee8ed4c930c 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -1424,7 +1424,7 @@ static const struct attribute_group mip4_attr_group = { .attrs = mip4_attrs, }; -static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int mip4_probe(struct i2c_client *client) { struct mip4_ts *ts; struct input_dev *input; @@ -1590,7 +1590,7 @@ MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids); static struct i2c_driver mip4_driver = { .id_table = mip4_i2c_ids, - .probe = mip4_probe, + .probe_new = mip4_probe, .driver = { .name = MIP4_DEVICE_NAME, .of_match_table = of_match_ptr(mip4_of_match), diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 79cd660d879e..ff0f605f3a3a 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -116,8 +116,7 @@ static void migor_ts_close(struct input_dev *dev) enable_irq(priv->irq); } -static int migor_ts_probe(struct i2c_client *client, - const struct i2c_device_id *idp) +static int migor_ts_probe(struct i2c_client *client) { struct migor_ts_priv *priv; struct input_dev *input; @@ -222,7 +221,7 @@ static struct i2c_driver migor_ts_driver = { .name = "migor_ts", .pm = &migor_ts_pm, }, - .probe = migor_ts_probe, + .probe_new = migor_ts_probe, .remove = migor_ts_remove, .id_table = migor_ts_id, }; diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 9fa3b0e421be..758b669391a7 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -440,8 +440,7 @@ static int mms114_parse_legacy_bindings(struct mms114_data *data) return 0; } -static int mms114_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mms114_probe(struct i2c_client *client) { struct mms114_data *data; struct input_dev *input_dev; @@ -639,7 +638,7 @@ static struct i2c_driver mms114_driver = { .pm = &mms114_pm_ops, .of_match_table = of_match_ptr(mms114_dt_match), }, - .probe = mms114_probe, + .probe_new = mms114_probe, .id_table = mms114_id, }; diff --git a/drivers/input/touchscreen/msg2638.c b/drivers/input/touchscreen/msg2638.c index 75536bc88969..4c0816b09d33 100644 --- a/drivers/input/touchscreen/msg2638.c +++ b/drivers/input/touchscreen/msg2638.c @@ -21,28 +21,49 @@ #include <linux/kernel.h> #include <linux/mod_devicetable.h> #include <linux/module.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #define MODE_DATA_RAW 0x5A -#define MAX_SUPPORTED_FINGER_NUM 5 +#define MSG2138_MAX_FINGERS 2 +#define MSG2638_MAX_FINGERS 5 + +#define MAX_BUTTONS 4 #define CHIP_ON_DELAY_MS 15 #define FIRMWARE_ON_DELAY_MS 50 #define RESET_DELAY_MIN_US 10000 #define RESET_DELAY_MAX_US 11000 -struct packet { +struct msg_chip_data { + irq_handler_t irq_handler; + unsigned int max_fingers; +}; + +struct msg2138_packet { + u8 xy_hi; /* higher bits of x and y coordinates */ + u8 x_low; + u8 y_low; +}; + +struct msg2138_touch_event { + u8 magic; + struct msg2138_packet pkt[MSG2138_MAX_FINGERS]; + u8 checksum; +}; + +struct msg2638_packet { u8 xy_hi; /* higher bits of x and y coordinates */ u8 x_low; u8 y_low; u8 pressure; }; -struct touch_event { +struct msg2638_touch_event { u8 mode; - struct packet pkt[MAX_SUPPORTED_FINGER_NUM]; + struct msg2638_packet pkt[MSG2638_MAX_FINGERS]; u8 proximity; u8 checksum; }; @@ -53,6 +74,9 @@ struct msg2638_ts_data { struct touchscreen_properties prop; struct regulator_bulk_data supplies[2]; struct gpio_desc *reset_gpiod; + int max_fingers; + u32 keycodes[MAX_BUTTONS]; + int num_keycodes; }; static u8 msg2638_checksum(u8 *data, u32 length) @@ -66,12 +90,102 @@ static u8 msg2638_checksum(u8 *data, u32 length) return (u8)((-sum) & 0xFF); } +static void msg2138_report_keys(struct msg2638_ts_data *msg2638, u8 keys) +{ + int i; + + /* keys can be 0x00 or 0xff when all keys have been released */ + if (keys == 0xff) + keys = 0; + + for (i = 0; i < msg2638->num_keycodes; ++i) + input_report_key(msg2638->input_dev, msg2638->keycodes[i], + keys & BIT(i)); +} + +static irqreturn_t msg2138_ts_irq_handler(int irq, void *msg2638_handler) +{ + struct msg2638_ts_data *msg2638 = msg2638_handler; + struct i2c_client *client = msg2638->client; + struct input_dev *input = msg2638->input_dev; + struct msg2138_touch_event touch_event; + u32 len = sizeof(touch_event); + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = sizeof(touch_event), + .buf = (u8 *)&touch_event, + }, + }; + struct msg2138_packet *p0, *p1; + u16 x, y, delta_x, delta_y; + int ret; + + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret != ARRAY_SIZE(msg)) { + dev_err(&client->dev, + "Failed I2C transfer in irq handler: %d\n", + ret < 0 ? ret : -EIO); + goto out; + } + + if (msg2638_checksum((u8 *)&touch_event, len - 1) != + touch_event.checksum) { + dev_err(&client->dev, "Failed checksum!\n"); + goto out; + } + + p0 = &touch_event.pkt[0]; + p1 = &touch_event.pkt[1]; + + /* Ignore non-pressed finger data, but check for key code */ + if (p0->xy_hi == 0xFF && p0->x_low == 0xFF && p0->y_low == 0xFF) { + if (p1->xy_hi == 0xFF && p1->y_low == 0xFF) + msg2138_report_keys(msg2638, p1->x_low); + goto report; + } + + x = ((p0->xy_hi & 0xF0) << 4) | p0->x_low; + y = ((p0->xy_hi & 0x0F) << 8) | p0->y_low; + + input_mt_slot(input, 0); + input_mt_report_slot_state(input, MT_TOOL_FINGER, true); + touchscreen_report_pos(input, &msg2638->prop, x, y, true); + + /* Ignore non-pressed finger data */ + if (p1->xy_hi == 0xFF && p1->x_low == 0xFF && p1->y_low == 0xFF) + goto report; + + /* Second finger is reported as a delta position */ + delta_x = ((p1->xy_hi & 0xF0) << 4) | p1->x_low; + delta_y = ((p1->xy_hi & 0x0F) << 8) | p1->y_low; + + /* Ignore second finger if both deltas equal 0 */ + if (delta_x == 0 && delta_y == 0) + goto report; + + x += delta_x; + y += delta_y; + + input_mt_slot(input, 1); + input_mt_report_slot_state(input, MT_TOOL_FINGER, true); + touchscreen_report_pos(input, &msg2638->prop, x, y, true); + +report: + input_mt_sync_frame(msg2638->input_dev); + input_sync(msg2638->input_dev); + +out: + return IRQ_HANDLED; +} + static irqreturn_t msg2638_ts_irq_handler(int irq, void *msg2638_handler) { struct msg2638_ts_data *msg2638 = msg2638_handler; struct i2c_client *client = msg2638->client; struct input_dev *input = msg2638->input_dev; - struct touch_event touch_event; + struct msg2638_touch_event touch_event; u32 len = sizeof(touch_event); struct i2c_msg msg[] = { { @@ -81,7 +195,7 @@ static irqreturn_t msg2638_ts_irq_handler(int irq, void *msg2638_handler) .buf = (u8 *)&touch_event, }, }; - struct packet *p; + struct msg2638_packet *p; u16 x, y; int ret; int i; @@ -103,7 +217,7 @@ static irqreturn_t msg2638_ts_irq_handler(int irq, void *msg2638_handler) goto out; } - for (i = 0; i < MAX_SUPPORTED_FINGER_NUM; i++) { + for (i = 0; i < msg2638->max_fingers; i++) { p = &touch_event.pkt[i]; /* Ignore non-pressed finger data */ @@ -190,6 +304,7 @@ static int msg2638_init_input_dev(struct msg2638_ts_data *msg2638) struct device *dev = &msg2638->client->dev; struct input_dev *input_dev; int error; + int i; input_dev = devm_input_allocate_device(dev); if (!input_dev) { @@ -206,6 +321,15 @@ static int msg2638_init_input_dev(struct msg2638_ts_data *msg2638) input_dev->open = msg2638_input_open; input_dev->close = msg2638_input_close; + if (msg2638->num_keycodes) { + input_dev->keycode = msg2638->keycodes; + input_dev->keycodemax = msg2638->num_keycodes; + input_dev->keycodesize = sizeof(msg2638->keycodes[0]); + for (i = 0; i < msg2638->num_keycodes; i++) + input_set_capability(input_dev, + EV_KEY, msg2638->keycodes[i]); + } + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); @@ -215,7 +339,7 @@ static int msg2638_init_input_dev(struct msg2638_ts_data *msg2638) return -EINVAL; } - error = input_mt_init_slots(input_dev, MAX_SUPPORTED_FINGER_NUM, + error = input_mt_init_slots(input_dev, msg2638->max_fingers, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); if (error) { dev_err(dev, "Failed to initialize MT slots: %d\n", error); @@ -233,6 +357,7 @@ static int msg2638_init_input_dev(struct msg2638_ts_data *msg2638) static int msg2638_ts_probe(struct i2c_client *client) { + const struct msg_chip_data *chip_data; struct device *dev = &client->dev; struct msg2638_ts_data *msg2638; int error; @@ -249,6 +374,14 @@ static int msg2638_ts_probe(struct i2c_client *client) msg2638->client = client; i2c_set_clientdata(client, msg2638); + chip_data = device_get_match_data(&client->dev); + if (!chip_data || !chip_data->max_fingers) { + dev_err(dev, "Invalid or missing chip data\n"); + return -EINVAL; + } + + msg2638->max_fingers = chip_data->max_fingers; + msg2638->supplies[0].supply = "vdd"; msg2638->supplies[1].supply = "vddio"; error = devm_regulator_bulk_get(dev, ARRAY_SIZE(msg2638->supplies), @@ -265,14 +398,33 @@ static int msg2638_ts_probe(struct i2c_client *client) return error; } - error = msg2638_init_input_dev(msg2638); - if (error) { - dev_err(dev, "Failed to initialize input device: %d\n", error); - return error; + msg2638->num_keycodes = device_property_count_u32(dev, + "linux,keycodes"); + if (msg2638->num_keycodes == -EINVAL) { + msg2638->num_keycodes = 0; + } else if (msg2638->num_keycodes < 0) { + dev_err(dev, "Unable to parse linux,keycodes property: %d\n", + msg2638->num_keycodes); + return msg2638->num_keycodes; + } else if (msg2638->num_keycodes > ARRAY_SIZE(msg2638->keycodes)) { + dev_warn(dev, "Found %d linux,keycodes but max is %zd, ignoring the rest\n", + msg2638->num_keycodes, ARRAY_SIZE(msg2638->keycodes)); + msg2638->num_keycodes = ARRAY_SIZE(msg2638->keycodes); + } + + if (msg2638->num_keycodes > 0) { + error = device_property_read_u32_array(dev, "linux,keycodes", + msg2638->keycodes, + msg2638->num_keycodes); + if (error) { + dev_err(dev, "Unable to read linux,keycodes values: %d\n", + error); + return error; + } } error = devm_request_threaded_irq(dev, client->irq, - NULL, msg2638_ts_irq_handler, + NULL, chip_data->irq_handler, IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, msg2638); if (error) { @@ -280,6 +432,12 @@ static int msg2638_ts_probe(struct i2c_client *client) return error; } + error = msg2638_init_input_dev(msg2638); + if (error) { + dev_err(dev, "Failed to initialize input device: %d\n", error); + return error; + } + return 0; } @@ -316,8 +474,19 @@ static int __maybe_unused msg2638_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(msg2638_pm_ops, msg2638_suspend, msg2638_resume); +static const struct msg_chip_data msg2138_data = { + .irq_handler = msg2138_ts_irq_handler, + .max_fingers = MSG2138_MAX_FINGERS, +}; + +static const struct msg_chip_data msg2638_data = { + .irq_handler = msg2638_ts_irq_handler, + .max_fingers = MSG2638_MAX_FINGERS, +}; + static const struct of_device_id msg2638_of_match[] = { - { .compatible = "mstar,msg2638" }, + { .compatible = "mstar,msg2138", .data = &msg2138_data }, + { .compatible = "mstar,msg2638", .data = &msg2638_data }, { } }; MODULE_DEVICE_TABLE(of, msg2638_of_match); diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index dc148b4bed74..7959947a3458 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -462,9 +462,9 @@ unlock: static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); -static int pixcir_i2c_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int pixcir_i2c_ts_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device *dev = &client->dev; struct pixcir_i2c_ts_data *tsdata; struct input_dev *input; @@ -617,7 +617,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = { .pm = &pixcir_dev_pm_ops, .of_match_table = of_match_ptr(pixcir_of_match), }, - .probe = pixcir_i2c_ts_probe, + .probe_new = pixcir_i2c_ts_probe, .id_table = pixcir_i2c_ts_id, }; diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 3d9c5758d8a4..d690a17240c2 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -21,6 +21,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/pm_wakeirq.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <asm/unaligned.h> @@ -134,8 +135,6 @@ struct raydium_data { u8 pkg_size; enum raydium_boot_mode boot_mode; - - bool wake_irq_enabled; }; /* @@ -1066,8 +1065,7 @@ static void raydium_i2c_power_off(void *_data) } } -static int raydium_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int raydium_i2c_probe(struct i2c_client *client) { union i2c_smbus_data dummy; struct raydium_data *ts; @@ -1224,8 +1222,6 @@ static int __maybe_unused raydium_i2c_suspend(struct device *dev) if (device_may_wakeup(dev)) { raydium_enter_sleep(client); - - ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0); } else { raydium_i2c_power_off(ts); } @@ -1239,8 +1235,6 @@ static int __maybe_unused raydium_i2c_resume(struct device *dev) struct raydium_data *ts = i2c_get_clientdata(client); if (device_may_wakeup(dev)) { - if (ts->wake_irq_enabled) - disable_irq_wake(client->irq); raydium_i2c_sw_reset(client); } else { raydium_i2c_power_on(ts); @@ -1279,7 +1273,7 @@ MODULE_DEVICE_TABLE(of, raydium_of_match); #endif static struct i2c_driver raydium_i2c_driver = { - .probe = raydium_i2c_probe, + .probe_new = raydium_i2c_probe, .id_table = raydium_i2c_id, .driver = { .name = "raydium_ts", diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c index 730596d599d8..833422e5fd6d 100644 --- a/drivers/input/touchscreen/rohm_bu21023.c +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -1095,8 +1095,7 @@ static void rohm_ts_close(struct input_dev *input_dev) ts->initialized = false; } -static int rohm_bu21023_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int rohm_bu21023_i2c_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct rohm_ts_data *ts; @@ -1184,7 +1183,7 @@ static struct i2c_driver rohm_bu21023_i2c_driver = { .driver = { .name = BU21023_NAME, }, - .probe = rohm_bu21023_i2c_probe, + .probe_new = rohm_bu21023_i2c_probe, .id_table = rohm_bu21023_i2c_id, }; module_i2c_driver(rohm_bu21023_i2c_driver); diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c index 1a7d00289b4c..cc417c03aaca 100644 --- a/drivers/input/touchscreen/s6sy761.c +++ b/drivers/input/touchscreen/s6sy761.c @@ -389,8 +389,7 @@ static void s6sy761_power_off(void *data) sdata->regulators); } -static int s6sy761_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int s6sy761_probe(struct i2c_client *client) { struct s6sy761_data *sdata; unsigned int max_x, max_y; @@ -540,7 +539,7 @@ static struct i2c_driver s6sy761_driver = { .of_match_table = of_match_ptr(s6sy761_of_match), .pm = &s6sy761_pm_ops, }, - .probe = s6sy761_probe, + .probe_new = s6sy761_probe, .remove = s6sy761_remove, .id_table = s6sy761_id, }; diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index 3eef8c01090f..8a7351c4414c 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c @@ -652,9 +652,9 @@ static void silead_disable_regulator(void *arg) regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); } -static int silead_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int silead_ts_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct silead_ts_data *data; struct device *dev = &client->dev; int error; @@ -826,7 +826,7 @@ MODULE_DEVICE_TABLE(of, silead_ts_of_match); #endif static struct i2c_driver silead_ts_driver = { - .probe = silead_ts_probe, + .probe_new = silead_ts_probe, .id_table = silead_ts_id, .driver = { .name = SILEAD_TS_NAME, diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c index 6274555f1673..5a493b15b25d 100644 --- a/drivers/input/touchscreen/sis_i2c.c +++ b/drivers/input/touchscreen/sis_i2c.c @@ -296,8 +296,7 @@ static void sis_ts_reset(struct sis_ts_data *ts) } } -static int sis_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int sis_ts_probe(struct i2c_client *client) { struct sis_ts_data *ts; struct input_dev *input; @@ -394,7 +393,7 @@ static struct i2c_driver sis_ts_driver = { .name = SIS_I2C_NAME, .of_match_table = of_match_ptr(sis_ts_dt_ids), }, - .probe = sis_ts_probe, + .probe_new = sis_ts_probe, .id_table = sis_ts_id, }; module_i2c_driver(sis_ts_driver); diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index e38ba3e4f183..bd68633dc6c0 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -220,9 +220,9 @@ static const struct st_chip_info st1633_chip_info = { .max_fingers = 5, }; -static int st1232_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int st1232_ts_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct st_chip_info *match; struct st1232_ts_data *ts; struct input_dev *input_dev; @@ -384,7 +384,7 @@ static const struct of_device_id st1232_ts_dt_ids[] = { MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); static struct i2c_driver st1232_ts_driver = { - .probe = st1232_ts_probe, + .probe_new = st1232_ts_probe, .id_table = st1232_ts_id, .driver = { .name = ST1232_TS_NAME, diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index d5bd170808fb..d092e89d40e8 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -624,8 +624,7 @@ static int stmfts_enable_led(struct stmfts_data *sdata) return 0; } -static int stmfts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int stmfts_probe(struct i2c_client *client) { int err; struct stmfts_data *sdata; @@ -809,7 +808,7 @@ static struct i2c_driver stmfts_driver = { .pm = &stmfts_pm_ops, .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe = stmfts_probe, + .probe_new = stmfts_probe, .remove = stmfts_remove, .id_table = stmfts_id, }; diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c index de85e57b2486..52ae73035830 100644 --- a/drivers/input/touchscreen/sx8654.c +++ b/drivers/input/touchscreen/sx8654.c @@ -306,9 +306,9 @@ static void sx8654_close(struct input_dev *dev) } } -static int sx8654_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int sx8654_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct sx8654 *sx8654; struct input_dev *input; int error; @@ -470,7 +470,7 @@ static struct i2c_driver sx8654_driver = { .of_match_table = of_match_ptr(sx8654_of_match), }, .id_table = sx8654_id_table, - .probe = sx8654_probe, + .probe_new = sx8654_probe, }; module_i2c_driver(sx8654_driver); diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 357a3108f2e5..f48871767763 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -119,7 +119,6 @@ err: static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) { s32 ret; - s32 loops = 0; u8 val; ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, @@ -141,7 +140,6 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); if (ret) return ret; - loops++; } return ret; diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c index a9565353ee98..575768b587bb 100644 --- a/drivers/input/touchscreen/tsc2004.c +++ b/drivers/input/touchscreen/tsc2004.c @@ -34,8 +34,7 @@ static int tsc2004_cmd(struct device *dev, u8 cmd) return 0; } -static int tsc2004_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int tsc2004_probe(struct i2c_client *i2c) { return tsc200x_probe(&i2c->dev, i2c->irq, &tsc2004_input_id, @@ -69,7 +68,7 @@ static struct i2c_driver tsc2004_driver = { .pm = &tsc200x_pm_ops, }, .id_table = tsc2004_idtable, - .probe = tsc2004_probe, + .probe_new = tsc2004_probe, .remove = tsc2004_remove, }; module_i2c_driver(tsc2004_driver); diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index 3e871d182c40..3c793fb70a0e 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -302,9 +302,9 @@ static void tsc2007_call_exit_platform_hw(void *data) pdata->exit_platform_hw(); } -static int tsc2007_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tsc2007_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); struct tsc2007 *ts; @@ -431,7 +431,7 @@ static struct i2c_driver tsc2007_driver = { .of_match_table = tsc2007_of_match, }, .id_table = tsc2007_idtable, - .probe = tsc2007_probe, + .probe_new = tsc2007_probe, }; module_i2c_driver(tsc2007_driver); diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index 141754b2764c..c9188ee00c62 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -162,8 +162,7 @@ static void wacom_i2c_close(struct input_dev *dev) disable_irq(client->irq); } -static int wacom_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int wacom_i2c_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct wacom_i2c *wac_i2c; @@ -265,7 +264,7 @@ static struct i2c_driver wacom_i2c_driver = { .pm = &wacom_i2c_pm, }, - .probe = wacom_i2c_probe, + .probe_new = wacom_i2c_probe, .id_table = wacom_i2c_id, }; module_i2c_driver(wacom_i2c_driver); diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index 166edeb77776..3f87db5cdca4 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c @@ -1064,8 +1064,7 @@ static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt) return 0; } -static int wdt87xx_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int wdt87xx_ts_probe(struct i2c_client *client) { struct wdt87xx_data *wdt; int error; @@ -1170,7 +1169,7 @@ static const struct acpi_device_id wdt87xx_acpi_id[] = { MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); static struct i2c_driver wdt87xx_driver = { - .probe = wdt87xx_ts_probe, + .probe_new = wdt87xx_ts_probe, .id_table = wdt87xx_dev_id, .driver = { .name = WDT87XX_NAME, diff --git a/drivers/input/touchscreen/zet6223.c b/drivers/input/touchscreen/zet6223.c index 3b6f7ee1e38f..bfa0c637d569 100644 --- a/drivers/input/touchscreen/zet6223.c +++ b/drivers/input/touchscreen/zet6223.c @@ -167,8 +167,7 @@ static int zet6223_query_device(struct zet6223_ts *ts) return 0; } -static int zet6223_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int zet6223_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct zet6223_ts *ts; @@ -249,7 +248,7 @@ static struct i2c_driver zet6223_driver = { .name = "zet6223", .of_match_table = zet6223_of_match, }, - .probe = zet6223_probe, + .probe_new = zet6223_probe, .id_table = zet6223_id }; module_i2c_driver(zet6223_driver); diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 495629628af6..24e78ca83fa3 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -732,8 +732,7 @@ static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev) return pdata; } -static int zforce_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int zforce_probe(struct i2c_client *client) { const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); struct zforce_ts *ts; @@ -945,7 +944,7 @@ static struct i2c_driver zforce_driver = { .pm = &zforce_pm_ops, .of_match_table = of_match_ptr(zforce_dt_idtable), }, - .probe = zforce_probe, + .probe_new = zforce_probe, .id_table = zforce_idtable, }; |