diff options
Diffstat (limited to 'drivers/input/misc')
-rw-r--r-- | drivers/input/misc/Kconfig | 23 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/misc/adxl34x-i2c.c | 21 | ||||
-rw-r--r-- | drivers/input/misc/ati_remote2.c | 4 | ||||
-rw-r--r-- | drivers/input/misc/axp20x-pek.c | 9 | ||||
-rw-r--r-- | drivers/input/misc/da9063_onkey.c | 226 | ||||
-rw-r--r-- | drivers/input/misc/drv260x.c | 13 | ||||
-rw-r--r-- | drivers/input/misc/drv2665.c | 322 | ||||
-rw-r--r-- | drivers/input/misc/gpio-beeper.c | 7 | ||||
-rw-r--r-- | drivers/input/misc/retu-pwrbutton.c | 3 | ||||
-rw-r--r-- | drivers/input/misc/soc_button_array.c | 1 | ||||
-rw-r--r-- | drivers/input/misc/twl4030-pwrbutton.c | 3 | ||||
-rw-r--r-- | drivers/input/misc/twl4030-vibra.c | 3 | ||||
-rw-r--r-- | drivers/input/misc/twl6040-vibra.c | 3 | ||||
-rw-r--r-- | drivers/input/misc/wm831x-on.c | 3 |
15 files changed, 617 insertions, 26 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 4436ab1b9..d4f0a817e 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -610,6 +610,16 @@ config INPUT_DA9055_ONKEY To compile this driver as a module, choose M here: the module will be called da9055_onkey. +config INPUT_DA9063_ONKEY + tristate "Dialog DA9063 OnKey" + depends on MFD_DA9063 + help + Support the ONKEY of Dialog DA9063 Power Management IC as an + input device reporting power button statue. + + To compile this driver as a module, choose M here: the module + will be called da9063_onkey. + config INPUT_DM355EVM tristate "TI DaVinci DM355 EVM Keypad and IR Remote" depends on MFD_DM355EVM_MSP @@ -775,6 +785,17 @@ config INPUT_DRV260X_HAPTICS To compile this driver as a module, choose M here: the module will be called drv260x-haptics. +config INPUT_DRV2665_HAPTICS + tristate "TI DRV2665 haptics support" + depends on INPUT && I2C + select INPUT_FF_MEMLESS + select REGMAP_I2C + help + Say Y to enable support for the TI DRV2665 haptics driver. + + To compile this driver as a module, choose M here: the + module will be called drv2665-haptics. + config INPUT_DRV2667_HAPTICS tristate "TI DRV2667 haptics support" depends on INPUT && I2C @@ -784,6 +805,6 @@ config INPUT_DRV2667_HAPTICS Say Y to enable support for the TI DRV2667 haptics driver. To compile this driver as a module, choose M here: the - module will be called drv260x-haptics. + module will be called drv2667-haptics. endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 78ba4c1b8..53df07dcc 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -25,9 +25,11 @@ obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o +obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_INPUT_E3X0_BUTTON) += e3x0-button.o obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o +obj-$(CONFIG_INPUT_DRV2665_HAPTICS) += drv2665.o obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 470bfd6f0..bdb5d03b2 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -10,6 +10,7 @@ #include <linux/input.h> /* BUS_I2C */ #include <linux/i2c.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/types.h> #include <linux/pm.h> #include "adxl34x.h" @@ -135,11 +136,31 @@ static const struct i2c_device_id adxl34x_id[] = { MODULE_DEVICE_TABLE(i2c, adxl34x_id); +#ifdef CONFIG_OF +static const struct of_device_id adxl34x_of_id[] = { + /* + * The ADXL346 is backward-compatible with the ADXL345. Differences are + * handled by runtime detection of the device model, there's thus no + * need for listing the "adi,adxl346" compatible value explicitly. + */ + { .compatible = "adi,adxl345", }, + /* + * Deprecated, DT nodes should use one or more of the device-specific + * compatible values "adi,adxl345" and "adi,adxl346". + */ + { .compatible = "adi,adxl34x", }, + { } +}; + +MODULE_DEVICE_TABLE(of, adxl34x_of_id); +#endif + static struct i2c_driver adxl34x_driver = { .driver = { .name = "adxl34x", .owner = THIS_MODULE, .pm = &adxl34x_i2c_pm, + .of_match_table = of_match_ptr(adxl34x_of_id), }, .probe = adxl34x_i2c_probe, .remove = adxl34x_i2c_remove, diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index f63341f20..cfd58e87d 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -94,7 +94,7 @@ static int ati_remote2_get_mode_mask(char *buffer, static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) -static struct kernel_param_ops param_ops_channel_mask = { +static const struct kernel_param_ops param_ops_channel_mask = { .set = ati_remote2_set_channel_mask, .get = ati_remote2_get_channel_mask, }; @@ -103,7 +103,7 @@ MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...< static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) -static struct kernel_param_ops param_ops_mode_mask = { +static const struct kernel_param_ops param_ops_mode_mask = { .set = ati_remote2_set_mode_mask, .get = ati_remote2_get_mode_mask, }; diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index f1c844739..1ac898db3 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -167,9 +167,13 @@ static irqreturn_t axp20x_pek_irq(int irq, void *pwr) struct input_dev *idev = pwr; struct axp20x_pek *axp20x_pek = input_get_drvdata(idev); - if (irq == axp20x_pek->irq_dbr) + /* + * The power-button is connected to ground so a falling edge (dbf) + * means it is pressed. + */ + if (irq == axp20x_pek->irq_dbf) input_report_key(idev, KEY_POWER, true); - else if (irq == axp20x_pek->irq_dbf) + else if (irq == axp20x_pek->irq_dbr) input_report_key(idev, KEY_POWER, false); input_sync(idev); @@ -288,3 +292,4 @@ module_platform_driver(axp20x_pek_driver); MODULE_DESCRIPTION("axp20x Power Button"); MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:axp20x-pek"); diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c new file mode 100644 index 000000000..f577585ef --- /dev/null +++ b/drivers/input/misc/da9063_onkey.c @@ -0,0 +1,226 @@ +/* + * OnKey device driver for DA9063 + * Copyright (C) 2015 Dialog Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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> +#include <linux/errno.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> +#include <linux/regmap.h> +#include <linux/of.h> +#include <linux/mfd/da9063/core.h> +#include <linux/mfd/da9063/pdata.h> +#include <linux/mfd/da9063/registers.h> + +struct da9063_onkey { + struct da9063 *hw; + struct delayed_work work; + struct input_dev *input; + struct device *dev; + bool key_power; +}; + +static void da9063_poll_on(struct work_struct *work) +{ + struct da9063_onkey *onkey = container_of(work, struct da9063_onkey, + work.work); + unsigned int val; + int fault_log = 0; + bool poll = true; + int error; + + /* Poll to see when the pin is released */ + error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); + if (error) { + dev_err(onkey->dev, + "Failed to read ON status: %d\n", error); + goto err_poll; + } + + if (!(val & DA9063_NONKEY)) { + error = regmap_update_bits(onkey->hw->regmap, + DA9063_REG_CONTROL_B, + DA9063_NONKEY_LOCK, 0); + if (error) { + dev_err(onkey->dev, + "Failed to reset the Key Delay %d\n", error); + goto err_poll; + } + + input_report_key(onkey->input, KEY_POWER, 0); + input_sync(onkey->input); + + poll = false; + } + + /* + * If the fault log KEY_RESET is detected, then clear it + * and shut down the system. + */ + error = regmap_read(onkey->hw->regmap, + DA9063_REG_FAULT_LOG, &fault_log); + if (error) { + dev_warn(&onkey->input->dev, + "Cannot read FAULT_LOG: %d\n", error); + } else if (fault_log & DA9063_KEY_RESET) { + error = regmap_write(onkey->hw->regmap, + DA9063_REG_FAULT_LOG, + DA9063_KEY_RESET); + if (error) { + dev_warn(&onkey->input->dev, + "Cannot reset KEY_RESET fault log: %d\n", + error); + } else { + /* at this point we do any S/W housekeeping + * and then send shutdown command + */ + dev_dbg(&onkey->input->dev, + "Sending SHUTDOWN to DA9063 ...\n"); + error = regmap_write(onkey->hw->regmap, + DA9063_REG_CONTROL_F, + DA9063_SHUTDOWN); + if (error) + dev_err(&onkey->input->dev, + "Cannot SHUTDOWN DA9063: %d\n", + error); + } + } + +err_poll: + if (poll) + schedule_delayed_work(&onkey->work, msecs_to_jiffies(50)); +} + +static irqreturn_t da9063_onkey_irq_handler(int irq, void *data) +{ + struct da9063_onkey *onkey = data; + unsigned int val; + int error; + + error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); + if (onkey->key_power && !error && (val & DA9063_NONKEY)) { + input_report_key(onkey->input, KEY_POWER, 1); + input_sync(onkey->input); + schedule_delayed_work(&onkey->work, 0); + dev_dbg(onkey->dev, "KEY_POWER pressed.\n"); + } else { + input_report_key(onkey->input, KEY_SLEEP, 1); + input_sync(onkey->input); + input_report_key(onkey->input, KEY_SLEEP, 0); + input_sync(onkey->input); + dev_dbg(onkey->dev, "KEY_SLEEP pressed.\n"); + } + + return IRQ_HANDLED; +} + +static void da9063_cancel_poll(void *data) +{ + struct da9063_onkey *onkey = data; + + cancel_delayed_work_sync(&onkey->work); +} + +static int da9063_onkey_probe(struct platform_device *pdev) +{ + struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); + struct da9063_pdata *pdata = dev_get_platdata(da9063->dev); + struct da9063_onkey *onkey; + int irq; + int error; + + onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey), + GFP_KERNEL); + if (!onkey) { + dev_err(&pdev->dev, "Failed to allocate memory.\n"); + return -ENOMEM; + } + + onkey->dev = &pdev->dev; + onkey->hw = da9063; + + if (pdata) + onkey->key_power = pdata->key_power; + else + onkey->key_power = + !of_property_read_bool(pdev->dev.of_node, + "dlg,disable-key-power"); + + onkey->input = devm_input_allocate_device(&pdev->dev); + if (!onkey->input) { + dev_err(&pdev->dev, "Failed to allocated input device.\n"); + return -ENOMEM; + } + + onkey->input->name = DA9063_DRVNAME_ONKEY; + onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0"; + onkey->input->dev.parent = &pdev->dev; + + if (onkey->key_power) + input_set_capability(onkey->input, EV_KEY, KEY_POWER); + + input_set_capability(onkey->input, EV_KEY, KEY_SLEEP); + + INIT_DELAYED_WORK(&onkey->work, da9063_poll_on); + + error = devm_add_action(&pdev->dev, da9063_cancel_poll, onkey); + if (error) { + dev_err(&pdev->dev, + "Failed to add cancel poll action: %d\n", + error); + return error; + } + + irq = platform_get_irq_byname(pdev, "ONKEY"); + if (irq < 0) { + error = irq; + dev_err(&pdev->dev, "Failed to get platform IRQ: %d\n", error); + return error; + } + + error = devm_request_threaded_irq(&pdev->dev, irq, + NULL, da9063_onkey_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "ONKEY", onkey); + if (error) { + dev_err(&pdev->dev, + "Failed to request IRQ %d: %d\n", irq, error); + return error; + } + + error = input_register_device(onkey->input); + if (error) { + dev_err(&pdev->dev, + "Failed to register input device: %d\n", error); + return error; + } + + platform_set_drvdata(pdev, onkey); + return 0; +} + +static struct platform_driver da9063_onkey_driver = { + .probe = da9063_onkey_probe, + .driver = { + .name = DA9063_DRVNAME_ONKEY, + }, +}; +module_platform_driver(da9063_onkey_driver); + +MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); +MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY); diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 599578042..e5d60ecd2 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -580,15 +580,10 @@ static int drv260x_probe(struct i2c_client *client, return error; } - haptics->enable_gpio = devm_gpiod_get(&client->dev, "enable"); - if (IS_ERR(haptics->enable_gpio)) { - error = PTR_ERR(haptics->enable_gpio); - if (error != -ENOENT && error != -ENOSYS) - return error; - haptics->enable_gpio = NULL; - } else { - gpiod_direction_output(haptics->enable_gpio, 1); - } + haptics->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", + GPIOD_OUT_HIGH); + if (IS_ERR(haptics->enable_gpio)) + return PTR_ERR(haptics->enable_gpio); haptics->input_dev = devm_input_allocate_device(&client->dev); if (!haptics->input_dev) { diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c new file mode 100644 index 000000000..0afaa33de --- /dev/null +++ b/drivers/input/misc/drv2665.c @@ -0,0 +1,322 @@ +/* + * DRV2665 haptics driver family + * + * Author: Dan Murphy <dmurphy@ti.com> + * + * Copyright: (C) 2015 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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/i2c.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/regulator/consumer.h> + +/* Contol registers */ +#define DRV2665_STATUS 0x00 +#define DRV2665_CTRL_1 0x01 +#define DRV2665_CTRL_2 0x02 +#define DRV2665_FIFO 0x0b + +/* Status Register */ +#define DRV2665_FIFO_FULL BIT(0) +#define DRV2665_FIFO_EMPTY BIT(1) + +/* Control 1 Register */ +#define DRV2665_25_VPP_GAIN 0x00 +#define DRV2665_50_VPP_GAIN 0x01 +#define DRV2665_75_VPP_GAIN 0x02 +#define DRV2665_100_VPP_GAIN 0x03 +#define DRV2665_DIGITAL_IN 0xfc +#define DRV2665_ANALOG_IN BIT(2) + +/* Control 2 Register */ +#define DRV2665_BOOST_EN BIT(1) +#define DRV2665_STANDBY BIT(6) +#define DRV2665_DEV_RST BIT(7) +#define DRV2665_5_MS_IDLE_TOUT 0x00 +#define DRV2665_10_MS_IDLE_TOUT 0x04 +#define DRV2665_15_MS_IDLE_TOUT 0x08 +#define DRV2665_20_MS_IDLE_TOUT 0x0c + +/** + * struct drv2665_data - + * @input_dev - Pointer to the input device + * @client - Pointer to the I2C client + * @regmap - Register map of the device + * @work - Work item used to off load the enable/disable of the vibration + * @regulator - Pointer to the regulator for the IC + */ +struct drv2665_data { + struct input_dev *input_dev; + struct i2c_client *client; + struct regmap *regmap; + struct work_struct work; + struct regulator *regulator; +}; + +/* 8kHz Sine wave to stream to the FIFO */ +static const u8 drv2665_sine_wave_form[] = { + 0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66, + 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10, + 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a, + 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00, +}; + +static struct reg_default drv2665_reg_defs[] = { + { DRV2665_STATUS, 0x02 }, + { DRV2665_CTRL_1, 0x28 }, + { DRV2665_CTRL_2, 0x40 }, + { DRV2665_FIFO, 0x00 }, +}; + +static void drv2665_worker(struct work_struct *work) +{ + struct drv2665_data *haptics = + container_of(work, struct drv2665_data, work); + unsigned int read_buf; + int error; + + error = regmap_read(haptics->regmap, DRV2665_STATUS, &read_buf); + if (error) { + dev_err(&haptics->client->dev, + "Failed to read status: %d\n", error); + return; + } + + if (read_buf & DRV2665_FIFO_EMPTY) { + error = regmap_bulk_write(haptics->regmap, + DRV2665_FIFO, + drv2665_sine_wave_form, + ARRAY_SIZE(drv2665_sine_wave_form)); + if (error) { + dev_err(&haptics->client->dev, + "Failed to write FIFO: %d\n", error); + return; + } + } +} + +static int drv2665_haptics_play(struct input_dev *input, void *data, + struct ff_effect *effect) +{ + struct drv2665_data *haptics = input_get_drvdata(input); + + schedule_work(&haptics->work); + + return 0; +} + +static void drv2665_close(struct input_dev *input) +{ + struct drv2665_data *haptics = input_get_drvdata(input); + int error; + + cancel_work_sync(&haptics->work); + + error = regmap_update_bits(haptics->regmap, + DRV2665_CTRL_2, DRV2665_STANDBY, 1); + if (error) + dev_err(&haptics->client->dev, + "Failed to enter standby mode: %d\n", error); +} + +static const struct reg_default drv2665_init_regs[] = { + { DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT }, + { DRV2665_CTRL_1, DRV2665_25_VPP_GAIN }, +}; + +static int drv2665_init(struct drv2665_data *haptics) +{ + int error; + + error = regmap_register_patch(haptics->regmap, + drv2665_init_regs, + ARRAY_SIZE(drv2665_init_regs)); + if (error) { + dev_err(&haptics->client->dev, + "Failed to write init registers: %d\n", + error); + return error; + } + + return 0; +} + +static const struct regmap_config drv2665_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = DRV2665_FIFO, + .reg_defaults = drv2665_reg_defs, + .num_reg_defaults = ARRAY_SIZE(drv2665_reg_defs), + .cache_type = REGCACHE_NONE, +}; + +static int drv2665_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct drv2665_data *haptics; + int error; + + haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL); + if (!haptics) + return -ENOMEM; + + haptics->regulator = devm_regulator_get(&client->dev, "vbat"); + if (IS_ERR(haptics->regulator)) { + error = PTR_ERR(haptics->regulator); + dev_err(&client->dev, + "unable to get regulator, error: %d\n", error); + return error; + } + + haptics->input_dev = devm_input_allocate_device(&client->dev); + if (!haptics->input_dev) { + dev_err(&client->dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + haptics->input_dev->name = "drv2665:haptics"; + haptics->input_dev->dev.parent = client->dev.parent; + haptics->input_dev->close = drv2665_close; + input_set_drvdata(haptics->input_dev, haptics); + input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE); + + error = input_ff_create_memless(haptics->input_dev, NULL, + drv2665_haptics_play); + if (error) { + dev_err(&client->dev, "input_ff_create() failed: %d\n", + error); + return error; + } + + INIT_WORK(&haptics->work, drv2665_worker); + + haptics->client = client; + i2c_set_clientdata(client, haptics); + + haptics->regmap = devm_regmap_init_i2c(client, &drv2665_regmap_config); + if (IS_ERR(haptics->regmap)) { + error = PTR_ERR(haptics->regmap); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + error); + return error; + } + + error = drv2665_init(haptics); + if (error) { + dev_err(&client->dev, "Device init failed: %d\n", error); + return error; + } + + error = input_register_device(haptics->input_dev); + if (error) { + dev_err(&client->dev, "couldn't register input device: %d\n", + error); + return error; + } + + return 0; +} + +static int __maybe_unused drv2665_suspend(struct device *dev) +{ + struct drv2665_data *haptics = dev_get_drvdata(dev); + int ret = 0; + + mutex_lock(&haptics->input_dev->mutex); + + if (haptics->input_dev->users) { + ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, + DRV2665_STANDBY, 1); + if (ret) { + dev_err(dev, "Failed to set standby mode\n"); + regulator_disable(haptics->regulator); + goto out; + } + + ret = regulator_disable(haptics->regulator); + if (ret) { + dev_err(dev, "Failed to disable regulator\n"); + regmap_update_bits(haptics->regmap, + DRV2665_CTRL_2, + DRV2665_STANDBY, 0); + } + } +out: + mutex_unlock(&haptics->input_dev->mutex); + return ret; +} + +static int __maybe_unused drv2665_resume(struct device *dev) +{ + struct drv2665_data *haptics = dev_get_drvdata(dev); + int ret = 0; + + mutex_lock(&haptics->input_dev->mutex); + + if (haptics->input_dev->users) { + ret = regulator_enable(haptics->regulator); + if (ret) { + dev_err(dev, "Failed to enable regulator\n"); + goto out; + } + + ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, + DRV2665_STANDBY, 0); + if (ret) { + dev_err(dev, "Failed to unset standby mode\n"); + regulator_disable(haptics->regulator); + goto out; + } + + } + +out: + mutex_unlock(&haptics->input_dev->mutex); + return ret; +} + +static SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume); + +static const struct i2c_device_id drv2665_id[] = { + { "drv2665", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, drv2665_id); + +#ifdef CONFIG_OF +static const struct of_device_id drv2665_of_match[] = { + { .compatible = "ti,drv2665", }, + { } +}; +MODULE_DEVICE_TABLE(of, drv2665_of_match); +#endif + +static struct i2c_driver drv2665_driver = { + .probe = drv2665_probe, + .driver = { + .name = "drv2665-haptics", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(drv2665_of_match), + .pm = &drv2665_pm_ops, + }, + .id_table = drv2665_id, +}; +module_i2c_driver(drv2665_driver); + +MODULE_DESCRIPTION("TI DRV2665 haptics driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c index 4817c5f0c..16272fffe 100644 --- a/drivers/input/misc/gpio-beeper.c +++ b/drivers/input/misc/gpio-beeper.c @@ -66,13 +66,12 @@ static int gpio_beeper_probe(struct platform_device *pdev) { struct gpio_beeper *beep; struct input_dev *input; - int err; beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); if (!beep) return -ENOMEM; - beep->desc = devm_gpiod_get(&pdev->dev, NULL); + beep->desc = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW); if (IS_ERR(beep->desc)) return PTR_ERR(beep->desc); @@ -92,10 +91,6 @@ static int gpio_beeper_probe(struct platform_device *pdev) input_set_capability(input, EV_SND, SND_BELL); - err = gpiod_direction_output(beep->desc, 0); - if (err) - return err; - input_set_drvdata(input, beep); return input_register_device(input); diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c index 0c8ac60e2..30b459b6b 100644 --- a/drivers/input/misc/retu-pwrbutton.c +++ b/drivers/input/misc/retu-pwrbutton.c @@ -63,7 +63,8 @@ static int retu_pwrbutton_probe(struct platform_device *pdev) input_set_drvdata(idev, rdev); error = devm_request_threaded_irq(&pdev->dev, irq, - NULL, retu_pwrbutton_irq, 0, + NULL, retu_pwrbutton_irq, + IRQF_ONESHOT, "retu-pwrbutton", idev); if (error) return error; diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index e8e010a85..c14b82709 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -18,7 +18,6 @@ #include <linux/gpio/consumer.h> #include <linux/gpio_keys.h> #include <linux/platform_device.h> -#include <linux/acpi.h> /* * Definition of buttons on the tablet. The ACPI index of each button diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index e98cc81a8..603fc2fad 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -71,7 +71,8 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) pwr->dev.parent = &pdev->dev; err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT, "twl4030_pwrbutton", pwr); if (err < 0) { dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index fc17b9592..10c4e3d46 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -183,7 +183,8 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, if (pdata && pdata->coexist) return true; - if (of_find_node_by_name(node, "codec")) { + node = of_find_node_by_name(node, "codec"); + if (node) { of_node_put(node); return true; } diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 0e0d094df..ea63fad48 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -308,7 +308,8 @@ static int twl6040_vibra_probe(struct platform_device *pdev) mutex_init(&info->mutex); error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, - twl6040_vib_irq_handler, 0, + twl6040_vib_irq_handler, + IRQF_ONESHOT, "twl6040_irq_vib", info); if (error) { dev_err(info->dev, "VIB IRQ request failed: %d\n", error); diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index 59d4f7bcb..1b44de265 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -99,7 +99,8 @@ static int wm831x_on_probe(struct platform_device *pdev) wm831x_on->dev->dev.parent = &pdev->dev; ret = request_threaded_irq(irq, NULL, wm831x_on_irq, - IRQF_TRIGGER_RISING, "wm831x_on", + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "wm831x_on", wm831x_on); if (ret < 0) { dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); |