diff options
33 files changed, 1207 insertions, 367 deletions
diff --git a/Documentation/devicetree/bindings/input/cypress,tm2-touchkey.txt b/Documentation/devicetree/bindings/input/cypress,tm2-touchkey.txt index 0c252d9306da..ef2ae729718f 100644 --- a/Documentation/devicetree/bindings/input/cypress,tm2-touchkey.txt +++ b/Documentation/devicetree/bindings/input/cypress,tm2-touchkey.txt @@ -1,13 +1,19 @@ Samsung tm2-touchkey Required properties: -- compatible: must be "cypress,tm2-touchkey" +- compatible: + * "cypress,tm2-touchkey" - for the touchkey found on the tm2 board + * "cypress,midas-touchkey" - for the touchkey found on midas boards + * "cypress,aries-touchkey" - for the touchkey found on aries boards - reg: I2C address of the chip. - interrupts: interrupt to which the chip is connected (see interrupt binding[0]). - vcc-supply : internal regulator output. 1.8V - vdd-supply : power supply for IC 3.3V +Optional properties: +- linux,keycodes: array of keycodes (max 4), default KEY_PHONE and KEY_BACK + [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt Example: @@ -21,5 +27,6 @@ Example: interrupts = <2 IRQ_TYPE_EDGE_FALLING>; vcc-supply=<&ldo32_reg>; vdd-supply=<&ldo33_reg>; + linux,keycodes = <KEY_PHONE KEY_BACK>; }; }; diff --git a/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt new file mode 100644 index 000000000000..b2a76301e632 --- /dev/null +++ b/Documentation/devicetree/bindings/input/ilitek,ili2xxx.txt @@ -0,0 +1,25 @@ +Ilitek ILI210x/ILI251x touchscreen controller + +Required properties: +- compatible: + ilitek,ili210x for ILI210x + ilitek,ili251x for ILI251x + +- reg: The I2C address of the device + +- interrupts: The sink for the touchscreen's IRQ output + See ../interrupt-controller/interrupts.txt + +Optional properties for main touchpad device: + +- reset-gpios: GPIO specifier for the touchscreen's reset pin (active low) + +Example: + + touchscreen@41 { + compatible = "ilitek,ili251x"; + reg = <0x41>; + interrupt-parent = <&gpio4>; + interrupts = <7 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>; + }; diff --git a/Documentation/devicetree/bindings/input/msm-vibrator.txt b/Documentation/devicetree/bindings/input/msm-vibrator.txt new file mode 100644 index 000000000000..8dcf014ef2e5 --- /dev/null +++ b/Documentation/devicetree/bindings/input/msm-vibrator.txt @@ -0,0 +1,36 @@ +* Device tree bindings for the Qualcomm MSM vibrator + +Required properties: + + - compatible: Should be one of + "qcom,msm8226-vibrator" + "qcom,msm8974-vibrator" + - reg: the base address and length of the IO memory for the registers. + - pinctrl-names: set to default. + - pinctrl-0: phandles pointing to pin configuration nodes. See + Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt + - clock-names: set to pwm + - clocks: phandle of the clock. See + Documentation/devicetree/bindings/clock/clock-bindings.txt + - enable-gpios: GPIO that enables the vibrator. + +Optional properties: + + - vcc-supply: phandle to the regulator that provides power to the sensor. + +Example from a LG Nexus 5 (hammerhead) phone: + +vibrator@fd8c3450 { + reg = <0xfd8c3450 0x400>; + compatible = "qcom,msm8974-vibrator"; + + vcc-supply = <&pm8941_l19>; + + clocks = <&mmcc CAMSS_GP1_CLK>; + clock-names = "pwm"; + + enable-gpios = <&msmgpio 60 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default"; + pinctrl-0 = <&vibrator_pin>; +}; diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index da2dc5d6c98b..870b8c5cce9b 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -1,11 +1,12 @@ FocalTech EDT-FT5x06 Polytouch driver ===================================== -There are 3 variants of the chip for various touch panel sizes +There are 5 variants of the chip for various touch panel sizes FT5206GE1 2.8" .. 3.8" FT5306DE4 4.3" .. 7" FT5406EE8 7" .. 8.9" FT5506EEG 7" .. 8.9" +FT5726NEI 5.7” .. 11.6" The software interface is identical for all those chips, so that currently there is no need for the driver to distinguish between the @@ -19,6 +20,7 @@ Required properties: or: "edt,edt-ft5306" or: "edt,edt-ft5406" or: "edt,edt-ft5506" + or: "evervision,ev-ft5726" or: "focaltech,ft6236" - reg: I2C slave address of the chip (0x38) @@ -42,6 +44,15 @@ Optional properties: - offset: allows setting the edge compensation in the range from 0 to 31. + + - offset-x: Same as offset, but applies only to the horizontal position. + Range from 0 to 80, only supported by evervision,ev-ft5726 + devices. + + - offset-y: Same as offset, but applies only to the vertical position. + Range from 0 to 80, only supported by evervision,ev-ft5726 + devices. + - touchscreen-size-x : See touchscreen.txt - touchscreen-size-y : See touchscreen.txt - touchscreen-fuzz-x : See touchscreen.txt diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt index f7e95c52f3c7..8cf0b4d38a7e 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt @@ -3,6 +3,7 @@ Device tree bindings for Goodix GT9xx series touchscreen controller Required properties: - compatible : Should be "goodix,gt1151" + or "goodix,gt5688" or "goodix,gt911" or "goodix,gt9110" or "goodix,gt912" @@ -18,11 +19,14 @@ Optional properties: - irq-gpios : GPIO pin used for IRQ. The driver uses the interrupt gpio pin as output to reset the device. - reset-gpios : GPIO pin used for reset - - - touchscreen-inverted-x : X axis is inverted (boolean) - - touchscreen-inverted-y : Y axis is inverted (boolean) - - touchscreen-swapped-x-y : X and Y axis are swapped (boolean) - (swapping is done after inverting the axis) + - touchscreen-inverted-x + - touchscreen-inverted-y + - touchscreen-size-x + - touchscreen-size-y + - touchscreen-swapped-x-y + +The touchscreen-* properties are documented in touchscreen.txt in this +directory. Example: diff --git a/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt b/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt index 64ad48b824a2..019373253b28 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt @@ -1,13 +1,17 @@ -* Sitronix st1232 touchscreen controller +* Sitronix st1232 or st1633 touchscreen controller Required properties: -- compatible: must be "sitronix,st1232" +- compatible: must contain one of + * "sitronix,st1232" + * "sitronix,st1633" - reg: I2C address of the chip - interrupts: interrupt to which the chip is connected Optional properties: - gpios: a phandle to the reset GPIO +For additional optional properties see: touchscreen.txt + Example: i2c@00000000 { diff --git a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt index 4886c4aa2906..0ebe6dd043c7 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/sx8654.txt @@ -1,10 +1,17 @@ * Semtech SX8654 I2C Touchscreen Controller Required properties: -- compatible: must be "semtech,sx8654" +- compatible: must be one of the following, depending on the model: + "semtech,sx8650" + "semtech,sx8654" + "semtech,sx8655" + "semtech,sx8656" - reg: i2c slave address - interrupts: touch controller interrupt +Optional properties: + - reset-gpios: GPIO specification for the NRST input + Example: sx8654@48 { @@ -12,4 +19,5 @@ Example: reg = <0x48>; interrupt-parent = <&gpio6>; interrupts = <3 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>; }; diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 804b1b80a8be..5a52b65bef9a 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -259,7 +259,7 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char db9_saturn_write_sub(port, type, 3, powered, 0); return data[0] = 0xe3; } - /* else: fall through */ + /* fall through */ default: return data[0]; } diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 492a971b95b5..6cd199e8a370 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -1015,8 +1015,18 @@ static int __maybe_unused gpio_keys_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); +static void gpio_keys_shutdown(struct platform_device *pdev) +{ + int ret; + + ret = gpio_keys_suspend(&pdev->dev); + if (ret) + dev_err(&pdev->dev, "failed to shutdown\n"); +} + static struct platform_driver gpio_keys_device_driver = { .probe = gpio_keys_probe, + .shutdown = gpio_keys_shutdown, .driver = { .name = "gpio-keys", .pm = &gpio_keys_pm_ops, diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index be56d4f262a7..b132662201a4 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -113,9 +113,8 @@ static int mcs_touchkey_probe(struct i2c_client *client, return -EINVAL; } - data = kzalloc(sizeof(struct mcs_touchkey_data) + - sizeof(data->keycodes[0]) * (pdata->key_maxval + 1), - GFP_KERNEL); + 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"); diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c index 02c67a1749fc..8e6ebab05ab4 100644 --- a/drivers/input/keyboard/mtk-pmic-keys.c +++ b/drivers/input/keyboard/mtk-pmic-keys.c @@ -14,18 +14,17 @@ * */ -#include <linux/module.h> -#include <linux/kernel.h> #include <linux/input.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> #include <linux/kernel.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/regmap.h> #include <linux/mfd/mt6323/registers.h> -#include <linux/mfd/mt6397/registers.h> #include <linux/mfd/mt6397/core.h> +#include <linux/mfd/mt6397/registers.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> #define MTK_PMIC_PWRKEY_RST_EN_MASK 0x1 #define MTK_PMIC_PWRKEY_RST_EN_SHIFT 6 diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index d466bc07aebb..6a43895b28e7 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -68,7 +68,6 @@ struct qt2160_data { struct i2c_client *client; struct input_dev *input; struct delayed_work dwork; - spinlock_t lock; /* Protects canceling/rescheduling of dwork */ unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; u16 key_matrix; #ifdef CONFIG_LEDS_CLASS @@ -212,22 +211,15 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160) static irqreturn_t qt2160_irq(int irq, void *_qt2160) { struct qt2160_data *qt2160 = _qt2160; - unsigned long flags; - - spin_lock_irqsave(&qt2160->lock, flags); mod_delayed_work(system_wq, &qt2160->dwork, 0); - spin_unlock_irqrestore(&qt2160->lock, flags); - return IRQ_HANDLED; } static void qt2160_schedule_read(struct qt2160_data *qt2160) { - spin_lock_irq(&qt2160->lock); schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL); - spin_unlock_irq(&qt2160->lock); } static void qt2160_worker(struct work_struct *work) @@ -391,7 +383,6 @@ static int qt2160_probe(struct i2c_client *client, qt2160->client = client; qt2160->input = input; INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker); - spin_lock_init(&qt2160->lock); input->name = "AT42QT2160 Touch Sense Keyboard"; input->id.bustype = BUS_I2C; diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index dc983ab6c0ad..cdeef180aead 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -219,9 +219,7 @@ static int tca6416_keypad_probe(struct i2c_client *client, return -EINVAL; } - chip = kzalloc(sizeof(struct tca6416_keypad_chip) + - pdata->nbuttons * sizeof(struct tca6416_button), - GFP_KERNEL); + chip = kzalloc(struct_size(chip, buttons, pdata->nbuttons), GFP_KERNEL); input = input_allocate_device(); if (!chip || !input) { error = -ENOMEM; diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c index abc266e40e17..d4455f3a5cf1 100644 --- a/drivers/input/keyboard/tm2-touchkey.c +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -22,12 +22,14 @@ #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> #define TM2_TOUCHKEY_DEV_NAME "tm2-touchkey" -#define TM2_TOUCHKEY_KEYCODE_REG 0x03 -#define TM2_TOUCHKEY_BASE_REG 0x00 + +#define ARIES_TOUCHKEY_CMD_LED_ON 0x1 +#define ARIES_TOUCHKEY_CMD_LED_OFF 0x2 #define TM2_TOUCHKEY_CMD_LED_ON 0x10 #define TM2_TOUCHKEY_CMD_LED_OFF 0x20 #define TM2_TOUCHKEY_BIT_PRESS_EV BIT(3) @@ -35,9 +37,13 @@ #define TM2_TOUCHKEY_LED_VOLTAGE_MIN 2500000 #define TM2_TOUCHKEY_LED_VOLTAGE_MAX 3300000 -enum { - TM2_TOUCHKEY_KEY_MENU = 0x1, - TM2_TOUCHKEY_KEY_BACK, +struct touchkey_variant { + u8 keycode_reg; + u8 base_reg; + u8 cmd_led_on; + u8 cmd_led_off; + bool no_reg; + bool fixed_regulator; }; struct tm2_touchkey_data { @@ -46,9 +52,33 @@ struct tm2_touchkey_data { struct led_classdev led_dev; struct regulator *vdd; struct regulator_bulk_data regulators[2]; + const struct touchkey_variant *variant; + u32 keycodes[4]; + int num_keycodes; +}; + +static const struct touchkey_variant tm2_touchkey_variant = { + .keycode_reg = 0x03, + .base_reg = 0x00, + .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON, + .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF, +}; + +static const struct touchkey_variant midas_touchkey_variant = { + .keycode_reg = 0x00, + .base_reg = 0x00, + .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON, + .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF, }; -static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev, +static struct touchkey_variant aries_touchkey_variant = { + .no_reg = true, + .fixed_regulator = true, + .cmd_led_on = ARIES_TOUCHKEY_CMD_LED_ON, + .cmd_led_off = ARIES_TOUCHKEY_CMD_LED_OFF, +}; + +static int tm2_touchkey_led_brightness_set(struct led_classdev *led_dev, enum led_brightness brightness) { struct tm2_touchkey_data *touchkey = @@ -58,15 +88,19 @@ static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev, if (brightness == LED_OFF) { volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN; - data = TM2_TOUCHKEY_CMD_LED_OFF; + data = touchkey->variant->cmd_led_off; } else { volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX; - data = TM2_TOUCHKEY_CMD_LED_ON; + data = touchkey->variant->cmd_led_on; } - regulator_set_voltage(touchkey->vdd, volt, volt); - i2c_smbus_write_byte_data(touchkey->client, - TM2_TOUCHKEY_BASE_REG, data); + if (!touchkey->variant->fixed_regulator) + regulator_set_voltage(touchkey->vdd, volt, volt); + + return touchkey->variant->no_reg ? + i2c_smbus_write_byte(touchkey->client, data) : + i2c_smbus_write_byte_data(touchkey->client, + touchkey->variant->base_reg, data); } static int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey) @@ -96,49 +130,57 @@ static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid) { struct tm2_touchkey_data *touchkey = devid; int data; - int key; - - data = i2c_smbus_read_byte_data(touchkey->client, - TM2_TOUCHKEY_KEYCODE_REG); + int index; + int i; + + if (touchkey->variant->no_reg) + data = i2c_smbus_read_byte(touchkey->client); + else + data = i2c_smbus_read_byte_data(touchkey->client, + touchkey->variant->keycode_reg); if (data < 0) { dev_err(&touchkey->client->dev, "failed to read i2c data: %d\n", data); goto out; } - switch (data & TM2_TOUCHKEY_BIT_KEYCODE) { - case TM2_TOUCHKEY_KEY_MENU: - key = KEY_PHONE; - break; - - case TM2_TOUCHKEY_KEY_BACK: - key = KEY_BACK; - break; - - default: + index = (data & TM2_TOUCHKEY_BIT_KEYCODE) - 1; + if (index < 0 || index >= touchkey->num_keycodes) { dev_warn(&touchkey->client->dev, - "unhandled keycode, data %#02x\n", data); + "invalid keycode index %d\n", index); goto out; } if (data & TM2_TOUCHKEY_BIT_PRESS_EV) { - input_report_key(touchkey->input_dev, KEY_PHONE, 0); - input_report_key(touchkey->input_dev, KEY_BACK, 0); + for (i = 0; i < touchkey->num_keycodes; i++) + input_report_key(touchkey->input_dev, + touchkey->keycodes[i], 0); } else { - input_report_key(touchkey->input_dev, key, 1); + input_report_key(touchkey->input_dev, + touchkey->keycodes[index], 1); } input_sync(touchkey->input_dev); out: + if (touchkey->variant->fixed_regulator && + data & TM2_TOUCHKEY_BIT_PRESS_EV) { + /* touch turns backlight on, so make sure we're in sync */ + if (touchkey->led_dev.brightness == LED_OFF) + tm2_touchkey_led_brightness_set(&touchkey->led_dev, + LED_OFF); + } + return IRQ_HANDLED; } static int tm2_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device_node *np = client->dev.of_node; struct tm2_touchkey_data *touchkey; int error; + int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -153,6 +195,8 @@ static int tm2_touchkey_probe(struct i2c_client *client, touchkey->client = client; i2c_set_clientdata(client, touchkey); + touchkey->variant = of_device_get_match_data(&client->dev); + touchkey->regulators[0].supply = "vcc"; touchkey->regulators[1].supply = "vdd"; error = devm_regulator_bulk_get(&client->dev, @@ -166,6 +210,16 @@ static int tm2_touchkey_probe(struct i2c_client *client, /* Save VDD for easy access */ touchkey->vdd = touchkey->regulators[1].consumer; + touchkey->num_keycodes = of_property_read_variable_u32_array(np, + "linux,keycodes", touchkey->keycodes, 0, + ARRAY_SIZE(touchkey->keycodes)); + if (touchkey->num_keycodes <= 0) { + /* default keycodes */ + touchkey->keycodes[0] = KEY_PHONE; + touchkey->keycodes[1] = KEY_BACK; + touchkey->num_keycodes = 2; + } + error = tm2_touchkey_power_enable(touchkey); if (error) { dev_err(&client->dev, "failed to power up device: %d\n", error); @@ -190,8 +244,9 @@ static int tm2_touchkey_probe(struct i2c_client *client, touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME; touchkey->input_dev->id.bustype = BUS_I2C; - input_set_capability(touchkey->input_dev, EV_KEY, KEY_PHONE); - input_set_capability(touchkey->input_dev, EV_KEY, KEY_BACK); + for (i = 0; i < touchkey->num_keycodes; i++) + input_set_capability(touchkey->input_dev, EV_KEY, + touchkey->keycodes[i]); error = input_register_device(touchkey->input_dev); if (error) { @@ -212,9 +267,10 @@ static int tm2_touchkey_probe(struct i2c_client *client, /* led device */ touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME; - touchkey->led_dev.brightness = LED_FULL; + touchkey->led_dev.brightness = LED_ON; touchkey->led_dev.max_brightness = LED_ON; - touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set; + touchkey->led_dev.brightness_set_blocking = + tm2_touchkey_led_brightness_set; error = devm_led_classdev_register(&client->dev, &touchkey->led_dev); if (error) { @@ -223,6 +279,9 @@ static int tm2_touchkey_probe(struct i2c_client *client, return error; } + if (touchkey->variant->fixed_regulator) + tm2_touchkey_led_brightness_set(&touchkey->led_dev, LED_ON); + return 0; } @@ -262,7 +321,16 @@ static const struct i2c_device_id tm2_touchkey_id_table[] = { MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table); static const struct of_device_id tm2_touchkey_of_match[] = { - { .compatible = "cypress,tm2-touchkey", }, + { + .compatible = "cypress,tm2-touchkey", + .data = &tm2_touchkey_variant, + }, { + .compatible = "cypress,midas-touchkey", + .data = &midas_touchkey_variant, + }, { + .compatible = "cypress,aries-touchkey", + .data = &aries_touchkey_variant, + }, { }, }; MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 279fb02a0f14..e15ed1bb8558 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -117,6 +117,16 @@ config INPUT_E3X0_BUTTON To compile this driver as a module, choose M here: the module will be called e3x0_button. +config INPUT_MSM_VIBRATOR + tristate "Qualcomm MSM vibrator driver" + select INPUT_FF_MEMLESS + help + Support for the vibrator that is found on various Qualcomm MSM + SOCs. + + To compile this driver as a module, choose M here: the module + will be called msm_vibrator. + config INPUT_PCSPKR tristate "PC Speaker support" depends on PCSPKR_PLATFORM diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 1b44202ad8f7..b936c5b1d4ac 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o obj-$(CONFIG_INPUT_MMA8450) += mma8450.o +obj-$(CONFIG_INPUT_MSM_VIBRATOR) += msm-vibrator.o obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 3d51175c4d72..74cf3b612f05 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -39,8 +39,6 @@ struct ims_pcu_gamepad { struct ims_pcu_backlight { struct led_classdev cdev; - struct work_struct work; - enum led_brightness desired_brightness; char name[32]; }; @@ -949,14 +947,14 @@ out: #define IMS_PCU_MAX_BRIGHTNESS 31998 -static void ims_pcu_backlight_work(struct work_struct *work) +static int ims_pcu_backlight_set_brightness(struct led_classdev *cdev, + enum led_brightness value) { struct ims_pcu_backlight *backlight = - container_of(work, struct ims_pcu_backlight, work); + container_of(cdev, struct ims_pcu_backlight, cdev); struct ims_pcu *pcu = container_of(backlight, struct ims_pcu, backlight); - int desired_brightness = backlight->desired_brightness; - __le16 br_val = cpu_to_le16(desired_brightness); + __le16 br_val = cpu_to_le16(value); int error; mutex_lock(&pcu->cmd_mutex); @@ -966,19 +964,11 @@ static void ims_pcu_backlight_work(struct work_struct *work) if (error && error != -ENODEV) dev_warn(pcu->dev, "Failed to set desired brightness %u, error: %d\n", - desired_brightness, error); + value, error); mutex_unlock(&pcu->cmd_mutex); -} -static void ims_pcu_backlight_set_brightness(struct led_classdev *cdev, - enum led_brightness value) -{ - struct ims_pcu_backlight *backlight = - container_of(cdev, struct ims_pcu_backlight, cdev); - - backlight->desired_brightness = value; - schedule_work(&backlight->work); + return error; } static enum led_brightness @@ -1015,14 +1005,14 @@ static int ims_pcu_setup_backlight(struct ims_pcu *pcu) struct ims_pcu_backlight *backlight = &pcu->backlight; int error; - INIT_WORK(&backlight->work, ims_pcu_backlight_work); snprintf(backlight->name, sizeof(backlight->name), "pcu%d::kbd_backlight", pcu->device_no); backlight->cdev.name = backlight->name; backlight->cdev.max_brightness = IMS_PCU_MAX_BRIGHTNESS; backlight->cdev.brightness_get = ims_pcu_backlight_get_brightness; - backlight->cdev.brightness_set = ims_pcu_backlight_set_brightness; + backlight->cdev.brightness_set_blocking = + ims_pcu_backlight_set_brightness; error = led_classdev_register(pcu->dev, &backlight->cdev); if (error) { @@ -1040,7 +1030,6 @@ static void ims_pcu_destroy_backlight(struct ims_pcu *pcu) struct ims_pcu_backlight *backlight = &pcu->backlight; led_classdev_unregister(&backlight->cdev); - cancel_work_sync(&backlight->work); } diff --git a/drivers/input/misc/msm-vibrator.c b/drivers/input/misc/msm-vibrator.c new file mode 100644 index 000000000000..b60f1aaee705 --- /dev/null +++ b/drivers/input/misc/msm-vibrator.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm MSM vibrator driver + * + * Copyright (c) 2018 Brian Masney <masneyb@onstation.org> + * + * Based on qcom,pwm-vibrator.c from: + * Copyright (c) 2018 Jonathan Marek <jonathan@marek.ca> + * + * Based on msm_pwm_vibrator.c from downstream Android sources: + * Copyright (C) 2009-2014 LGE, Inc. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/input.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> + +#define REG_CMD_RCGR 0x00 +#define REG_CFG_RCGR 0x04 +#define REG_M 0x08 +#define REG_N 0x0C +#define REG_D 0x10 +#define REG_CBCR 0x24 +#define MMSS_CC_M_DEFAULT 1 + +struct msm_vibrator { + struct input_dev *input; + struct mutex mutex; + struct work_str |