From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755342AbbCCBfk (ORCPT ); Mon, 2 Mar 2015 20:35:40 -0500 Received: from mailout3.samsung.com ([203.254.224.33]:43531 "EHLO mailout3.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752896AbbCCBfh (ORCPT ); Mon, 2 Mar 2015 20:35:37 -0500 X-AuditID: cbfee68e-f79b46d000002b74-7e-54f50fe68756 Message-id: <54F50FE5.3060605@samsung.com> Date: Tue, 03 Mar 2015 10:35:33 +0900 From: Jaewon Kim User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-version: 1.0 To: Dmitry Torokhov Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-pm@vger.kernel.org, linux-input@vger.kernel.org, Inki Dae , SangBae Lee , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Lee Jones , Chanwoo Choi , Sebastian Reichel , Beomho Seo Subject: Re: [PATCH v7 4/5] Input: add haptic drvier on max77843 References: <1425291038-18269-1-git-send-email-jaewon02.kim@samsung.com> <1425291038-18269-5-git-send-email-jaewon02.kim@samsung.com> <20150302173223.GA17094@dtor-ws> In-reply-to: <20150302173223.GA17094@dtor-ws> Content-type: text/plain; charset=windows-1252; format=flowed Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrAIsWRmVeSWpSXmKPExsWyRsSkWPcZ/9cQg+nPNC1Of9rGbnH9y3NW i/lHzrFaHF70gtGi/81CVotzr1YyWky6P4HF4v7Xo4wWNz99Y7W4vGsOm8Xn3iOMFkuvX2Sy mDB9LYtF694j7BbHPx1ksTi9u8RBwGPNvDWMHpf7epk8ds66y+6xcvkXNo9NqzrZPO5c28Pm 0bdlFaPH501yARxRXDYpqTmZZalF+nYJXBlrFqQV9KVV3Hr0jLGBcVpwFyMnh4SAicTzqx9Y IWwxiQv31rN1MXJxCAksZZS4Ma+XBabo281zUIlFjBJntqxkgXBeM0rMXHycGaSKV0BLYtH8 BrAOFgFViWWPvoPF2QS0Jb6vXwy2QlQgQmL+sddQ9YISPybfA6sXEdCX2D77FyPIUGaB6SwS h48cBWsQFnCQeLtmDSvEtlWMEhee/GACSXAK6Eo8mzKREcRmFrCVWPB+HQuELS+xec1bZpAG CYGFHBJPNi5jhThJQOLb5ENARRxACVmJTQeYIX6TlDi44gbLBEaxWUiOmoVk7CwkYxcwMq9i FE0tSC4oTkovMtIrTswtLs1L10vOz93ECIz40/+e9e1gvHnA+hCjAAejEg/vC86vIUKsiWXF lbmHGE2BrpjILCWanA9MK3kl8YbGZkYWpiamxkbmlmZK4rwJUj+DhQTSE0tSs1NTC1KL4otK c1KLDzEycXBKNTAu2r++5tXuoEt/P5lWvptwxnVuUNL8EkG/OfplK4yNxVcsesgYVZ70JueL 1juvyUnG2U5On2Rt3/gciDFk05cJ5Pw4+3zyv2ihPQtfKmqe/N6uaS4xM2dChEHLV4YznsHJ 3UtO8/g+TpgyJaaG/2LdlvNv9n94Xer0Zb5NxDv2DV1qKQznj2gqsRRnJBpqMRcVJwIASQbb 8fMCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrFKsWRmVeSWpSXmKPExsVy+t9jAd1n/F9DDN62yVmc/rSN3eL6l+es FvOPnGO1OLzoBaNF/5uFrBbnXq1ktJh0fwKLxf2vRxktbn76xmpxedccNovPvUcYLZZev8hk MWH6WhaL1r1H2C2OfzrIYnF6d4mDgMeaeWsYPS739TJ57Jx1l91j5fIvbB6bVnWyedy5tofN o2/LKkaPz5vkAjiiGhhtMlITU1KLFFLzkvNTMvPSbZW8g+Od403NDAx1DS0tzJUU8hJzU22V XHwCdN0yc4BeUFIoS8wpBQoFJBYXK+nbYZoQGuKmawHTGKHrGxIE12NkgAYS1jBmrFmQVtCX VnHr0TPGBsZpwV2MnBwSAiYS326eY4OwxSQu3FsPZHNxCAksYpQ4s2UlC4TzmlFi5uLjzCBV vAJaEovmN7CA2CwCqhLLHn0Hi7MJaEt8X7+YFcQWFYiQmH/sNVS9oMSPyffA6kUE9CW2z/7F CDKUWWA6i8ThI0fBGoQFHCTerlnDCrFtFaPEhSc/mEASnAK6Es+mTGQEsZkFbCUWvF/HAmHL S2xe85Z5AqPALCRLZiEpm4WkbAEj8ypG0dSC5ILipPRcQ73ixNzi0rx0veT83E2M4HTyTGoH 48oGi0OMAhyMSjy8Lzi/hgixJpYVV+YeYpTgYFYS4Y1gAgrxpiRWVqUW5ccXleakFh9iNAWG wURmKdHkfGCqyyuJNzQ2MTOyNDI3tDAyNlcS51WybwsREkhPLEnNTk0tSC2C6WPi4JRqYDTc /dbUdf3VrOaYVXlzaqLYl+X9F0oWPlbv79Z4qfHKBRXpAxs/7jwWd8veKz3O4JPnbY47zt8E H6w1WJ+jP+Ho3bzpN1IdHkbPdpDqUHztdS5t1svI3pKV9RZT9fat35nvnDG52FhASrW+vTCI dYH3zClC+klHM92S/kw50bNts9sTJr+S80osxRmJhlrMRcWJACdxe8Y9AwAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Dmitry, On 03/03/2015 02:32, Dmitry Torokhov wrote: > On Mon, Mar 02, 2015 at 07:10:37PM +0900, Jaewon Kim wrote: >> This patch adds support for haptic driver on max77843 >> MFD(Multi Function Device) with PMIC, MUIC, LED, CHARGER. >> >> This driver supports external pwm and LRA(Linear Resonant Actuator) motor. >> And it supports ff-memless interface from inpu framework. >> >> Cc: Dmitry Torokhov >> Signed-off-by: Jaewon Kim > Acked-by: Dmitry Torokhov > > Do you want it to go through my or MFD tree? Other drivers merged in each maintainers git. If you don`t hava a problem, please merge your input git tree. > >> --- >> drivers/input/misc/Kconfig | 12 ++ >> drivers/input/misc/Makefile | 1 + >> drivers/input/misc/max77843-haptic.c | 358 ++++++++++++++++++++++++++++++++++ >> 3 files changed, 371 insertions(+) >> create mode 100644 drivers/input/misc/max77843-haptic.c >> >> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig >> index 6deb8da..aa8c072 100644 >> --- a/drivers/input/misc/Kconfig >> +++ b/drivers/input/misc/Kconfig >> @@ -165,6 +165,18 @@ config INPUT_MAX77693_HAPTIC >> To compile this driver as module, choose M here: the >> module will be called max77693-haptic. >> >> +config INPUT_MAX77843_HAPTIC >> + tristate "MAXIM MAX77843 haptic controller support" >> + depends on MFD_MAX77843 && PWM >> + select INPUT_FF_MEMLESS >> + help >> + This option enables support for the haptic controller on >> + MAXIM MAX77843 chip. The driver supports ff-memless interface >> + from input framework. >> + >> + To compile this driver as module, choose M here: the >> + module will be called max77843-haptic. >> + >> config INPUT_MAX8925_ONKEY >> tristate "MAX8925 ONKEY support" >> depends on MFD_MAX8925 >> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile >> index 403a1a5..75b5884 100644 >> --- a/drivers/input/misc/Makefile >> +++ b/drivers/input/misc/Makefile >> @@ -39,6 +39,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o >> obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o >> obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o >> obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o >> +obj-$(CONFIG_INPUT_MAX77843_HAPTIC) += max77843-haptic.o >> obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o >> obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o >> obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o >> diff --git a/drivers/input/misc/max77843-haptic.c b/drivers/input/misc/max77843-haptic.c >> new file mode 100644 >> index 0000000..eef9862 >> --- /dev/null >> +++ b/drivers/input/misc/max77843-haptic.c >> @@ -0,0 +1,358 @@ >> +/* >> + * MAXIM MAX77693 Haptic device driver >> + * >> + * Copyright (C) 2015 Samsung Electronics >> + * Author: Jaewon Kim >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define MAX_MAGNITUDE_SHIFT 16 >> + >> +enum max77843_haptic_motor_type { >> + MAX77843_HAPTIC_ERM = 0, >> + MAX77843_HAPTIC_LRA, >> +}; >> + >> +enum max77843_haptic_pwm_divisor { >> + MAX77843_HAPTIC_PWM_DIVISOR_32 = 0, >> + MAX77843_HAPTIC_PWM_DIVISOR_64, >> + MAX77843_HAPTIC_PWM_DIVISOR_128, >> + MAX77843_HAPTIC_PWM_DIVISOR_256, >> +}; >> + >> +struct max77843_haptic { >> + struct regmap *regmap_haptic; >> + struct device *dev; >> + struct input_dev *input_dev; >> + struct pwm_device *pwm_dev; >> + struct regulator *motor_reg; >> + struct work_struct work; >> + struct mutex mutex; >> + >> + unsigned int magnitude; >> + unsigned int pwm_duty; >> + >> + bool active; >> + bool suspended; >> + >> + enum max77843_haptic_motor_type type; >> + enum max77843_haptic_pwm_divisor pwm_divisor; >> +}; >> + >> +static int max77843_haptic_set_duty_cycle(struct max77843_haptic *haptic) >> +{ >> + int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2; >> + int error; >> + >> + error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period); >> + if (error) { >> + dev_err(haptic->dev, "failed to configure pwm: %d\n", error); >> + return error; >> + } >> + >> + return 0; >> +} >> + >> +static int max77843_haptic_bias(struct max77843_haptic *haptic, bool on) >> +{ >> + int error; >> + >> + error = regmap_update_bits(haptic->regmap_haptic, >> + MAX77843_SYS_REG_MAINCTRL1, >> + MAX77843_MAINCTRL1_BIASEN_MASK, >> + on << MAINCTRL1_BIASEN_SHIFT); >> + if (error) { >> + dev_err(haptic->dev, "failed to %s bias: %d\n", >> + on ? "enable" : "disable", error); >> + return error; >> + } >> + >> + return 0; >> +} >> + >> +static int max77843_haptic_config(struct max77843_haptic *haptic, bool enable) >> +{ >> + unsigned int value; >> + int error; >> + >> + value = ((haptic->type << MCONFIG_MODE_SHIFT) | >> + (enable << MCONFIG_MEN_SHIFT) | >> + (haptic->pwm_divisor << MCONFIG_PDIV_SHIFT)); >> + >> + error = regmap_write(haptic->regmap_haptic, >> + MAX77843_HAP_REG_MCONFIG, value); >> + if (error) { >> + dev_err(haptic->dev, >> + "failed to update haptic config: %d\n", error); >> + return error; >> + } >> + >> + return 0; >> +} >> + >> +static int max77843_haptic_enable(struct max77843_haptic *haptic) >> +{ >> + int error; >> + >> + if (haptic->active) >> + return 0; >> + >> + error = pwm_enable(haptic->pwm_dev); >> + if (error) { >> + dev_err(haptic->dev, >> + "failed to enable pwm device: %d\n", error); >> + return error; >> + } >> + >> + error = max77843_haptic_config(haptic, true); >> + if (error) >> + goto err_config; >> + >> + haptic->active = true; >> + >> + return 0; >> + >> +err_config: >> + pwm_disable(haptic->pwm_dev); >> + >> + return error; >> +} >> + >> +static int max77843_haptic_disable(struct max77843_haptic *haptic) >> +{ >> + int error; >> + >> + if (!haptic->active) >> + return 0; >> + >> + error = max77843_haptic_config(haptic, false); >> + if (error) >> + return error; >> + >> + pwm_disable(haptic->pwm_dev); >> + >> + haptic->active = false; >> + >> + return 0; >> +} >> + >> +static void max77843_haptic_play_work(struct work_struct *work) >> +{ >> + struct max77843_haptic *haptic = >> + container_of(work, struct max77843_haptic, work); >> + int error; >> + >> + mutex_lock(&haptic->mutex); >> + >> + if (haptic->suspended) >> + goto out_unlock; >> + >> + if (haptic->magnitude) { >> + error = max77843_haptic_set_duty_cycle(haptic); >> + if (error) { >> + dev_err(haptic->dev, >> + "failed to set duty cycle: %d\n", error); >> + goto out_unlock; >> + } >> + >> + error = max77843_haptic_enable(haptic); >> + if (error) >> + dev_err(haptic->dev, >> + "cannot enable haptic: %d\n", error); >> + } else { >> + error = max77843_haptic_disable(haptic); >> + if (error) >> + dev_err(haptic->dev, >> + "cannot disable haptic: %d\n", error); >> + } >> + >> +out_unlock: >> + mutex_unlock(&haptic->mutex); >> +} >> + >> +static int max77843_haptic_play_effect(struct input_dev *dev, void *data, >> + struct ff_effect *effect) >> +{ >> + struct max77843_haptic *haptic = input_get_drvdata(dev); >> + u64 period_mag_multi; >> + >> + haptic->magnitude = effect->u.rumble.strong_magnitude; >> + if (!haptic->magnitude) >> + haptic->magnitude = effect->u.rumble.weak_magnitude; >> + >> + period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude; >> + haptic->pwm_duty = (unsigned int)(period_mag_multi >> >> + MAX_MAGNITUDE_SHIFT); >> + >> + schedule_work(&haptic->work); >> + >> + return 0; >> +} >> + >> +static int max77843_haptic_open(struct input_dev *dev) >> +{ >> + struct max77843_haptic *haptic = input_get_drvdata(dev); >> + int error; >> + >> + error = max77843_haptic_bias(haptic, true); >> + if (error) >> + return error; >> + >> + error = regulator_enable(haptic->motor_reg); >> + if (error) { >> + dev_err(haptic->dev, >> + "failed to enable regulator: %d\n", error); >> + return error; >> + } >> + >> + return 0; >> +} >> + >> +static void max77843_haptic_close(struct input_dev *dev) >> +{ >> + struct max77843_haptic *haptic = input_get_drvdata(dev); >> + int error; >> + >> + cancel_work_sync(&haptic->work); >> + max77843_haptic_disable(haptic); >> + >> + error = regulator_disable(haptic->motor_reg); >> + if (error) >> + dev_err(haptic->dev, >> + "failed to disable regulator: %d\n", error); >> + >> + max77843_haptic_bias(haptic, false); >> +} >> + >> +static int max77843_haptic_probe(struct platform_device *pdev) >> +{ >> + struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); >> + struct max77843_haptic *haptic; >> + int error; >> + >> + haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL); >> + if (!haptic) >> + return -ENOMEM; >> + >> + haptic->regmap_haptic = max77843->regmap; >> + haptic->dev = &pdev->dev; >> + haptic->type = MAX77843_HAPTIC_LRA; >> + haptic->pwm_divisor = MAX77843_HAPTIC_PWM_DIVISOR_128; >> + >> + INIT_WORK(&haptic->work, max77843_haptic_play_work); >> + mutex_init(&haptic->mutex); >> + >> + haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL); >> + if (IS_ERR(haptic->pwm_dev)) { >> + dev_err(&pdev->dev, "failed to get pwm device\n"); >> + return PTR_ERR(haptic->pwm_dev); >> + } >> + >> + haptic->motor_reg = devm_regulator_get_exclusive(&pdev->dev, "haptic"); >> + if (IS_ERR(haptic->motor_reg)) { >> + dev_err(&pdev->dev, "failed to get regulator\n"); >> + return PTR_ERR(haptic->motor_reg); >> + } >> + >> + haptic->input_dev = devm_input_allocate_device(&pdev->dev); >> + if (!haptic->input_dev) { >> + dev_err(&pdev->dev, "failed to allocate input device\n"); >> + return -ENOMEM; >> + } >> + >> + haptic->input_dev->name = "max77843-haptic"; >> + haptic->input_dev->id.version = 1; >> + haptic->input_dev->dev.parent = &pdev->dev; >> + haptic->input_dev->open = max77843_haptic_open; >> + haptic->input_dev->close = max77843_haptic_close; >> + input_set_drvdata(haptic->input_dev, haptic); >> + input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE); >> + >> + error = input_ff_create_memless(haptic->input_dev, NULL, >> + max77843_haptic_play_effect); >> + if (error) { >> + dev_err(&pdev->dev, "failed to create force-feedback\n"); >> + return error; >> + } >> + >> + error = input_register_device(haptic->input_dev); >> + if (error) { >> + dev_err(&pdev->dev, "failed to register input device\n"); >> + return error; >> + } >> + >> + platform_set_drvdata(pdev, haptic); >> + >> + return 0; >> +} >> + >> +static int __maybe_unused max77843_haptic_suspend(struct device *dev) >> +{ >> + struct platform_device *pdev = to_platform_device(dev); >> + struct max77843_haptic *haptic = platform_get_drvdata(pdev); >> + int error; >> + >> + error = mutex_lock_interruptible(&haptic->mutex); >> + if (error) >> + return error; >> + >> + max77843_haptic_disable(haptic); >> + >> + haptic->suspended = true; >> + >> + mutex_unlock(&haptic->mutex); >> + >> + return 0; >> +} >> + >> +static int __maybe_unused max77843_haptic_resume(struct device *dev) >> +{ >> + struct platform_device *pdev = to_platform_device(dev); >> + struct max77843_haptic *haptic = platform_get_drvdata(pdev); >> + unsigned int magnitude; >> + >> + mutex_lock(&haptic->mutex); >> + >> + haptic->suspended = false; >> + >> + magnitude = ACCESS_ONCE(haptic->magnitude); >> + if (magnitude) >> + max77843_haptic_enable(haptic); >> + >> + mutex_unlock(&haptic->mutex); >> + >> + return 0; >> +} >> + >> +static SIMPLE_DEV_PM_OPS(max77843_haptic_pm_ops, >> + max77843_haptic_suspend, max77843_haptic_resume); >> + >> +static struct platform_driver max77843_haptic_driver = { >> + .driver = { >> + .name = "max77843-haptic", >> + .pm = &max77843_haptic_pm_ops, >> + }, >> + .probe = max77843_haptic_probe, >> +}; >> +module_platform_driver(max77843_haptic_driver); >> + >> +MODULE_AUTHOR("Jaewon Kim "); >> +MODULE_DESCRIPTION("MAXIM MAX77843 Haptic driver"); >> +MODULE_LICENSE("GPL"); >> -- >> 1.7.9.5 >> > Thanks. > Thanks to review my patch. Thanks, Jaewon Kim