* Re: [PATCH v4 2/3] Input: add new vibrator driver for various MSM SOCs
From: Dmitry Torokhov @ 2019-02-06 18:16 UTC (permalink / raw)
To: Brian Masney
Cc: andy.gross, david.brown, robh+dt, mark.rutland, linux-input,
linux-kernel, linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20190206013329.18195-3-masneyb@onstation.org>
On Tue, Feb 05, 2019 at 08:33:28PM -0500, Brian Masney wrote:
> This patch adds a new vibrator driver that supports various Qualcomm
> MSM SOCs. Driver was tested on a LG Nexus 5 (hammerhead) phone.
>
> Signed-off-by: Brian Masney <masneyb@onstation.org>
Applied together with binding patch, thank you.
> ---
> Changes since v3:
> - Made msm_vibrator_write a function instead of a macro.
> - Check for -EPROBE_DEFER for gpio and clk for consistency with the
> regulator.
> - Check for NULL return value from devm_ioremap() instead of using
> IS_ERR()
> - Don't set dev.parent
> - Use platform_get_drvdata() in suspend and resume
>
> drivers/input/misc/Kconfig | 10 ++
> drivers/input/misc/Makefile | 1 +
> drivers/input/misc/msm-vibrator.c | 282 ++++++++++++++++++++++++++++++
> 3 files changed, 293 insertions(+)
> create mode 100644 drivers/input/misc/msm-vibrator.c
>
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index ca59a2be9bc5..e39aef84f357 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 9d0f9d1ff68f..96a6419cb1f2 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/msm-vibrator.c b/drivers/input/misc/msm-vibrator.c
> new file mode 100644
> index 000000000000..c06941021447
> --- /dev/null
> +++ b/drivers/input/misc/msm-vibrator.c
> @@ -0,0 +1,282 @@
> +// 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.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_struct worker;
> + void __iomem *base;
> + struct regulator *vcc;
> + struct clk *clk;
> + struct gpio_desc *enable_gpio;
> + u16 magnitude;
> + bool enabled;
> +};
> +
> +static void msm_vibrator_write(struct msm_vibrator *vibrator, int offset,
> + u32 value)
> +{
> + writel(value, vibrator->base + offset);
> +}
> +
> +static int msm_vibrator_start(struct msm_vibrator *vibrator)
> +{
> + int d_reg_val, ret = 0;
> +
> + mutex_lock(&vibrator->mutex);
> +
> + if (!vibrator->enabled) {
> + ret = clk_set_rate(vibrator->clk, 24000);
> + if (ret) {
> + dev_err(&vibrator->input->dev,
> + "Failed to set clock rate: %d\n", ret);
> + goto unlock;
> + }
> +
> + ret = clk_prepare_enable(vibrator->clk);
> + if (ret) {
> + dev_err(&vibrator->input->dev,
> + "Failed to enable clock: %d\n", ret);
> + goto unlock;
> + }
> +
> + ret = regulator_enable(vibrator->vcc);
> + if (ret) {
> + dev_err(&vibrator->input->dev,
> + "Failed to enable regulator: %d\n", ret);
> + clk_disable(vibrator->clk);
> + goto unlock;
> + }
> +
> + gpiod_set_value_cansleep(vibrator->enable_gpio, 1);
> +
> + vibrator->enabled = true;
> + }
> +
> + d_reg_val = 127 - ((126 * vibrator->magnitude) / 0xffff);
> + msm_vibrator_write(vibrator, REG_CFG_RCGR,
> + (2 << 12) | /* dual edge mode */
> + (0 << 8) | /* cxo */
> + (7 << 0));
> + msm_vibrator_write(vibrator, REG_M, 1);
> + msm_vibrator_write(vibrator, REG_N, 128);
> + msm_vibrator_write(vibrator, REG_D, d_reg_val);
> + msm_vibrator_write(vibrator, REG_CMD_RCGR, 1);
> + msm_vibrator_write(vibrator, REG_CBCR, 1);
> +
> +unlock:
> + mutex_unlock(&vibrator->mutex);
> +
> + return ret;
> +}
> +
> +static void msm_vibrator_stop(struct msm_vibrator *vibrator)
> +{
> + mutex_lock(&vibrator->mutex);
> +
> + if (vibrator->enabled) {
> + gpiod_set_value_cansleep(vibrator->enable_gpio, 0);
> + regulator_disable(vibrator->vcc);
> + clk_disable(vibrator->clk);
> + vibrator->enabled = false;
> + }
> +
> + mutex_unlock(&vibrator->mutex);
> +}
> +
> +static void msm_vibrator_worker(struct work_struct *work)
> +{
> + struct msm_vibrator *vibrator = container_of(work,
> + struct msm_vibrator,
> + worker);
> +
> + if (vibrator->magnitude)
> + msm_vibrator_start(vibrator);
> + else
> + msm_vibrator_stop(vibrator);
> +}
> +
> +static int msm_vibrator_play_effect(struct input_dev *dev, void *data,
> + struct ff_effect *effect)
> +{
> + struct msm_vibrator *vibrator = input_get_drvdata(dev);
> +
> + mutex_lock(&vibrator->mutex);
> +
> + if (effect->u.rumble.strong_magnitude > 0)
> + vibrator->magnitude = effect->u.rumble.strong_magnitude;
> + else
> + vibrator->magnitude = effect->u.rumble.weak_magnitude;
> +
> + mutex_unlock(&vibrator->mutex);
> +
> + schedule_work(&vibrator->worker);
> +
> + return 0;
> +}
> +
> +static void msm_vibrator_close(struct input_dev *input)
> +{
> + struct msm_vibrator *vibrator = input_get_drvdata(input);
> +
> + cancel_work_sync(&vibrator->worker);
> + msm_vibrator_stop(vibrator);
> +}
> +
> +static int msm_vibrator_probe(struct platform_device *pdev)
> +{
> + struct msm_vibrator *vibrator;
> + struct resource *res;
> + int ret;
> +
> + vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
> + if (!vibrator)
> + return -ENOMEM;
> +
> + vibrator->input = devm_input_allocate_device(&pdev->dev);
> + if (!vibrator->input)
> + return -ENOMEM;
> +
> + vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
> + if (IS_ERR(vibrator->vcc)) {
> + if (PTR_ERR(vibrator->vcc) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "Failed to get regulator: %ld\n",
> + PTR_ERR(vibrator->vcc));
> + return PTR_ERR(vibrator->vcc);
> + }
> +
> + vibrator->enable_gpio = devm_gpiod_get(&pdev->dev, "enable",
> + GPIOD_OUT_LOW);
> + if (IS_ERR(vibrator->enable_gpio)) {
> + if (PTR_ERR(vibrator->enable_gpio) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "Failed to get enable gpio: %ld\n",
> + PTR_ERR(vibrator->enable_gpio));
> + return PTR_ERR(vibrator->enable_gpio);
> + }
> +
> + vibrator->clk = devm_clk_get(&pdev->dev, "pwm");
> + if (IS_ERR(vibrator->clk)) {
> + if (PTR_ERR(vibrator->clk) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "Failed to lookup pwm clock: %ld\n",
> + PTR_ERR(vibrator->clk));
> + return PTR_ERR(vibrator->clk);
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "Failed to get platform resource\n");
> + return -ENODEV;
> + }
> +
> + vibrator->base = devm_ioremap(&pdev->dev, res->start,
> + resource_size(res));
> + if (!vibrator->base) {
> + dev_err(&pdev->dev, "Failed to iomap resource: %ld\n",
> + PTR_ERR(vibrator->base));
> + return -ENOMEM;
> + }
> +
> + vibrator->enabled = false;
> + mutex_init(&vibrator->mutex);
> + INIT_WORK(&vibrator->worker, msm_vibrator_worker);
> +
> + vibrator->input->name = "msm-vibrator";
> + vibrator->input->id.bustype = BUS_HOST;
> + vibrator->input->close = msm_vibrator_close;
> +
> + input_set_drvdata(vibrator->input, vibrator);
> + input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
> +
> + ret = input_ff_create_memless(vibrator->input, NULL,
> + msm_vibrator_play_effect);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to create ff memless: %d", ret);
> + return ret;
> + }
> +
> + ret = input_register_device(vibrator->input);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to register input device: %d", ret);
> + return ret;
> + }
> +
> + platform_set_drvdata(pdev, vibrator);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused msm_vibrator_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct msm_vibrator *vibrator = platform_get_drvdata(pdev);
> +
> + cancel_work_sync(&vibrator->worker);
> +
> + if (vibrator->enabled)
> + msm_vibrator_stop(vibrator);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused msm_vibrator_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct msm_vibrator *vibrator = platform_get_drvdata(pdev);
> +
> + if (vibrator->enabled)
> + msm_vibrator_start(vibrator);
> +
> + return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(msm_vibrator_pm_ops, msm_vibrator_suspend,
> + msm_vibrator_resume);
> +
> +static const struct of_device_id msm_vibrator_of_match[] = {
> + { .compatible = "qcom,msm8226-vibrator" },
> + { .compatible = "qcom,msm8974-vibrator" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, msm_vibrator_of_match);
> +
> +static struct platform_driver msm_vibrator_driver = {
> + .probe = msm_vibrator_probe,
> + .driver = {
> + .name = "msm-vibrator",
> + .pm = &msm_vibrator_pm_ops,
> + .of_match_table = of_match_ptr(msm_vibrator_of_match),
> + },
> +};
> +module_platform_driver(msm_vibrator_driver);
> +
> +MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>");
> +MODULE_DESCRIPTION("Qualcomm MSM vibrator driver");
> +MODULE_LICENSE("GPL");
> --
> 2.17.2
>
--
Dmitry
^ permalink raw reply
* [PATCH] Input: tm2-touchkey - acknowledge that setting brightness is a blocking call
From: Dmitry Torokhov @ 2019-02-06 18:16 UTC (permalink / raw)
To: linux-input; +Cc: Paweł Chmiel, Jonathan Bakker, Andi Shyti, linux-kernel
We need to access I2C bus when switching brightness, and that may block,
therefore we have to set stmfts_brightness_set() as LED's
brightness_set_blocking() method.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/keyboard/tm2-touchkey.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
index 7dbef96559d2..d4455f3a5cf1 100644
--- a/drivers/input/keyboard/tm2-touchkey.c
+++ b/drivers/input/keyboard/tm2-touchkey.c
@@ -78,7 +78,7 @@ static struct touchkey_variant aries_touchkey_variant = {
.cmd_led_off = ARIES_TOUCHKEY_CMD_LED_OFF,
};
-static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
+static int tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
enum led_brightness brightness)
{
struct tm2_touchkey_data *touchkey =
@@ -97,9 +97,8 @@ static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
if (!touchkey->variant->fixed_regulator)
regulator_set_voltage(touchkey->vdd, volt, volt);
- if (touchkey->variant->no_reg)
- i2c_smbus_write_byte(touchkey->client, data);
- else
+ return touchkey->variant->no_reg ?
+ i2c_smbus_write_byte(touchkey->client, data) :
i2c_smbus_write_byte_data(touchkey->client,
touchkey->variant->base_reg, data);
}
@@ -270,7 +269,8 @@ static int tm2_touchkey_probe(struct i2c_client *client,
touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
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) {
--
2.20.1.611.gfbb209baf1-goog
--
Dmitry
^ permalink raw reply related
* [PATCH] Input: ims-pcu - switch to using brightness_set_blocking()
From: Dmitry Torokhov @ 2019-02-06 18:08 UTC (permalink / raw)
To: linux-input; +Cc: linux-kernel, Chris Healy
Now that LEDs core allows "blocking" flavor of "set brightness" method we
can use it and get rid of private work item.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/misc/ims-pcu.c | 27 ++++++++-------------------
1 file changed, 8 insertions(+), 19 deletions(-)
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 @@ static void ims_pcu_process_async_firmware(const struct firmware *fw,
#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);
}
--
2.20.1.611.gfbb209baf1-goog
--
Dmitry
^ permalink raw reply related
* Re: [PATCH] Input: cap11xx - switch to using set_brightness_blocking()
From: Sven Van Asbroeck @ 2019-02-06 14:33 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Jacek Anaszewski, Linux Kernel Mailing List
In-Reply-To: <20190205222050.GA145676@dtor-ws>
On Tue, Feb 5, 2019 at 5:20 PM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>
> Updating LED state requires access to regmap and therefore we may sleep, so
> we could not do that directly form set_brightness() method. Historically
> we used private work to adjust the brightness, but with the introduction of
> set_brightness_blocking() we no longer need it.
>
Elegant solution, nice !
I read the patch to verify that the user-after-free is now gone, but
obviously I cannot test,
as I have no cap11xx hardware. For what it's worth:
Reviewed-by: Sven Van Asbroeck <TheSven73@googlemail.com>
^ permalink raw reply
* [PATCH v4 3/3] ARM: dts: qcom: msm8974-hammerhead: add device tree bindings for vibrator
From: Brian Masney @ 2019-02-06 1:33 UTC (permalink / raw)
To: dmitry.torokhov, andy.gross
Cc: david.brown, robh+dt, mark.rutland, linux-input, linux-kernel,
linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20190206013329.18195-1-masneyb@onstation.org>
This patch adds device device tree bindings for the vibrator found on
the LG Nexus 5 (hammerhead) phone.
Signed-off-by: Brian Masney <masneyb@onstation.org>
---
Changes since v3:
- None
.../qcom-msm8974-lge-nexus5-hammerhead.dts | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
index b3b04736a159..1fd9f429f34a 100644
--- a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
@@ -5,6 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/clock/qcom,mmcc-msm8974.h>
/ {
model = "LGE MSM 8974 HAMMERHEAD";
@@ -306,6 +307,36 @@
input-enable;
};
};
+
+ vibrator_pin: vibrator {
+ pwm {
+ pins = "gpio27";
+ function = "gp1_clk";
+
+ drive-strength = <6>;
+ bias-disable;
+ };
+
+ enable {
+ pins = "gpio60";
+ function = "gpio";
+ };
+ };
+ };
+
+ vibrator@fd8c3450 {
+ compatible = "qcom,msm8974-vibrator";
+ reg = <0xfd8c3450 0x400>;
+
+ 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>;
};
sdhci@f9824900 {
--
2.17.2
^ permalink raw reply related
* [PATCH v4 2/3] Input: add new vibrator driver for various MSM SOCs
From: Brian Masney @ 2019-02-06 1:33 UTC (permalink / raw)
To: dmitry.torokhov, andy.gross
Cc: david.brown, robh+dt, mark.rutland, linux-input, linux-kernel,
linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20190206013329.18195-1-masneyb@onstation.org>
This patch adds a new vibrator driver that supports various Qualcomm
MSM SOCs. Driver was tested on a LG Nexus 5 (hammerhead) phone.
Signed-off-by: Brian Masney <masneyb@onstation.org>
---
Changes since v3:
- Made msm_vibrator_write a function instead of a macro.
- Check for -EPROBE_DEFER for gpio and clk for consistency with the
regulator.
- Check for NULL return value from devm_ioremap() instead of using
IS_ERR()
- Don't set dev.parent
- Use platform_get_drvdata() in suspend and resume
drivers/input/misc/Kconfig | 10 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/msm-vibrator.c | 282 ++++++++++++++++++++++++++++++
3 files changed, 293 insertions(+)
create mode 100644 drivers/input/misc/msm-vibrator.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ca59a2be9bc5..e39aef84f357 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 9d0f9d1ff68f..96a6419cb1f2 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/msm-vibrator.c b/drivers/input/misc/msm-vibrator.c
new file mode 100644
index 000000000000..c06941021447
--- /dev/null
+++ b/drivers/input/misc/msm-vibrator.c
@@ -0,0 +1,282 @@
+// 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.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_struct worker;
+ void __iomem *base;
+ struct regulator *vcc;
+ struct clk *clk;
+ struct gpio_desc *enable_gpio;
+ u16 magnitude;
+ bool enabled;
+};
+
+static void msm_vibrator_write(struct msm_vibrator *vibrator, int offset,
+ u32 value)
+{
+ writel(value, vibrator->base + offset);
+}
+
+static int msm_vibrator_start(struct msm_vibrator *vibrator)
+{
+ int d_reg_val, ret = 0;
+
+ mutex_lock(&vibrator->mutex);
+
+ if (!vibrator->enabled) {
+ ret = clk_set_rate(vibrator->clk, 24000);
+ if (ret) {
+ dev_err(&vibrator->input->dev,
+ "Failed to set clock rate: %d\n", ret);
+ goto unlock;
+ }
+
+ ret = clk_prepare_enable(vibrator->clk);
+ if (ret) {
+ dev_err(&vibrator->input->dev,
+ "Failed to enable clock: %d\n", ret);
+ goto unlock;
+ }
+
+ ret = regulator_enable(vibrator->vcc);
+ if (ret) {
+ dev_err(&vibrator->input->dev,
+ "Failed to enable regulator: %d\n", ret);
+ clk_disable(vibrator->clk);
+ goto unlock;
+ }
+
+ gpiod_set_value_cansleep(vibrator->enable_gpio, 1);
+
+ vibrator->enabled = true;
+ }
+
+ d_reg_val = 127 - ((126 * vibrator->magnitude) / 0xffff);
+ msm_vibrator_write(vibrator, REG_CFG_RCGR,
+ (2 << 12) | /* dual edge mode */
+ (0 << 8) | /* cxo */
+ (7 << 0));
+ msm_vibrator_write(vibrator, REG_M, 1);
+ msm_vibrator_write(vibrator, REG_N, 128);
+ msm_vibrator_write(vibrator, REG_D, d_reg_val);
+ msm_vibrator_write(vibrator, REG_CMD_RCGR, 1);
+ msm_vibrator_write(vibrator, REG_CBCR, 1);
+
+unlock:
+ mutex_unlock(&vibrator->mutex);
+
+ return ret;
+}
+
+static void msm_vibrator_stop(struct msm_vibrator *vibrator)
+{
+ mutex_lock(&vibrator->mutex);
+
+ if (vibrator->enabled) {
+ gpiod_set_value_cansleep(vibrator->enable_gpio, 0);
+ regulator_disable(vibrator->vcc);
+ clk_disable(vibrator->clk);
+ vibrator->enabled = false;
+ }
+
+ mutex_unlock(&vibrator->mutex);
+}
+
+static void msm_vibrator_worker(struct work_struct *work)
+{
+ struct msm_vibrator *vibrator = container_of(work,
+ struct msm_vibrator,
+ worker);
+
+ if (vibrator->magnitude)
+ msm_vibrator_start(vibrator);
+ else
+ msm_vibrator_stop(vibrator);
+}
+
+static int msm_vibrator_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct msm_vibrator *vibrator = input_get_drvdata(dev);
+
+ mutex_lock(&vibrator->mutex);
+
+ if (effect->u.rumble.strong_magnitude > 0)
+ vibrator->magnitude = effect->u.rumble.strong_magnitude;
+ else
+ vibrator->magnitude = effect->u.rumble.weak_magnitude;
+
+ mutex_unlock(&vibrator->mutex);
+
+ schedule_work(&vibrator->worker);
+
+ return 0;
+}
+
+static void msm_vibrator_close(struct input_dev *input)
+{
+ struct msm_vibrator *vibrator = input_get_drvdata(input);
+
+ cancel_work_sync(&vibrator->worker);
+ msm_vibrator_stop(vibrator);
+}
+
+static int msm_vibrator_probe(struct platform_device *pdev)
+{
+ struct msm_vibrator *vibrator;
+ struct resource *res;
+ int ret;
+
+ vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
+ if (!vibrator)
+ return -ENOMEM;
+
+ vibrator->input = devm_input_allocate_device(&pdev->dev);
+ if (!vibrator->input)
+ return -ENOMEM;
+
+ vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
+ if (IS_ERR(vibrator->vcc)) {
+ if (PTR_ERR(vibrator->vcc) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get regulator: %ld\n",
+ PTR_ERR(vibrator->vcc));
+ return PTR_ERR(vibrator->vcc);
+ }
+
+ vibrator->enable_gpio = devm_gpiod_get(&pdev->dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(vibrator->enable_gpio)) {
+ if (PTR_ERR(vibrator->enable_gpio) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get enable gpio: %ld\n",
+ PTR_ERR(vibrator->enable_gpio));
+ return PTR_ERR(vibrator->enable_gpio);
+ }
+
+ vibrator->clk = devm_clk_get(&pdev->dev, "pwm");
+ if (IS_ERR(vibrator->clk)) {
+ if (PTR_ERR(vibrator->clk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to lookup pwm clock: %ld\n",
+ PTR_ERR(vibrator->clk));
+ return PTR_ERR(vibrator->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get platform resource\n");
+ return -ENODEV;
+ }
+
+ vibrator->base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!vibrator->base) {
+ dev_err(&pdev->dev, "Failed to iomap resource: %ld\n",
+ PTR_ERR(vibrator->base));
+ return -ENOMEM;
+ }
+
+ vibrator->enabled = false;
+ mutex_init(&vibrator->mutex);
+ INIT_WORK(&vibrator->worker, msm_vibrator_worker);
+
+ vibrator->input->name = "msm-vibrator";
+ vibrator->input->id.bustype = BUS_HOST;
+ vibrator->input->close = msm_vibrator_close;
+
+ input_set_drvdata(vibrator->input, vibrator);
+ input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
+
+ ret = input_ff_create_memless(vibrator->input, NULL,
+ msm_vibrator_play_effect);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to create ff memless: %d", ret);
+ return ret;
+ }
+
+ ret = input_register_device(vibrator->input);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register input device: %d", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, vibrator);
+
+ return 0;
+}
+
+static int __maybe_unused msm_vibrator_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct msm_vibrator *vibrator = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&vibrator->worker);
+
+ if (vibrator->enabled)
+ msm_vibrator_stop(vibrator);
+
+ return 0;
+}
+
+static int __maybe_unused msm_vibrator_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct msm_vibrator *vibrator = platform_get_drvdata(pdev);
+
+ if (vibrator->enabled)
+ msm_vibrator_start(vibrator);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(msm_vibrator_pm_ops, msm_vibrator_suspend,
+ msm_vibrator_resume);
+
+static const struct of_device_id msm_vibrator_of_match[] = {
+ { .compatible = "qcom,msm8226-vibrator" },
+ { .compatible = "qcom,msm8974-vibrator" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, msm_vibrator_of_match);
+
+static struct platform_driver msm_vibrator_driver = {
+ .probe = msm_vibrator_probe,
+ .driver = {
+ .name = "msm-vibrator",
+ .pm = &msm_vibrator_pm_ops,
+ .of_match_table = of_match_ptr(msm_vibrator_of_match),
+ },
+};
+module_platform_driver(msm_vibrator_driver);
+
+MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>");
+MODULE_DESCRIPTION("Qualcomm MSM vibrator driver");
+MODULE_LICENSE("GPL");
--
2.17.2
^ permalink raw reply related
* [PATCH v4 1/3] dt-bindings: Input: new bindings for MSM vibrator
From: Brian Masney @ 2019-02-06 1:33 UTC (permalink / raw)
To: dmitry.torokhov, andy.gross
Cc: david.brown, robh+dt, mark.rutland, linux-input, linux-kernel,
linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20190206013329.18195-1-masneyb@onstation.org>
This patch adds the device tree bindings for the vibrator found on
various Qualcomm MSM SOCs.
Signed-off-by: Brian Masney <masneyb@onstation.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes since v3:
- None
.../bindings/input/msm-vibrator.txt | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/msm-vibrator.txt
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>;
+};
--
2.17.2
^ permalink raw reply related
* [PATCH v4 0/3] ARM: qcom: add vibrator support for various MSM SOCs
From: Brian Masney @ 2019-02-06 1:33 UTC (permalink / raw)
To: dmitry.torokhov, andy.gross
Cc: david.brown, robh+dt, mark.rutland, linux-input, linux-kernel,
linux-arm-msm, linux-soc, devicetree, jonathan
This patch set adds support for the vibrator found on various Qualcomm
MSM SOCs. This is based on work from:
Jonathan Marek from qcom,pwm-vibrator.c in the PostmarketOS repo:
https://gitlab.com/postmarketOS/linux-postmarketos/commit/7647fb36cb1cbd060f8b52087a68ab93583292b5
Jongrak Kwon and Devin Kim from msm_pwm_vibrator.c in the downstream
Android 3.4.0 sources:
https://android.googlesource.com/kernel/msm/+/android-msm-lenok-3.10-lollipop-wear-release/drivers/misc/msm_pwm_vibrator.c
Driver was tested on a LG Nexus 5 (hammerhead) phone using rumble-test:
https://git.collabora.com/cgit/user/sre/rumble-test.git/plain/rumble-test.c
Changes since v3
- Patch 2 is the only one that changed based on feedback from Dmitry
Torokhov. See notes on that patch for details.
Changes since v2
- Moved from pwm to input subsystem based on feedback from
https://lore.kernel.org/lkml/20181012114749.GC31561@ulmo/. I
previously wired this into the input system via pwm-vibra.
Changes since v1
- Update device tree binding document based on feedback from Rob
Herring.
- Changed the driver description to: Qualcomm PWM driver for the MSM
vibrator.
Brian Masney (3):
dt-bindings: Input: new bindings for MSM vibrator
Input: add new vibrator driver for various MSM SOCs
ARM: dts: qcom: msm8974-hammerhead: add device tree bindings for
vibrator
.../bindings/input/msm-vibrator.txt | 36 +++
.../qcom-msm8974-lge-nexus5-hammerhead.dts | 31 ++
drivers/input/misc/Kconfig | 10 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/msm-vibrator.c | 282 ++++++++++++++++++
5 files changed, 360 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/msm-vibrator.txt
create mode 100644 drivers/input/misc/msm-vibrator.c
--
2.17.2
^ permalink raw reply
* Re: [PATCH v3 2/3] Input: add new vibrator driver for various MSM SOCs
From: Brian Masney @ 2019-02-06 0:52 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: andy.gross, david.brown, robh+dt, mark.rutland, linux-input,
linux-kernel, linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20190205194246.GA19151@dtor-ws>
On Tue, Feb 05, 2019 at 11:42:46AM -0800, Dmitry Torokhov wrote:
> > + dev_err(&pdev->dev, "Failed to lookup pwm clock: %ld\n",
> > + PTR_ERR(vibrator->clk));
> > + return PTR_ERR(vibrator->clk);
> > + }
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + if (!res) {
> > + dev_err(&pdev->dev, "Failed to get platform resource\n");
> > + return -ENODEV;
> > + }
> > +
> > + vibrator->base = devm_ioremap(&pdev->dev, res->start,
> > + resource_size(res));
> > + if (IS_ERR(vibrator->base)) {
>
> devm_ioremap() returns NULL on error. You either need to check for NULL
> or see of you can use devm_ioremap_resource().
I originally tried to use devm_ioremap_resource() but the call to
devm_request_mem_region() would fail. I'll go with the NULL check here
for devm_ioremap().
Thanks for the review!
Brian
^ permalink raw reply
* Re: [PATCH] Input: gpio-keys - Add shutdown callback
From: Dmitry Torokhov @ 2019-02-06 0:45 UTC (permalink / raw)
To: Florian Fainelli
Cc: linux-kernel, Jeffy Chen, Rob Herring, Andy Shevchenko,
open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...
In-Reply-To: <65d6350f-2cd8-c183-6d8b-dbb11ae31819@gmail.com>
On Tue, Feb 05, 2019 at 02:02:49PM -0800, Florian Fainelli wrote:
> On 2/1/19 11:24 AM, Florian Fainelli wrote:
> > On some platforms (e.g.: ARCH_BRCMSTB) it is possible to enter
> > "poweroff" while leaving some wake-up sources enabled such as key
> > presses in order to allow for the system to wake-up.
> >
> > Wire up a .shutdown() callback which calls into the existing
> > gpio_keys_suspend() since the logic is essentially the same.
> >
> > Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> > ---
> > drivers/input/keyboard/gpio_keys.c | 10 ++++++++++
> > 1 file changed, 10 insertions(+)
>
> Any feedback on this?
OK, I'll take it. Hopefully it won't affect existing systems as the
change is unconditional.
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH] Input: stmfts - acknowledge that setting brightness is a blocking call
From: Dmitry Torokhov @ 2019-02-05 22:46 UTC (permalink / raw)
To: linux-input; +Cc: Andi Shyti, Jacek Anaszewski, linux-kernel
We need to turn regulators on and off when switching brightness, and
that may block, therefore we have to set stmfts_brightness_set() as
LED's brightness_set_blocking() method.
Fixes: 78bcac7b2ae1 ("Input: add support for the STMicroelectronics FingerTip touchscreen")
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/touchscreen/stmfts.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 704e99046916..b6f95f20f924 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -106,27 +106,29 @@ struct stmfts_data {
bool running;
};
-static void stmfts_brightness_set(struct led_classdev *led_cdev,
+static int stmfts_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct stmfts_data *sdata = container_of(led_cdev,
struct stmfts_data, led_cdev);
int err;
- if (value == sdata->led_status || !sdata->ledvdd)
- return;
-
- if (!value) {
- regulator_disable(sdata->ledvdd);
- } else {
- err = regulator_enable(sdata->ledvdd);
- if (err)
- dev_warn(&sdata->client->dev,
- "failed to disable ledvdd regulator: %d\n",
- err);
+ if (value != sdata->led_status && sdata->ledvdd) {
+ if (!value) {
+ regulator_disable(sdata->ledvdd);
+ } else {
+ err = regulator_enable(sdata->ledvdd);
+ if (err) {
+ dev_warn(&sdata->client->dev,
+ "failed to disable ledvdd regulator: %d\n",
+ err);
+ return err;
+ }
+ }
+ sdata->led_status = value;
}
- sdata->led_status = value;
+ return 0;
}
static enum led_brightness stmfts_brightness_get(struct led_classdev *led_cdev)
@@ -608,7 +610,7 @@ static int stmfts_enable_led(struct stmfts_data *sdata)
sdata->led_cdev.name = STMFTS_DEV_NAME;
sdata->led_cdev.max_brightness = LED_ON;
sdata->led_cdev.brightness = LED_OFF;
- sdata->led_cdev.brightness_set = stmfts_brightness_set;
+ sdata->led_cdev.brightness_set_blocking = stmfts_brightness_set;
sdata->led_cdev.brightness_get = stmfts_brightness_get;
err = devm_led_classdev_register(&sdata->client->dev, &sdata->led_cdev);
--
2.20.1.611.gfbb209baf1-goog
--
Dmitry
^ permalink raw reply related
* [PATCH] Input: cap11xx - switch to using set_brightness_blocking()
From: Dmitry Torokhov @ 2019-02-05 22:20 UTC (permalink / raw)
To: linux-input; +Cc: Sven Van Asbroeck, Jacek Anaszewski, linux-kernel
Updating LED state requires access to regmap and therefore we may sleep, so
we could not do that directly form set_brightness() method. Historically
we used private work to adjust the brightness, but with the introduction of
set_brightness_blocking() we no longer need it.
As a bonus, not having our own work item means we do not have
use-after-free issue as we neglected to cancel outstanding work on driver
unbind.
Reported-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/keyboard/cap11xx.c | 47 ++++++++++++++------------------
1 file changed, 21 insertions(+), 26 deletions(-)
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 312916f99597..c0baf323ddda 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -75,9 +75,8 @@
struct cap11xx_led {
struct cap11xx_priv *priv;
struct led_classdev cdev;
- struct work_struct work;
u32 reg;
- enum led_brightness new_brightness;
+ enum led_brightness brightness;
};
#endif
@@ -233,30 +232,28 @@ static void cap11xx_input_close(struct input_dev *idev)
}
#ifdef CONFIG_LEDS_CLASS
-static void cap11xx_led_work(struct work_struct *work)
-{
- struct cap11xx_led *led = container_of(work, struct cap11xx_led, work);
- struct cap11xx_priv *priv = led->priv;
- int value = led->new_brightness;
-
- /*
- * All LEDs share the same duty cycle as this is a HW limitation.
- * Brightness levels per LED are either 0 (OFF) and 1 (ON).
- */
- regmap_update_bits(priv->regmap, CAP11XX_REG_LED_OUTPUT_CONTROL,
- BIT(led->reg), value ? BIT(led->reg) : 0);
-}
-
-static void cap11xx_led_set(struct led_classdev *cdev,
- enum led_brightness value)
+static int cap11xx_led_set(struct led_classdev *cdev,
+ enum led_brightness value)
{
struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
+ struct cap11xx_priv *priv = led->priv;
+ int error = 0;
+
+ if (led->brightness != value) {
+ /*
+ * All LEDs share the same duty cycle as this is a HW
+ * limitation. Brightness levels per LED are either
+ * 0 (OFF) and 1 (ON).
+ */
+ error = regmap_update_bits(priv->regmap,
+ CAP11XX_REG_LED_OUTPUT_CONTROL,
+ BIT(led->reg),
+ value ? BIT(led->reg) : 0);
+ if (!error)
+ led->brightness = value;
+ }
- if (led->new_brightness == value)
- return;
-
- led->new_brightness = value;
- schedule_work(&led->work);
+ return error;
}
static int cap11xx_init_leds(struct device *dev,
@@ -299,7 +296,7 @@ static int cap11xx_init_leds(struct device *dev,
led->cdev.default_trigger =
of_get_property(child, "linux,default-trigger", NULL);
led->cdev.flags = 0;
- led->cdev.brightness_set = cap11xx_led_set;
+ led->cdev.brightness_set_blocking = cap11xx_led_set;
led->cdev.max_brightness = 1;
led->cdev.brightness = LED_OFF;
@@ -312,8 +309,6 @@ static int cap11xx_init_leds(struct device *dev,
led->reg = reg;
led->priv = priv;
- INIT_WORK(&led->work, cap11xx_led_work);
-
error = devm_led_classdev_register(dev, &led->cdev);
if (error) {
of_node_put(child);
--
2.20.1.611.gfbb209baf1-goog
--
Dmitry
^ permalink raw reply related
* Re: [PATCH] Input: gpio-keys - Add shutdown callback
From: Florian Fainelli @ 2019-02-05 22:02 UTC (permalink / raw)
To: linux-kernel
Cc: Dmitry Torokhov, Jeffy Chen, Rob Herring, Andy Shevchenko,
open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...
In-Reply-To: <20190201192417.15037-1-f.fainelli@gmail.com>
On 2/1/19 11:24 AM, Florian Fainelli wrote:
> On some platforms (e.g.: ARCH_BRCMSTB) it is possible to enter
> "poweroff" while leaving some wake-up sources enabled such as key
> presses in order to allow for the system to wake-up.
>
> Wire up a .shutdown() callback which calls into the existing
> gpio_keys_suspend() since the logic is essentially the same.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> drivers/input/keyboard/gpio_keys.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
Any feedback on this?
>
> 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,
>
--
Florian
^ permalink raw reply
* Re: [PATCH v3 2/3] Input: add new vibrator driver for various MSM SOCs
From: Dmitry Torokhov @ 2019-02-05 19:42 UTC (permalink / raw)
To: Brian Masney
Cc: andy.gross, david.brown, robh+dt, mark.rutland, linux-input,
linux-kernel, linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20181025012937.2154-3-masneyb@onstation.org>
Hi Brian,
On Wed, Oct 24, 2018 at 09:29:36PM -0400, Brian Masney wrote:
> This patch adds a new vibrator driver that supports various Qualcomm
> MSM SOCs. Driver was tested on a LG Nexus 5 (hammerhead) phone.
>
...
> +
> +#define msm_vibrator_write(msm_vibrator, offset, value) \
> + writel((value), (void __iomem *)((msm_vibrator)->base + (offset)))
Make in a function? It will be inlined anyways...
> +
> + vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
> + if (IS_ERR(vibrator->vcc)) {
> + if (PTR_ERR(vibrator->vcc) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "Failed to get regulator: %ld\n",
> + PTR_ERR(vibrator->vcc));
> + return PTR_ERR(vibrator->vcc);
> + }
> +
> + vibrator->enable_gpio = devm_gpiod_get(&pdev->dev, "enable",
> + GPIOD_OUT_LOW);
> + if (IS_ERR(vibrator->enable_gpio)) {
You have explicit deferral handling for the regulator, but not gpio. I'd
prefer if we did (or not) it consistently.
> + dev_err(&pdev->dev, "Failed to get enable gpio: %ld\n",
> + PTR_ERR(vibrator->enable_gpio));
> + return PTR_ERR(vibrator->enable_gpio);
> + }
> +
> + vibrator->clk = devm_clk_get(&pdev->dev, "pwm");
> + if (IS_ERR(vibrator->clk)) {
Same here.
> + dev_err(&pdev->dev, "Failed to lookup pwm clock: %ld\n",
> + PTR_ERR(vibrator->clk));
> + return PTR_ERR(vibrator->clk);
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "Failed to get platform resource\n");
> + return -ENODEV;
> + }
> +
> + vibrator->base = devm_ioremap(&pdev->dev, res->start,
> + resource_size(res));
> + if (IS_ERR(vibrator->base)) {
devm_ioremap() returns NULL on error. You either need to check for NULL
or see of you can use devm_ioremap_resource().
> + dev_err(&pdev->dev, "Failed to iomap resource: %ld\n",
> + PTR_ERR(vibrator->base));
> + return PTR_ERR(vibrator->base);
> + }
> +
> + vibrator->enabled = false;
> + mutex_init(&vibrator->mutex);
> + INIT_WORK(&vibrator->worker, msm_vibrator_worker);
> +
> + vibrator->input->name = "msm-vibrator";
> + vibrator->input->id.bustype = BUS_HOST;
> + vibrator->input->dev.parent = &pdev->dev;
You allocated input device with devm so there is no need to set parent
by hand.
> + vibrator->input->close = msm_vibrator_close;
> +
> + input_set_drvdata(vibrator->input, vibrator);
> + input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
> +
> + ret = input_ff_create_memless(vibrator->input, NULL,
> + msm_vibrator_play_effect);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to create ff memless: %d", ret);
> + return ret;
> + }
> +
> + ret = input_register_device(vibrator->input);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to register input device: %d", ret);
> + return ret;
> + }
> +
> + platform_set_drvdata(pdev, vibrator);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused msm_vibrator_suspend(struct device *dev)
> +{
> + struct msm_vibrator *vibrator = dev_get_drvdata(dev);
Prefer explicit platform_get_drvdata() since we are working with
platform device (even though it resolves to the same thing).
> +
> + cancel_work_sync(&vibrator->worker);
> +
> + if (vibrator->enabled)
> + msm_vibrator_stop(vibrator);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused msm_vibrator_resume(struct device *dev)
> +{
> + struct msm_vibrator *vibrator = dev_get_drvdata(dev);
Same here.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2] platform/x86: silead_dmi: Add touchscreen platform data for the Chuwi Hi8 Air tablet
From: Andy Shevchenko @ 2019-02-05 18:18 UTC (permalink / raw)
To: Kai Renzig
Cc: Hans de Goede, Darren Hart, Andy Shevchenko, linux-input,
Platform Driver, Linux Kernel Mailing List
In-Reply-To: <20190203183423.7661-1-k.renzig@gmail.com>
On Sun, Feb 3, 2019 at 8:34 PM Kai Renzig <k.renzig@gmail.com> wrote:
>
> Add touchscreen platform data for the Chuwi Hi8 Air tablet.
>
Pushed to my review and testing queue, thanks!
> Signed-off-by: Kai Renzig <k.renzig@gmail.com>
> ---
> Changes in v2:
> - Fix the firmware filename to match the actual touchscreen controller.
>
> drivers/platform/x86/touchscreen_dmi.c | 23 +++++++++++++++++++++++
> 1 file changed, 23 insertions(+)
>
> diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
> index 8c5d47c0aea6..1f66405928a9 100644
> --- a/drivers/platform/x86/touchscreen_dmi.c
> +++ b/drivers/platform/x86/touchscreen_dmi.c
> @@ -41,6 +41,20 @@ static const struct ts_dmi_data chuwi_hi8_data = {
> .properties = chuwi_hi8_props,
> };
>
> +static const struct property_entry chuwi_hi8_air_props[] = {
> + PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
> + PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
> + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
> + PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-hi8-air.fw"),
> + PROPERTY_ENTRY_U32("silead,max-fingers", 10),
> + { }
> +};
> +
> +static const struct ts_dmi_data chuwi_hi8_air_data = {
> + .acpi_name = "MSSL1680:00",
> + .properties = chuwi_hi8_air_props,
> +};
> +
> static const struct property_entry chuwi_hi8_pro_props[] = {
> PROPERTY_ENTRY_U32("touchscreen-min-x", 6),
> PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
> @@ -497,6 +511,15 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
> DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
> },
> },
> + {
> + /* Chuwi Hi8 Air (CWI543) */
> + .driver_data = (void *)&chuwi_hi8_air_data,
> + .matches = {
> + DMI_MATCH(DMI_BOARD_VENDOR, "Default string"),
> + DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "Hi8 Air"),
> + },
> + },
> {
> /* Chuwi Hi8 Pro (CWI513) */
> .driver_data = (void *)&chuwi_hi8_pro_data,
> --
> 2.19.1
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/2] Input: add Apple SPI keyboard and trackpad driver.
From: Andy Shevchenko @ 2019-02-05 15:32 UTC (permalink / raw)
To: Life is hard, and then you die
Cc: Andy Shevchenko, Dmitry Torokhov, Henrik Rydberg, Lukas Wunner,
Federico Lorenzi, linux-input, Linux Kernel Mailing List
In-Reply-To: <20190205131812.GC4225@innovation.ch>
On Tue, Feb 5, 2019 at 4:21 PM Life is hard, and then you die
<ronald@innovation.ch> wrote:
> > > +config KEYBOARD_APPLESPI
> > > + tristate "Apple SPI keyboard and trackpad"
> >
> > > + depends on (X86 && ACPI && SPI) || COMPILE_TEST
> >
> > COMPILE_TEST more or less makes sense in conjunction with architecture selection.
> > It means, your code always dependant to ACPI and SPI frameworks.
> > That's why 0day complained.
>
> Thanks. Yes, looking at this again I realized I somewhat misunderstood
> the uses of COMPILE_TEST. I've changed this now to
>
> depends on ACPI && SPI && (X86 || COMPILE_TEST)
Better to split like
depends on SPI && ACPI
depends on X86 || COMPILE_TEST
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/2] Input: add Apple SPI keyboard and trackpad driver.
From: Life is hard, and then you die @ 2019-02-05 13:18 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Dmitry Torokhov, Henrik Rydberg, Lukas Wunner, Federico Lorenzi,
linux-input, linux-kernel
In-Reply-To: <20190205114522.GV9224@smile.fi.intel.com>
Hi Andy,
On Tue, Feb 05, 2019 at 01:45:22PM +0200, Andy Shevchenko wrote:
> On Mon, Feb 04, 2019 at 12:19:47AM -0800, Ronald Tschalär wrote:
> > The keyboard and trackpad on recent MacBook's (since 8,1) and
> > MacBookPro's (13,* and 14,*) are attached to an SPI controller instead
> > of USB, as previously. The higher level protocol is not publicly
> > documented and hence has been reverse engineered. As a consequence there
> > are still a number of unknown fields and commands. However, the known
> > parts have been working well and received extensive testing and use.
> >
> > In order for this driver to work, the proper SPI drivers need to be
> > loaded too; for MB8,1 these are spi_pxa2xx_platform and spi_pxa2xx_pci;
> > for all others they are spi_pxa2xx_platform and intel_lpss_pci. For this
> > reason enabling this driver in the config implies enabling the above
> > drivers.
>
> > +config KEYBOARD_APPLESPI
> > + tristate "Apple SPI keyboard and trackpad"
>
> > + depends on (X86 && ACPI && SPI) || COMPILE_TEST
>
> COMPILE_TEST more or less makes sense in conjunction with architecture selection.
> It means, your code always dependant to ACPI and SPI frameworks.
> That's why 0day complained.
Thanks. Yes, looking at this again I realized I somewhat misunderstood
the uses of COMPILE_TEST. I've changed this now to
depends on ACPI && SPI && (X86 || COMPILE_TEST)
Cheers,
Ronald
^ permalink raw reply
* Re: [PATCH 2/2] Input: add Apple SPI keyboard and trackpad driver.
From: Life is hard, and then you die @ 2019-02-05 13:15 UTC (permalink / raw)
To: Dan Carpenter
Cc: kbuild, kbuild-all, Dmitry Torokhov, Henrik Rydberg, Lukas Wunner,
Federico Lorenzi, Andy Shevchenko, linux-input, linux-kernel
In-Reply-To: <20190205102110.GG2581@kadam>
Hi Dan,
On Tue, Feb 05, 2019 at 01:21:10PM +0300, Dan Carpenter wrote:
> Hi Ronald,
>
> Thank you for the patch! Perhaps something to improve:
>
> url: https://github.com/0day-ci/linux/commits/Ronald-Tschal-r/drm-bridge-sil_sii8620-depend-on-INPUT-instead-of-selecting-it/20190205-003319
> base: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
>
> smatch warnings:
> drivers/input/keyboard/applespi.c:1551 applespi_get_saved_bl_level() warn: returning -1 instead of -ENOMEM is sloppy
[snip]
> cfa9f3705 Ronald Tschalär 2019-02-04 1549 efivar_entry = kmalloc(sizeof(*efivar_entry), GFP_KERNEL);
> cfa9f3705 Ronald Tschalär 2019-02-04 1550 if (!efivar_entry)
> cfa9f3705 Ronald Tschalär 2019-02-04 @1551 return -1;
Agreed, that is sloppy. Fixed in for next version. Thanks!
Cheers,
Ronald
^ permalink raw reply
* Re: [PATCH 0/2] Add Apple SPI keyboard and trackpad driver
From: Life is hard, and then you die @ 2019-02-05 13:14 UTC (permalink / raw)
To: Henrik Rydberg
Cc: Dmitry Torokhov, Lukas Wunner, Federico Lorenzi, Andy Shevchenko,
linux-input, linux-kernel
In-Reply-To: <cdca5121-4f2b-2f74-8a1c-63fda385ee6f@bitmath.org>
Hi Henrik,
On Mon, Feb 04, 2019 at 09:47:55PM +0100, Henrik Rydberg wrote:
> Hi Ronald,
>
> > This changeset adds a driver for the SPI keyboard and trackpad on recent
> > MacBook's and MacBook Pro's. The driver has seen a fair amount of use
> > over the last 2 years (basically anybody running linux on these
> > machines), with only relatively small changes in the last year or so.
> > For those interested, the driver development has been hosted at
> > https://github.com/cb22/macbook12-spi-driver/ (as well as my clone at
> > https://github.com/roadrunner2/macbook12-spi-driver/).
> >
> > The first patch is just a placeholder for now and is provided in case
> > somebody wants to compile the driver while it's being reviewed here; the
> > real patch has been submitted to dri-devel and is being discussed there,
> > with the intent/hope that I can get an Ack and permission to merge it
> > through the input subsystem tree here as part of this patch series.
>
> Great to see this upstream. The patch obviously has a lot in common with the
> previous keyboard and touchpad drivers; foremost this is a change of
> transport protocol and not functionality. That said, the code is compact and
> clear enough to make it hard to motivate any major effort to share more of
> existing code, at least initially.
Yes, some pieces have been copy-pasted from the existing drivers.
However, when I last reviewed those pieces they seemed a bit small and
I had a hard time seeing how to share them usefully at least for some
of it.
The pieces in question on the keyboard side (from the hid-apple
driver) are really the 'applespi_fn_codes' and 'apple_iso_keyboard'
tables, the corresponding 'applespi_find_translation()' function, and
some bits in the of the 'applespi_code_to_key()' function. Pulling out
the tables and maybe the applespi_find_translation() function into a
common include might be a simple change and take care of most of the
shared stuff.
A few lines were also lifted from the bcm5974 driver, basically the
'struct tp_finger' and the 'report_tp_state()' function. Though here
it's even harder to see how to share, as there are various small
differences scattered throughout the implemenation of that function.
> Barring detailed comments that are likely
> to produce new revisions, this looks like really good work.
Thank you for looking at this.
Cheers,
Ronald
^ permalink raw reply
* Re: [PATCH 2/2] Input: add Apple SPI keyboard and trackpad driver.
From: Andy Shevchenko @ 2019-02-05 11:45 UTC (permalink / raw)
To: Ronald Tschalär
Cc: Dmitry Torokhov, Henrik Rydberg, Lukas Wunner, Federico Lorenzi,
linux-input, linux-kernel
In-Reply-To: <20190204081947.25152-3-ronald@innovation.ch>
On Mon, Feb 04, 2019 at 12:19:47AM -0800, Ronald Tschalär wrote:
> The keyboard and trackpad on recent MacBook's (since 8,1) and
> MacBookPro's (13,* and 14,*) are attached to an SPI controller instead
> of USB, as previously. The higher level protocol is not publicly
> documented and hence has been reverse engineered. As a consequence there
> are still a number of unknown fields and commands. However, the known
> parts have been working well and received extensive testing and use.
>
> In order for this driver to work, the proper SPI drivers need to be
> loaded too; for MB8,1 these are spi_pxa2xx_platform and spi_pxa2xx_pci;
> for all others they are spi_pxa2xx_platform and intel_lpss_pci. For this
> reason enabling this driver in the config implies enabling the above
> drivers.
> +config KEYBOARD_APPLESPI
> + tristate "Apple SPI keyboard and trackpad"
> + depends on (X86 && ACPI && SPI) || COMPILE_TEST
COMPILE_TEST more or less makes sense in conjunction with architecture selection.
It means, your code always dependant to ACPI and SPI frameworks.
That's why 0day complained.
> + imply SPI_PXA2XX
> + imply SPI_PXA2XX_PCI
> + imply MFD_INTEL_LPSS_PCI
> + help
> + Say Y here if you are running Linux on any Apple MacBook8,1 or later,
> + or any MacBookPro13,* or MacBookPro14,*.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called applespi.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/2] Input: add Apple SPI keyboard and trackpad driver.
From: Dan Carpenter @ 2019-02-05 10:21 UTC (permalink / raw)
To: kbuild, Ronald Tschalär
Cc: Dmitry Torokhov, Henrik Rydberg, linux-kernel, Lukas Wunner,
Federico Lorenzi, kbuild-all, linux-input, Andy Shevchenko
In-Reply-To: <20190204081947.25152-3-ronald@innovation.ch>
Hi Ronald,
Thank you for the patch! Perhaps something to improve:
url: https://github.com/0day-ci/linux/commits/Ronald-Tschal-r/drm-bridge-sil_sii8620-depend-on-INPUT-instead-of-selecting-it/20190205-003319
base: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
smatch warnings:
drivers/input/keyboard/applespi.c:1551 applespi_get_saved_bl_level() warn: returning -1 instead of -ENOMEM is sloppy
# https://github.com/0day-ci/linux/commit/cfa9f37054a5b21113aa8b00c455275145114f8e
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout cfa9f37054a5b21113aa8b00c455275145114f8e
vim +1551 drivers/input/keyboard/applespi.c
cfa9f3705 Ronald Tschalär 2019-02-04 1541
cfa9f3705 Ronald Tschalär 2019-02-04 1542 static int applespi_get_saved_bl_level(void)
cfa9f3705 Ronald Tschalär 2019-02-04 1543 {
cfa9f3705 Ronald Tschalär 2019-02-04 1544 struct efivar_entry *efivar_entry;
cfa9f3705 Ronald Tschalär 2019-02-04 1545 u16 efi_data = 0;
cfa9f3705 Ronald Tschalär 2019-02-04 1546 unsigned long efi_data_len;
cfa9f3705 Ronald Tschalär 2019-02-04 1547 int sts;
cfa9f3705 Ronald Tschalär 2019-02-04 1548
cfa9f3705 Ronald Tschalär 2019-02-04 1549 efivar_entry = kmalloc(sizeof(*efivar_entry), GFP_KERNEL);
cfa9f3705 Ronald Tschalär 2019-02-04 1550 if (!efivar_entry)
cfa9f3705 Ronald Tschalär 2019-02-04 @1551 return -1;
cfa9f3705 Ronald Tschalär 2019-02-04 1552
cfa9f3705 Ronald Tschalär 2019-02-04 1553 memcpy(efivar_entry->var.VariableName, EFI_BL_LEVEL_NAME,
cfa9f3705 Ronald Tschalär 2019-02-04 1554 sizeof(EFI_BL_LEVEL_NAME));
cfa9f3705 Ronald Tschalär 2019-02-04 1555 efivar_entry->var.VendorGuid = EFI_BL_LEVEL_GUID;
cfa9f3705 Ronald Tschalär 2019-02-04 1556 efi_data_len = sizeof(efi_data);
cfa9f3705 Ronald Tschalär 2019-02-04 1557
cfa9f3705 Ronald Tschalär 2019-02-04 1558 sts = efivar_entry_get(efivar_entry, NULL, &efi_data_len, &efi_data);
cfa9f3705 Ronald Tschalär 2019-02-04 1559 if (sts && sts != -ENOENT)
cfa9f3705 Ronald Tschalär 2019-02-04 1560 pr_warn("Error getting backlight level from EFI vars: %d\n",
cfa9f3705 Ronald Tschalär 2019-02-04 1561 sts);
cfa9f3705 Ronald Tschalär 2019-02-04 1562
cfa9f3705 Ronald Tschalär 2019-02-04 1563 kfree(efivar_entry);
cfa9f3705 Ronald Tschalär 2019-02-04 1564
cfa9f3705 Ronald Tschalär 2019-02-04 1565 return efi_data;
cfa9f3705 Ronald Tschalär 2019-02-04 1566 }
cfa9f3705 Ronald Tschalär 2019-02-04 1567
^ permalink raw reply
* Re: [PATCH 2/2] Input: st1232 - switch to gpiod API
From: Martin Kepplinger @ 2019-02-05 10:20 UTC (permalink / raw)
To: Martin Kepplinger, devicetree, linux-input
Cc: dmitry.torokhov, robh+dt, mark.rutland, linux-kernel
In-Reply-To: <20190129102347.27754-2-martink@posteo.de>
[-- Attachment #1: Type: text/plain, Size: 3231 bytes --]
Martin Kepplinger | Entwicklung Software
GINZINGER ELECTRONIC SYSTEMS GMBH
Tel.: +43 7723 5422 157
Mail: martin.kepplinger@ginzinger.com
Web: www.ginzinger.com
On 29.01.19 11:23, Martin Kepplinger wrote:
> From: Martin Kepplinger <martin.kepplinger@ginzinger.com>
>
> Use devm_gpiod_get_optional() and gpiod_set_value_cansleep() instead
> of the old API. The st1232_ts_power() now passes on the inverted "poweron"
> value to reflect the correct logical value.
>
> Signed-off-by: Martin Kepplinger <martin.kepplinger@ginzinger.com>
> ---
>
> Tested and works. thanks for your help Dmitry,
>
is this what you had in mind? any problems or questions?
thanks
martin
>
>
>
> drivers/input/touchscreen/st1232.c | 22 ++++++++++------------
> 1 file changed, 10 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
> index 777df903605d..04d75b08be44 100644
> --- a/drivers/input/touchscreen/st1232.c
> +++ b/drivers/input/touchscreen/st1232.c
> @@ -45,7 +45,7 @@ struct st1232_ts_data {
> struct i2c_client *client;
> struct input_dev *input_dev;
> struct dev_pm_qos_request low_latency_req;
> - int reset_gpio;
> + struct gpio_desc *reset_gpio;
> const struct st_chip_info *chip_info;
> int read_buf_len;
> u8 *read_buf;
> @@ -142,8 +142,8 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
>
> static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron)
> {
> - if (gpio_is_valid(ts->reset_gpio))
> - gpio_direction_output(ts->reset_gpio, poweron);
> + if (ts->reset_gpio)
> + gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
> }
>
> static const struct st_chip_info st1232_chip_info = {
> @@ -215,15 +215,13 @@ static int st1232_ts_probe(struct i2c_client *client,
> ts->client = client;
> ts->input_dev = input_dev;
>
> - ts->reset_gpio = of_get_gpio(client->dev.of_node, 0);
> - if (gpio_is_valid(ts->reset_gpio)) {
> - error = devm_gpio_request(&client->dev, ts->reset_gpio, NULL);
> - if (error) {
> - dev_err(&client->dev,
> - "Unable to request GPIO pin %d.\n",
> - ts->reset_gpio);
> - return error;
> - }
> + ts->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
> + GPIOD_OUT_HIGH);
> + if (IS_ERR(ts->reset_gpio)) {
> + error = PTR_ERR(ts->reset_gpio);
> + dev_err(&client->dev, "Unable to request GPIO pin: %d.\n",
> + error);
> + return error;
> }
>
> st1232_ts_power(ts, true);
>
________________________________________
Ginzinger electronic systems GmbH
Gewerbegebiet Pirath 16
4952 Weng im Innkreis
www.ginzinger.com
Firmenbuchnummer: FN 364958d
Firmenbuchgericht: Ried im Innkreis
UID-Nr.: ATU66521089
Diese Nachricht ist vertraulich und darf nicht an andere Personen weitergegeben oder von diesen verwendet werden. Verständigen Sie uns, wenn Sie irrtümlich eine Mitteilung empfangen haben.
This message is confidential. It may not be disclosed to, or used by, anyone other than the addressee. If you receive this message by mistake, please advise the sender.
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 3616 bytes --]
^ permalink raw reply
* Re: [PATCH v3 2/3] Input: add new vibrator driver for various MSM SOCs
From: Brian Masney @ 2019-02-05 9:26 UTC (permalink / raw)
To: dmitry.torokhov
Cc: andy.gross, david.brown, robh+dt, mark.rutland, linux-input,
linux-kernel, linux-arm-msm, linux-soc, devicetree, jonathan
In-Reply-To: <20181025012937.2154-3-masneyb@onstation.org>
Hi Dmitry,
On Wed, Oct 24, 2018 at 09:29:36PM -0400, Brian Masney wrote:
> This patch adds a new vibrator driver that supports various Qualcomm
> MSM SOCs. Driver was tested on a LG Nexus 5 (hammerhead) phone.
>
> Signed-off-by: Brian Masney <masneyb@onstation.org>
Any chance that I can get a review of this patch series? Let me know if
you're not the right maintainer that I should send this series to.
Thanks,
Brian
^ permalink raw reply
* [PATCH v4 10/10] MAINTAINERS: add an entry for max77650 mfd driver
From: Bartosz Golaszewski @ 2019-02-05 9:12 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Linus Walleij, Dmitry Torokhov,
Jacek Anaszewski, Pavel Machek, Lee Jones, Sebastian Reichel,
Liam Girdwood, Greg Kroah-Hartman
Cc: linux-kernel, linux-gpio, devicetree, linux-input, linux-leds,
linux-pm, Bartosz Golaszewski
In-Reply-To: <20190205091237.6448-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
I plan on extending this set of drivers so add myself as maintainer.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
MAINTAINERS | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8c68de3cfd80..70106d30272b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9221,6 +9221,20 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/max9860.txt
F: sound/soc/codecs/max9860.*
+MAXIM MAX77650 PMIC MFD DRIVER
+M: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/*/*max77650.txt
+F: Documentation/devicetree/bindings/*/max77650*.txt
+F: include/linux/mfd/max77650.h
+F: drivers/mfd/max77650.c
+F: drivers/regulator/max77650-regulator.c
+F: drivers/power/supply/max77650-charger.c
+F: drivers/input/misc/max77650-onkey.c
+F: drivers/leds/leds-max77650.c
+F: drivers/gpio/gpio-max77650.c
+
MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
M: Javier Martinez Canillas <javier@dowhile0.org>
L: linux-kernel@vger.kernel.org
--
2.20.1
^ permalink raw reply related
* [PATCH v4 09/10] input: max77650: add onkey support
From: Bartosz Golaszewski @ 2019-02-05 9:12 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Linus Walleij, Dmitry Torokhov,
Jacek Anaszewski, Pavel Machek, Lee Jones, Sebastian Reichel,
Liam Girdwood, Greg Kroah-Hartman
Cc: linux-kernel, linux-gpio, devicetree, linux-input, linux-leds,
linux-pm, Bartosz Golaszewski
In-Reply-To: <20190205091237.6448-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Add support for the push- and slide-button events for max77650.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/misc/Kconfig | 9 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/max77650-onkey.c | 127 ++++++++++++++++++++++++++++
3 files changed, 137 insertions(+)
create mode 100644 drivers/input/misc/max77650-onkey.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ca59a2be9bc5..bb9c45c1269e 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -180,6 +180,15 @@ config INPUT_M68K_BEEP
tristate "M68k Beeper support"
depends on M68K
+config INPUT_MAX77650_ONKEY
+ tristate "Maxim MAX77650 ONKEY support"
+ depends on MFD_MAX77650
+ help
+ Support the ONKEY of the MAX77650 PMIC as an input device.
+
+ To compile this driver as a module, choose M here: the module
+ will be called max77650-onkey.
+
config INPUT_MAX77693_HAPTIC
tristate "MAXIM MAX77693/MAX77843 haptic controller support"
depends on (MFD_MAX77693 || MFD_MAX77843) && PWM
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 9d0f9d1ff68f..5bd53590ce60 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
+obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o
obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
diff --git a/drivers/input/misc/max77650-onkey.c b/drivers/input/misc/max77650-onkey.c
new file mode 100644
index 000000000000..7fc3e9196abb
--- /dev/null
+++ b/drivers/input/misc/max77650-onkey.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// ONKEY driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_ONKEY_MODE_MASK BIT(3)
+#define MAX77650_ONKEY_MODE_PUSH 0x00
+#define MAX77650_ONKEY_MODE_SLIDE BIT(3)
+
+struct max77650_onkey {
+ struct input_dev *input;
+ unsigned int code;
+};
+
+static irqreturn_t max77650_onkey_falling(int irq, void *data)
+{
+ struct max77650_onkey *onkey = data;
+
+ input_report_key(onkey->input, onkey->code, 0);
+ input_sync(onkey->input);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t max77650_onkey_rising(int irq, void *data)
+{
+ struct max77650_onkey *onkey = data;
+
+ input_report_key(onkey->input, onkey->code, 1);
+ input_sync(onkey->input);
+
+ return IRQ_HANDLED;
+}
+
+static int max77650_onkey_probe(struct platform_device *pdev)
+{
+ int irq_r, irq_f, error, mode;
+ struct max77650_onkey *onkey;
+ struct device *dev, *parent;
+ const char *mode_prop;
+ struct regmap *map;
+
+ dev = &pdev->dev;
+ parent = dev->parent;
+
+ map = dev_get_regmap(parent, NULL);
+ if (!map)
+ return -ENODEV;
+
+ onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+ if (!onkey)
+ return -ENOMEM;
+
+ error = device_property_read_u32(dev, "linux,code", &onkey->code);
+ if (error)
+ onkey->code = KEY_POWER;
+
+ error = device_property_read_string(dev,
+ "maxim,onkey-mode", &mode_prop);
+ if (error)
+ mode_prop = "push";
+
+ if (strcmp(mode_prop, "push") == 0)
+ mode = MAX77650_ONKEY_MODE_PUSH;
+ else if (strcmp(mode_prop, "slide") == 0)
+ mode = MAX77650_ONKEY_MODE_SLIDE;
+ else
+ return -EINVAL;
+
+ error = regmap_update_bits(map, MAX77650_REG_CNFG_GLBL,
+ MAX77650_ONKEY_MODE_MASK, mode);
+ if (error)
+ return error;
+
+ irq_f = platform_get_irq_byname(pdev, "nEN_F");
+ if (irq_f < 0)
+ return irq_f;
+
+ irq_r = platform_get_irq_byname(pdev, "nEN_R");
+ if (irq_r < 0)
+ return irq_r;
+
+ onkey->input = devm_input_allocate_device(dev);
+ if (!onkey->input)
+ return -ENOMEM;
+
+ onkey->input->name = "max77650_onkey";
+ onkey->input->phys = "max77650_onkey/input0";
+ onkey->input->id.bustype = BUS_I2C;
+ input_set_capability(onkey->input, EV_KEY, onkey->code);
+
+ error = devm_request_any_context_irq(dev, irq_f,
+ max77650_onkey_falling,
+ IRQF_ONESHOT, "onkey-down",
+ onkey);
+ if (error < 0)
+ return error;
+
+ error = devm_request_any_context_irq(dev, irq_r, max77650_onkey_rising,
+ IRQF_ONESHOT, "onkey-up", onkey);
+ if (error < 0)
+ return error;
+
+ return input_register_device(onkey->input);
+}
+
+static struct platform_driver max77650_onkey_driver = {
+ .driver = {
+ .name = "max77650-onkey",
+ },
+ .probe = max77650_onkey_probe,
+};
+module_platform_driver(max77650_onkey_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 ONKEY driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
--
2.20.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox