diff options
author | Linus Torvalds | 2023-09-06 09:24:25 -0700 |
---|---|---|
committer | Linus Torvalds | 2023-09-06 09:24:25 -0700 |
commit | 744a759492b5c57ff24a6e8aabe47b17ad8ee964 (patch) | |
tree | 8fff7ccd0a038adfa7ea38652005d55f0a250666 /drivers/input | |
parent | 29057cc5bddc785ea0a11534d7ad2546fa0872d3 (diff) | |
parent | 1ac731c529cd4d6adbce134754b51ff7d822b145 (diff) |
Merge tag 'input-for-v6.6-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
- a new driver for Azoteq IQS7210A/7211A/E touch controllers
- support for Azoteq IQS7222D variant added to iqs7222 driver
- support for touch keys functionality added to Melfas MMS114 driver
- new hardware IDs added to exc3000 and Goodix drivers
- xpad driver gained support for GameSir T4 Kaleid Controller
- a fix for xpad driver to properly support some third-party
controllers that need a magic packet to start properly
- a fix for psmouse driver to more reliably switch to RMI4 mode on
devices that use native RMI4/SMbus protocol
- a quirk for i8042 for TUXEDO Gemini 17 Gen1/Clevo PD70PN laptops
- multiple drivers have been updated to make use of devm and other
newer APIs such as dev_err_probe(), devm_regulator_get_enable(), and
others.
* tag 'input-for-v6.6-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (83 commits)
Input: goodix - add support for ACPI ID GDX9110
Input: rpckbd - fix the return value handle for platform_get_irq()
Input: tca6416-keypad - switch to using input core's polling features
Input: tca6416-keypad - convert to use devm_* api
Input: tca6416-keypad - fix interrupt enable disbalance
Input: tca6416-keypad - rely on I2C core to set up suspend/resume
Input: tca6416-keypad - always expect proper IRQ number in i2c client
Input: lm8323 - convert to use devm_* api
Input: lm8323 - rely on device core to create kp_disable attribute
Input: qt2160 - convert to use devm_* api
Input: qt2160 - do not hard code interrupt trigger
Input: qt2160 - switch to using threaded interrupt handler
Input: qt2160 - tweak check for i2c adapter functionality
Input: psmouse - add delay when deactivating for SMBus mode
Input: mcs-touchkey - fix uninitialized use of error in mcs_touchkey_probe()
Input: qt1070 - convert to use devm_* api
Input: mcs-touchkey - convert to use devm_* api
Input: amikbd - convert to use devm_* api
Input: lm8333 - convert to use devm_* api
Input: mms114 - add support for touch keys
...
Diffstat (limited to 'drivers/input')
73 files changed, 3638 insertions, 1029 deletions
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 5a2c2fb3217d..fe73b26e647a 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig @@ -25,6 +25,7 @@ if GAMEPORT config GAMEPORT_NS558 tristate "Classic ISA and PnP gameport support" + depends on ISA help Say Y here if you have an ISA or PnP gameport. @@ -35,6 +36,7 @@ config GAMEPORT_NS558 config GAMEPORT_L4 tristate "PDPI Lightning 4 gamecard support" + depends on ISA help Say Y here if you have a PDPI Lightning 4 gamecard. @@ -53,7 +55,7 @@ config GAMEPORT_EMU10K1 config GAMEPORT_FM801 tristate "ForteMedia FM801 gameport support" - depends on PCI + depends on PCI && HAS_IOPORT help Say Y here if you have ForteMedia FM801 PCI audio controller (Abit AU10, Genius Sound Maker, HP Workstation zx2000, diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index a1443320b419..34f416a3ebcb 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -519,12 +519,32 @@ EXPORT_SYMBOL(gameport_set_phys); static void gameport_default_trigger(struct gameport *gameport) { +#ifdef CONFIG_HAS_IOPORT outb(0xff, gameport->io); +#endif } static unsigned char gameport_default_read(struct gameport *gameport) { +#ifdef CONFIG_HAS_IOPORT return inb(gameport->io); +#else + return 0xff; +#endif +} + +static void gameport_setup_default_handlers(struct gameport *gameport) +{ + if ((!gameport->trigger || !gameport->read) && + !IS_ENABLED(CONFIG_HAS_IOPORT)) + dev_err(&gameport->dev, + "I/O port access is required for %s (%s) but is not available\n", + gameport->phys, gameport->name); + + if (!gameport->trigger) + gameport->trigger = gameport_default_trigger; + if (!gameport->read) + gameport->read = gameport_default_read; } /* @@ -545,11 +565,7 @@ static void gameport_init_port(struct gameport *gameport) if (gameport->parent) gameport->dev.parent = &gameport->parent->dev; - if (!gameport->trigger) - gameport->trigger = gameport_default_trigger; - if (!gameport->read) - gameport->read = gameport_default_read; - + gameport_setup_default_handlers(gameport); INIT_LIST_HEAD(&gameport->node); spin_lock_init(&gameport->timer_lock); timer_setup(&gameport->poll_timer, gameport_run_poll_handler, 0); diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index cdb193317c3b..ede380551e55 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -264,6 +264,7 @@ static const struct xpad_device { { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE }, { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x00c5, "Hori Fighting Commander ONE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0f0d, 0x00dc, "HORIPAD FPS for Nintendo Switch", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, @@ -365,6 +366,7 @@ static const struct xpad_device { { 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 }, { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 }, + { 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 }, { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } @@ -499,6 +501,8 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */ XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */ XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ + XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ + XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ { } }; @@ -1720,6 +1724,27 @@ static int xpad_start_input(struct usb_xpad *xpad) return error; } } + if (xpad->xtype == XTYPE_XBOX360) { + /* + * Some third-party controllers Xbox 360-style controllers + * require this message to finish initialization. + */ + u8 dummy[20]; + + error = usb_control_msg_recv(xpad->udev, 0, + /* bRequest */ 0x01, + /* bmRequestType */ + USB_TYPE_VENDOR | USB_DIR_IN | + USB_RECIP_INTERFACE, + /* wValue */ 0x100, + /* wIndex */ 0x00, + dummy, sizeof(dummy), + 25, GFP_KERNEL); + if (error) + dev_warn(&xpad->dev->dev, + "unable to receive magic message: %d\n", + error); + } return 0; } diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 896a5a989ddc..61e8e43e9c2b 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -713,17 +713,11 @@ static int adp5588_fw_parse(struct adp5588_kpad *kpad) return 0; } -static void adp5588_disable_regulator(void *reg) -{ - regulator_disable(reg); -} - static int adp5588_probe(struct i2c_client *client) { struct adp5588_kpad *kpad; struct input_dev *input; struct gpio_desc *gpio; - struct regulator *vcc; unsigned int revid; int ret; int error; @@ -749,16 +743,7 @@ static int adp5588_probe(struct i2c_client *client) if (error) return error; - vcc = devm_regulator_get(&client->dev, "vcc"); - if (IS_ERR(vcc)) - return PTR_ERR(vcc); - - error = regulator_enable(vcc); - if (error) - return error; - - error = devm_add_action_or_reset(&client->dev, - adp5588_disable_regulator, vcc); + error = devm_regulator_get_enable(&client->dev, "vcc"); if (error) return error; diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index a20a4e186639..e305c44cd0aa 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -196,7 +196,7 @@ static int __init amikbd_probe(struct platform_device *pdev) struct input_dev *dev; int i, err; - dev = input_allocate_device(); + dev = devm_input_allocate_device(&pdev->dev); if (!dev) { dev_err(&pdev->dev, "Not enough memory for input device\n"); return -ENOMEM; @@ -208,7 +208,6 @@ static int __init amikbd_probe(struct platform_device *pdev) dev->id.vendor = 0x0001; dev->id.product = 0x0001; dev->id.version = 0x0100; - dev->dev.parent = &pdev->dev; dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); @@ -218,35 +217,21 @@ static int __init amikbd_probe(struct platform_device *pdev) amikbd_init_console_keymaps(); ciaa.cra &= ~0x41; /* serial data in, turn off TA */ - err = request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", - dev); + err = devm_request_irq(&pdev->dev, IRQ_AMIGA_CIAA_SP, amikbd_interrupt, + 0, "amikbd", dev); if (err) - goto fail2; + return err; err = input_register_device(dev); if (err) - goto fail3; + return err; platform_set_drvdata(pdev, dev); return 0; - - fail3: free_irq(IRQ_AMIGA_CIAA_SP, dev); - fail2: input_free_device(dev); - return err; -} - -static int __exit amikbd_remove(struct platform_device *pdev) -{ - struct input_dev *dev = platform_get_drvdata(pdev); - - free_irq(IRQ_AMIGA_CIAA_SP, dev); - input_unregister_device(dev); - return 0; } static struct platform_driver amikbd_driver = { - .remove = __exit_p(amikbd_remove), .driver = { .name = "amiga-keyboard", }, diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c index 56a919ec23b5..f3c3746acd4c 100644 --- a/drivers/input/keyboard/bcm-keypad.c +++ b/drivers/input/keyboard/bcm-keypad.c @@ -307,7 +307,6 @@ static int bcm_kp_probe(struct platform_device *pdev) { struct bcm_kp *kp; struct input_dev *input_dev; - struct resource *res; int error; kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); @@ -353,29 +352,16 @@ static int bcm_kp_probe(struct platform_device *pdev) return error; } - /* Get the KEYPAD base address */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Missing keypad base address resource\n"); - return -ENODEV; - } - - kp->base = devm_ioremap_resource(&pdev->dev, res); + kp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kp->base)) return PTR_ERR(kp->base); /* Enable clock */ - kp->clk = devm_clk_get(&pdev->dev, "peri_clk"); + kp->clk = devm_clk_get_optional(&pdev->dev, "peri_clk"); if (IS_ERR(kp->clk)) { - error = PTR_ERR(kp->clk); - if (error != -ENOENT) { - if (error != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get clock\n"); - return error; - } - dev_dbg(&pdev->dev, - "No clock specified. Assuming it's enabled\n"); - kp->clk = NULL; + return dev_err_probe(&pdev->dev, PTR_ERR(kp->clk), "Failed to get clock\n"); + } else if (!kp->clk) { + dev_dbg(&pdev->dev, "No clock specified. Assuming it's enabled\n"); } else { unsigned int desired_rate; long actual_rate; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index c928829a8b0c..2e7c2c046e67 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -523,18 +523,15 @@ static int gpio_keys_setup_key(struct platform_device *pdev, NULL, GPIOD_IN, desc); if (IS_ERR(bdata->gpiod)) { error = PTR_ERR(bdata->gpiod); - if (error == -ENOENT) { - /* - * GPIO is optional, we may be dealing with - * purely interrupt-driven setup. - */ - bdata->gpiod = NULL; - } else { - if (error != -EPROBE_DEFER) - dev_err(dev, "failed to get gpio: %d\n", - error); - return error; - } + if (error != -ENOENT) + return dev_err_probe(dev, error, + "failed to get gpio\n"); + + /* + * GPIO is optional, we may be dealing with + * purely interrupt-driven setup. + */ + bdata->gpiod = NULL; } } else if (gpio_is_valid(button->gpio)) { /* diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index c3937d2fc744..ba00ecfbd343 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -299,13 +299,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) NULL, GPIOD_IN, button->desc); if (IS_ERR(bdata->gpiod)) { - error = PTR_ERR(bdata->gpiod); - if (error != -EPROBE_DEFER) - dev_err(dev, - "failed to get gpio: %d\n", - error); fwnode_handle_put(child); - return error; + return dev_err_probe(dev, PTR_ERR(bdata->gpiod), + "failed to get gpio\n"); } } else if (gpio_is_valid(button->gpio)) { /* diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 3964f6e0f6af..7bee93e9b0f5 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -556,6 +556,7 @@ static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, const char *name) { struct lm8323_pwm *pwm; + int err; BUG_ON(id > 3); @@ -575,9 +576,11 @@ static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, pwm->cdev.name = name; pwm->cdev.brightness_set = lm8323_pwm_set_brightness; pwm->cdev.groups = lm8323_pwm_groups; - if (led_classdev_register(dev, &pwm->cdev) < 0) { - dev_err(dev, "couldn't register PWM %d\n", id); - return -1; + + err = devm_led_classdev_register(dev, &pwm->cdev); + if (err) { + dev_err(dev, "couldn't register PWM %d: %d\n", id, err); + return err; } pwm->enabled = true; } @@ -585,8 +588,6 @@ static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, return 0; } -static struct i2c_driver lm8323_i2c_driver; - static ssize_t lm8323_show_disable(struct device *dev, struct device_attribute *attr, char *buf) { @@ -615,6 +616,12 @@ static ssize_t lm8323_set_disable(struct device *dev, } static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable); +static struct attribute *lm8323_attrs[] = { + &dev_attr_disable_kp.attr, + NULL, +}; +ATTRIBUTE_GROUPS(lm8323); + static int lm8323_probe(struct i2c_client *client) { struct lm8323_platform_data *pdata = dev_get_platdata(&client->dev); @@ -642,12 +649,13 @@ static int lm8323_probe(struct i2c_client *client) return -EINVAL; } - lm = kzalloc(sizeof *lm, GFP_KERNEL); - idev = input_allocate_device(); - if (!lm || !idev) { - err = -ENOMEM; - goto fail1; - } + lm = devm_kzalloc(&client->dev, sizeof(*lm), GFP_KERNEL); + if (!lm) + return -ENOMEM; + + idev = devm_input_allocate_device(&client->dev); + if (!idev) + return -ENOMEM; lm->client = client; lm->idev = idev; @@ -663,8 +671,10 @@ static int lm8323_probe(struct i2c_client *client) lm8323_reset(lm); - /* Nothing's set up to service the IRQ yet, so just spin for max. - * 100ms until we can configure. */ + /* + * Nothing's set up to service the IRQ yet, so just spin for max. + * 100ms until we can configure. + */ tmo = jiffies + msecs_to_jiffies(100); while (lm8323_read(lm, LM8323_CMD_READ_INT, data, 1) == 1) { if (data[0] & INT_NOINIT) @@ -684,21 +694,17 @@ static int lm8323_probe(struct i2c_client *client) /* If a true probe check the device */ if (lm8323_read_id(lm, data) != 0) { dev_err(&client->dev, "device not found\n"); - err = -ENODEV; - goto fail1; + return -ENODEV; } for (pwm = 0; pwm < LM8323_NUM_PWMS; pwm++) { err = init_pwm(lm, pwm + 1, &client->dev, pdata->pwm_names[pwm]); - if (err < 0) - goto fail2; + if (err) + return err; } lm->kp_enabled = true; - err = device_create_file(&client->dev, &dev_attr_disable_kp); - if (err < 0) - goto fail2; idev->name = pdata->name ? : "LM8323 keypad"; snprintf(lm->phys, sizeof(lm->phys), @@ -719,14 +725,16 @@ static int lm8323_probe(struct i2c_client *client) err = input_register_device(idev); if (err) { dev_dbg(&client->dev, "error registering input device\n"); - goto fail3; + return err; } - err = request_threaded_irq(client->irq, NULL, lm8323_irq, - IRQF_TRIGGER_LOW|IRQF_ONESHOT, "lm8323", lm); + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, lm8323_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "lm8323", lm); if (err) { dev_err(&client->dev, "could not get IRQ %d\n", client->irq); - goto fail4; + return err; } i2c_set_clientdata(client, lm); @@ -735,39 +743,6 @@ static int lm8323_probe(struct i2c_client *client) enable_irq_wake(client->irq); return 0; - -fail4: - input_unregister_device(idev); - idev = NULL; -fail3: - device_remove_file(&client->dev, &dev_attr_disable_kp); -fail2: - while (--pwm >= 0) - if (lm->pwm[pwm].enabled) - led_classdev_unregister(&lm->pwm[pwm].cdev); -fail1: - input_free_device(idev); - kfree(lm); - return err; -} - -static void lm8323_remove(struct i2c_client *client) -{ - struct lm8323_chip *lm = i2c_get_clientdata(client); - int i; - - disable_irq_wake(client->irq); - free_irq(client->irq, lm); - - input_unregister_device(lm->idev); - - device_remove_file(&lm->client->dev, &dev_attr_disable_kp); - - for (i = 0; i < 3; i++) - if (lm->pwm[i].enabled) - led_classdev_unregister(&lm->pwm[i].cdev); - - kfree(lm); } /* @@ -823,11 +798,11 @@ static const struct i2c_device_id lm8323_id[] = { static struct i2c_driver lm8323_i2c_driver = { .driver = { - .name = "lm8323", - .pm = pm_sleep_ptr(&lm8323_pm_ops), + .name = "lm8323", + .pm = pm_sleep_ptr(&lm8323_pm_ops), + .dev_groups = lm8323_groups, }, .probe = lm8323_probe, - .remove = lm8323_remove, .id_table = lm8323_id, }; MODULE_DEVICE_TABLE(i2c, lm8323_id); diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index c9f05764e36d..1c070c499c85 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -142,18 +142,18 @@ static int lm8333_probe(struct i2c_client *client) return -EINVAL; } - lm8333 = kzalloc(sizeof(*lm8333), GFP_KERNEL); - input = input_allocate_device(); - if (!lm8333 || !input) { - err = -ENOMEM; - goto free_mem; - } + lm8333 = devm_kzalloc(&client->dev, sizeof(*lm8333), GFP_KERNEL); + if (!lm8333) + return -ENOMEM; + + input = devm_input_allocate_device(&client->dev); + if (!input) + return -ENOMEM; lm8333->client = client; lm8333->input = input; input->name = client->name; - input->dev.parent = &client->dev; input->id.bustype = BUS_I2C; input_set_capability(input, EV_MSC, MSC_SCAN); @@ -162,7 +162,7 @@ static int lm8333_probe(struct i2c_client *client) LM8333_NUM_ROWS, LM8333_NUM_COLS, lm8333->keycodes, input); if (err) - goto free_mem; + return err; if (pdata->debounce_time) { err = lm8333_write8(lm8333, LM8333_DEBOUNCE, @@ -178,34 +178,19 @@ static int lm8333_probe(struct i2c_client *client) dev_warn(&client->dev, "Unable to set active time\n"); } - err = request_threaded_irq(client->irq, NULL, lm8333_irq_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "lm8333", lm8333); + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, lm8333_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "lm8333", lm8333); if (err) - goto free_mem; + return err; err = input_register_device(input); if (err) - goto free_irq; + return err; i2c_set_clientdata(client, lm8333); return 0; - - free_irq: - free_irq(client->irq, lm8333); - free_mem: - input_free_device(input); - kfree(lm8333); - return err; -} - -static void lm8333_remove(struct i2c_client *client) -{ - struct lm8333 *lm8333 = i2c_get_clientdata(client); - - free_irq(client->irq, lm8333); - input_unregister_device(lm8333->input); - kfree(lm8333); } static const struct i2c_device_id lm8333_id[] = { @@ -219,7 +204,6 @@ static struct i2c_driver lm8333_driver = { .name = "lm8333", }, .probe = lm8333_probe, - .remove = lm8333_remove, .id_table = lm8333_id, }; module_i2c_driver(lm8333_driver); diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index 911e1181cd6f..322a87807159 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -160,17 +160,10 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev) { struct lpc32xx_kscan_drv *kscandat; struct input_dev *input; - struct resource *res; size_t keymap_size; int error; int irq; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get platform I/O memory\n"); - return -EINVAL; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) return -EINVAL; @@ -221,7 +214,7 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev) input_set_drvdata(kscandat->input, kscandat); - kscandat->kscan_base = devm_ioremap_resource(&pdev->dev, res); + kscandat->kscan_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kscandat->kscan_base)) return PTR_ERR(kscandat->kscan_base); diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index de312d8eb974..2410f676c7f9 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -92,6 +92,13 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +static void mcs_touchkey_poweroff(void *data) +{ + struct mcs_touchkey_data *touchkey = data; + + touchkey->poweron(false); +} + static int mcs_touchkey_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); @@ -109,13 +116,16 @@ static int mcs_touchkey_probe(struct i2c_client *client) return -EINVAL; } - data = kzalloc(struct_size(data, keycodes, pdata->key_maxval + 1), - GFP_KERNEL); - input_dev = input_allocate_device(); - if (!data || !input_dev) { - dev_err(&client->dev, "Failed to allocate memory\n"); - error = -ENOMEM; - goto err_free_mem; + data = devm_kzalloc(&client->dev, + struct_size(data, keycodes, pdata->key_maxval + 1), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) { + dev_err(&client->dev, "Failed to allocate input device\n"); + return -ENOMEM; } data->client = client; @@ -136,15 +146,13 @@ static int mcs_touchkey_probe(struct i2c_client *client) fw_ver = i2c_smbus_read_byte_data(client, fw_reg); if (fw_ver < 0) { - error = fw_ver; - dev_err(&client->dev, "i2c read error[%d]\n", error); - goto err_free_mem; + dev_err(&client->dev, "i2c read error[%d]\n", fw_ver); + return fw_ver; } dev_info(&client->dev, "Firmware version: %d\n", fw_ver); input_dev->name = "MELFAS MCS Touchkey"; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; input_dev->evbit[0] = BIT_MASK(EV_KEY); if (!pdata->no_autorepeat) input_dev->evbit[0] |= BIT_MASK(EV_REP); @@ -169,40 +177,28 @@ static int mcs_touchkey_probe(struct i2c_client *client) if (pdata->poweron) { data->poweron = pdata->poweron; data->poweron(true); + + error = devm_add_action_or_reset(&client->dev, + mcs_touchkey_poweroff, data); + if (error) + return error; } - error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->dev.driver->name, data); + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, mcs_touchkey_interrupt, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->dev.driver->name, data); if (error) { dev_err(&client->dev, "Failed to register interrupt\n"); - goto err_free_mem; + return error; } error = input_register_device(input_dev); if (error) - goto err_free_irq; + return error; i2c_set_clientdata(client, data); return 0; - -err_free_irq: - free_irq(client->irq, data); -err_free_mem: - input_free_device(input_dev); - kfree(data); - return error; -} - -static void mcs_touchkey_remove(struct i2c_client *client) -{ - struct mcs_touchkey_data *data = i2c_get_clientdata(client); - - free_irq(client->irq, data); - if (data->poweron) - data->poweron(false); - input_unregister_device(data->input_dev); - kfree(data); } static void mcs_touchkey_shutdown(struct i2c_client *client) @@ -259,7 +255,6 @@ static struct i2c_driver mcs_touchkey_driver = { .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops), }, .probe = mcs_touchkey_probe, - .remove = mcs_touchkey_remove, .shutdown = mcs_touchkey_shutdown, .id_table = mcs_touchkey_id, }; diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 970f2a671c2e..b3ccc97f61e1 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -221,13 +221,20 @@ static irqreturn_t ske_keypad_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static void ske_keypad_board_exit(void *data) +{ + struct ske_keypad *keypad = data; + + keypad->board->exit(); +} + static int __init ske_keypad_probe(struct platform_device *pdev) { const struct ske_keypad_platform_data *plat = dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; struct ske_keypad *keypad; struct input_dev *input; - struct resource *res; int irq; int error; @@ -238,20 +245,14 @@ static int __init ske_keypad_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return -EINVAL; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "missing platform resources\n"); - return -EINVAL; - } + return irq; - keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL); - input = input_allocate_device(); + keypad = devm_kzalloc(dev, sizeof(struct ske_keypad), + GFP_KERNEL); + input = devm_input_allocate_device(dev); if (!keypad || !input) { dev_err(&pdev->dev, "failed to allocate keypad memory\n"); - error = -ENOMEM; - goto err_free_mem; + return -ENOMEM; } keypad->irq = irq; @@ -259,31 +260,20 @@ static int __init ske_keypad_probe(struct platform_device *pdev) keypad->input = input; spin_lock_init(&keypad->ske_keypad_lock); - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - error = -EBUSY; - goto err_free_mem; - } - - keypad->reg_base = ioremap(res->start, resource_size(res)); - if (!keypad->reg_base) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - error = -ENXIO; - goto err_free_mem_region; - } + keypad->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(keypad->reg_base)) + return PTR_ERR(keypad->reg_base); - keypad->pclk = clk_get(&pdev->dev, "apb_pclk"); + keypad->pclk = devm_clk_get_enabled(dev, "apb_pclk"); if (IS_ERR(keypad->pclk)) { dev_err(&pdev->dev, "failed to get pclk\n"); - error = PTR_ERR(keypad->pclk); - goto err_iounmap; + return PTR_ERR(keypad->pclk); } - keypad->clk = clk_get(&pdev->dev, NULL); + keypad->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get clk\n"); - error = PTR_ERR(keypad->clk); - goto err_pclk; + return PTR_ERR(keypad->clk); } input->id.bustype = BUS_HOST; @@ -295,48 +285,43 @@ static int __init ske_keypad_probe(struct platform_device *pdev) keypad->keymap, input); if (error) { dev_err(&pdev->dev, "Failed to build keymap\n"); - goto err_clk; + return error; } input_set_capability(input, EV_MSC, MSC_SCAN); if (!plat->no_autorepeat) __set_bit(EV_REP, input->evbit); - error = clk_prepare_enable(keypad->pclk); - if (error) { - dev_err(&pdev->dev, "Failed to prepare/enable pclk\n"); - goto err_clk; - } - - error = clk_prepare_enable(keypad->clk); - if (error) { - dev_err(&pdev->dev, "Failed to prepare/enable clk\n"); - goto err_pclk_disable; - } - - /* go through board initialization helpers */ if (keypad->board->init) keypad->board->init(); + if (keypad->board->exit) { + error = devm_add_action_or_reset(dev, ske_keypad_board_exit, + keypad); + if (error) + return error; + } + error = ske_keypad_chip_init(keypad); if (error) { dev_err(&pdev->dev, "unable to init keypad hardware\n"); - goto err_clk_disable; + return error; } - error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq, - IRQF_ONESHOT, "ske-keypad", keypad); + error = devm_request_threaded_irq(dev, keypad->irq, + NULL, ske_keypad_irq, + IRQF_ONESHOT, "ske-keypad", keypad); if (error) { dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq); - goto err_clk_disable; + return error; } error = input_register_device(input); if (error) { dev_err(&pdev->dev, - "unable to register input device: %d\n", error); - goto err_free_irq; + "unable to register input device: %d\n", error); + return error; } if (plat->wakeup_enable) @@ -345,47 +330,6 @@ static int __init ske_keypad_probe(struct platform_device *pdev) platform_set_drvdata(pdev, keypad); return 0; - -err_free_irq: - free_irq(keypad->irq, keypad); -err_clk_disable: - clk_disable_unprepare(keypad->clk); -err_pclk_disable: - clk_disable_unprepare(keypad->pclk); -err_clk: - clk_put(keypad->clk); -err_pclk: - clk_put(keypad->pclk); -err_iounmap: - iounmap(keypad->reg_base); -err_free_mem_region: - release_mem_region(res->start, resource_size(res)); -err_free_mem: - input_free_device(input); - kfree(keypad); - return error; -} - -static int ske_keypad_remove(struct platform_device *pdev) -{ - struct ske_keypad *keypad = platform_get_drvdata(pdev); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - free_irq(keypad->irq, keypad); - - input_unregister_device(keypad->input); - - clk_disable_unprepare(keypad->clk); - clk_put(keypad->clk); - - if (keypad->board->exit) - keypad->board->exit(); - - iounmap(keypad->reg_base); - release_mem_region(res->start, resource_size(res)); - kfree(keypad); - - return 0; } static int ske_keypad_suspend(struct device *dev) @@ -424,7 +368,6 @@ static struct platform_driver ske_keypad_driver = { .name = "nmk-ske-keypad", .pm = pm_sleep_ptr(&ske_keypad_dev_pm_ops), }, - .remove = ske_keypad_remove, }; module_platform_driver_probe(ske_keypad_driver, ske_keypad_probe); diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index e9fa1423f136..096c18d7bca1 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -186,8 +186,7 @@ static int nspire_keypad_probe(struct platform_device *pdev) return PTR_ERR(keypad->clk); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - keypad->reg_base = devm_ioremap_resource(&pdev->dev, res); + keypad->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(keypad->reg_base)) return PTR_ERR(keypad->reg_base); diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 9f085d5679db..773e55eed88b 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -341,17 +341,10 @@ static int omap4_keypad_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct omap4_keypad *keypad_data; struct input_dev *input_dev; - struct resource *res; unsigned int max_keys; int irq; int error; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no base address specified\n"); - return -EINVAL; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -370,7 +363,7 @@ static int omap4_keypad_probe(struct platform_device *pdev) if (error) return error; - keypad_data->base = devm_ioremap_resource(dev, res); + keypad_data->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(keypad_data->base)) return PTR_ERR(keypad_data->base); diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index b0ea387414c1..7ffe1a70c856 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c @@ -39,15 +39,8 @@ static int opencores_kbd_probe(struct platform_device *pdev) { struct input_dev *input; struct opencores_kbd *opencores_kbd; - struct resource *res; int irq, i, error; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "missing board memory resource\n"); - return -EINVAL; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) return -EINVAL; @@ -65,7 +58,7 @@ static int opencores_kbd_probe(struct platform_device *pdev) opencores_kbd->input = input; - opencores_kbd->addr = devm_ioremap_resource(&pdev->dev, res); + opencores_kbd->addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(opencores_kbd->addr)) return PTR_ERR(opencores_kbd->addr); diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c index 038ff3549a7a..147b1f288a33 100644 --- a/drivers/input/keyboard/pinephone-keyboard.c +++ b/drivers/input/keyboard/pinephone-keyboard.c @@ -318,40 +318,22 @@ static void ppkb_close(struct input_dev *input) ppkb_set_scan(client, false); } -static void ppkb_regulator_disable(void *regulator) -{ - regulator_disable(regulator); -} - static int ppkb_probe(struct i2c_client *client) { struct device *dev = &client->dev; unsigned int phys_rows, phys_cols; struct pinephone_keyboard *ppkb; - struct regulator *vbat_supply; u8 info[PPKB_MATRIX_SIZE + 1]; struct device_node *i2c_bus; int ret; int error; - vbat_supply = devm_regulator_get(dev, "vbat"); - error = PTR_ERR_OR_ZERO(vbat_supply); + error = devm_regulator_get_enable(dev, "vbat"); if (error) { dev_err(dev, "Failed to get VBAT supply: %d\n", error); return error; } - error = regulator_enable(vbat_supply); - if (error) { - dev_err(dev, "Failed to enable VBAT: %d\n", error); - return error; - } - - error = devm_add_action_or_reset(dev, ppkb_regulator_disable, - vbat_supply); - if (error) - return error; - ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info); if (ret != sizeof(info)) { error = ret < 0 ? ret : -EIO; diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 871f858d0ba7..3724363d140e 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -717,7 +717,6 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct pxa27x_keypad *keypad; struct input_dev *input_dev; - struct resource *res; int irq, error; /* Driver need build keycode from device tree or pdata */ @@ -728,12 +727,6 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) if (irq < 0) return -ENXIO; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); - return -ENXIO; - } - keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL); if (!keypad) @@ -747,7 +740,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) keypad->input_dev = input_dev; keypad->irq = irq; - keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res); + keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(keypad->mmio_base)) return PTR_ERR(keypad->mmio_base); diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index 91aaa9fc43a4..9b093b042bf1 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -149,20 +149,20 @@ static int qt1070_probe(struct i2c_client *client) if (!qt1070_identify(client)) return -ENODEV; - data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL); - input = input_allocate_device(); - if (!data || !input) { - dev_err(&client->dev, "insufficient memory\n"); - err = -ENOMEM; - goto err_free_mem; - } + data = devm_kzalloc(&client->dev, sizeof(struct qt1070_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + input = devm_input_allocate_device(&client->dev); + if (!input) + return -ENOMEM; data->client = client; data->input = input; data->irq = client->irq; input->name = "AT42QT1070 QTouch Sensor"; - input->dev.parent = &client->dev; input->id.bustype = BUS_I2C; /* Add the keycode */ @@ -185,19 +185,20 @@ static int qt1070_probe(struct i2c_client *client) qt1070_write(client, RESET, 1); msleep(QT1070_RESET_TIME); - err = request_threaded_irq(client->irq, NULL, qt1070_interrupt, - IRQF_TRIGGER_NONE | IRQF_ONESHOT, - client->dev.driver->name, data); + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, qt1070_interrupt, + IRQF_TRIGGER_NONE | IRQF_ONESHOT, + client->dev.driver->name, data); if (err) { dev_err(&client->dev, "fail to request irq\n"); - goto err_free_mem; + return err; } /* Register the input device */ err = input_register_device(data->input); if (err) { dev_err(&client->dev, "Failed to register input device\n"); - goto err_free_irq; + return err; } i2c_set_clientdata(client, data); @@ -206,24 +207,6 @@ static int qt1070_probe(struct i2c_client *client) qt1070_read(client, DET_STATUS); return 0; - -err_free_irq: - free_irq(client->irq, data); -err_free_mem: - input_free_device(input); - kfree(data); - return err; -} - -static void qt1070_remove(struct i2c_client *client) -{ - struct qt1070_data *data = i2c_get_clientdata(client); - - /* Release IRQ */ - free_irq(client->irq, data); - - input_unregister_device(data->input); - kfree(data); } static int qt1070_suspend(struct device *dev) @@ -272,7 +255,6 @@ static struct i2c_driver qt1070_driver = { }, .id_table = qt1070_id, .probe = qt1070_probe, - .remove = qt1070_remove, }; module_i2c_driver(qt1070_driver); diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 599ea85cfd30..7e3b09642ab7 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -32,7 +32,7 @@ #define QT2160_NUM_LEDS_X 8 -#define QT2160_CYCLE_INTERVAL (2*HZ) +#define QT2160_CYCLE_INTERVAL 2000 /* msec - 2 sec */ static unsigned char qt2160_key2code[] = { KEY_0, KEY_1, KEY_2, KEY_3, @@ -54,7 +54,6 @@ struct qt2160_led { struct qt2160_data { struct i2c_client *client; struct input_dev *input; - struct delayed_work dwork; unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; u16 key_matrix; #ifdef CONFIG_LEDS_CLASS @@ -155,10 +154,10 @@ static int qt2160_read_block(struct i2c_client *client, return 0; } -static int qt2160_get_key_matrix(struct qt2160_data *qt2160) +static void qt2160_get_key_matrix(struct input_dev *input) { + struct qt2160_data *qt2160 = input_get_drvdata(input); struct i2c_client *client = qt2160->client; - struct input_dev *input = qt2160->input; u8 regs[6]; u16 old_matrix, new_matrix; int ret, i, mask; @@ -173,7 +172,7 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160) if (ret) { dev_err(&client->dev, "could not perform chip read.\n"); - return ret; + return; } old_matrix = qt2160->key_matrix; @@ -191,37 +190,17 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160) } input_sync(input); - - return 0; } -static irqreturn_t qt2160_irq(int irq, void *_qt2160) +static irqreturn_t qt2160_irq(int irq, void *data) { - struct qt2160_data *qt2160 = _qt2160; + struct input_dev *input = data; - mod_delayed_work(system_wq, &qt2160->dwork, 0); + qt2160_get_key_matrix(input); return IRQ_HANDLED; } -static void qt2160_schedule_read(struct qt2160_data *qt2160) -{ - schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL); -} - -static void qt2160_worker(struct work_struct *work) -{ - struct qt2160_data *qt2160 = - container_of(work, struct qt2160_data, dwork.work); - - dev_dbg(&qt2160->client->dev, "worker\n"); - - qt2160_get_key_matrix(qt2160); - - /* Avoid device lock up by checking every so often */ - qt2160_schedule_read(qt2160); -} - static int qt2160_read(struct i2c_client *client, u8 reg) { int ret; @@ -260,7 +239,7 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data) static int qt2160_register_leds(struct qt2160_data *qt2160) { struct i2c_client *client = qt2160->client; - int ret; + int error; int i; for (i = 0; i < QT2160_NUM_LEDS_X; i++) { @@ -273,9 +252,9 @@ static int qt2160_register_leds(struct qt2160_data *qt2160) led->id = i; led->qt2160 = qt2160; - ret = led_classdev_register(&client->dev, &led->cdev); - if (ret < 0) - return ret; + error = devm_led_classdev_register(&client->dev, &led->cdev); + if (error) + return error; } /* Tur off LEDs */ @@ -286,14 +265,6 @@ static int qt2160_register_leds(struct qt2160_data *qt2160) return 0; } -static void qt2160_unregister_leds(struct qt2160_data *qt2160) -{ - int i; - - for (i = 0; i < QT2160_NUM_LEDS_X; i++) - led_classdev_unregister(&qt2160->leds[i].cdev); -} - #else static inline int qt2160_register_leds(struct qt2160_data *qt2160) @@ -301,10 +272,6 @@ static inline int qt2160_register_leds(struct qt2160_data *qt2160) return 0; } -static inline void qt2160_unregister_leds(struct qt2160_data *qt2160) -{ -} - #endif static bool qt2160_identify(struct i2c_client *client) @@ -345,12 +312,9 @@ static int qt2160_probe(struct i2c_client *client) int i; int error; - /* Check functionality */ - error = i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE); - if (!error) { + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { dev_err(&client->dev, "%s adapter not supported\n", - dev_driver_string(&client->adapter->dev)); + dev_driver_string(&client->adapter->dev)); return -ENODEV; } @@ -358,17 +322,16 @@ static int qt2160_probe(struct i2c_client *client) return -ENODEV; /* Chip is valid and active. Allocate structure */ - qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL); - input = input_allocate_device(); - if (!qt2160 || !input) { - dev_err(&client->dev, "insufficient memory\n"); - error = -ENOMEM; - goto err_free_mem; - } + qt2160 = devm_kzalloc(&client->dev, sizeof(*qt2160), GFP_KERNEL); + if (!qt2160) + return -ENOMEM; + + input = devm_input_allocate_device(&client->dev); + if (!input) + return -ENOMEM; qt2160->client = client; qt2160->input = input; - INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker); input->name = "AT42QT2160 Touch Sense Keyboard"; input->id.bustype = BUS_I2C; @@ -385,66 +348,48 @@ static int qt2160_probe(struct i2c_client *client) } __clear_bit(KEY_RESERVED, input->keybit); + input_set_drvdata(input, qt2160); + /* Calibrate device */ error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1); if (error) { dev_err(&client->dev, "failed to calibrate device\n"); - goto err_free_mem; + return error; } if (client->irq) { - error = request_irq(client->irq, qt2160_irq, - IRQF_TRIGGER_FALLING, "qt2160", qt2160); + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, qt2160_irq, + IRQF_ONESHOT, + "qt2160", input); if (error) { dev_err(&client->dev, "failed to allocate irq %d\n", client->irq); - goto err_free_mem; + return error; + } + } else { + error = input_setup_polling(input, qt2160_get_key_matrix); + if (error) { + dev_err(&client->dev, "Failed to setup polling\n"); + return error; } + input_set_poll_interval(input, QT2160_CYCLE_INTERVAL); } error = qt2160_register_leds(qt2160); if (error) { dev_err(&client->dev, "Failed to register leds\n"); - goto err_free_irq; + return error; } error = input_register_device(qt2160->input); if (error) { dev_err(&client->dev, "Failed to register input device\n"); - goto err_unregister_leds; + return error; } - i2c_set_clientdata(client, qt2160); - qt2160_schedule_read(qt2160); - return 0; - -err_unregister_leds: - qt2160_unregister_leds(qt2160); -err_free_irq: - if (client->irq) - free_irq(client->irq, qt2160); -err_free_mem: - input_free_device(input); - kfree(qt2160); - return error; -} - -static void qt2160_remove(struct i2c_client *client) -{ - struct qt2160_data *qt2160 = i2c_get_clientdata(client); - - qt2160_unregister_leds(qt2160); - - /* Release IRQ so no queue will be scheduled */ - if (client->irq) - free_irq(client->irq, qt2160); - - cancel_delayed_work_sync(&qt2160->dwork); - - input_unregister_device(qt2160->input); - kfree(qt2160); } static const struct i2c_device_id qt2160_idtable[] = { @@ -461,7 +406,6 @@ static struct i2c_driver qt2160_driver = { .id_table = qt2160_idtable, .probe = qt2160_probe, - .remove = qt2160_remove, }; module_i2c_driver(qt2160_driver); diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c index 15c15c0958b0..f304cab0ebdb 100644 --- a/drivers/input/keyboard/sun4i-lradc-keys.c +++ b/drivers/input/keyboard/sun4i-lradc-keys.c @@ -21,10 +21,11 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_wakeirq.h> #include <linux/pm_wakeup.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/reset.h> #include <linux/slab.h> @@ -307,8 +308,7 @@ static int sun4i_lradc_probe(struct platform_device *pdev) input_set_drvdata(lradc->input, lradc); - lradc->base = devm_ioremap_resource(dev, - platform_get_resource(pdev, IORESOURCE_MEM, 0)); + lradc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(lradc->base)) return PTR_ERR(lradc->base); diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 2f745cabf4f2..8af59ced1ec2 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -24,6 +24,8 @@ #define TCA6416_INVERT 2 #define TCA6416_DIRECTION 3 +#define TCA6416_POLL_INTERVAL 100 /* msec */ + static const struct i2c_device_id tca6416_id[] = { { "tca6416-keys", 16, }, { "tca6408-keys", 8, }, @@ -43,7 +45,6 @@ struct tca6416_keypad_chip { struct i2c_client *client; struct input_dev *input; - struct delayed_work dwork; int io_size; int irqnum; u16 pinmask; @@ -85,9 +86,9 @@ static int tca6416_read_reg(struct tca6416_keypad_chip *chip, int reg, u16 *val) return 0; } -static void tca6416_keys_scan(struct tca6416_keypad_chip *chip) +static void tca6416_keys_scan(struct input_dev *input) { - struct input_dev *input = chip->input; + struct tca6416_keypad_chip *chip = input_get_drvdata(input); u16 reg_val, val; int error, i, pin_index; @@ -122,33 +123,20 @@ static void tca6416_keys_scan(struct tca6416_keypad_chip *chip) */ static irqreturn_t tca6416_keys_isr(int irq, void *dev_id) { - struct tca6416_keypad_chip *chip = dev_id; - - tca6416_keys_scan(chip); + tca6416_keys_scan(dev_id); return IRQ_HANDLED; } -static void tca6416_keys_work_func(struct work_struct *work) -{ - struct tca6416_keypad_chip *chip = - container_of(work, struct tca6416_keypad_chip, dwork.work); - - tca6416_keys_scan(chip); - schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); -} - static int tca6416_keys_open(struct input_dev *dev) { struct tca6416_keypad_chip *chip = input_get_drvdata(dev); - /* Get initial device state in case it has switches */ - tca6416_keys_scan(chip); - - if (chip->use_polling) - schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); - else - enable_irq(chip->irqnum); + if (!chip->use_polling) { + /* Get initial device state in case it has switches */ + tca6416_keys_scan(dev); + enable_irq(chip->client->irq); + } return 0; } @@ -157,10 +145,8 @@ static void tca6416_keys_close(struct input_dev *dev) { struct tca6416_keypad_chip *chip = input_get_drvdata(dev); - if (chip->use_polling) - cancel_delayed_work_sync(&chip->dwork); - else - disable_irq(chip->irqnum); + if (!chip->use_polling) + disable_irq(chip->client->irq); } static int tca6416_setup_registers(struct tca6416_keypad_chip *chip) @@ -216,12 +202,15 @@ static int tca6416_keypad_probe(struct i2c_client *client) return -EINVAL; } - chip = kzalloc(struct_size(chip, buttons, pdata->nbuttons), GFP_KERNEL); - input = input_allocate_device(); - if (!chip || !input) { - error = -ENOMEM; - goto fail1; - } + chip = devm_kzalloc(&client->dev, + struct_size(chip, buttons, pdata->nbuttons), + GFP_KERNEL); + if (!chip) + return -ENOMEM; + + input = devm_input_allocate_device(&client->dev); + if (!input) + return -ENOMEM; chip->client = client; chip->input = input; @@ -229,11 +218,8 @@ static int tca6416_keypad_probe(struct i2c_client *client) chip->pinmask = pdata->pinmask; chip->use_polling = pdata->use_polling; - INIT_DELAYED_WORK(&chip->dwork, tca6416_keys_work_func); - input->phys = "tca6416-keys/input0"; input->name = client->name; - input->dev.parent = &client->dev; input->open = tca6416_keys_open; input->close = tca6416_keys_close; @@ -263,24 +249,28 @@ static int tca6416_keypad_probe(struct i2c_client *client) */ error = tca6416_setup_registers(chip); if (error) - goto fail1; + return error; - if (!chip->use_polling) { - if (pdata->irq_is_gpio) - chip->irqnum = gpio_to_irq(client->irq); - else - chip->irqnum = client->irq; - - error = request_threaded_irq(chip->irqnum, NULL, - tca6416_keys_isr, - IRQF_TRIGGER_FALLING | - IRQF_ONESHOT | IRQF_NO_AUTOEN, - "tca6416-keypad", chip); + if (chip->use_polling) { + error = input_setup_polling(input, tca6416_keys_scan); + if (error) { + dev_err(&client->dev, "Failed to setup polling\n"); + return error; + } + + input_set_poll_interval(input, TCA6416_POLL_INTERVAL); + } else { + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, tca6416_keys_isr, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT | + IRQF_NO_AUTOEN, + "tca6416-keypad", input); if (error) { dev_dbg(&client->dev, "Unable to claim irq %d; error %d\n", - chip->irqnum, error); - goto fail1; + client->irq, error); + return error; } } @@ -288,70 +278,19 @@ static int tca6416_keypad_probe(struct i2c_client *client) if (error) { dev_dbg(&client->dev, "Unable to register input device, error: %d\n", error); - goto fail2; + return error; } i2c_set_clientdata(client, chip); - device_init_wakeup(&client->dev, 1); return 0; - -fail2: - if (!chip->use_polling) { - free_irq(chip->irqnum, chip); - enable_irq(chip->irqnum); - } -fail1: - input_free_device(input); - kfree(chip); - return error; } -static void tca6416_keypad_remove(struct i2c_client *client) -{ - struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); - - if (!chip->use_polling) { - free_irq(chip->irqnum, chip); - enable_irq(chip->irqnum); - } - - input_unregister_device(chip->input); - kfree(chip); -} - -static int tca6416_keypad_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); - - if (device_may_wakeup(dev)) - enable_irq_wake(chip->irqnum); - - return 0; -} - -static int tca6416_keypad_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); - - if (device_may_wakeup(dev)) - disable_irq_wake(chip->irqnum); - - return 0; -} - -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 = pm_sleep_ptr(&tca6416_keypad_dev_pm_ops), }, .probe = tca6416_keypad_probe, - .remove = tca6416_keypad_remove, .id_table = tca6416_id, }; diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index d5a6c7d8eb25..c9a823ea45d0 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -640,7 +640,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) timer_setup(&kbc->timer, tegra_kbc_keypress_timer, 0); - kbc->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + kbc->mmio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kbc->mmio)) return PTR_ERR(kbc->mmio); diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c index 75bd3ea51194..0fd761ae052f 100644 --- a/drivers/input/keyboard/tm2-touchkey.c +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -19,7 +19,6 @@ #include <linux/leds.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pm.h> #include <linux/regulator/consumer.h> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 8a320e6218e3..6ba984d7f0b1 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -791,10 +791,10 @@ config INPUT_IQS626A module will be called iqs626a. config INPUT_IQS7222 - tristate "Azoteq IQS7222A/B/C capacitive touch controller" + tristate "Azoteq IQS7222A/B/C/D capacitive touch controller" depends on I2C help - Say Y to enable support for the Azoteq IQS7222A/B/C family + Say Y to enable support for the Azoteq IQS7222A/B/C/D family of capacitive touch controllers. To compile this driver as a module, choose M here: the diff --git a/drivers/input/misc/cpcap-pwrbutton.c b/drivers/input/misc/cpcap-pwrbutton.c index 879790bbf9fe..85cddb84717a 100644 --- a/drivers/input/misc/cpcap-pwrbutton.c +++ b/drivers/input/misc/cpcap-pwrbutton.c @@ -1,16 +1,8 @@ -/** +// SPDX-License-Identifier: GPL-2.0-only +/* * CPCAP Power Button Input Driver * * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org> - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of this - * archive for more details. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/module.h> diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c index b14a389600c9..74808bae326a 100644 --- a/drivers/input/misc/da9063_onkey.c +++ b/drivers/input/misc/da9063_onkey.c @@ -10,6 +10,7 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/pm_wakeirq.h> #include <linux/workqueue.h> #include <linux/regmap.h> #include <linux/of.h> @@ -251,6 +252,14 @@ static int da9063_onkey_probe(struct platform_device *pdev) return error; } + error = dev_pm_set_wake_irq(&pdev->dev, irq); + if (error) + dev_warn(&pdev->dev, + "Failed to set IRQ %d as a wake IRQ: %d\n", + irq, error); + else + device_init_wakeup(&pdev->dev, true); + error = input_register_device(onkey->input); if (error) { dev_err(&pdev->dev, diff --git a/drivers/input/misc/gpio-vibra.c b/drivers/input/misc/gpio-vibra.c index 134a1309ba92..ad44b4d18a2a 100644 --- a/drivers/input/misc/gpio-vibra.c +++ b/drivers/input/misc/gpio-vibra.c @@ -18,7 +18,7 @@ #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/regulator/consumer.h> @@ -113,22 +113,14 @@ static int gpio_vibrator_probe(struct platform_device *pdev) return -ENOMEM; vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); - err = PTR_ERR_OR_ZERO(vibrator->vcc); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request regulator: %d\n", - err); - return err; - } + if (IS_ERR(vibrator->vcc)) + return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->vcc), + "Failed to request regulator\n"); vibrator->gpio = devm_gpiod_get(&pdev->dev, "enable", GPIOD_OUT_LOW); - err = PTR_ERR_OR_ZERO(vibrator->gpio); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request main gpio: %d\n", - err); - return err; - } + if (IS_ERR(vibrator->gpio)) + return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->gpio), + "Failed to request main gpio\n"); INIT_WORK(&vibrator->play_work, gpio_vibrator_play_work); diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c index 1272ef7b5794..c0a085639870 100644 --- a/drivers/input/misc/iqs269a.c +++ b/drivers/input/misc/iqs269a.c @@ -17,9 +17,9 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> #include <linux/property.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/input/misc/iqs626a.c b/drivers/input/misc/iqs626a.c index 50035c25c3f7..0dab54d3a060 100644 --- a/drivers/input/misc/iqs626a.c +++ b/drivers/input/misc/iqs626a.c @@ -19,8 +19,8 @@ #include <linux/input/touchscreen.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/property.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index 096b0925f41b..36aeeae77611 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Azoteq IQS7222A/B/C Capacitive Touch Controller + * Azoteq IQS7222A/B/C/D Capacitive Touch Controller * * Copyright (C) 2022 Jeff LaBundy <jeff@labundy.com> */ @@ -12,11 +12,12 @@ #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/input.h> +#include <linux/input/touchscreen.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/ktime.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/property.h> #include <linux/slab.h> #include <asm/unaligned.h> @@ -25,6 +26,7 @@ #define IQS7222_PROD_NUM_A 840 #define IQS7222_PROD_NUM_B 698 #define IQS7222_PROD_NUM_C 863 +#define IQS7222_PROD_NUM_D 1046 #define IQS7222_SYS_STATUS 0x10 #define IQS7222_SYS_STATUS_RESET BIT(3) @@ -54,6 +56,7 @@ #define IQS7222_EVENT_MASK_ATI BIT(12) #define IQS7222_EVENT_MASK_SLDR BIT(10) +#define IQS7222_EVENT_MASK_TPAD IQS7222_EVENT_MASK_SLDR #define IQS7222_EVENT_MASK_TOUCH BIT(1) #define IQS7222_EVENT_MASK_PROX BIT(0) @@ -71,6 +74,7 @@ #define IQS7222_MAX_COLS_CHAN 6 #define IQS7222_MAX_COLS_FILT 2 #define IQS7222_MAX_COLS_SLDR 11 +#define IQS7222_MAX_COLS_TPAD 24 #define IQS7222_MAX_COLS_GPIO 3 #define IQS7222_MAX_COLS_SYS 13 @@ -102,16 +106,18 @@ enum iqs7222_reg_grp_id { IQS7222_REG_GRP_BTN, IQS7222_REG_GRP_CHAN, IQS7222_REG_GRP_SLDR, + IQS7222_REG_GRP_TPAD, IQS7222_REG_GRP_GPIO, IQS7222_REG_GRP_SYS, IQS7222_NUM_REG_GRPS }; 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", + [IQS7222_REG_GRP_CYCLE] = "cycle-%d", + [IQS7222_REG_GRP_CHAN] = "channel-%d", + [IQS7222_REG_GRP_SLDR] = "slider-%d", + [IQS7222_REG_GRP_TPAD] = "trackpad", + [IQS7222_REG_GRP_GPIO] = "gpio-%d", }; static const unsigned int iqs7222_max_cols[IQS7222_NUM_REG_GRPS] = { @@ -122,6 +128,7 @@ static const unsigned int iqs7222_max_cols[IQS7222_NUM_REG_GRPS] = { [IQS7222_REG_GRP_CHAN] = IQS7222_MAX_COLS_CHAN, [IQS7222_REG_GRP_FILT] = IQS7222_MAX_COLS_FILT, [IQS7222_REG_GRP_SLDR] = IQS7222_MAX_COLS_SLDR, + [IQS7222_REG_GRP_TPAD] = IQS7222_MAX_COLS_TPAD, [IQS7222_REG_GRP_GPIO] = IQS7222_MAX_COLS_GPIO, [IQS7222_REG_GRP_SYS] = IQS7222_MAX_COLS_SYS, }; @@ -130,8 +137,10 @@ static const unsigned int iqs7222_gpio_links[] = { 2, 5, 6, }; struct iqs7222_event_desc { const char *name; + u16 link; u16 mask; u16 val; + u16 strict; u16 enable; enum iqs7222_reg_key_id reg_key; }; @@ -188,6 +197,93 @@ static const struct iqs7222_event_desc iqs7222_sl_events[] = { }, }; +static const struct iqs7222_event_desc iqs7222_tp_events[] = { + { + .name = "event-press", + .link = BIT(7), + }, + { + .name = "event-tap", + .link = BIT(0), + .mask = BIT(0), + .val = BIT(0), + .enable = BIT(0), + .reg_key = IQS7222_REG_KEY_TAP, + }, + { + .name = "event-swipe-x-pos", + .link = BIT(2), + .mask = BIT(2) | BIT(1), + .val = BIT(2), + .strict = BIT(4), + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-swipe-y-pos", + .link = BIT(3), + .mask = BIT(3) | BIT(1), + .val = BIT(3), + .strict = BIT(3), + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-swipe-x-neg", + .link = BIT(4), + .mask = BIT(4) | BIT(1), + .val = BIT(4), + .strict = BIT(4), + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-swipe-y-neg", + .link = BIT(5), + .mask = BIT(5) | BIT(1), + .val = BIT(5), + .strict = BIT(3), + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-flick-x-pos", + .link = BIT(2), + .mask = BIT(2) | BIT(1), + .val = BIT(2) | BIT(1), + .strict = BIT(4), + .enable = BIT(2), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-flick-y-pos", + .link = BIT(3), + .mask = BIT(3) | BIT(1), + .val = BIT(3) | BIT(1), + .strict = BIT(3), + .enable = BIT(2), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-flick-x-neg", + .link = BIT(4), + .mask = BIT(4) | BIT(1), + .val = BIT(4) | BIT(1), + .strict = BIT(4), + .enable = BIT(2), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-flick-y-neg", + .link = BIT(5), + .mask = BIT(5) | BIT(1), + .val = BIT(5) | BIT(1), + .strict = BIT(3), + .enable = BIT(2), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, +}; + struct iqs7222_reg_grp_desc { u16 base; int num_row; @@ -524,6 +620,62 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, }, }, + { + .prod_num = IQS7222_PROD_NUM_D, + .fw_major = 0, + .fw_minor = 37, + .touch_link = 1770, + .allow_offset = 9, + .event_offset = 10, + .comms_offset = 11, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 7, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 7, + .num_col = 2, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8700, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 14, + .num_col = 3, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xA000, + .num_row = 14, + .num_col = 4, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xAE00, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_TPAD] = { + .base = 0xB000, + .num_row = 1, + .num_col = 24, + }, + [IQS7222_REG_GRP_GPIO] = { + .base = 0xC000, + .num_row = 3, + .num_col = 3, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 12, + }, + }, + }, }; struct iqs7222_prop_desc { @@ -1009,6 +1161,123 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .label = "maximum gesture time", }, { + .name = "azoteq,num-rows", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 0, + .reg_shift = 4, + .reg_width = 4, + .val_min = 1, + .val_max = 12, + .label = "number of rows", + }, + { + .name = "azoteq,num-cols", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 0, + .reg_shift = 0, + .reg_width = 4, + .val_min = 1, + .val_max = 12, + .label = "number of columns", + }, + { + .name = "azoteq,lower-cal-y", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 1, + .reg_shift = 8, + .reg_width = 8, + .label = "lower vertical calibration", + }, + { + .name = "azoteq,lower-cal-x", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 8, + .label = "lower horizontal calibration", + }, + { + .name = "azoteq,upper-cal-y", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 2, + .reg_shift = 8, + .reg_width = 8, + .label = "upper vertical calibration", + }, + { + .name = "azoteq,upper-cal-x", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 2, + .reg_shift = 0, + .reg_width = 8, + .label = "upper horizontal calibration", + }, + { + .name = "azoteq,top-speed", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 3, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 4, + .label = "top speed", + }, + { + .name = "azoteq,bottom-speed", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_offset = 3, + .reg_shift = 0, + .reg_width = 8, + .label = "bottom speed", + }, + { + .name = "azoteq,gesture-min-ms", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_key = IQS7222_REG_KEY_TAP, + .reg_offset = 20, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 16, + .label = "minimum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_key = IQS7222_REG_KEY_AXIAL, + .reg_offset = 21, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 16, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_key = IQS7222_REG_KEY_TAP, + .reg_offset = 21, + .reg_shift = 0, + .reg_width = 8, + .val_pitch = 16, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-dist", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_key = IQS7222_REG_KEY_TAP, + .reg_offset = 22, + .reg_shift = 0, + .reg_width = 16, + .label = "gesture distance", + }, + { + .name = "azoteq,gesture-dist", + .reg_grp = IQS7222_REG_GRP_TPAD, + .reg_key = IQS7222_REG_KEY_AXIAL, + .reg_offset = 23, + .reg_shift = 0, + .reg_width = 16, + .label = "gesture distance", + }, + { .name = "drive-open-drain", .reg_grp = IQS7222_REG_GRP_GPIO, .reg_offset = 0, @@ -1091,16 +1360,19 @@ struct iqs7222_private { struct gpio_desc *irq_gpio; struct i2c_client *client; struct input_dev *keypad; + struct touchscreen_properties prop; unsigned int kp_type[IQS7222_MAX_CHAN][ARRAY_SIZE(iqs7222_kp_events)]; unsigned int kp_code[IQS7222_MAX_CHAN][ARRAY_SIZE(iqs7222_kp_events)]; unsigned int sl_code[IQS7222_MAX_SLDR][ARRAY_SIZE(iqs7222_sl_events)]; unsigned int sl_axis[IQS7222_MAX_SLDR]; + unsigned int tp_code[ARRAY_SIZE(iqs7222_tp_events)]; u16 cycle_setup[IQS7222_MAX_CHAN / 2][IQS7222_MAX_COLS_CYCLE]; u16 glbl_setup[IQS7222_MAX_COLS_GLBL]; u16 btn_setup[IQS7222_MAX_CHAN][IQS7222_MAX_COLS_BTN]; u16 chan_setup[IQS7222_MAX_CHAN][IQS7222_MAX_COLS_CHAN]; u16 filt_setup[IQS7222_MAX_COLS_FILT]; u16 sldr_setup[IQS7222_MAX_SLDR][IQS7222_MAX_COLS_SLDR]; + u16 tpad_setup[IQS7222_MAX_COLS_TPAD]; u16 gpio_setup[ARRAY_SIZE(iqs7222_gpio_links)][IQS7222_MAX_COLS_GPIO]; u16 sys_setup[IQS7222_MAX_COLS_SYS]; }; @@ -1127,6 +1399,9 @@ static u16 *iqs7222_setup(struct iqs7222_private *iqs7222, case IQS7222_REG_GRP_SLDR: return iqs7222->sldr_setup[row]; + case IQS7222_REG_GRP_TPAD: + return iqs7222->tpad_setup; + case IQS7222_REG_GRP_GPIO: return iqs7222->gpio_setup[row]; @@ -1381,9 +1656,6 @@ static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222) if (error) return error; - sys_setup &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK; - sys_setup &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK; - for (i = 0; i < IQS7222_NUM_RETRIES; i++) { /* * Trigger ATI from streaming and normal-power modes so that @@ -1561,8 +1833,11 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) return error; } - if (dir == READ) + if (dir == READ) { + iqs7222->sys_setup[0] &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK; + iqs7222->sys_setup[0] &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK; return 0; + } return iqs7222_ati_trigger(iqs7222); } @@ -1936,6 +2211,14 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, ref_setup[4] = dev_desc->touch_link; if (fwnode_property_present(chan_node, "azoteq,use-prox")) ref_setup[4] -= 2; + } else if (dev_desc->reg_grps[IQS7222_REG_GRP_TPAD].num_row && + fwnode_property_present(chan_node, + "azoteq,counts-filt-enable")) { + /* + * In the case of IQS7222D, however, the reference mode field + * is partially repurposed as a counts filter enable control. + */ + chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_REF; } if (fwnode_property_present(chan_node, "azoteq,rx-enable")) { @@ -2278,6 +2561,136 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, IQS7222_REG_KEY_NO_WHEEL); } +static int iqs7222_parse_tpad(struct iqs7222_private *iqs7222, + struct fwnode_handle *tpad_node, int tpad_index) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct touchscreen_properties *prop = &iqs7222->prop; + struct i2c_client *client = iqs7222->client; + int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; + int count, error, i; + u16 *event_mask = &iqs7222->sys_setup[dev_desc->event_offset]; + u16 *tpad_setup = iqs7222->tpad_setup; + unsigned int chan_sel[12]; + + error = iqs7222_parse_props(iqs7222, tpad_node, tpad_index, + IQS7222_REG_GRP_TPAD, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + count = fwnode_property_count_u32(tpad_node, "azoteq,channel-select"); + if (count < 0) { + dev_err(&client->dev, "Failed to count %s channels: %d\n", + fwnode_get_name(tpad_node), count); + return count; + } else if (!count || count > ARRAY_SIZE(chan_sel)) { + dev_err(&client->dev, "Invalid number of %s channels\n", + fwnode_get_name(tpad_node)); + return -EINVAL; + } + + error = fwnode_property_read_u32_array(tpad_node, + "azoteq,channel-select", + chan_sel, count); + if (error) { + dev_err(&client->dev, "Failed to read %s channels: %d\n", + fwnode_get_name(tpad_node), error); + return error; + } + + tpad_setup[6] &= ~GENMASK(num_chan - 1, 0); + + for (i = 0; i < ARRAY_SIZE(chan_sel); i++) { + tpad_setup[8 + i] = 0; + if (i >= count || chan_sel[i] == U8_MAX) + continue; + + if (chan_sel[i] >= num_chan) { + dev_err(&client->dev, "Invalid %s channel: %u\n", + fwnode_get_name(tpad_node), chan_sel[i]); + return -EINVAL; + } + + /* + * The following fields indicate which channels participate in + * the trackpad, as well as each channel's relative placement. + */ + tpad_setup[6] |= BIT(chan_sel[i]); + tpad_setup[8 + i] = chan_sel[i] * 34 + 1072; + } + + tpad_setup[7] = dev_desc->touch_link; + if (fwnode_property_present(tpad_node, "azoteq,use-prox")) + tpad_setup[7] -= 2; + + for (i = 0; i < ARRAY_SIZE(iqs7222_tp_events); i++) + tpad_setup[20] &= ~(iqs7222_tp_events[i].strict | + iqs7222_tp_events[i].enable); + + for (i = 0; i < ARRAY_SIZE(iqs7222_tp_events); i++) { + const char *event_name = iqs7222_tp_events[i].name; + struct fwnode_handle *event_node; + + event_node = fwnode_get_named_child_node(tpad_node, event_name); + if (!event_node) + continue; + + if (fwnode_property_present(event_node, + "azoteq,gesture-angle-tighten")) + tpad_setup[20] |= iqs7222_tp_events[i].strict; + + tpad_setup[20] |= iqs7222_tp_events[i].enable; + + error = iqs7222_parse_event(iqs7222, event_node, tpad_index, + IQS7222_REG_GRP_TPAD, + iqs7222_tp_events[i].reg_key, + iqs7222_tp_events[i].link, 1566, + NULL, + &iqs7222->tp_code[i]); + fwnode_handle_put(event_node); + if (error) + return error; + + if (!dev_desc->event_offset) + continue; + + /* + * The press/release event is determined based on whether the + * coordinate fields report 0xFFFF and solely relies on touch + * or proximity interrupts to be unmasked. + */ + if (i) + *event_mask |= IQS7222_EVENT_MASK_TPAD; + else if (tpad_setup[7] == dev_desc->touch_link) + *event_mask |= IQS7222_EVENT_MASK_TOUCH; + else + *event_mask |= IQS7222_EVENT_MASK_PROX; + } + + if (!iqs7222->tp_code[0]) + return 0; + + input_set_abs_params(iqs7222->keypad, ABS_X, + 0, (tpad_setup[4] ? : 1) - 1, 0, 0); + + input_set_abs_params(iqs7222->keypad, ABS_Y, + 0, (tpad_setup[5] ? : 1) - 1, 0, 0); + + touchscreen_parse_properties(iqs7222->keypad, false, prop); + + if (prop->max_x >= U16_MAX || prop->max_y >= U16_MAX) { + dev_err(&client->dev, "Invalid trackpad size: %u*%u\n", + prop->max_x, prop->max_y); + return -EINVAL; + } + + tpad_setup[4] = prop->max_x + 1; + tpad_setup[5] = prop->max_y + 1; + + return 0; +} + static int (*iqs7222_parse_extra[IQS7222_NUM_REG_GRPS]) (struct iqs7222_private *iqs7222, struct fwnode_handle *reg_grp_node, @@ -2285,6 +2698,7 @@ static int (*iqs7222_parse_extra[IQS7222_NUM_REG_GRPS]) [IQS7222_REG_GRP_CYCLE] = iqs7222_parse_cycle, [IQS7222_REG_GRP_CHAN] = iqs7222_parse_chan, [IQS7222_REG_GRP_SLDR] = iqs7222_parse_sldr, + [IQS7222_REG_GRP_TPAD] = iqs7222_parse_tpad, }; static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222, @@ -2298,7 +2712,7 @@ static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222, if (iqs7222_reg_grp_names[reg_grp]) { char reg_grp_name[16]; - snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d", + snprintf(reg_grp_name, sizeof(reg_grp_name), iqs7222_reg_grp_names[reg_grp], reg_grp_index); reg_grp_node = device_get_named_child_node(&client->dev, @@ -2346,8 +2760,8 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222) continue; /* - * The IQS7222C exposes multiple GPIO and must be informed - * as to which GPIO this group represents. + * The IQS7222C and IQS7222D expose multiple GPIO and must be + * informed as to which GPIO this group represents. */ for (j = 0; j < ARRAY_SIZE(iqs7222_gpio_links); j++) gpio_setup[0] &= ~BIT(iqs7222_gpio_links[j]); @@ -2480,6 +2894,41 @@ static int iqs7222_report(struct iqs7222_private *iqs7222) iqs7222->sl_code[i][j], 0); } + for (i = 0; i < dev_desc->reg_grps[IQS7222_REG_GRP_TPAD].num_row; i++) { + u16 tpad_pos_x = le16_to_cpu(status[4]); + u16 tpad_pos_y = le16_to_cpu(status[5]); + u16 state = le16_to_cpu(status[6]); + + input_report_key(iqs7222->keypad, iqs7222->tp_code[0], + tpad_pos_x < U16_MAX); + + if (tpad_pos_x < U16_MAX) + touchscreen_report_pos(iqs7222->keypad, &iqs7222->prop, + tpad_pos_x, tpad_pos_y, false); + + if (!(le16_to_cpu(status[1]) & IQS7222_EVENT_MASK_TPAD)) + continue; + + /* + * Skip the press/release event, as it does not have separate + * status fields and is handled separately. + */ + for (j = 1; j < ARRAY_SIZE(iqs7222_tp_events); j++) { + u16 mask = iqs7222_tp_events[j].mask; + u16 val = iqs7222_tp_events[j].val; + + input_report_key(iqs7222->keypad, + iqs7222->tp_code[j], + (state & mask) == val); + } + + input_sync(iqs7222->keypad); + + for (j = 1; j < ARRAY_SIZE(iqs7222_tp_events); j++) + input_report_key(iqs7222->keypad, + iqs7222->tp_code[j], 0); + } + input_sync(iqs7222->keypad); return 0; @@ -2584,6 +3033,7 @@ static const struct of_device_id iqs7222_of_match[] = { { .compatible = "azoteq,iqs7222a" }, { .compatible = "azoteq,iqs7222b" }, { .compatible = "azoteq,iqs7222c" }, + { .compatible = "azoteq,iqs7222d" }, { } }; MODULE_DEVICE_TABLE(of, iqs7222_of_match); @@ -2598,5 +3048,5 @@ static struct i2c_driver iqs7222_i2c_driver = { module_i2c_driver(iqs7222_i2c_driver); MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>"); -MODULE_DESCRIPTION("Azoteq IQS7222A/B/C Capacitive Touch Controller"); +MODULE_DESCRIPTION("Azoteq IQS7222A/B/C/D Capacitive Touch Controller"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 76a190b2220b..662b436d765b 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -11,7 +11,7 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/input.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #define MMA8450_DRV_NAME "mma8450" diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index 74d77d8aaeff..ba747c5b2b5f 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/regmap.h> diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index 04cb87efd799..5c288fe7accf 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -7,7 +7,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 89fb137e3715..c406a1cca5c4 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -12,7 +12,6 @@ #include <linux/regmap.h> #include <linux/log2.h> #include <linux/of.h> -#include <linux/of_device.h> #define PON_CNTL_1 0x1C #define PON_CNTL_PULL_UP BIT(7) diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 3cf1812384e6..1e731d8397c6 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -132,13 +132,8 @@ static int pwm_beeper_probe(struct platform_device *pdev) return -ENOMEM; beeper->pwm = devm_pwm_get(dev, NULL); - if (IS_ERR(beeper->pwm)) { - error = PTR_ERR(beeper->pwm); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to request PWM device: %d\n", - error); - return error; - } + if (IS_ERR(beeper->pwm)) + return dev_err_probe(dev, PTR_ERR(beeper->pwm), "Failed to request PWM device\n"); /* Sync up PWM state and ensure it is off. */ pwm_init_state(beeper->pwm, &state); @@ -151,13 +146,9 @@ static int pwm_beeper_probe(struct platform_device *pdev) } beeper->amplifier = devm_regulator_get(dev, "amp"); - if (IS_ERR(beeper->amplifier)) { - error = PTR_ERR(beeper->amplifier); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get 'amp' regulator: %d\n", - error); - return error; - } + if (IS_ERR(beeper->amplifier)) + return dev_err_probe(dev, PTR_ERR(beeper->amplifier), + "Failed to get 'amp' regulator\n"); INIT_WORK(&beeper->work, pwm_beeper_work); diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c index 2ba035299db8..acac79c488aa 100644 --- a/drivers/input/misc/pwm-vibra.c +++ b/drivers/input/misc/pwm-vibra.c @@ -15,7 +15,7 @@ #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/pwm.h> @@ -140,32 +140,20 @@ static int pwm_vibrator_probe(struct platform_device *pdev) return -ENOMEM; vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); - err = PTR_ERR_OR_ZERO(vibrator->vcc); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request regulator: %d\n", - err); - return err; - } + if (IS_ERR(vibrator->vcc)) + return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->vcc), + "Failed to request regulator\n"); vibrator->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW); - err = PTR_ERR_OR_ZERO(vibrator->enable_gpio); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request enable gpio: %d\n", - err); - return err; - } + if (IS_ERR(vibrator->enable_gpio)) + return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->enable_gpio), + "Failed to request enable gpio\n"); vibrator->pwm = devm_pwm_get(&pdev->dev, "enable"); - err = PTR_ERR_OR_ZERO(vibrator->pwm); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request main pwm: %d\n", - err); - return err; - } + if (IS_ERR(vibrator->pwm)) + return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->pwm), + "Failed to request main pwm\n"); INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work); diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 22ec62083065..e94cab8133be 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -236,12 +236,8 @@ static int rotary_encoder_probe(struct platform_device *pdev) device_property_read_bool(dev, "rotary-encoder,relative-axis"); encoder->gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); - if (IS_ERR(encoder->gpios)) { - err = PTR_ERR(encoder->gpios); - if (err != -EPROBE_DEFER) - dev_err(dev, "unable to get gpios: %d\n", err); - return err; - } + if (IS_ERR(encoder->gpios)) + return dev_err_probe(dev, PTR_ERR(encoder->gpios), "unable to get gpios\n"); if (encoder->gpios->ndescs < 2) { dev_err(dev, "not enough gpios found\n"); return -EINVAL; @@ -255,7 +251,6 @@ static int rotary_encoder_probe(struct platform_device *pdev) input->name = pdev->name; input->id.bustype = BUS_HOST; - input->dev.parent = dev; if (encoder->relative_axis) input_set_capability(input, EV_REL, encoder->axis); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index cdcb7737c46a..e5dd84725c6e 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -9,7 +9,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include <asm/io.h> diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 0cff742302a9..148a601396f9 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1221,13 +1221,8 @@ static int elan_probe(struct i2c_client *client) mutex_init(&data->sysfs_mutex); data->vcc = devm_regulator_get(dev, "vcc"); - if (IS_ERR(data->vcc)) { - error = PTR_ERR(data->vcc); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get 'vcc' regulator: %d\n", - error); - return error; - } + if (IS_ERR(data->vcc)) + return dev_err_probe(dev, PTR_ERR(data->vcc), "Failed to get 'vcc' regulator\n"); error = regulator_enable(data->vcc); if (error) { diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c index 2a2459b1b4f2..7b13de979908 100644 --- a/drivers/input/mouse/psmouse-smbus.c +++ b/drivers/input/mouse/psmouse-smbus.c @@ -5,6 +5,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/libps2.h> @@ -118,13 +119,18 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct psmouse *psmouse) return PSMOUSE_FULL_PACKET; } -static int psmouse_smbus_reconnect(struct psmouse *psmouse) +static void psmouse_activate_smbus_mode(struct psmouse_smbus_dev *smbdev) { - struct psmouse_smbus_dev *smbdev = psmouse->private; - - if (smbdev->need_deactivate) - psmouse_deactivate(psmouse); + if (smbdev->need_deactivate) { + psmouse_deactivate(smbdev->psmouse); + /* Give the device time to switch into SMBus mode */ + msleep(30); + } +} +static int psmouse_smbus_reconnect(struct psmouse *psmouse) +{ + psmouse_activate_smbus_mode(psmouse->private); return 0; } @@ -257,8 +263,7 @@ int psmouse_smbus_init(struct psmouse *psmouse, } } - if (need_deactivate) - psmouse_deactivate(psmouse); + psmouse_activate_smbus_mode(smbdev); psmouse->private = smbdev; psmouse->protocol_handler = psmouse_smbus_process_byte; diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c index 513d96e40e0e..3f6866d39b86 100644 --- a/drivers/input/serio/apbps2.c +++ b/drivers/input/serio/apbps2.c @@ -14,11 +14,11 @@ * Contributors: Daniel Hellstrom <daniel@gaisler.com> */ #include <linux/platform_device.h> -#include <linux/of_device.h> #include <linux/module.h> #include <linux/serio.h> #include <linux/errno.h> #include <linux/interrupt.h> +#include <linux/of.h> #include <linux/of_irq.h> #include <linux/device.h> #include <linux/delay.h> diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 028e45bd050b..1724d6cb8649 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -1281,6 +1281,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) }, + /* See comment on TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU above */ + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PD5x_7xPNP_PNR_PNN_PNT"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOAUX) + }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "X170SM"), diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index c712c1fe0605..b68793bf05c8 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -2,7 +2,9 @@ #ifndef _I8042_SPARCIO_H #define _I8042_SPARCIO_H -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/types.h> #include <asm/io.h> diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index ce420eb1f51b..e8a9709f32eb 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -101,12 +101,12 @@ static int rpckbd_probe(struct platform_device *dev) int tx_irq, rx_irq; rx_irq = platform_get_irq(dev, 0); - if (rx_irq <= 0) - return rx_irq < 0 ? rx_irq : -ENXIO; + if (rx_irq < 0) + return rx_irq; tx_irq = platform_get_irq(dev, 1); - if (tx_irq <= 0) - return tx_irq < 0 ? tx_irq : -ENXIO; + if (tx_irq < 0) + return tx_irq; serio = kzalloc(sizeof(struct serio), GFP_KERNEL); rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL); diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 960d7601fbc8..f3d28da70b75 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -14,10 +14,10 @@ #include <linux/slab.h> #include <linux/list.h> #include <linux/io.h> +#include <linux/mod_devicetable.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #define DRIVER_NAME "xilinx_ps2" diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index c2cbd332af1d..e3e2324547b9 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -655,10 +655,10 @@ config TOUCHSCREEN_MTOUCH module will be called mtouch. config TOUCHSCREEN_NOVATEK_NVT_TS - tristate "Novatek NVT-ts touchscreen support" + tristate "Novatek NT11205 touchscreen support" depends on I2C help - Say Y here if you have a Novatek NVT-ts touchscreen. + Say Y here if you have a Novatek NT11205 touchscreen. If unsure, say N. To compile this driver as a module, choose M here: the @@ -1365,6 +1365,16 @@ config TOUCHSCREEN_IQS5XX To compile this driver as a module, choose M here: the module will be called iqs5xx. +config TOUCHSCREEN_IQS7211 + tristate "Azoteq IQS7210A/7211A/E trackpad/touchscreen controller" + depends on I2C + help + Say Y to enable support for the Azoteq IQS7210A/7211A/E + family of trackpad/touchscreen controllers. + + To compile this driver as a module, choose M here: the + module will be called iqs7211. + config TOUCHSCREEN_ZINITIX tristate "Zinitix touchscreen support" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 159cd5136fdb..62bd24f3ac8e 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -115,5 +115,6 @@ obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o 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_IQS7211) += iqs7211.o obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 85332cfaa29d..652439a79e21 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -410,31 +410,32 @@ static int bu21013_probe(struct i2c_client *client) struct input_dev *in_dev; struct input_absinfo *info; u32 max_x = 0, max_y = 0; + struct device *dev = &client->dev; int error; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "i2c smbus byte data not supported\n"); + dev_err(dev, "i2c smbus byte data not supported\n"); return -EIO; } if (!client->irq) { - dev_err(&client->dev, "No IRQ set up\n"); + dev_err(dev, "No IRQ set up\n"); return -EINVAL; } - ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); if (!ts) return -ENOMEM; ts->client = client; - ts->x_flip = device_property_read_bool(&client->dev, "rohm,flip-x"); - ts->y_flip = device_property_read_bool(&client->dev, "rohm,flip-y"); + ts->x_flip = device_property_read_bool(dev, "rohm,flip-x"); + ts->y_flip = device_property_read_bool(dev, "rohm,flip-y"); - in_dev = devm_input_allocate_device(&client->dev); + in_dev = devm_input_allocate_device(dev); if (!in_dev) { - dev_err(&client->dev, "device memory alloc failed\n"); + dev_err(dev, "device memory alloc failed\n"); return -ENOMEM; } ts->in_dev = in_dev; @@ -444,8 +445,8 @@ static int bu21013_probe(struct i2c_client *client) in_dev->name = DRIVER_TP; in_dev->id.bustype = BUS_I2C; - device_property_read_u32(&client->dev, "rohm,touch-max-x", &max_x); - device_property_read_u32(&client->dev, "rohm,touch-max-y", &max_y); + device_property_read_u32(dev, "rohm,touch-max-x", &max_x); + device_property_read_u32(dev, "rohm,touch-max-y", &max_y); input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, max_x, 0, 0); input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, max_y, 0, 0); @@ -454,14 +455,14 @@ static int bu21013_probe(struct i2c_client *client) /* Adjust for the legacy "flip" properties, if present */ if (!ts->props.invert_x && - device_property_read_bool(&client->dev, "rohm,flip-x")) { + device_property_read_bool(dev, "rohm,flip-x")) { info = &in_dev->absinfo[ABS_MT_POSITION_X]; info->maximum -= info->minimum; info->minimum = 0; } if (!ts->props.invert_y && - device_property_read_bool(&client->dev, "rohm,flip-y")) { + device_property_read_bool(dev, "rohm,flip-y")) { info = &in_dev->absinfo[ABS_MT_POSITION_Y]; info->maximum -= info->minimum; info->minimum = 0; @@ -471,55 +472,46 @@ static int bu21013_probe(struct i2c_client *client) INPUT_MT_DIRECT | INPUT_MT_TRACK | INPUT_MT_DROP_UNUSED); if (error) { - dev_err(&client->dev, "failed to initialize MT slots"); + dev_err(dev, "failed to initialize MT slots"); return error; } - ts->regulator = devm_regulator_get(&client->dev, "avdd"); + ts->regulator = devm_regulator_get(dev, "avdd"); if (IS_ERR(ts->regulator)) { - dev_err(&client->dev, "regulator_get failed\n"); + dev_err(dev, "regulator_get failed\n"); return PTR_ERR(ts->regulator); } error = regulator_enable(ts->regulator); if (error) { - dev_err(&client->dev, "regulator enable failed\n"); + dev_err(dev, "regulator enable failed\n"); return error; } - error = devm_add_action_or_reset(&client->dev, bu21013_power_off, ts); + error = devm_add_action_or_reset(dev, bu21013_power_off, ts); if (error) { - dev_err(&client->dev, "failed to install power off handler\n"); + dev_err(dev, "failed to install power off handler\n"); return error; } /* Named "CS" on the chip, DT binding is "reset" */ - ts->cs_gpiod = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); - error = PTR_ERR_OR_ZERO(ts->cs_gpiod); - if (error) { - if (error != -EPROBE_DEFER) - dev_err(&client->dev, "failed to get CS GPIO\n"); - return error; - } + ts->cs_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ts->cs_gpiod)) + return dev_err_probe(dev, PTR_ERR(ts->cs_gpiod), "failed to get CS GPIO\n"); + gpiod_set_consumer_name(ts->cs_gpiod, "BU21013 CS"); - error = devm_add_action_or_reset(&client->dev, - bu21013_disable_chip, ts); + error = devm_add_action_or_reset(dev, bu21013_disable_chip, ts); if (error) { - dev_err(&client->dev, - "failed to install chip disable handler\n"); + dev_err(dev, "failed to install chip disable handler\n"); return error; } /* Named "INT" on the chip, DT binding is "touch" */ - ts->int_gpiod = devm_gpiod_get_optional(&client->dev, - "touch", GPIOD_IN); + ts->int_gpiod = devm_gpiod_get_optional(dev, "touch", GPIOD_IN); error = PTR_ERR_OR_ZERO(ts->int_gpiod); - if (error) { - if (error != -EPROBE_DEFER) - dev_err(&client->dev, "failed to get INT GPIO\n"); - return error; - } + if (error) + return dev_err_probe(dev, error, "failed to get INT GPIO\n"); if (ts->int_gpiod) gpiod_set_consumer_name(ts->int_gpiod, "BU21013 INT"); @@ -527,22 +519,20 @@ static int bu21013_probe(struct i2c_client *client) /* configure the touch panel controller */ error = bu21013_init_chip(ts); if (error) { - dev_err(&client->dev, "error in bu21013 config\n"); + dev_err(dev, "error in bu21013 config\n"); return error; } - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, bu21013_gpio_irq, + error = devm_request_threaded_irq(dev, client->irq, NULL, bu21013_gpio_irq, IRQF_ONESHOT, DRIVER_TP, ts); if (error) { - dev_err(&client->dev, "request irq %d failed\n", - client->irq); + dev_err(dev, "request irq %d failed\n", client->irq); return error; } error = input_register_device(in_dev); if (error) { - dev_err(&client->dev, "failed to register input device\n"); + dev_err(dev, "failed to register input device\n"); return error; } diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c index c8126d2efe95..e1dfbd92ab64 100644 --- a/drivers/input/touchscreen/bu21029_ts.c +++ b/drivers/input/touchscreen/bu21029_ts.c @@ -333,6 +333,7 @@ static void bu21029_stop_chip(struct input_dev *dev) static int bu21029_probe(struct i2c_client *client) { + struct device *dev = &client->dev; struct bu21029_ts_data *bu21029; struct input_dev *in_dev; int error; @@ -341,45 +342,33 @@ static int bu21029_probe(struct i2c_client *client) I2C_FUNC_SMBUS_WRITE_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - dev_err(&client->dev, - "i2c functionality support is not sufficient\n"); + dev_err(dev, "i2c functionality support is not sufficient\n"); return -EIO; } - bu21029 = devm_kzalloc(&client->dev, sizeof(*bu21029), GFP_KERNEL); + bu21029 = devm_kzalloc(dev, sizeof(*bu21029), GFP_KERNEL); if (!bu21029) return -ENOMEM; - error = device_property_read_u32(&client->dev, "rohm,x-plate-ohms", - &bu21029->x_plate_ohms); + error = device_property_read_u32(dev, "rohm,x-plate-ohms", &bu21029->x_plate_ohms); if (error) { - dev_err(&client->dev, - "invalid 'x-plate-ohms' supplied: %d\n", error); + dev_err(dev, "invalid 'x-plate-ohms' supplied: %d\n", error); return error; } - bu21029->vdd = devm_regulator_get(&client->dev, "vdd"); - if (IS_ERR(bu21029->vdd)) { - error = PTR_ERR(bu21029->vdd); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "failed to acquire 'vdd' supply: %d\n", error); - return error; - } + bu21029->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(bu21029->vdd)) + return dev_err_probe(dev, PTR_ERR(bu21029->vdd), + "failed to acquire 'vdd' supply\n"); - bu21029->reset_gpios = devm_gpiod_get_optional(&client->dev, - "reset", GPIOD_OUT_HIGH); - if (IS_ERR(bu21029->reset_gpios)) { - error = PTR_ERR(bu21029->reset_gpios); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "failed to acquire 'reset' gpio: %d\n", error); - return error; - } + bu21029->reset_gpios = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(bu21029->reset_gpios)) + return dev_err_probe(dev, PTR_ERR(bu21029->reset_gpios), + "failed to acquire 'reset' gpio\n"); - in_dev = devm_input_allocate_device(&client->dev); + in_dev = devm_input_allocate_device(dev); if (!in_dev) { - dev_err(&client->dev, "unable to allocate input device\n"); + dev_err(dev, "unable to allocate input device\n"); return -ENOMEM; } @@ -400,20 +389,18 @@ static int bu21029_probe(struct i2c_client *client) input_set_drvdata(in_dev, bu21029); - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, bu21029_touch_soft_irq, + error = devm_request_threaded_irq(dev, client->irq, NULL, + bu21029_touch_soft_irq, IRQF_ONESHOT | IRQF_NO_AUTOEN, DRIVER_NAME, bu21029); if (error) { - dev_err(&client->dev, - "unable to request touch irq: %d\n", error); + dev_err(dev, "unable to request touch irq: %d\n", error); return error; } error = input_register_device(in_dev); if (error) { - dev_err(&client->dev, - "unable to register input device: %d\n", error); + dev_err(dev, "unable to register input device: %d\n", error); return error; } diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c index 9fbeaf17f00b..d6876d10b252 100644 --- a/drivers/input/touchscreen/chipone_icn8318.c +++ b/drivers/input/touchscreen/chipone_icn8318.c @@ -191,12 +191,8 @@ static int icn8318_probe(struct i2c_client *client) return -ENOMEM; data->wake_gpio = devm_gpiod_get(dev, "wake", GPIOD_OUT_LOW); - if (IS_ERR(data->wake_gpio)) { - error = PTR_ERR(data->wake_gpio); - if (error != -EPROBE_DEFER) - dev_err(dev, "Error getting wake gpio: %d\n", error); - return error; - } + if (IS_ERR(data->wake_gpio)) + return dev_err_probe(dev, PTR_ERR(data->wake_gpio), "Error getting wake gpio\n"); input = devm_input_allocate_device(dev); if (!input) diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c index 967ecde23e83..ea3895167b82 100644 --- a/drivers/input/touchscreen/cy8ctma140.c +++ b/drivers/input/touchscreen/cy8ctma140.c @@ -258,12 +258,8 @@ static int cy8ctma140_probe(struct i2c_client *client) ts->regulators[1].supply = "vdd"; error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators), ts->regulators); - if (error) { - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get regulators %d\n", - error); - return error; - } + if (error) + return dev_err_probe(dev, error, "Failed to get regulators\n"); error = cy8ctma140_power_up(ts); if (error) diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c index b461ded946fc..db5a885ecd72 100644 --- a/drivers/input/touchscreen/cyttsp5.c +++ b/drivers/input/touchscreen/cyttsp5.c @@ -18,8 +18,8 @@ #include <linux/input/touchscreen.h> #include <linux/interrupt.h> #include <linux/i2c.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <asm/unaligned.h> diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 795c7dad22bf..457d53337fbb 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -1168,13 +1168,9 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client) tsdata->max_support_points = chip_data->max_support_points; tsdata->vcc = devm_regulator_get(&client->dev, "vcc"); - if (IS_ERR(tsdata->vcc)) { - error = PTR_ERR(tsdata->vcc); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "failed to request regulator: %d\n", error); - return error; - } + if (IS_ERR(tsdata->vcc)) + return dev_err_probe(&client->dev, PTR_ERR(tsdata->vcc), + "failed to request regulator\n"); tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc"); if (IS_ERR(tsdata->iovcc)) { diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c index fd8724a3c19f..cc3103b9cbfb 100644 --- a/drivers/input/touchscreen/ektf2127.c +++ b/drivers/input/touchscreen/ektf2127.c @@ -264,12 +264,8 @@ static int ektf2127_probe(struct i2c_client *client) /* This requests the gpio *and* turns on the touchscreen controller */ ts->power_gpios = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH); - if (IS_ERR(ts->power_gpios)) { - error = PTR_ERR(ts->power_gpios); - if (error != -EPROBE_DEFER) - dev_err(dev, "Error getting power gpio: %d\n", error); - return error; - } + if (IS_ERR(ts->power_gpios)) + return dev_err_probe(dev, PTR_ERR(ts->power_gpios), "Error getting power gpio\n"); input = devm_input_allocate_device(dev); if (!input) diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 2da1db64126d..a1af3de9f310 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1438,24 +1438,14 @@ static int elants_i2c_probe(struct i2c_client *client) i2c_set_clientdata(client, ts); ts->vcc33 = devm_regulator_get(&client->dev, "vcc33"); - if (IS_ERR(ts->vcc33)) { - error = PTR_ERR(ts->vcc33); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get 'vcc33' regulator: %d\n", - error); - return error; - } + if (IS_ERR(ts->vcc33)) + return dev_err_probe(&client->dev, PTR_ERR(ts->vcc33), + "Failed to get 'vcc33' regulator\n"); ts->vccio = devm_regulator_get(&client->dev, "vccio"); - if (IS_ERR(ts->vccio)) { - error = PTR_ERR(ts->vccio); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get 'vccio' regulator: %d\n", - error); - return error; - } + if (IS_ERR(ts->vccio)) + return dev_err_probe(&client->dev, PTR_ERR(ts->vccio), + "Failed to get 'vccio' regulator\n"); ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ts->reset_gpio)) { diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index 4af4c1e5d0da..4c0d99aae9e0 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -7,6 +7,7 @@ * minimal implementation based on egalax_ts.c and egalax_i2c.c */ +#include <linux/acpi.h> #include <linux/bitops.h> #include <linux/delay.h> #include <linux/device.h> @@ -18,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/regulator/consumer.h> #include <linux/sizes.h> #include <linux/timer.h> #include <asm/unaligned.h> @@ -360,6 +362,12 @@ static int exc3000_probe(struct i2c_client *client) if (IS_ERR(data->reset)) return PTR_ERR(data->reset); + /* For proper reset sequence, enable power while reset asserted */ + error = devm_regulator_get_enable(&client->dev, "vdd"); + if (error && error != -ENODEV) + return dev_err_probe(&client->dev, error, + "failed to request vdd regulator\n"); + if (data->reset) { msleep(EXC3000_RESET_MS); gpiod_set_value_cansleep(data->reset, 0); @@ -454,10 +462,19 @@ static const struct of_device_id exc3000_of_match[] = { MODULE_DEVICE_TABLE(of, exc3000_of_match); #endif +#ifdef CONFIG_ACPI +static const struct acpi_device_id exc3000_acpi_match[] = { + { "EGA00001", .driver_data = (kernel_ulong_t)&exc3000_info[EETI_EXC80H60] }, + { } +}; +MODULE_DEVICE_TABLE(acpi, exc3000_acpi_match); +#endif + static struct i2c_driver exc3000_driver = { .driver = { .name = "exc3000", .of_match_table = of_match_ptr(exc3000_of_match), + .acpi_match_table = ACPI_PTR(exc3000_acpi_match), }, .id_table = exc3000_id, .probe = exc3000_probe, diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index f5aa240739f9..da9954d6df44 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -935,7 +935,6 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) */ static int goodix_get_gpio_config(struct goodix_ts_data *ts) { - int error; struct device *dev; struct gpio_desc *gpiod; bool added_acpi_mappings = false; @@ -951,33 +950,20 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts) ts->gpiod_rst_flags = GPIOD_IN; ts->avdd28 = devm_regulator_get(dev, "AVDD28"); - if (IS_ERR(ts->avdd28)) { - error = PTR_ERR(ts->avdd28); - if (error != -EPROBE_DEFER) - dev_err(dev, - "Failed to get AVDD28 regulator: %d\n", error); - return error; - } + if (IS_ERR(ts->avdd28)) + return dev_err_probe(dev, PTR_ERR(ts->avdd28), "Failed to get AVDD28 regulator\n"); ts->vddio = devm_regulator_get(dev, "VDDIO"); - if (IS_ERR(ts->vddio)) { - error = PTR_ERR(ts->vddio); - if (error != -EPROBE_DEFER) - dev_err(dev, - "Failed to get VDDIO regulator: %d\n", error); - return error; - } + if (IS_ERR(ts->vddio)) + return dev_err_probe(dev, PTR_ERR(ts->vddio), "Failed to get VDDIO regulator\n"); retry_get_irq_gpio: /* Get the interrupt GPIO pin number */ gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); - if (IS_ERR(gpiod)) { - error = PTR_ERR(gpiod); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get %s GPIO: %d\n", - GOODIX_GPIO_INT_NAME, error); - return error; - } + if (IS_ERR(gpiod)) + return dev_err_probe(dev, PTR_ERR(gpiod), "Failed to get %s GPIO\n", + GOODIX_GPIO_INT_NAME); + if (!gpiod && has_acpi_companion(dev) && !added_acpi_mappings) { added_acpi_mappings = true; if (goodix_add_acpi_gpio_mappings(ts) == 0) @@ -988,13 +974,9 @@ retry_get_irq_gpio: /* Get the reset line GPIO pin number */ gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, ts->gpiod_rst_flags); - if (IS_ERR(gpiod)) { - error = PTR_ERR(gpiod); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get %s GPIO: %d\n", - GOODIX_GPIO_RST_NAME, error); - return error; - } + if (IS_ERR(gpiod)) + return dev_err_probe(dev, PTR_ERR(gpiod), "Failed to get %s GPIO\n", + GOODIX_GPIO_RST_NAME); ts->gpiod_rst = gpiod; @@ -1517,6 +1499,7 @@ MODULE_DEVICE_TABLE(i2c, goodix_ts_id); static const struct acpi_device_id goodix_acpi_match[] = { { "GDIX1001", 0 }, { "GDIX1002", 0 }, + { "GDX9110", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index f7cd773f7292..ad6828e4f2e2 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -8,8 +8,8 @@ #include <linux/input/mt.h> #include <linux/input/touchscreen.h> #include <linux/interrupt.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/sizes.h> #include <linux/slab.h> #include <asm/unaligned.h> diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c index 0aa9d6492df8..b4768b66eb10 100644 --- a/drivers/input/touchscreen/iqs5xx.c +++ b/drivers/input/touchscreen/iqs5xx.c @@ -23,8 +23,8 @@ #include <linux/input/touchscreen.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/slab.h> #include <asm/unaligned.h> diff --git a/drivers/input/touchscreen/iqs7211.c b/drivers/input/touchscreen/iqs7211.c new file mode 100644 index 000000000000..dc084f873762 --- /dev/null +++ b/drivers/input/touchscreen/iqs7211.c @@ -0,0 +1,2557 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Azoteq IQS7210A/7211A/E Trackpad/Touchscreen Controller + * + * Copyright (C) 2023 Jeff LaBundy <jeff@labundy.com> + */ + +#include <linux/bits.h> +#include <linux/delay.h> +#include <linux/device.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/iopoll.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/property.h> +#include <linux/slab.h> +#include <asm/unaligned.h> + +#define IQS7211_PROD_NUM 0x00 + +#define IQS7211_EVENT_MASK_ALL GENMASK(14, 8) +#define IQS7211_EVENT_MASK_ALP BIT(13) +#define IQS7211_EVENT_MASK_BTN BIT(12) +#define IQS7211_EVENT_MASK_ATI BIT(11) +#define IQS7211_EVENT_MASK_MOVE BIT(10) +#define IQS7211_EVENT_MASK_GSTR BIT(9) +#define IQS7211_EVENT_MODE BIT(8) + +#define IQS7211_COMMS_ERROR 0xEEEE +#define IQS7211_COMMS_RETRY_MS 50 +#define IQS7211_COMMS_SLEEP_US 100 +#define IQS7211_COMMS_TIMEOUT_US (100 * USEC_PER_MSEC) +#define IQS7211_RESET_TIMEOUT_MS 150 +#define IQS7211_START_TIMEOUT_US (1 * USEC_PER_SEC) + +#define IQS7211_NUM_RETRIES 5 +#define IQS7211_NUM_CRX 8 +#define IQS7211_MAX_CTX 13 + +#define IQS7211_MAX_CONTACTS 2 +#define IQS7211_MAX_CYCLES 21 + +/* + * The following delay is used during instances that must wait for the open- + * drain RDY pin to settle. Its value is calculated as 5*R*C, where R and C + * represent typical datasheet values of 4.7k and 100 nF, respectively. + */ +#define iqs7211_irq_wait() usleep_range(2500, 2600) + +enum iqs7211_dev_id { + IQS7210A, + IQS7211A, + IQS7211E, +}; + +enum iqs7211_comms_mode { + IQS7211_COMMS_MODE_WAIT, + IQS7211_COMMS_MODE_FREE, + IQS7211_COMMS_MODE_FORCE, +}; + +struct iqs7211_reg_field_desc { + struct list_head list; + u8 addr; + u16 mask; + u16 val; +}; + +enum iqs7211_reg_key_id { + IQS7211_REG_KEY_NONE, + IQS7211_REG_KEY_PROX, + IQS7211_REG_KEY_TOUCH, + IQS7211_REG_KEY_TAP, + IQS7211_REG_KEY_HOLD, + IQS7211_REG_KEY_PALM, + IQS7211_REG_KEY_AXIAL_X, + IQS7211_REG_KEY_AXIAL_Y, + IQS7211_REG_KEY_RESERVED +}; + +enum iqs7211_reg_grp_id { + IQS7211_REG_GRP_TP, + IQS7211_REG_GRP_BTN, + IQS7211_REG_GRP_ALP, + IQS7211_REG_GRP_SYS, + IQS7211_NUM_REG_GRPS +}; + +static const char * const iqs7211_reg_grp_names[IQS7211_NUM_REG_GRPS] = { + [IQS7211_REG_GRP_TP] = "trackpad", + [IQS7211_REG_GRP_BTN] = "button", + [IQS7211_REG_GRP_ALP] = "alp", +}; + +static const u16 iqs7211_reg_grp_masks[IQS7211_NUM_REG_GRPS] = { + [IQS7211_REG_GRP_TP] = IQS7211_EVENT_MASK_GSTR, + [IQS7211_REG_GRP_BTN] = IQS7211_EVENT_MASK_BTN, + [IQS7211_REG_GRP_ALP] = IQS7211_EVENT_MASK_ALP, +}; + +struct iqs7211_event_desc { + const char *name; + u16 mask; + u16 enable; + enum iqs7211_reg_grp_id reg_grp; + enum iqs7211_reg_key_id reg_key; +}; + +static const struct iqs7211_event_desc iqs7210a_kp_events[] = { + { + .mask = BIT(10), + .enable = BIT(13) | BIT(12), + .reg_grp = IQS7211_REG_GRP_ALP, + }, + { + .name = "event-prox", + .mask = BIT(2), + .enable = BIT(5) | BIT(4), + .reg_grp = IQS7211_REG_GRP_BTN, + .reg_key = IQS7211_REG_KEY_PROX, + }, + { + .name = "event-touch", + .mask = BIT(3), + .enable = BIT(5) | BIT(4), + .reg_grp = IQS7211_REG_GRP_BTN, + .reg_key = IQS7211_REG_KEY_TOUCH, + }, + { + .name = "event-tap", + .mask = BIT(0), + .enable = BIT(0), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_TAP, + }, + { + .name = "event-hold", + .mask = BIT(1), + .enable = BIT(1), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, + { + .name = "event-swipe-x-neg", + .mask = BIT(2), + .enable = BIT(2), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_X, + }, + { + .name = "event-swipe-x-pos", + .mask = BIT(3), + .enable = BIT(3), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_X, + }, + { + .name = "event-swipe-y-pos", + .mask = BIT(4), + .enable = BIT(4), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + }, + { + .name = "event-swipe-y-neg", + .mask = BIT(5), + .enable = BIT(5), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + }, +}; + +static const struct iqs7211_event_desc iqs7211a_kp_events[] = { + { + .mask = BIT(14), + .reg_grp = IQS7211_REG_GRP_ALP, + }, + { + .name = "event-tap", + .mask = BIT(0), + .enable = BIT(0), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_TAP, + }, + { + .name = "event-hold", + .mask = BIT(1), + .enable = BIT(1), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, + { + .name = "event-swipe-x-neg", + .mask = BIT(2), + .enable = BIT(2), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_X, + }, + { + .name = "event-swipe-x-pos", + .mask = BIT(3), + .enable = BIT(3), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_X, + }, + { + .name = "event-swipe-y-pos", + .mask = BIT(4), + .enable = BIT(4), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + }, + { + .name = "event-swipe-y-neg", + .mask = BIT(5), + .enable = BIT(5), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + }, +}; + +static const struct iqs7211_event_desc iqs7211e_kp_events[] = { + { + .mask = BIT(14), + .reg_grp = IQS7211_REG_GRP_ALP, + }, + { + .name = "event-tap", + .mask = BIT(0), + .enable = BIT(0), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_TAP, + }, + { + .name = "event-tap-double", + .mask = BIT(1), + .enable = BIT(1), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_TAP, + }, + { + .name = "event-tap-triple", + .mask = BIT(2), + .enable = BIT(2), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_TAP, + }, + { + .name = "event-hold", + .mask = BIT(3), + .enable = BIT(3), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, + { + .name = "event-palm", + .mask = BIT(4), + .enable = BIT(4), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_PALM, + }, + { + .name = "event-swipe-x-pos", + .mask = BIT(8), + .enable = BIT(8), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_X, + }, + { + .name = "event-swipe-x-neg", + .mask = BIT(9), + .enable = BIT(9), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_X, + }, + { + .name = "event-swipe-y-pos", + .mask = BIT(10), + .enable = BIT(10), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + }, + { + .name = "event-swipe-y-neg", + .mask = BIT(11), + .enable = BIT(11), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + }, + { + .name = "event-swipe-x-pos-hold", + .mask = BIT(12), + .enable = BIT(12), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, + { + .name = "event-swipe-x-neg-hold", + .mask = BIT(13), + .enable = BIT(13), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, + { + .name = "event-swipe-y-pos-hold", + .mask = BIT(14), + .enable = BIT(14), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, + { + .name = "event-swipe-y-neg-hold", + .mask = BIT(15), + .enable = BIT(15), + .reg_grp = IQS7211_REG_GRP_TP, + .reg_key = IQS7211_REG_KEY_HOLD, + }, +}; + +struct iqs7211_dev_desc { + const char *tp_name; + const char *kp_name; + u16 prod_num; + u16 show_reset; + u16 ati_error[IQS7211_NUM_REG_GRPS]; + u16 ati_start[IQS7211_NUM_REG_GRPS]; + u16 suspend; + u16 ack_reset; + u16 comms_end; + u16 comms_req; + int charge_shift; + int info_offs; + int gesture_offs; + int contact_offs; + u8 sys_stat; + u8 sys_ctrl; + u8 alp_config; + u8 tp_config; + u8 exp_file; + u8 kp_enable[IQS7211_NUM_REG_GRPS]; + u8 gesture_angle; + u8 rx_tx_map; + u8 cycle_alloc[2]; + u8 cycle_limit[2]; + const struct iqs7211_event_desc *kp_events; + int num_kp_events; + int min_crx_alp; + int num_ctx; +}; + +static const struct iqs7211_dev_desc iqs7211_devs[] = { + [IQS7210A] = { + .tp_name = "iqs7210a_trackpad", + .kp_name = "iqs7210a_keys", + .prod_num = 944, + .show_reset = BIT(15), + .ati_error = { + [IQS7211_REG_GRP_TP] = BIT(12), + [IQS7211_REG_GRP_BTN] = BIT(0), + [IQS7211_REG_GRP_ALP] = BIT(8), + }, + .ati_start = { + [IQS7211_REG_GRP_TP] = BIT(13), + [IQS7211_REG_GRP_BTN] = BIT(1), + [IQS7211_REG_GRP_ALP] = BIT(9), + }, + .suspend = BIT(11), + .ack_reset = BIT(7), + .comms_end = BIT(2), + .comms_req = BIT(1), + .charge_shift = 4, + .info_offs = 0, + .gesture_offs = 1, + .contact_offs = 4, + .sys_stat = 0x0A, + .sys_ctrl = 0x35, + .alp_config = 0x39, + .tp_config = 0x4E, + .exp_file = 0x57, + .kp_enable = { + [IQS7211_REG_GRP_TP] = 0x58, + [IQS7211_REG_GRP_BTN] = 0x37, + [IQS7211_REG_GRP_ALP] = 0x37, + }, + .gesture_angle = 0x5F, + .rx_tx_map = 0x60, + .cycle_alloc = { 0x66, 0x75, }, + .cycle_limit = { 10, 6, }, + .kp_events = iqs7210a_kp_events, + .num_kp_events = ARRAY_SIZE(iqs7210a_kp_events), + .min_crx_alp = 4, + .num_ctx = IQS7211_MAX_CTX - 1, + }, + [IQS7211A] = { + .tp_name = "iqs7211a_trackpad", + .kp_name = "iqs7211a_keys", + .prod_num = 763, + .show_reset = BIT(7), + .ati_error = { + [IQS7211_REG_GRP_TP] = BIT(3), + [IQS7211_REG_GRP_ALP] = BIT(5), + }, + .ati_start = { + [IQS7211_REG_GRP_TP] = BIT(5), + [IQS7211_REG_GRP_ALP] = BIT(6), + }, + .ack_reset = BIT(7), + .comms_req = BIT(4), + .charge_shift = 0, + .info_offs = 0, + .gesture_offs = 1, + .contact_offs = 4, + .sys_stat = 0x10, + .sys_ctrl = 0x50, + .tp_config = 0x60, + .alp_config = 0x72, + .exp_file = 0x74, + .kp_enable = { + [IQS7211_REG_GRP_TP] = 0x80, + }, + .gesture_angle = 0x87, + .rx_tx_map = 0x90, + .cycle_alloc = { 0xA0, 0xB0, }, + .cycle_limit = { 10, 8, }, + .kp_events = iqs7211a_kp_events, + .num_kp_events = ARRAY_SIZE(iqs7211a_kp_events), + .num_ctx = IQS7211_MAX_CTX - 1, + }, + [IQS7211E] = { + .tp_name = "iqs7211e_trackpad", + .kp_name = "iqs7211e_keys", + .prod_num = 1112, + .show_reset = BIT(7), + .ati_error = { + [IQS7211_REG_GRP_TP] = BIT(3), + [IQS7211_REG_GRP_ALP] = BIT(5), + }, + .ati_start = { + [IQS7211_REG_GRP_TP] = BIT(5), + [IQS7211_REG_GRP_ALP] = BIT(6), + }, + .suspend = BIT(11), + .ack_reset = BIT(7), + .comms_end = BIT(6), + .comms_req = BIT(4), + .charge_shift = 0, + .info_offs = 1, + .gesture_offs = 0, + .contact_offs = 2, + .sys_stat = 0x0E, + .sys_ctrl = 0x33, + .tp_config = 0x41, + .alp_config = 0x36, + .exp_file = 0x4A, + .kp_enable = { + [IQS7211_REG_GRP_TP] = 0x4B, + }, + .gesture_angle = 0x55, + .rx_tx_map = 0x56, + .cycle_alloc = { 0x5D, 0x6C, }, + .cycle_limit = { 10, 11, }, + .kp_events = iqs7211e_kp_events, + .num_kp_events = ARRAY_SIZE(iqs7211e_kp_events), + .num_ctx = IQS7211_MAX_CTX, + }, +}; + +struct iqs7211_prop_desc { + const char *name; + enum iqs7211_reg_key_id reg_key; + u8 reg_addr[IQS7211_NUM_REG_GRPS][ARRAY_SIZE(iqs7211_devs)]; + int reg_shift; + int reg_width; + int val_pitch; + int val_min; + int val_max; + const char *label; +}; + +static const struct iqs7211_prop_desc iqs7211_props[] = { + { + .name = "azoteq,ati-frac-div-fine", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x1E, + [IQS7211A] = 0x30, + [IQS7211E] = 0x21, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x22, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x23, + [IQS7211A] = 0x36, + [IQS7211E] = 0x25, + }, + }, + .reg_shift = 9, + .reg_width = 5, + .label = "ATI fine fractional divider", + }, + { + .name = "azoteq,ati-frac-mult-coarse", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x1E, + [IQS7211A] = 0x30, + [IQS7211E] = 0x21, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x22, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x23, + [IQS7211A] = 0x36, + [IQS7211E] = 0x25, + }, + }, + .reg_shift = 5, + .reg_width = 4, + .label = "ATI coarse fractional multiplier", + }, + { + .name = "azoteq,ati-frac-div-coarse", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x1E, + [IQS7211A] = 0x30, + [IQS7211E] = 0x21, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x22, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x23, + [IQS7211A] = 0x36, + [IQS7211E] = 0x25, + }, + }, + .reg_shift = 0, + .reg_width = 5, + .label = "ATI coarse fractional divider", + }, + { + .name = "azoteq,ati-comp-div", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x1F, + [IQS7211E] = 0x22, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x24, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7211E] = 0x26, + }, + }, + .reg_shift = 0, + .reg_width = 8, + .val_max = 31, + .label = "ATI compensation divider", + }, + { + .name = "azoteq,ati-comp-div", + .reg_addr = { + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x24, + }, + }, + .reg_shift = 8, + .reg_width = 8, + .val_max = 31, + .label = "ATI compensation divider", + }, + { + .name = "azoteq,ati-comp-div", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7211A] = 0x31, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7211A] = 0x37, + }, + }, + .val_max = 31, + .label = "ATI compensation divider", + }, + { + .name = "azoteq,ati-target", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x20, + [IQS7211A] = 0x32, + [IQS7211E] = 0x23, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x27, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x28, + [IQS7211A] = 0x38, + [IQS7211E] = 0x27, + }, + }, + .label = "ATI target", + }, + { + .name = "azoteq,ati-base", + .reg_addr[IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x26, + }, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 8, + .label = "ATI base", + }, + { + .name = "azoteq,ati-base", + .reg_addr[IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x26, + }, + .reg_shift = 0, + .reg_width = 8, + .val_pitch = 8, + .label = "ATI base", + }, + { + .name = "azoteq,rate-active-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x29, + [IQS7211A] = 0x40, + [IQS7211E] = 0x28, + }, + .label = "active mode report rate", + }, + { + .name = "azoteq,rate-touch-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x2A, + [IQS7211A] = 0x41, + [IQS7211E] = 0x29, + }, + .label = "idle-touch mode report rate", + }, + { + .name = "azoteq,rate-idle-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x2B, + [IQS7211A] = 0x42, + [IQS7211E] = 0x2A, + }, + .label = "idle mode report rate", + }, + { + .name = "azoteq,rate-lp1-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x2C, + [IQS7211A] = 0x43, + [IQS7211E] = 0x2B, + }, + .label = "low-power mode 1 report rate", + }, + { + .name = "azoteq,rate-lp2-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x2D, + [IQS7211A] = 0x44, + [IQS7211E] = 0x2C, + }, + .label = "low-power mode 2 report rate", + }, + { + .name = "azoteq,timeout-active-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x2E, + [IQS7211A] = 0x45, + [IQS7211E] = 0x2D, + }, + .val_pitch = 1000, + .label = "active mode timeout", + }, + { + .name = "azoteq,timeout-touch-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x2F, + [IQS7211A] = 0x46, + [IQS7211E] = 0x2E, + }, + .val_pitch = 1000, + .label = "idle-touch mode timeout", + }, + { + .name = "azoteq,timeout-idle-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x30, + [IQS7211A] = 0x47, + [IQS7211E] = 0x2F, + }, + .val_pitch = 1000, + .label = "idle mode timeout", + }, + { + .name = "azoteq,timeout-lp1-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x31, + [IQS7211A] = 0x48, + [IQS7211E] = 0x30, + }, + .val_pitch = 1000, + .label = "low-power mode 1 timeout", + }, + { + .name = "azoteq,timeout-lp2-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x32, + [IQS7211E] = 0x31, + }, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 1000, + .val_max = 60000, + .label = "trackpad reference value update rate", + }, + { + .name = "azoteq,timeout-lp2-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7211A] = 0x49, + }, + .val_pitch = 1000, + .val_max = 60000, + .label = "trackpad reference value update rate", + }, + { + .name = "azoteq,timeout-ati-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x32, + [IQS7211E] = 0x31, + }, + .reg_width = 8, + .val_pitch = 1000, + .val_max = 60000, + .label = "ATI error timeout", + }, + { + .name = "azoteq,timeout-ati-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7211A] = 0x35, + }, + .val_pitch = 1000, + .val_max = 60000, + .label = "ATI error timeout", + }, + { + .name = "azoteq,timeout-comms-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x33, + [IQS7211A] = 0x4A, + [IQS7211E] = 0x32, + }, + .label = "communication timeout", + }, + { + .name = "azoteq,timeout-press-ms", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x34, + }, + .reg_width = 8, + .val_pitch = 1000, + .val_max = 60000, + .label = "press timeout", + }, + { + .name = "azoteq,ati-mode", + .reg_addr[IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x37, + }, + .reg_shift = 15, + .reg_width = 1, + .label = "ATI mode", + }, + { + .name = "azoteq,ati-mode", + .reg_addr[IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x37, + }, + .reg_shift = 7, + .reg_width = 1, + .label = "ATI mode", + }, + { + .name = "azoteq,sense-mode", + .reg_addr[IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x37, + [IQS7211A] = 0x72, + [IQS7211E] = 0x36, + }, + .reg_shift = 8, + .reg_width = 1, + .label = "sensing mode", + }, + { + .name = "azoteq,sense-mode", + .reg_addr[IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x37, + }, + .reg_shift = 0, + .reg_width = 2, + .val_max = 2, + .label = "sensing mode", + }, + { + .name = "azoteq,fosc-freq", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x38, + [IQS7211A] = 0x52, + [IQS7211E] = 0x35, + }, + .reg_shift = 4, + .reg_width = 1, + .label = "core clock frequency selection", + }, + { + .name = "azoteq,fosc-trim", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x38, + [IQS7211A] = 0x52, + [IQS7211E] = 0x35, + }, + .reg_shift = 0, + .reg_width = 4, + .label = "core clock frequency trim", + }, + { + .name = "azoteq,touch-exit", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x3B, + [IQS7211A] = 0x53, + [IQS7211E] = 0x38, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x3E, + }, + }, + .reg_shift = 8, + .reg_width = 8, + .label = "touch exit factor", + }, + { + .name = "azoteq,touch-enter", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x3B, + [IQS7211A] = 0x53, + [IQS7211E] = 0x38, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x3E, + }, + }, + .reg_shift = 0, + .reg_width = 8, + .label = "touch entrance factor", + }, + { + .name = "azoteq,thresh", + .reg_addr = { + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x3C, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x3D, + [IQS7211A] = 0x54, + [IQS7211E] = 0x39, + }, + }, + .label = "threshold", + }, + { + .name = "azoteq,debounce-exit", + .reg_addr = { + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x3F, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x40, + [IQS7211A] = 0x56, + [IQS7211E] = 0x3A, + }, + }, + .reg_shift = 8, + .reg_width = 8, + .label = "debounce exit factor", + }, + { + .name = "azoteq,debounce-enter", + .reg_addr = { + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x3F, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x40, + [IQS7211A] = 0x56, + [IQS7211E] = 0x3A, + }, + }, + .reg_shift = 0, + .reg_width = 8, + .label = "debounce entrance factor", + }, + { + .name = "azoteq,conv-frac", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x48, + [IQS7211A] = 0x58, + [IQS7211E] = 0x3D, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x49, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x4A, + [IQS7211A] = 0x59, + [IQS7211E] = 0x3E, + }, + }, + .reg_shift = 8, + .reg_width = 8, + .label = "conversion frequency fractional divider", + }, + { + .name = "azoteq,conv-period", + .reg_addr = { + [IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x48, + [IQS7211A] = 0x58, + [IQS7211E] = 0x3D, + }, + [IQS7211_REG_GRP_BTN] = { + [IQS7210A] = 0x49, + }, + [IQS7211_REG_GRP_ALP] = { + [IQS7210A] = 0x4A, + [IQS7211A] = 0x59, + [IQS7211E] = 0x3E, + }, + }, + .reg_shift = 0, + .reg_width = 8, + .label = "conversion period", + }, + { + .name = "azoteq,thresh", + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x55, + [IQS7211A] = 0x67, + [IQS7211E] = 0x48, + }, + .reg_shift = 0, + .reg_width = 8, + .label = "threshold", + }, + { + .name = "azoteq,contact-split", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x55, + [IQS7211A] = 0x67, + [IQS7211E] = 0x48, + }, + .reg_shift = 8, + .reg_width = 8, + .label = "contact split factor", + }, + { + .name = "azoteq,trim-x", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x56, + [IQS7211E] = 0x49, + }, + .reg_shift = 0, + .reg_width = 8, + .label = "horizontal trim width", + }, + { + .name = "azoteq,trim-x", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7211A] = 0x68, + }, + .label = "horizontal trim width", + }, + { + .name = "azoteq,trim-y", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7210A] = 0x56, + [IQS7211E] = 0x49, + }, + .reg_shift = 8, + .reg_width = 8, + .label = "vertical trim height", + }, + { + .name = "azoteq,trim-y", + .reg_addr[IQS7211_REG_GRP_SYS] = { + [IQS7211A] = 0x69, + }, + .label = "vertical trim height", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_key = IQS7211_REG_KEY_TAP, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x59, + [IQS7211A] = 0x81, + [IQS7211E] = 0x4C, + }, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-mid-ms", + .reg_key = IQS7211_REG_KEY_TAP, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7211E] = 0x4D, + }, + .label = "repeated gesture time", + }, + { + .name = "azoteq,gesture-dist", + .reg_key = IQS7211_REG_KEY_TAP, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5A, + [IQS7211A] = 0x82, + [IQS7211E] = 0x4E, + }, + .label = "gesture distance", + }, + { + .name = "azoteq,gesture-dist", + .reg_key = IQS7211_REG_KEY_HOLD, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5A, + [IQS7211A] = 0x82, + [IQS7211E] = 0x4E, + }, + .label = "gesture distance", + }, + { + .name = "azoteq,gesture-min-ms", + .reg_key = IQS7211_REG_KEY_HOLD, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5B, + [IQS7211A] = 0x83, + [IQS7211E] = 0x4F, + }, + .label = "minimum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_key = IQS7211_REG_KEY_AXIAL_X, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5C, + [IQS7211A] = 0x84, + [IQS7211E] = 0x50, + }, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5C, + [IQS7211A] = 0x84, + [IQS7211E] = 0x50, + }, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-dist", + .reg_key = IQS7211_REG_KEY_AXIAL_X, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5D, + [IQS7211A] = 0x85, + [IQS7211E] = 0x51, + }, + .label = "gesture distance", + }, + { + .name = "azoteq,gesture-dist", + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7210A] = 0x5E, + [IQS7211A] = 0x86, + [IQS7211E] = 0x52, + }, + .label = "gesture distance", + }, + { + .name = "azoteq,gesture-dist-rep", + .reg_key = IQS7211_REG_KEY_AXIAL_X, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7211E] = 0x53, + }, + .label = "repeated gesture distance", + }, + { + .name = "azoteq,gesture-dist-rep", + .reg_key = IQS7211_REG_KEY_AXIAL_Y, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7211E] = 0x54, + }, + .label = "repeated gesture distance", + }, + { + .name = "azoteq,thresh", + .reg_key = IQS7211_REG_KEY_PALM, + .reg_addr[IQS7211_REG_GRP_TP] = { + [IQS7211E] = 0x55, + }, + .reg_shift = 8, + .reg_width = 8, + .val_max = 42, + .label = "threshold", + }, +}; + +static const u8 iqs7211_gesture_angle[] = { + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, + 0x0E, 0x0F, 0x10, 0x11, + 0x12, 0x14, 0x15, 0x16, + 0x17, 0x19, 0x1A, 0x1B, + 0x1C, 0x1E, 0x1F, 0x21, + 0x22, 0x23, 0x25, 0x26, + 0x28, 0x2A, 0x2B, 0x2D, + 0x2E, 0x30, 0x32, 0x34, + 0x36, 0x38, 0x3A, 0x3C, + 0x3E, 0x40, 0x42, 0x45, + 0x47, 0x4A, 0x4C, 0x4F, + 0x52, 0x55, 0x58, 0x5B, + 0x5F, 0x63, 0x66, 0x6B, + 0x6F, 0x73, 0x78, 0x7E, + 0x83, 0x89, 0x90, 0x97, + 0x9E, 0xA7, 0xB0, 0xBA, + 0xC5, 0xD1, 0xDF, 0xEF, +}; + +struct iqs7211_ver_info { + __le16 prod_num; + __le16 major; + __le16 minor; + __le32 patch; +} __packed; + +struct iqs7211_touch_data { + __le16 abs_x; + __le16 abs_y; + __le16 pressure; + __le16 area; +} __packed; + +struct iqs7211_tp_config { + u8 tp_settings; + u8 total_rx; + u8 total_tx; + u8 num_contacts; + __le16 max_x; + __le16 max_y; +} __packed; + +struct iqs7211_private { + const struct iqs7211_dev_desc *dev_desc; + struct gpio_desc *reset_gpio; + struct gpio_desc *irq_gpio; + struct i2c_client *client; + struct input_dev *tp_idev; + struct input_dev *kp_idev; + struct iqs7211_ver_info ver_info; + struct iqs7211_tp_config tp_config; + struct touchscreen_properties prop; + struct list_head reg_field_head; + enum iqs7211_comms_mode comms_init; + enum iqs7211_comms_mode comms_mode; + unsigned int num_contacts; + unsigned int kp_code[ARRAY_SIZE(iqs7211e_kp_events)]; + u8 rx_tx_map[IQS7211_MAX_CTX + 1]; + u8 cycle_alloc[2][33]; + u8 exp_file[2]; + u16 event_mask; + u16 ati_start; + u16 gesture_cache; +}; + +static int iqs7211_irq_poll(struct iqs7211_private *iqs7211, u64 timeout_us) +{ + int error, val; + + error = readx_poll_timeout(gpiod_get_value_cansleep, iqs7211->irq_gpio, + val, val, IQS7211_COMMS_SLEEP_US, timeout_us); + + return val < 0 ? val : error; +} + +static int iqs7211_hard_reset(struct iqs7211_private *iqs7211) +{ + if (!iqs7211->reset_gpio) + return 0; + + gpiod_set_value_cansleep(iqs7211->reset_gpio, 1); + + /* + * The following delay ensures the shared RDY/MCLR pin is sampled in + * between periodic assertions by the device and assumes the default + * communication timeout has not been overwritten in OTP memory. + */ + if (iqs7211->reset_gpio == iqs7211->irq_gpio) + msleep(IQS7211_RESET_TIMEOUT_MS); + else + usleep_range(1000, 1100); + + gpiod_set_value_cansleep(iqs7211->reset_gpio, 0); + if (iqs7211->reset_gpio == iqs7211->irq_gpio) + iqs7211_irq_wait(); + + return iqs7211_irq_poll(iqs7211, IQS7211_START_TIMEOUT_US); +} + +static int iqs7211_force_comms(struct iqs7211_private *iqs7211) +{ + u8 msg_buf[] = { 0xFF, }; + int ret; + + switch (iqs7211->comms_mode) { + case IQS7211_COMMS_MODE_WAIT: + return iqs7211_irq_poll(iqs7211, IQS7211_START_TIMEOUT_US); + + case IQS7211_COMMS_MODE_FREE: + return 0; + + case IQS7211_COMMS_MODE_FORCE: + break; + + default: + return -EINVAL; + } + + /* + * The device cannot communicate until it asserts its interrupt (RDY) + * pin. Attempts to do so while RDY is deasserted return an ACK; how- + * ever all write data is ignored, and all read data returns 0xEE. + * + * Unsolicited communication must be preceded by a special force com- + * munication command, after which the device eventually asserts its + * RDY pin and agrees to communicate. + * + * Regardless of whether communication is forced or the result of an + * interrupt, the device automatically deasserts its RDY pin once it + * detects an I2C stop condition, or a timeout expires. + */ + ret = gpiod_get_value_cansleep(iqs7211->irq_gpio); + if (ret < 0) + return ret; + else if (ret > 0) + return 0; + + ret = i2c_master_send(iqs7211->client, msg_buf, sizeof(msg_buf)); + if (ret < (int)sizeof(msg_buf)) { + if (ret >= 0) + ret = -EIO; + + msleep(IQS7211_COMMS_RETRY_MS); + return ret; + } + + iqs7211_irq_wait(); + + return iqs7211_irq_poll(iqs7211, IQS7211_COMMS_TIMEOUT_US); +} + +static int iqs7211_read_burst(struct iqs7211_private *iqs7211, + u8 reg, void *val, u16 val_len) +{ + int ret, i; + struct i2c_client *client = iqs7211->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = sizeof(reg), + .buf = ®, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = val_len, + .buf = (u8 *)val, + }, + }; + + /* + * The following loop protects against an edge case in which the RDY + * pin is automatically deasserted just as the read is initiated. In + * that case, the read must be retried using forced communication. + */ + for (i = 0; i < IQS7211_NUM_RETRIES; i++) { + ret = iqs7211_force_comms(iqs7211); + if (ret < 0) + continue; + + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret < (int)ARRAY_SIZE(msg)) { + if (ret >= 0) + ret = -EIO; + + msleep(IQS7211_COMMS_RETRY_MS); + continue; + } + + if (get_unaligned_le16(msg[1].buf) == IQS7211_COMMS_ERROR) { + ret = -ENODATA; + continue; + } + + ret = 0; + break; + } + + iqs7211_irq_wait(); + + if (ret < 0) + dev_err(&client->dev, + "Failed to read from address 0x%02X: %d\n", reg, ret); + + return ret; +} + +static int iqs7211_read_word(struct iqs7211_private *iqs7211, u8 reg, u16 *val) +{ + __le16 val_buf; + int error; + + error = iqs7211_read_burst(iqs7211, reg, &val_buf, sizeof(val_buf)); + if (error) + return error; + + *val = le16_to_cpu(val_buf); + + return 0; +} + +static int iqs7211_write_burst(struct iqs7211_private *iqs7211, + u8 reg, const void *val, u16 val_len) +{ + int msg_len = sizeof(reg) + val_len; + int ret, i; + struct i2c_client *client = iqs7211->client; + u8 *msg_buf; + + msg_buf = kzalloc(msg_len, GFP_KERNEL); + if (!msg_buf) + return -ENOMEM; + + *msg_buf = reg; + memcpy(msg_buf + sizeof(reg), val, val_len); + + /* + * The following loop protects against an edge case in which the RDY + * pin is automatically asserted just before the force communication + * command is sent. + * + * In that case, the subsequent I2C stop condition tricks the device + * into preemptively deasserting the RDY pin and the command must be + * sent again. + */ + for (i = 0; i < IQS7211_NUM_RETRIES; i++) { + ret = iqs7211_force_comms(iqs7211); + if (ret < 0) + continue; + + ret = i2c_master_send(client, msg_buf, msg_len); + if (ret < msg_len) { + if (ret >= 0) + ret = -EIO; + + msleep(IQS7211_COMMS_RETRY_MS); + continue; + } + + ret = 0; + break; + } + + kfree(msg_buf); + + iqs7211_irq_wait(); + + if (ret < 0) + dev_err(&client->dev, + "Failed to write to address 0x%02X: %d\n", reg, ret); + + return ret; +} + +static int iqs7211_write_word(struct iqs7211_private *iqs7211, u8 reg, u16 val) +{ + __le16 val_buf = cpu_to_le16(val); + + return iqs7211_write_burst(iqs7211, reg, &val_buf, sizeof(val_buf)); +} + +static int iqs7211_start_comms(struct iqs7211_private *iqs7211) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct i2c_client *client = iqs7211->client; + bool forced_comms; + unsigned int val; + u16 comms_setup; + int error; + + /* + * Until forced communication can be enabled, the host must wait for a + * communication window each time it intends to elicit a response from + * the device. + * + * Forced communication is not necessary, however, if the host adapter + * can support clock stretching. In that case, the device freely clock + * stretches until all pending conversions are complete. + */ + forced_comms = device_property_present(&client->dev, + "azoteq,forced-comms"); + + error = device_property_read_u32(&client->dev, + "azoteq,forced-comms-default", &val); + if (error == -EINVAL) { + iqs7211->comms_init = IQS7211_COMMS_MODE_WAIT; + } else if (error) { + dev_err(&client->dev, + "Failed to read default communication mode: %d\n", + error); + return error; + } else if (val) { + iqs7211->comms_init = forced_comms ? IQS7211_COMMS_MODE_FORCE + : IQS7211_COMMS_MODE_WAIT; + } else { + iqs7211->comms_init = forced_comms ? IQS7211_COMMS_MODE_WAIT + : IQS7211_COMMS_MODE_FREE; + } + + iqs7211->comms_mode = iqs7211->comms_init; + + error = iqs7211_hard_reset(iqs7211); + if (error) { + dev_err(&client->dev, "Failed to reset device: %d\n", error); + return error; + } + + error = iqs7211_read_burst(iqs7211, IQS7211_PROD_NUM, + &iqs7211->ver_info, + sizeof(iqs7211->ver_info)); + if (error) + return error; + + if (le16_to_cpu(iqs7211->ver_info.prod_num) != dev_desc->prod_num) { + dev_err(&client->dev, "Invalid product number: %u\n", + le16_to_cpu(iqs7211->ver_info.prod_num)); + return -EINVAL; + } + + error = iqs7211_read_word(iqs7211, dev_desc->sys_ctrl + 1, + &comms_setup); + if (error) + return error; + + if (forced_comms) + comms_setup |= dev_desc->comms_req; + else + comms_setup &= ~dev_desc->comms_req; + + error = iqs7211_write_word(iqs7211, dev_desc->sys_ctrl + 1, + comms_setup | dev_desc->comms_end); + if (error) + return error; + + if (forced_comms) + iqs7211->comms_mode = IQS7211_COMMS_MODE_FORCE; + else + iqs7211->comms_mode = IQS7211_COMMS_MODE_FREE; + + error = iqs7211_read_burst(iqs7211, dev_desc->exp_file, + iqs7211->exp_file, + sizeof(iqs7211->exp_file)); + if (error) + return error; + + error = iqs7211_read_burst(iqs7211, dev_desc->tp_config, + &iqs7211->tp_config, + sizeof(iqs7211->tp_config)); + if (error) + return error; + + error = iqs7211_write_word(iqs7211, dev_desc->sys_ctrl + 1, + comms_setup); + if (error) + return error; + + iqs7211->event_mask = comms_setup & ~IQS7211_EVENT_MASK_ALL; + iqs7211->event_mask |= (IQS7211_EVENT_MASK_ATI | IQS7211_EVENT_MODE); + + return 0; +} + +static int iqs7211_init_device(struct iqs7211_private *iqs7211) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct iqs7211_reg_field_desc *reg_field; + __le16 sys_ctrl[] = { + cpu_to_le16(dev_desc->ack_reset), + cpu_to_le16(iqs7211->event_mask), + }; + int error, i; + + /* + * Acknowledge reset before writing any registers in case the device + * suffers a spurious reset during initialization. The communication + * mode is configured at this time as well. + */ + error = iqs7211_write_burst(iqs7211, dev_desc->sys_ctrl, sys_ctrl, + sizeof(sys_ctrl)); + if (error) + return error; + + if (iqs7211->event_mask & dev_desc->comms_req) + iqs7211->comms_mode = IQS7211_COMMS_MODE_FORCE; + else + iqs7211->comms_mode = IQS7211_COMMS_MODE_FREE; + + /* + * Take advantage of the stop-bit disable function, if available, to + * save the trouble of having to reopen a communication window after + * each read or write. + */ + error = iqs7211_write_word(iqs7211, dev_desc->sys_ctrl + 1, + iqs7211->event_mask | dev_desc->comms_end); + if (error) + return error; + + list_for_each_entry(reg_field, &iqs7211->reg_field_head, list) { + u16 new_val = reg_field->val; + + if (reg_field->mask < U16_MAX) { + u16 old_val; + + error = iqs7211_read_word(iqs7211, reg_field->addr, + &old_val); + if (error) + return error; + + new_val = old_val & ~reg_field->mask; + new_val |= reg_field->val; + + if (new_val == old_val) + continue; + } + + error = iqs7211_write_word(iqs7211, reg_field->addr, new_val); + if (error) + return error; + } + + error = iqs7211_write_burst(iqs7211, dev_desc->tp_config, + &iqs7211->tp_config, + sizeof(iqs7211->tp_config)); + if (error) + return error; + + if (**iqs7211->cycle_alloc) { + error = iqs7211_write_burst(iqs7211, dev_desc->rx_tx_map, + &iqs7211->rx_tx_map, + dev_desc->num_ctx); + if (error) + return error; + + for (i = 0; i < sizeof(dev_desc->cycle_limit); i++) { + error = iqs7211_write_burst(iqs7211, + dev_desc->cycle_alloc[i], + iqs7211->cycle_alloc[i], + dev_desc->cycle_limit[i] * 3); + if (error) + return error; + } + } + + *sys_ctrl = cpu_to_le16(iqs7211->ati_start); + + return iqs7211_write_burst(iqs7211, dev_desc->sys_ctrl, sys_ctrl, + sizeof(sys_ctrl)); +} + +static int iqs7211_add_field(struct iqs7211_private *iqs7211, + struct iqs7211_reg_field_desc new_field) +{ + struct i2c_client *client = iqs7211->client; + struct iqs7211_reg_field_desc *reg_field; + + if (!new_field.addr) + return 0; + + list_for_each_entry(reg_field, &iqs7211->reg_field_head, list) { + if (reg_field->addr != new_field.addr) + continue; + + reg_field->mask |= new_field.mask; + reg_field->val |= new_field.val; + return 0; + } + + reg_field = devm_kzalloc(&client->dev, sizeof(*reg_field), GFP_KERNEL); + if (!reg_field) + return -ENOMEM; + + reg_field->addr = new_field.addr; + reg_field->mask = new_field.mask; + reg_field->val = new_field.val; + + list_add(®_field->list, &iqs7211->reg_field_head); + + return 0; +} + +static int iqs7211_parse_props(struct iqs7211_private *iqs7211, + struct fwnode_handle *reg_grp_node, + enum iqs7211_reg_grp_id reg_grp, + enum iqs7211_reg_key_id reg_key) +{ + struct i2c_client *client = iqs7211->client; + int i; + + for (i = 0; i < ARRAY_SIZE(iqs7211_props); i++) { + const char *name = iqs7211_props[i].name; + u8 reg_addr = iqs7211_props[i].reg_addr[reg_grp] + [iqs7211->dev_desc - + iqs7211_devs]; + int reg_shift = iqs7211_props[i].reg_shift; + int reg_width = iqs7211_props[i].reg_width ? : 16; + int val_pitch = iqs7211_props[i].val_pitch ? : 1; + int val_min = iqs7211_props[i].val_min; + int val_max = iqs7211_props[i].val_max; + const char *label = iqs7211_props[i].label ? : name; + struct iqs7211_reg_field_desc reg_field; + unsigned int val; + int error; + + if (iqs7211_props[i].reg_key != reg_key) + continue; + + if (!reg_addr) + continue; + + error = fwnode_property_read_u32(reg_grp_node, name, &val); + if (error == -EINVAL) { + continue; + } else if (error) { + dev_err(&client->dev, "Failed to read %s %s: %d\n", + fwnode_get_name(reg_grp_node), label, error); + return error; + } + + if (!val_max) + val_max = GENMASK(reg_width - 1, 0) * val_pitch; + + if (val < val_min || val > val_max) { + dev_err(&client->dev, "Invalid %s: %u\n", label, val); + return -EINVAL; + } + + reg_field.addr = reg_addr; + reg_field.mask = GENMASK(reg_shift + reg_width - 1, reg_shift); + reg_field.val = val / val_pitch << reg_shift; + + error = iqs7211_add_field(iqs7211, reg_field); + if (error) + return error; + } + + return 0; +} + +static int iqs7211_parse_event(struct iqs7211_private *iqs7211, + struct fwnode_handle *event_node, + enum iqs7211_reg_grp_id reg_grp, + enum iqs7211_reg_key_id reg_key, + unsigned int *event_code) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct i2c_client *client = iqs7211->client; + struct iqs7211_reg_field_desc reg_field; + unsigned int val; + int error; + + error = iqs7211_parse_props(iqs7211, event_node, reg_grp, reg_key); + if (error) + return error; + + if (reg_key == IQS7211_REG_KEY_AXIAL_X || + reg_key == IQS7211_REG_KEY_AXIAL_Y) { + error = fwnode_property_read_u32(event_node, + "azoteq,gesture-angle", &val); + if (!error) { + if (val >= ARRAY_SIZE(iqs7211_gesture_angle)) { + dev_err(&client->dev, + "Invalid %s gesture angle: %u\n", + fwnode_get_name(event_node), val); + return -EINVAL; + } + + reg_field.addr = dev_desc->gesture_angle; + reg_field.mask = U8_MAX; + reg_field.val = iqs7211_gesture_angle[val]; + + error = iqs7211_add_field(iqs7211, reg_field); + if (error) + return error; + } else if (error != -EINVAL) { + dev_err(&client->dev, + "Failed to read %s gesture angle: %d\n", + fwnode_get_name(event_node), error); + return error; + } + } + + error = fwnode_property_read_u32(event_node, "linux,code", event_code); + if (error == -EINVAL) + error = 0; + else if (error) + dev_err(&client->dev, "Failed to read %s code: %d\n", + fwnode_get_name(event_node), error); + + return error; +} + +static int iqs7211_parse_cycles(struct iqs7211_private *iqs7211, + struct fwnode_handle *tp_node) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct i2c_client *client = iqs7211->client; + int num_cycles = dev_desc->cycle_limit[0] + dev_desc->cycle_limit[1]; + int error, count, i, j, k, cycle_start; + unsigned int cycle_alloc[IQS7211_MAX_CYCLES][2]; + u8 total_rx = iqs7211->tp_config.total_rx; + u8 total_tx = iqs7211->tp_config.total_tx; + + for (i = 0; i < IQS7211_MAX_CYCLES * 2; i++) + *(cycle_alloc[0] + i) = U8_MAX; + + count = fwnode_property_count_u32(tp_node, "azoteq,channel-select"); + if (count == -EINVAL) { + /* + * Assign each sensing cycle's slots (0 and 1) to a channel, + * defined as the intersection between two CRx and CTx pins. + * A channel assignment of 255 means the slot is unused. + */ + for (i = 0, cycle_start = 0; i < total_tx; i++) { + int cycle_stop = 0; + + for (j = 0; j < total_rx; j++) { + /* + * Channels formed by CRx0-3 and CRx4-7 are + * bound to slots 0 and 1, respectively. + */ + int slot = iqs7211->rx_tx_map[j] < 4 ? 0 : 1; + int chan = i * total_rx + j; + + for (k = cycle_start; k < num_cycles; k++) { + if (cycle_alloc[k][slot] < U8_MAX) + continue; + + cycle_alloc[k][slot] = chan; + break; + } + + if (k < num_cycles) { + cycle_stop = max(k, cycle_stop); + continue; + } + + dev_err(&client->dev, + "Insufficient number of cycles\n"); + return -EINVAL; + } + + /* + * Sensing cycles cannot straddle more than one CTx + * pin. As such, the next row's starting cycle must + * be greater than the previous row's highest cycle. + */ + cycle_start = cycle_stop + 1; + } + } else if (count < 0) { + dev_err(&client->dev, "Failed to count channels: %d\n", count); + return count; + } else if (count > num_cycles * 2) { + dev_err(&client->dev, "Insufficient number of cycles\n"); + return -EINVAL; + } else if (count > 0) { + error = fwnode_property_read_u32_array(tp_node, + "azoteq,channel-select", + cycle_alloc[0], count); + if (error) { + dev_err(&client->dev, "Failed to read channels: %d\n", + error); + return error; + } + + for (i = 0; i < count; i++) { + int chan = *(cycle_alloc[0] + i); + + if (chan == U8_MAX) + continue; + + if (chan >= total_rx * total_tx) { + dev_err(&client->dev, "Invalid channel: %d\n", + chan); + return -EINVAL; + } + + for (j = 0; j < count; j++) { + if (j == i || *(cycle_alloc[0] + j) != chan) + continue; + + dev_err(&client->dev, "Duplicate channel: %d\n", + chan); + return -EINVAL; + } + } + } + + /* + * Once the raw channel assignments have been derived, they must be + * packed according to the device's register map. + */ + for (i = 0, cycle_start = 0; i < sizeof(dev_desc->cycle_limit); i++) { + int offs = 0; + + for (j = cycle_start; + j < cycle_start + dev_desc->cycle_limit[i]; j++) { + iqs7211->cycle_alloc[i][offs++] = 0x05; + iqs7211->cycle_alloc[i][offs++] = cycle_alloc[j][0]; + iqs7211->cycle_alloc[i][offs++] = cycle_alloc[j][1]; + } + + cycle_start += dev_desc->cycle_limit[i]; + } + + return 0; +} + +static int iqs7211_parse_tp(struct iqs7211_private *iqs7211, + struct fwnode_handle *tp_node) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct i2c_client *client = iqs7211->client; + unsigned int pins[IQS7211_MAX_CTX]; + int error, count, i, j; + + count = fwnode_property_count_u32(tp_node, "azoteq,rx-enable"); + if (count == -EINVAL) { + return 0; + } else if (count < 0) { + dev_err(&client->dev, "Failed to count CRx pins: %d\n", count); + return count; + } else if (count > IQS7211_NUM_CRX) { + dev_err(&client->dev, "Invalid number of CRx pins\n"); + return -EINVAL; + } + + error = fwnode_property_read_u32_array(tp_node, "azoteq,rx-enable", + pins, count); + if (error) { + dev_err(&client->dev, "Failed to read CRx pins: %d\n", error); + return error; + } + + for (i = 0; i < count; i++) { + if (pins[i] >= IQS7211_NUM_CRX) { + dev_err(&client->dev, "Invalid CRx pin: %u\n", pins[i]); + return -EINVAL; + } + + iqs7211->rx_tx_map[i] = pins[i]; + } + + iqs7211->tp_config.total_rx = count; + + count = fwnode_property_count_u32(tp_node, "azoteq,tx-enable"); + if (count < 0) { + dev_err(&client->dev, "Failed to count CTx pins: %d\n", count); + return count; + } else if (count > dev_desc->num_ctx) { + dev_err(&client->dev, "Invalid number of CTx pins\n"); + return -EINVAL; + } + + error = fwnode_property_read_u32_array(tp_node, "azoteq,tx-enable", + pins, count); + if (error) { + dev_err(&client->dev, "Failed to read CTx pins: %d\n", error); + return error; + } + + for (i = 0; i < count; i++) { + if (pins[i] >= dev_desc->num_ctx) { + dev_err(&client->dev, "Invalid CTx pin: %u\n", pins[i]); + return -EINVAL; + } + + for (j = 0; j < iqs7211->tp_config.total_rx; j++) { + if (iqs7211->rx_tx_map[j] != pins[i]) + continue; + + dev_err(&client->dev, "Conflicting CTx pin: %u\n", + pins[i]); + return -EINVAL; + } + + iqs7211->rx_tx_map[iqs7211->tp_config.total_rx + i] = pins[i]; + } + + iqs7211->tp_config.total_tx = count; + + return iqs7211_parse_cycles(iqs7211, tp_node); +} + +static int iqs7211_parse_alp(struct iqs7211_private *iqs7211, + struct fwnode_handle *alp_node) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct i2c_client *client = iqs7211->client; + struct iqs7211_reg_field_desc reg_field; + int error, count, i; + + count = fwnode_property_count_u32(alp_node, "azoteq,rx-enable"); + if (count < 0 && count != -EINVAL) { + dev_err(&client->dev, "Failed to count CRx pins: %d\n", count); + return count; + } else if (count > IQS7211_NUM_CRX) { + dev_err(&client->dev, "Invalid number of CRx pins\n"); + return -EINVAL; + } else if (count >= 0) { + unsigned int pins[IQS7211_NUM_CRX]; + + error = fwnode_property_read_u32_array(alp_node, + "azoteq,rx-enable", + pins, count); + if (error) { + dev_err(&client->dev, "Failed to read CRx pins: %d\n", + error); + return error; + } + + reg_field.addr = dev_desc->alp_config; + reg_field.mask = GENMASK(IQS7211_NUM_CRX - 1, 0); + reg_field.val = 0; + + for (i = 0; i < count; i++) { + if (pins[i] < dev_desc->min_crx_alp || + pins[i] >= IQS7211_NUM_CRX) { + dev_err(&client->dev, "Invalid CRx pin: %u\n", + pins[i]); + return -EINVAL; + } + + reg_field.val |= BIT(pins[i]); + } + + error = iqs7211_add_field(iqs7211, reg_field); + if (error) + return error; + } + + count = fwnode_property_count_u32(alp_node, "azoteq,tx-enable"); + if (count < 0 && count != -EINVAL) { + dev_err(&client->dev, "Failed to count CTx pins: %d\n", count); + return count; + } else if (count > dev_desc->num_ctx) { + dev_err(&client->dev, "Invalid number of CTx pins\n"); + return -EINVAL; + } else if (count >= 0) { + unsigned int pins[IQS7211_MAX_CTX]; + + error = fwnode_property_read_u32_array(alp_node, + "azoteq,tx-enable", + pins, count); + if (error) { + dev_err(&client->dev, "Failed to read CTx pins: %d\n", + error); + return error; + } + + reg_field.addr = dev_desc->alp_config + 1; + reg_field.mask = GENMASK(dev_desc->num_ctx - 1, 0); + reg_field.val = 0; + + for (i = 0; i < count; i++) { + if (pins[i] >= dev_desc->num_ctx) { + dev_err(&client->dev, "Invalid CTx pin: %u\n", + pins[i]); + return -EINVAL; + } + + reg_field.val |= BIT(pins[i]); + } + + error = iqs7211_add_field(iqs7211, reg_field); + if (error) + return error; + } + + return 0; +} + +static int (*iqs7211_parse_extra[IQS7211_NUM_REG_GRPS]) + (struct iqs7211_private *iqs7211, + struct fwnode_handle *reg_grp_node) = { + [IQS7211_REG_GRP_TP] = iqs7211_parse_tp, + [IQS7211_REG_GRP_ALP] = iqs7211_parse_alp, +}; + +static int iqs7211_parse_reg_grp(struct iqs7211_private *iqs7211, + struct fwnode_handle *reg_grp_node, + enum iqs7211_reg_grp_id reg_grp) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct iqs7211_reg_field_desc reg_field; + int error, i; + + error = iqs7211_parse_props(iqs7211, reg_grp_node, reg_grp, + IQS7211_REG_KEY_NONE); + if (error) + return error; + + if (iqs7211_parse_extra[reg_grp]) { + error = iqs7211_parse_extra[reg_grp](iqs7211, reg_grp_node); + if (error) + return error; + } + + iqs7211->ati_start |= dev_desc->ati_start[reg_grp]; + + reg_field.addr = dev_desc->kp_enable[reg_grp]; + reg_field.mask = 0; + reg_field.val = 0; + + for (i = 0; i < dev_desc->num_kp_events; i++) { + const char *event_name = dev_desc->kp_events[i].name; + struct fwnode_handle *event_node; + + if (dev_desc->kp_events[i].reg_grp != reg_grp) + continue; + + reg_field.mask |= dev_desc->kp_events[i].enable; + + if (event_name) + event_node = fwnode_get_named_child_node(reg_grp_node, + event_name); + else + event_node = fwnode_handle_get(reg_grp_node); + + if (!event_node) + continue; + + error = iqs7211_parse_event(iqs7211, event_node, + dev_desc->kp_events[i].reg_grp, + dev_desc->kp_events[i].reg_key, + &iqs7211->kp_code[i]); + fwnode_handle_put(event_node); + if (error) + return error; + + reg_field.val |= dev_desc->kp_events[i].enable; + + iqs7211->event_mask |= iqs7211_reg_grp_masks[reg_grp]; + } + + return iqs7211_add_field(iqs7211, reg_field); +} + +static int iqs7211_register_kp(struct iqs7211_private *iqs7211) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct input_dev *kp_idev = iqs7211->kp_idev; + struct i2c_client *client = iqs7211->client; + int error, i; + + for (i = 0; i < dev_desc->num_kp_events; i++) + if (iqs7211->kp_code[i]) + break; + + if (i == dev_desc->num_kp_events) + return 0; + + kp_idev = devm_input_allocate_device(&client->dev); + if (!kp_idev) + return -ENOMEM; + + iqs7211->kp_idev = kp_idev; + + kp_idev->name = dev_desc->kp_name; + kp_idev->id.bustype = BUS_I2C; + + for (i = 0; i < dev_desc->num_kp_events; i++) + if (iqs7211->kp_code[i]) + input_set_capability(iqs7211->kp_idev, EV_KEY, + iqs7211->kp_code[i]); + + error = input_register_device(kp_idev); + if (error) + dev_err(&client->dev, "Failed to register %s: %d\n", + kp_idev->name, error); + + return error; +} + +static int iqs7211_register_tp(struct iqs7211_private *iqs7211) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct touchscreen_properties *prop = &iqs7211->prop; + struct input_dev *tp_idev = iqs7211->tp_idev; + struct i2c_client *client = iqs7211->client; + int error; + + error = device_property_read_u32(&client->dev, "azoteq,num-contacts", + &iqs7211->num_contacts); + if (error == -EINVAL) { + return 0; + } else if (error) { + dev_err(&client->dev, "Failed to read number of contacts: %d\n", + error); + return error; + } else if (iqs7211->num_contacts > IQS7211_MAX_CONTACTS) { + dev_err(&client->dev, "Invalid number of contacts: %u\n", + iqs7211->num_contacts); + return -EINVAL; + } + + iqs7211->tp_config.num_contacts = iqs7211->num_contacts ? : 1; + + if (!iqs7211->num_contacts) + return 0; + + iqs7211->event_mask |= IQS7211_EVENT_MASK_MOVE; + + tp_idev = devm_input_allocate_device(&client->dev); + if (!tp_idev) + return -ENOMEM; + + iqs7211->tp_idev = tp_idev; + + tp_idev->name = dev_desc->tp_name; + tp_idev->id.bustype = BUS_I2C; + + input_set_abs_params(tp_idev, ABS_MT_POSITION_X, + 0, le16_to_cpu(iqs7211->tp_config.max_x), 0, 0); + + input_set_abs_params(tp_idev, ABS_MT_POSITION_Y, + 0, le16_to_cpu(iqs7211->tp_config.max_y), 0, 0); + + input_set_abs_params(tp_idev, ABS_MT_PRESSURE, 0, U16_MAX, 0, 0); + + touchscreen_parse_properties(tp_idev, true, prop); + + /* + * The device reserves 0xFFFF for coordinates that correspond to slots + * which are not in a state of touch. + */ + if (prop->max_x >= U16_MAX || prop->max_y >= U16_MAX) { + dev_err(&client->dev, "Invalid trackpad size: %u*%u\n", + prop->max_x, prop->max_y); + return -EINVAL; + } + + iqs7211->tp_config.max_x = cpu_to_le16(prop->max_x); + iqs7211->tp_config.max_y = cpu_to_le16(prop->max_y); + + error = input_mt_init_slots(tp_idev, iqs7211->num_contacts, + INPUT_MT_DIRECT); + if (error) { + dev_err(&client->dev, "Failed to initialize slots: %d\n", + error); + return error; + } + + error = input_register_device(tp_idev); + if (error) + dev_err(&client->dev, "Failed to register %s: %d\n", + tp_idev->name, error); + + return error; +} + +static int iqs7211_report(struct iqs7211_private *iqs7211) +{ + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + struct i2c_client *client = iqs7211->client; + struct iqs7211_touch_data *touch_data; + u16 info_flags, charge_mode, gesture_flags; + __le16 status[12]; + int error, i; + + error = iqs7211_read_burst(iqs7211, dev_desc->sys_stat, status, + dev_desc->contact_offs * sizeof(__le16) + + iqs7211->num_contacts * sizeof(*touch_data)); + if (error) + return error; + + info_flags = le16_to_cpu(status[dev_desc->info_offs]); + + if (info_flags & dev_desc->show_reset) { + dev_err(&client->dev, "Unexpected device reset\n"); + + /* + * The device may or may not expect forced communication after + * it exits hardware reset, so the corresponding state machine + * must be reset as well. + */ + iqs7211->comms_mode = iqs7211->comms_init; + + return iqs7211_init_device(iqs7211); + } + + for (i = 0; i < ARRAY_SIZE(dev_desc->ati_error); i++) { + if (!(info_flags & dev_desc->ati_error[i])) + continue; + + dev_err(&client->dev, "Unexpected %s ATI error\n", + iqs7211_reg_grp_names[i]); + return 0; + } + + for (i = 0; i < iqs7211->num_contacts; i++) { + u16 pressure; + + touch_data = (struct iqs7211_touch_data *) + &status[dev_desc->contact_offs] + i; + pressure = le16_to_cpu(touch_data->pressure); + + input_mt_slot(iqs7211->tp_idev, i); + if (input_mt_report_slot_state(iqs7211->tp_idev, MT_TOOL_FINGER, + pressure != 0)) { + touchscreen_report_pos(iqs7211->tp_idev, &iqs7211->prop, + le16_to_cpu(touch_data->abs_x), + le16_to_cpu(touch_data->abs_y), + true); + input_report_abs(iqs7211->tp_idev, ABS_MT_PRESSURE, + pressure); + } + } + + if (iqs7211->num_contacts) { + input_mt_sync_frame(iqs7211->tp_idev); + input_sync(iqs7211->tp_idev); + } + + if (!iqs7211->kp_idev) + return 0; + + charge_mode = info_flags & GENMASK(dev_desc->charge_shift + 2, + dev_desc->charge_shift); + charge_mode >>= dev_desc->charge_shift; + + /* + * A charging mode higher than 2 (idle mode) indicates the device last + * operated in low-power mode and intends to express an ALP event. + */ + if (info_flags & dev_desc->kp_events->mask && charge_mode > 2) { + input_report_key(iqs7211->kp_idev, *iqs7211->kp_code, 1); + input_sync(iqs7211->kp_idev); + + input_report_key(iqs7211->kp_idev, *iqs7211->kp_code, 0); + } + + for (i = 0; i < dev_desc->num_kp_events; i++) { + if (dev_desc->kp_events[i].reg_grp != IQS7211_REG_GRP_BTN) + continue; + + input_report_key(iqs7211->kp_idev, iqs7211->kp_code[i], + info_flags & dev_desc->kp_events[i].mask); + } + + gesture_flags = le16_to_cpu(status[dev_desc->gesture_offs]); + + for (i = 0; i < dev_desc->num_kp_events; i++) { + enum iqs7211_reg_key_id reg_key = dev_desc->kp_events[i].reg_key; + u16 mask = dev_desc->kp_events[i].mask; + + if (dev_desc->kp_events[i].reg_grp != IQS7211_REG_GRP_TP) + continue; + + if ((gesture_flags ^ iqs7211->gesture_cache) & mask) + input_report_key(iqs7211->kp_idev, iqs7211->kp_code[i], + gesture_flags & mask); + + iqs7211->gesture_cache &= ~mask; + + /* + * Hold and palm gestures persist while the contact remains in + * place; all others are momentary and hence are followed by a + * complementary release event. + */ + if (reg_key == IQS7211_REG_KEY_HOLD || + reg_key == IQS7211_REG_KEY_PALM) { + iqs7211->gesture_cache |= gesture_flags & mask; + gesture_flags &= ~mask; + } + } + + if (gesture_flags) { + input_sync(iqs7211->kp_idev); + + for (i = 0; i < dev_desc->num_kp_events; i++) + if (dev_desc->kp_events[i].reg_grp == IQS7211_REG_GRP_TP && + gesture_flags & dev_desc->kp_events[i].mask) + input_report_key(iqs7211->kp_idev, + iqs7211->kp_code[i], 0); + } + + input_sync(iqs7211->kp_idev); + + return 0; +} + +static irqreturn_t iqs7211_irq(int irq, void *context) +{ + struct iqs7211_private *iqs7211 = context; + + return iqs7211_report(iqs7211) ? IRQ_NONE : IRQ_HANDLED; +} + +static int iqs7211_suspend(struct device *dev) +{ + struct iqs7211_private *iqs7211 = dev_get_drvdata(dev); + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + int error; + + if (!dev_desc->suspend || device_may_wakeup(dev)) + return 0; + + /* + * I2C communication prompts the device to assert its RDY pin if it is + * not already asserted. As such, the interrupt must be disabled so as + * to prevent reentrant interrupts. + */ + disable_irq(gpiod_to_irq(iqs7211->irq_gpio)); + + error = iqs7211_write_word(iqs7211, dev_desc->sys_ctrl, + dev_desc->suspend); + + enable_irq(gpiod_to_irq(iqs7211->irq_gpio)); + + return error; +} + +static int iqs7211_resume(struct device *dev) +{ + struct iqs7211_private *iqs7211 = dev_get_drvdata(dev); + const struct iqs7211_dev_desc *dev_desc = iqs7211->dev_desc; + __le16 sys_ctrl[] = { + 0, + cpu_to_le16(iqs7211->event_mask), + }; + int error; + + if (!dev_desc->suspend || device_may_wakeup(dev)) + return 0; + + disable_irq(gpiod_to_irq(iqs7211->irq_gpio)); + + /* + * Forced communication, if in use, must be explicitly enabled as part + * of the wake-up command. + */ + error = iqs7211_write_burst(iqs7211, dev_desc->sys_ctrl, sys_ctrl, + sizeof(sys_ctrl)); + + enable_irq(gpiod_to_irq(iqs7211->irq_gpio)); + + return error; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(iqs7211_pm, iqs7211_suspend, iqs7211_resume); + +static ssize_t fw_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs7211_private *iqs7211 = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u.%u.%u.%u:%u.%u\n", + le16_to_cpu(iqs7211->ver_info.prod_num), + le32_to_cpu(iqs7211->ver_info.patch), + le16_to_cpu(iqs7211->ver_info.major), + le16_to_cpu(iqs7211->ver_info.minor), + iqs7211->exp_file[1], iqs7211->exp_file[0]); +} + +static DEVICE_ATTR_RO(fw_info); + +static struct attribute *iqs7211_attrs[] = { + &dev_attr_fw_info.attr, + NULL +}; +ATTRIBUTE_GROUPS(iqs7211); + +static const struct of_device_id iqs7211_of_match[] = { + { + .compatible = "azoteq,iqs7210a", + .data = &iqs7211_devs[IQS7210A], + }, + { + .compatible = "azoteq,iqs7211a", + .data = &iqs7211_devs[IQS7211A], + }, + { + .compatible = "azoteq,iqs7211e", + .data = &iqs7211_devs[IQS7211E], + }, + { } +}; +MODULE_DEVICE_TABLE(of, iqs7211_of_match); + +static int iqs7211_probe(struct i2c_client *client) +{ + struct iqs7211_private *iqs7211; + enum iqs7211_reg_grp_id reg_grp; + unsigned long irq_flags; + bool shared_irq; + int error, irq; + + iqs7211 = devm_kzalloc(&client->dev, sizeof(*iqs7211), GFP_KERNEL); + if (!iqs7211) + return -ENOMEM; + + i2c_set_clientdata(client, iqs7211); + iqs7211->client = client; + + INIT_LIST_HEAD(&iqs7211->reg_field_head); + + iqs7211->dev_desc = device_get_match_data(&client->dev); + if (!iqs7211->dev_desc) + return -ENODEV; + + shared_irq = iqs7211->dev_desc->num_ctx == IQS7211_MAX_CTX; + + /* + * The RDY pin behaves as an interrupt, but must also be polled ahead + * of unsolicited I2C communication. As such, it is first opened as a + * GPIO and then passed to gpiod_to_irq() to register the interrupt. + * + * If an extra CTx pin is present, the RDY and MCLR pins are combined + * into a single bidirectional pin. In that case, the platform's GPIO + * must be configured as an open-drain output. + */ + iqs7211->irq_gpio = devm_gpiod_get(&client->dev, "irq", + shared_irq ? GPIOD_OUT_LOW + : GPIOD_IN); + if (IS_ERR(iqs7211->irq_gpio)) { + error = PTR_ERR(iqs7211->irq_gpio); + dev_err(&client->dev, "Failed to request IRQ GPIO: %d\n", + error); + return error; + } + + if (shared_irq) { + iqs7211->reset_gpio = iqs7211->irq_gpio; + } else { + iqs7211->reset_gpio = devm_gpiod_get_optional(&client->dev, + "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(iqs7211->reset_gpio)) { + error = PTR_ERR(iqs7211->reset_gpio); + dev_err(&client->dev, + "Failed to request reset GPIO: %d\n", error); + return error; + } + } + + error = iqs7211_start_comms(iqs7211); + if (error) + return error; + + for (reg_grp = 0; reg_grp < IQS7211_NUM_REG_GRPS; reg_grp++) { + const char *reg_grp_name = iqs7211_reg_grp_names[reg_grp]; + struct fwnode_handle *reg_grp_node; + + if (reg_grp_name) + 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) + continue; + + error = iqs7211_parse_reg_grp(iqs7211, reg_grp_node, reg_grp); + fwnode_handle_put(reg_grp_node); + if (error) + return error; + } + + error = iqs7211_register_kp(iqs7211); + if (error) + return error; + + error = iqs7211_register_tp(iqs7211); + if (error) + return error; + + error = iqs7211_init_device(iqs7211); + if (error) + return error; + + irq = gpiod_to_irq(iqs7211->irq_gpio); + if (irq < 0) + return irq; + + irq_flags = gpiod_is_active_low(iqs7211->irq_gpio) ? IRQF_TRIGGER_LOW + : IRQF_TRIGGER_HIGH; + irq_flags |= IRQF_ONESHOT; + + error = devm_request_threaded_irq(&client->dev, irq, NULL, iqs7211_irq, + irq_flags, client->name, iqs7211); + if (error) + dev_err(&client->dev, "Failed to request IRQ: %d\n", error); + + return error; +} + +static struct i2c_driver iqs7211_i2c_driver = { + .probe = iqs7211_probe, + .driver = { + .name = "iqs7211", + .of_match_table = iqs7211_of_match, + .dev_groups = iqs7211_groups, + .pm = pm_sleep_ptr(&iqs7211_pm), + }, +}; +module_i2c_driver(iqs7211_i2c_driver); + +MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>"); +MODULE_DESCRIPTION("Azoteq IQS7210A/7211A/E Trackpad/Touchscreen Controller"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index 15b5cb763526..9bad8b93c039 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -198,54 +198,36 @@ static void lpc32xx_ts_close(struct input_dev *dev) static int lpc32xx_ts_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct lpc32xx_tsc *tsc; struct input_dev *input; - struct resource *res; - resource_size_t size; int irq; int error; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Can't get memory resource\n"); - return -ENOENT; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - tsc = kzalloc(sizeof(*tsc), GFP_KERNEL); - input = input_allocate_device(); - if (!tsc || !input) { - dev_err(&pdev->dev, "failed allocating memory\n"); - error = -ENOMEM; - goto err_free_mem; - } + tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL); + if (!tsc) + return -ENOMEM; - tsc->dev = input; tsc->irq = irq; - size = resource_size(res); - - if (!request_mem_region(res->start, size, pdev->name)) { - dev_err(&pdev->dev, "TSC registers are not free\n"); - error = -EBUSY; - goto err_free_mem; - } + tsc->tsc_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(tsc->tsc_base)) + return PTR_ERR(tsc->tsc_base); - tsc->tsc_base = ioremap(res->start, size); - if (!tsc->tsc_base) { - dev_err(&pdev->dev, "Can't map memory\n"); - error = -ENOMEM; - goto err_release_mem; - } - - tsc->clk = clk_get(&pdev->dev, NULL); + tsc->clk = devm_clk_get(dev, NULL); if (IS_ERR(tsc->clk)) { dev_err(&pdev->dev, "failed getting clock\n"); - error = PTR_ERR(tsc->clk); - goto err_unmap; + return PTR_ERR(tsc->clk); + } + + input = devm_input_allocate_device(dev); + if (!input) { + dev_err(&pdev->dev, "failed allocating input device\n"); + return -ENOMEM; } input->name = MOD_NAME; @@ -254,68 +236,33 @@ static int lpc32xx_ts_probe(struct platform_device *pdev) input->id.vendor = 0x0001; input->id.product = 0x0002; input->id.version = 0x0100; - input->dev.parent = &pdev->dev; input->open = lpc32xx_ts_open; input->close = lpc32xx_ts_close; - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_capability(input, EV_KEY, BTN_TOUCH); input_set_abs_params(input, ABS_X, LPC32XX_TSC_MIN_XY_VAL, LPC32XX_TSC_MAX_XY_VAL, 0, 0); input_set_abs_params(input, ABS_Y, LPC32XX_TSC_MIN_XY_VAL, LPC32XX_TSC_MAX_XY_VAL, 0, 0); input_set_drvdata(input, tsc); + tsc->dev = input; - error = request_irq(tsc->irq, lpc32xx_ts_interrupt, - 0, pdev->name, tsc); + error = devm_request_irq(dev, tsc->irq, lpc32xx_ts_interrupt, + 0, pdev->name, tsc); if (error) { dev_err(&pdev->dev, "failed requesting interrupt\n"); - goto err_put_clock; + return error; } error = input_register_device(input); if (error) { dev_err(&pdev->dev, "failed registering input device\n"); - goto err_free_irq; + return error; } platform_set_drvdata(pdev, tsc); - device_init_wakeup(&pdev->dev, 1); - - return 0; - -err_free_irq: - free_irq(tsc->irq, tsc); -err_put_clock: - clk_put(tsc->clk); -err_unmap: - iounmap(tsc->tsc_base); -err_release_mem: - release_mem_region(res->start, size); -err_free_mem: - input_free_device(input); - kfree(tsc); - - return error; -} - -static int lpc32xx_ts_remove(struct platform_device *pdev) -{ - struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev); - struct resource *res; - - free_irq(tsc->irq, tsc); - - input_unregister_device(tsc->dev); - - clk_put(tsc->clk); - - iounmap(tsc->tsc_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - kfree(tsc); + device_init_wakeup(&pdev->dev, true); return 0; } @@ -384,7 +331,6 @@ MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); static struct platform_driver lpc32xx_ts_driver = { .probe = lpc32xx_ts_probe, - .remove = lpc32xx_ts_remove, .driver = { .name = MOD_NAME, .pm = LPC32XX_TS_PM_OPS, diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 32896e5085bd..2ac4483fbc25 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -1451,13 +1451,8 @@ static int mip4_probe(struct i2c_client *client) ts->gpio_ce = devm_gpiod_get_optional(&client->dev, "ce", GPIOD_OUT_LOW); - if (IS_ERR(ts->gpio_ce)) { - error = PTR_ERR(ts->gpio_ce); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get gpio: %d\n", error); - return error; - } + if (IS_ERR(ts->gpio_ce)) + return dev_err_probe(&client->dev, PTR_ERR(ts->gpio_ce), "Failed to get gpio\n"); error = mip4_power_on(ts); if (error) diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index ac12494c7930..af233b6a16d9 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -7,7 +7,6 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/i2c.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> @@ -43,6 +42,7 @@ /* Touchscreen absolute values */ #define MMS114_MAX_AREA 0xff +#define MMS114_MAX_TOUCHKEYS 15 #define MMS114_MAX_TOUCH 10 #define MMS114_EVENT_SIZE 8 #define MMS136_EVENT_SIZE 6 @@ -70,6 +70,9 @@ struct mms114_data { unsigned int contact_threshold; unsigned int moving_threshold; + u32 keycodes[MMS114_MAX_TOUCHKEYS]; + int num_keycodes; + /* Use cache data for mode control register(write only) */ u8 cache_mode_control; }; @@ -167,11 +170,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou return; } - if (touch->type != MMS114_TYPE_TOUCHSCREEN) { - dev_err(&client->dev, "Wrong touch type (%d)\n", touch->type); - return; - } - id = touch->id - 1; x = touch->x_lo | touch->x_hi << 8; y = touch->y_lo | touch->y_hi << 8; @@ -191,9 +189,33 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou } } +static void mms114_process_touchkey(struct mms114_data *data, + struct mms114_touch *touch) +{ + struct i2c_client *client = data->client; + struct input_dev *input_dev = data->input_dev; + unsigned int keycode_id; + + if (touch->id == 0) + return; + + if (touch->id > data->num_keycodes) { + dev_err(&client->dev, "Wrong touch id for touchkey (%d)\n", + touch->id); + return; + } + + keycode_id = touch->id - 1; + dev_dbg(&client->dev, "keycode id: %d, pressed: %d\n", keycode_id, + touch->pressed); + + input_report_key(input_dev, data->keycodes[keycode_id], touch->pressed); +} + static irqreturn_t mms114_interrupt(int irq, void *dev_id) { struct mms114_data *data = dev_id; + struct i2c_client *client = data->client; struct input_dev *input_dev = data->input_dev; struct mms114_touch touch[MMS114_MAX_TOUCH]; int packet_size; @@ -223,8 +245,22 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id) if (error < 0) goto out; - for (index = 0; index < touch_size; index++) - mms114_process_mt(data, touch + index); + for (index = 0; index < touch_size; index++) { + switch (touch[index].type) { + case MMS114_TYPE_TOUCHSCREEN: + mms114_process_mt(data, touch + index); + break; + + case MMS114_TYPE_TOUCHKEY: + mms114_process_touchkey(data, touch + index); + break; + + default: + dev_err(&client->dev, "Wrong touch type (%d)\n", + touch[index].type); + break; + } + } input_mt_report_pointer_emulation(data->input_dev, true); input_sync(data->input_dev); @@ -446,6 +482,7 @@ static int mms114_probe(struct i2c_client *client) struct input_dev *input_dev; const void *match_data; int error; + int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "Not supported I2C adapter\n"); @@ -469,6 +506,42 @@ static int mms114_probe(struct i2c_client *client) data->type = (enum mms_type)match_data; + data->num_keycodes = device_property_count_u32(&client->dev, + "linux,keycodes"); + if (data->num_keycodes == -EINVAL) { + data->num_keycodes = 0; + } else if (data->num_keycodes < 0) { + dev_err(&client->dev, + "Unable to parse linux,keycodes property: %d\n", + data->num_keycodes); + return data->num_keycodes; + } else if (data->num_keycodes > MMS114_MAX_TOUCHKEYS) { + dev_warn(&client->dev, + "Found %d linux,keycodes but max is %d, ignoring the rest\n", + data->num_keycodes, MMS114_MAX_TOUCHKEYS); + data->num_keycodes = MMS114_MAX_TOUCHKEYS; + } + + if (data->num_keycodes > 0) { + error = device_property_read_u32_array(&client->dev, + "linux,keycodes", + data->keycodes, + data->num_keycodes); + if (error) { + dev_err(&client->dev, + "Unable to read linux,keycodes values: %d\n", + error); + return error; + } + + input_dev->keycode = data->keycodes; + input_dev->keycodemax = data->num_keycodes; + input_dev->keycodesize = sizeof(data->keycodes[0]); + for (i = 0; i < data->num_keycodes; i++) + input_set_capability(input_dev, + EV_KEY, data->keycodes[i]); + } + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0); diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c index 7f7d879aac6d..1a797e410a3f 100644 --- a/drivers/input/touchscreen/novatek-nvt-ts.c +++ b/drivers/input/touchscreen/novatek-nvt-ts.c @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Driver for Novatek i2c touchscreen controller as found on - * the Acer Iconia One 7 B1-750 tablet. The Touchscreen controller - * model-number is unknown. Android calls this a "NVT-ts" touchscreen, - * but that may apply to other Novatek controller models too. + * Driver for Novatek NT11205 i2c touchscreen controller as found + * on the Acer Iconia One 7 B1-750 tablet. * * Copyright (c) 2023 Hans de Goede <hdegoede@redhat.com> */ @@ -272,7 +270,7 @@ static int nvt_ts_probe(struct i2c_client *client) error = input_register_device(input); if (error) { - dev_err(dev, "failed to request irq: %d\n", error); + dev_err(dev, "failed to register input device: %d\n", error); return error; } @@ -296,6 +294,6 @@ static struct i2c_driver nvt_ts_driver = { module_i2c_driver(nvt_ts_driver); -MODULE_DESCRIPTION("Novatek NVT-ts touchscreen driver"); +MODULE_DESCRIPTION("Novatek NT11205 touchscreen driver"); MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 554e179c2e48..4ede0687beb0 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -13,8 +13,8 @@ #include <linux/input/mt.h> #include <linux/input/touchscreen.h> #include <linux/interrupt.h> -#include <linux/of_device.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/slab.h> #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ @@ -515,41 +515,27 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client) input_set_drvdata(input, tsdata); tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN); - if (IS_ERR(tsdata->gpio_attb)) { - error = PTR_ERR(tsdata->gpio_attb); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to request ATTB gpio: %d\n", - error); - return error; - } + if (IS_ERR(tsdata->gpio_attb)) + return dev_err_probe(dev, PTR_ERR(tsdata->gpio_attb), + "Failed to request ATTB gpio\n"); tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(tsdata->gpio_reset)) { - error = PTR_ERR(tsdata->gpio_reset); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to request RESET gpio: %d\n", - error); - return error; - } + if (IS_ERR(tsdata->gpio_reset)) + return dev_err_probe(dev, PTR_ERR(tsdata->gpio_reset), + "Failed to request RESET gpio\n"); tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake", GPIOD_OUT_HIGH); - if (IS_ERR(tsdata->gpio_wake)) { - error = PTR_ERR(tsdata->gpio_wake); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get wake gpio: %d\n", error); - return error; - } + if (IS_ERR(tsdata->gpio_wake)) + return dev_err_probe(dev, PTR_ERR(tsdata->gpio_wake), + "Failed to get wake gpio\n"); tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); - if (IS_ERR(tsdata->gpio_enable)) { - error = PTR_ERR(tsdata->gpio_enable); - if (error != -EPROBE_DEFER) - dev_err(dev, "Failed to get enable gpio: %d\n", error); - return error; - } + if (IS_ERR(tsdata->gpio_enable)) + return dev_err_probe(dev, PTR_ERR(tsdata->gpio_enable), + "Failed to get enable gpio\n"); if (tsdata->gpio_enable) msleep(100); diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 76e7d62d5870..78dd3059d585 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -1087,32 +1087,20 @@ static int raydium_i2c_probe(struct i2c_client *client) i2c_set_clientdata(client, ts); ts->avdd = devm_regulator_get(&client->dev, "avdd"); - if (IS_ERR(ts->avdd)) { - error = PTR_ERR(ts->avdd); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get 'avdd' regulator: %d\n", error); - return error; - } + if (IS_ERR(ts->avdd)) + return dev_err_probe(&client->dev, PTR_ERR(ts->avdd), + "Failed to get 'avdd' regulator\n"); ts->vccio = devm_regulator_get(&client->dev, "vccio"); - if (IS_ERR(ts->vccio)) { - error = PTR_ERR(ts->vccio); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get 'vccio' regulator: %d\n", error); - return error; - } + if (IS_ERR(ts->vccio)) + return dev_err_probe(&client->dev, PTR_ERR(ts->vccio), + "Failed to get 'vccio' regulator\n"); ts->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(ts->reset_gpio)) { - error = PTR_ERR(ts->reset_gpio); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "failed to get reset gpio: %d\n", error); - return error; - } + if (IS_ERR(ts->reset_gpio)) + return dev_err_probe(&client->dev, PTR_ERR(ts->reset_gpio), + "Failed to get reset gpio\n"); error = raydium_i2c_power_on(ts); if (error) diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index 6f754a8d30b1..7e761ec73273 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -210,12 +210,8 @@ static int grts_probe(struct platform_device *pdev) /* get the channels from IIO device */ st->iio_chans = devm_iio_channel_get_all(dev); - if (IS_ERR(st->iio_chans)) { - error = PTR_ERR(st->iio_chans); - if (error != -EPROBE_DEFER) - dev_err(dev, "can't get iio channels.\n"); - return error; - } + if (IS_ERR(st->iio_chans)) + return dev_err_probe(dev, PTR_ERR(st->iio_chans), "can't get iio channels\n"); if (!device_property_present(dev, "io-channel-names")) return -ENODEV; diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index 9e28f962e059..62f562ad5026 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c @@ -706,11 +706,9 @@ static int silead_ts_probe(struct i2c_client *client) /* Power GPIO pin */ data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); - if (IS_ERR(data->gpio_power)) { - if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER) - dev_err(dev, "Shutdown GPIO request failed\n"); - return PTR_ERR(data->gpio_power); - } + if (IS_ERR(data->gpio_power)) + return dev_err_probe(dev, PTR_ERR(data->gpio_power), + "Shutdown GPIO request failed\n"); error = silead_ts_setup(client); if (error) diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c index 426564d0fc39..ed56cb546f39 100644 --- a/drivers/input/touchscreen/sis_i2c.c +++ b/drivers/input/touchscreen/sis_i2c.c @@ -310,23 +310,15 @@ static int sis_ts_probe(struct i2c_client *client) ts->attn_gpio = devm_gpiod_get_optional(&client->dev, "attn", GPIOD_IN); - if (IS_ERR(ts->attn_gpio)) { - error = PTR_ERR(ts->attn_gpio); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get attention GPIO: %d\n", error); - return error; - } + if (IS_ERR(ts->attn_gpio)) + return dev_err_probe(&client->dev, PTR_ERR(ts->attn_gpio), + "Failed to get attention GPIO\n"); ts->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(ts->reset_gpio)) { - error = PTR_ERR(ts->reset_gpio); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, - "Failed to get reset GPIO: %d\n", error); - return error; - } + if (IS_ERR(ts->reset_gpio)) + return dev_err_probe(&client->dev, PTR_ERR(ts->reset_gpio), + "Failed to get reset GPIO\n"); sis_ts_reset(ts); diff --git a/drivers/input/touchscreen/surface3_spi.c b/drivers/input/touchscreen/surface3_spi.c index 31d140248f2e..7efbcd0fde4f 100644 --- a/drivers/input/touchscreen/surface3_spi.c +++ b/drivers/input/touchscreen/surface3_spi.c @@ -221,7 +221,6 @@ static void surface3_spi_power(struct surface3_ts_data *data, bool on) */ static int surface3_spi_get_gpio_config(struct surface3_ts_data *data) { - int error; struct device *dev; struct gpio_desc *gpiod; int i; @@ -231,15 +230,9 @@ static int surface3_spi_get_gpio_config(struct surface3_ts_data *data) /* Get the reset lines GPIO pin number */ for (i = 0; i < 2; i++) { gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_OUT_LOW); - if (IS_ERR(gpiod)) { - error = PTR_ERR(gpiod); - if (error != -EPROBE_DEFER) - dev_err(dev, - "Failed to get power GPIO %d: %d\n", - i, - error); - return error; - } + if (IS_ERR(gpiod)) + return dev_err_probe(dev, PTR_ERR(gpiod), + "Failed to get power GPIO %d\n", i); data->gpiod_rst[i] = gpiod; } diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c index 0293c493bc79..f5c5881cef6b 100644 --- a/drivers/input/touchscreen/sx8654.c +++ b/drivers/input/touchscreen/sx8654.c @@ -323,13 +323,9 @@ static int sx8654_probe(struct i2c_client *client) sx8654->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(sx8654->gpio_reset)) { - error = PTR_ERR(sx8654->gpio_reset); - if (error != -EPROBE_DEFER) - dev_err(&client->dev, "unable to get reset-gpio: %d\n", - error); - return error; - } + if (IS_ERR(sx8654->gpio_reset)) + return dev_err_probe(&client->dev, PTR_ERR(sx8654->gpio_reset), + "unable to get reset-gpio\n"); dev_dbg(&client->dev, "got GPIO reset pin\n"); sx8654->data = device_get_match_data(&client->dev); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index decf2d24a115..9aa4e35fb4f5 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -25,7 +25,6 @@ #include <linux/io.h> #include <linux/delay.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/sort.h> #include <linux/pm_wakeirq.h> |