Skip to contentSkip to conversation

input: add driver support for MAX8997-haptic

PATCH In review Chanwoo Choi 3 participants 9 messages Mar 12, 2012 – Mar 16, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v3 2/2 input: add driver support for MAX8997-haptic

The MAX8997-haptic function can be used to control motor. User can control the haptic driver by using force feedback framework. This patch supports the haptic function in MAX8997.

---
v2
- code clean and remove unnecessary code according to comment of Dmitry Torokhov

v3
- use work_struct to enable/disable max8997-haptic instead of using mutex in irq handler statck of forced feedbacky

 drivers/input/misc/Kconfig          |   12 +
 drivers/input/misc/Makefile         |    1 +
 drivers/input/misc/max8997_haptic.c |  377
+++++++++++++++++++++++++++++++++++
 3 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/misc/max8997_haptic.c
drivers/input/misc/Kconfig +12 -0
index 7b46781..c828c2e 100644
@@ -134,6 +134,18 @@ config INPUT_MAX8925_ONKEY
 	  To compile this driver as a module, choose M here: the module
 	  will be called max8925_onkey.
 
+config INPUT_MAX8997_HAPTIC
+	tristate "MAXIM MAX8997 haptic controller support"
+	depends on HAVE_PWM && MFD_MAX8997
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the haptic controller
+	  on MAXIM MAX8997 chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called max8997-haptic.
+
 config INPUT_MC13783_PWRBUTTON
 	tristate "MC13783 ON buttons"
 	depends on MFD_MC13783
drivers/input/misc/Makefile +1 -0
index 46671a8..f0574a6 100644
@@ -30,6 +30,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_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_MPU3050)		+= mpu3050.o
(quoted diff) +0 -0

b/drivers/input/misc/max8997_haptic.c
new file mode 100644
index 0000000..ee02d7e

drivers/input/misc/max8997_haptic.c new file +21 -0
@@ -0,0 +1,377 @@
+/*
+ *  MAX8997-haptic controller driver
+ *
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Donggeun Kim <[email protected]>
+ *
+ * This program is not provided / owned by Maxim Integrated Products.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307

USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+#include <linux/input.h>
+#include <linux/mfd/max8997-private.h>
+#include <linux/mfd/max8997.h>
+#include <linux/regulator/consumer.h>
+
+/* Haptic configuration 2 register */
+#define MAX8997_MOTOR_TYPE_SHIFT 7
+#define MAX8997_ENABLE_SHIFT 6
+#define MAX8997_MODE_SHIFT 5
+
+/* Haptic driver configuration register */
+#define MAX8997_CYCLE_SHIFT 6
+#define MAX8997_SIG_PERIOD_SHIFT 4
+#define MAX8997_SIG_DUTY_SHIFT 2
+#define MAX8997_PWM_DUTY_SHIFT 0
+
+struct max8997_haptic {
+ struct device *dev;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct regulator *regulator;
+ struct work_struct work;
+
+ bool enabled;
+
+ unsigned int level;
+
+ struct pwm_device *pwm;
+ int pwm_period;
+ enum max8997_haptic_pwm_divisor pwm_divisor;
+
+ enum max8997_haptic_motor_type type;
+ enum max8997_haptic_pulse_mode mode;
+
+ int internal_mode_pattern;
+ int pattern_cycle;
+ int pattern_signal_period;
+};
+
+static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip) +{
+ int duty, i;
+ int ret;
+ u8 duty_index;
+
+ if (chip->mode == MAX8997_EXTERNAL_MODE) {
+ duty = chip->pwm_period * chip->level / 100;
+ ret = pwm_config(chip->pwm, duty, chip->pwm_period);
+ } else {
+ for (i = 0; i <= 64; i++) {
+ if (chip->level <= i * 100 / 64) {
+ duty_index = i;
+ break;
+ }
+ }
+ switch (chip->internal_mode_pattern) {
+ case 0:
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
+ break;
+ case 1:
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
+ break;
+ case 2:
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
+ break;
+ case 3:
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
+ break;
+ default:
+ break;
+ }
+ }
+ return ret;
+}
+
+static void max8997_haptic_configure(struct max8997_haptic *chip) +{
+ u8 value;
+
+ value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
+ chip->enabled << MAX8997_ENABLE_SHIFT |
+ chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
+ max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
+
+ if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
+ value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |

+		      chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
+		      chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
+		      chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;

+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_DRVCONF, value);
+
+ switch (chip->internal_mode_pattern) {
+ case 0:
+ value = chip->pattern_cycle << 4;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_CYCLECONF1, value);
+ value = chip->pattern_signal_period;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGCONF1, value);
+ break;
+ case 1:
+ value = chip->pattern_cycle;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_CYCLECONF1, value);
+ value = chip->pattern_signal_period;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGCONF2, value);
+ break;
+ case 2:
+ value = chip->pattern_cycle << 4;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_CYCLECONF2, value);
+ value = chip->pattern_signal_period;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGCONF3, value);
+ break;
+ case 3:
+ value = chip->pattern_cycle;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_CYCLECONF2, value);
+ value = chip->pattern_signal_period;
+ max8997_write_reg(chip->client,
+ MAX8997_HAPTIC_REG_SIGCONF4, value);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void max8997_haptic_enable(struct max8997_haptic *chip, bool enable) +{
+ if (chip->enabled == enable)
+ return;
+
+ chip->enabled = enable;
+
+ if (enable) {
+ regulator_enable(chip->regulator);
+ max8997_haptic_configure(chip);
+ if (chip->mode == MAX8997_EXTERNAL_MODE)
+ pwm_enable(chip->pwm);
+ } else {
+ max8997_haptic_configure(chip);
+ if (chip->mode == MAX8997_EXTERNAL_MODE)
+ pwm_disable(chip->pwm);
+ regulator_disable(chip->regulator);
+ }
+}
+
+static void max8997_haptic_play_effect_work(struct work_struct *work) +{
+ struct max8997_haptic *chip =
+ container_of(work, struct max8997_haptic, work);
+ int ret;
+
+ if (chip->level) {
+ ret = max8997_haptic_set_duty_cycle(chip);
+ if (ret) {
+ dev_err(chip->dev, "set_pwm_cycle failed\n");
+ return;
+ }
+ max8997_haptic_enable(chip, true);
+ } else
+ max8997_haptic_enable(chip, false);
+}
+
+
+static int max8997_haptic_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct max8997_haptic *chip = input_get_drvdata(dev);
+
+ chip->level = effect->u.rumble.strong_magnitude;
+ if (!chip->level)
+ chip->level = effect->u.rumble.weak_magnitude;
+
+ schedule_work(&chip->work);
+
+ return 0;
+}
+
+static int __devinit max8997_haptic_probe(struct platform_device *pdev) +{
+ struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct max8997_haptic_platform_data *haptic_pdata =
+ pdata->haptic_pdata;
+ struct max8997_haptic *chip;
+ struct input_dev *input_dev;
+ int ret;
+
+ if (!haptic_pdata) {
+ dev_err(&pdev->dev, "no haptic platform data\n");
+ return -EINVAL;
+ }
+
+ chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL);
+ if (!chip) {
+ dev_err(&pdev->dev, "unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&pdev->dev,
+ "unable to allocate memory for input dev\n");
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ chip->client = iodev->haptic;
+ chip->dev = &pdev->dev;
+ chip->input_dev = input_dev;
+ chip->pwm_period = haptic_pdata->pwm_period;
+ chip->type = haptic_pdata->type;
+ chip->mode = haptic_pdata->mode;
+ chip->pwm_divisor = haptic_pdata->pwm_divisor;
+ if (chip->mode == MAX8997_INTERNAL_MODE) {
+ chip->internal_mode_pattern =
+ haptic_pdata->internal_mode_pattern;
+ chip->pattern_cycle = haptic_pdata->pattern_cycle;
+ chip->pattern_signal_period =
+ haptic_pdata->pattern_signal_period;
+ }
+
+ if (chip->mode == MAX8997_EXTERNAL_MODE) {
+ chip->pwm = pwm_request(haptic_pdata->pwm_channel_id,
+ "max8997-haptic");
+ if (IS_ERR(chip->pwm)) {
+ dev_err(&pdev->dev,
+ "unable to request PWM for haptic\n");
+ ret = PTR_ERR(chip->pwm);
+ goto err_pwm;
+ }
+ }
+
+ chip->regulator = regulator_get(&pdev->dev, "inmotor");
+ if (IS_ERR(chip->regulator)) {
+ dev_err(&pdev->dev, "unable to get regulator\n");
+ ret = PTR_ERR(chip->regulator);
+ goto err_regulator;
+ }
+
+ platform_set_drvdata(pdev, chip);
+
+ input_dev->name = "max8997-haptic";
+ input_dev->id.version = 1;
+ input_dev->dev.parent = &pdev->dev;
+ input_set_drvdata(input_dev, chip);
+ input_set_capability(input_dev, EV_FF, FF_RUMBLE);
+
+ ret = input_ff_create_memless(input_dev, NULL,
+ max8997_haptic_play_effect);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "unable to create FF device(ret : %d)\n", ret);
+ goto err_ff_memless;
+ }
+ INIT_WORK(&chip->work,
+ max8997_haptic_play_effect_work);
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "unable to register input device(ret : %d)\n", ret);
+ goto err_input_register;
+ }
+
+ return 0;
+
+err_input_register:
+ destroy_work_on_stack(&chip->work);
+ input_ff_destroy(input_dev);
+err_ff_memless:
+ regulator_put(chip->regulator);
+err_regulator:
+ if (chip->mode == MAX8997_EXTERNAL_MODE)
+ pwm_free(chip->pwm);
+err_pwm:
+ input_free_device(input_dev);
+err_input_alloc:
+ kfree(chip);
+
+ return ret;
+}
+
+static int __devexit max8997_haptic_remove(struct platform_device *pdev) +{
+ struct max8997_haptic *chip = platform_get_drvdata(pdev);
+
+ destroy_work_on_stack(&chip->work);
+ input_unregister_device(chip->input_dev);
+ regulator_put(chip->regulator);
+
+ if (chip->mode == MAX8997_EXTERNAL_MODE)
+ pwm_free(chip->pwm);
+
+ kfree(chip);
+
+ return 0;
+}
+
+static int max8997_haptic_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct max8997_haptic *chip = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = chip->input_dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&input_dev->event_lock, flags);
+ max8997_haptic_enable(chip, false);
+ spin_unlock_irqrestore(&input_dev->event_lock, flags);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
+
+static const struct platform_device_id max8997_haptic_id[] = {
+ { "max8997-haptic", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, max8997_haptic_id);
+
+static struct platform_driver max8997_haptic_driver = {
+ .driver = {
+ .name = "max8997-haptic",
+ .owner = THIS_MODULE,
+ .pm = &max8997_haptic_pm_ops,
+ },
+ .probe = max8997_haptic_probe,
+ .remove = __devexit_p(max8997_haptic_remove),
+ .id_table = max8997_haptic_id,
+};
+
+module_platform_driver(max8997_haptic_driver);
+
+MODULE_ALIAS("platform:max8997-haptic"); +MODULE_AUTHOR("Donggeun Kim <[email protected]>"); +MODULE_DESCRIPTION("max8997_haptic driver"); +MODULE_LICENSE("GPL");

Signature · 1 line
1.7.0.4
maintainer
#1 lore raw

Hi Chanwoo,

Review

Quoted 6 lines · Chanwoo Choi
(quoted diff) +6 -0
+
+static int __devexit max8997_haptic_remove(struct platform_device *pdev)
+{
+	struct max8997_haptic *chip = platform_get_drvdata(pdev);
+
+	destroy_work_on_stack(&chip->work);

This does not make sense because:

- chip->work is not on stack
- even if you "destroy" work nothing stops play effect to schedule a new one - you need to cancel work in close method.

Quoted 12 lines
(quoted diff) +12 -0
+	input_unregister_device(chip->input_dev);
+	regulator_put(chip->regulator);
+
+	if (chip->mode == MAX8997_EXTERNAL_MODE)
+		pwm_free(chip->pwm);
+
+	kfree(chip);
+
+	return 0;
+}
+
+static int max8997_haptic_suspend(struct device *dev)

Review

Quoted 10 lines
(quoted diff) +10 -0
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct max8997_haptic *chip = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = chip->input_dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&input_dev->event_lock, flags);
+	max8997_haptic_enable(chip, false);
+	spin_unlock_irqrestore(&input_dev->event_lock, flags);
+

This is not proper locking between playing effect and suspend. Now that you are using workqueue you need to synchronize access with it, not with play_effect method.

Does the following patch work for you?

Thanks.

Signature · 22 lines
Dmitry


Input: add driver support for MAX8997-haptic

From: Donggeun Kim <[email protected]>

The MAX8997-haptic function can be used to control motor. User can
control the haptic driver by using force feedback framework.

Signed-off-by: Donggeun Kim <[email protected]>
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
---

 drivers/input/misc/Kconfig          |   12 +
 drivers/input/misc/Makefile         |    1 
 drivers/input/misc/max8997_haptic.c |  407 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/max8997.h         |   53 ++++-
 4 files changed, 472 insertions(+), 1 deletions(-)
 create mode 100644 drivers/input/misc/max8997_haptic.c
drivers/input/misc/Kconfig +12 -0
index 2337c3e..ee077a4 100644
@@ -134,6 +134,18 @@ config INPUT_MAX8925_ONKEY
 	  To compile this driver as a module, choose M here: the module
 	  will be called max8925_onkey.
 
+config INPUT_MAX8997_HAPTIC
+	tristate "MAXIM MAX8997 haptic controller support"
+	depends on HAVE_PWM && MFD_MAX8997
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the haptic controller
+	  on MAXIM MAX8997 chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called max8997-haptic.
+
 config INPUT_MC13783_PWRBUTTON
 	tristate "MC13783 ON buttons"
 	depends on MFD_MC13783
drivers/input/misc/Makefile +1 -0
index a6d8de0..f55cdf4 100644
@@ -31,6 +31,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_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_MPU3050)		+= mpu3050.o
drivers/input/misc/max8997_haptic.c new file +407 -0

407 lines not on this page · raw message

include/linux/mfd/max8997.h +52 -1

65 lines not on this page · raw message

#2 lore raw
Quoted 12 lines · Dmitry Torokhov

Hi Chanwoo,

drivers/input/misc/max8997_haptic.c

Quoted 6 lines · Chanwoo Choi
drivers/input/misc/max8997_haptic.c new file +6 -0
+
+static int __devexit max8997_haptic_remove(struct platform_device *pdev)
+{
+	struct max8997_haptic *chip = platform_get_drvdata(pdev);
+
+	destroy_work_on_stack(&chip->work);

This does not make sense because:

Quoted 4 lines

- chip->work is not on stack
- even if you "destroy" work nothing stops play effect to schedule a new one - you need to cancel work in close method.

Agreed, I will fix it.

Quoted 27 lines
Quoted 12 lines
drivers/input/misc/max8997_haptic.c new file +12 -0
+	input_unregister_device(chip->input_dev);
+	regulator_put(chip->regulator);
+
+	if (chip->mode == MAX8997_EXTERNAL_MODE)
+		pwm_free(chip->pwm);
+
+	kfree(chip);
+
+	return 0;
+}
+
+static int max8997_haptic_suspend(struct device *dev)

drivers/input/misc/max8997_haptic.c line 379

Quoted 10 lines
drivers/input/misc/max8997_haptic.c new file +10 -0
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct max8997_haptic *chip = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = chip->input_dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&input_dev->event_lock, flags);
+	max8997_haptic_enable(chip, false);
+	spin_unlock_irqrestore(&input_dev->event_lock, flags);
+

This is not proper locking between playing effect and suspend. Now that you are using workqueue you need to synchronize access with it, not with play_effect method.

Quoted 1 line

Does the following patch work for you?

You're right. As you said, I face with the kernel panic when enter suspend state
while testing max8997-haptic by using fftest at once.

Previously, I tested for each operation of max8997-haptic and suspend/resume.
I will fix it according to your comment.

Thank you for your comment.

Best Regards,
Chanwoo Choi

#3 lore raw
In reply to Dmitry Torokhov

Hi Dmitry,

Quoted 6 lines

This is not proper locking between playing effect and suspend. Now that you are using workqueue you need to synchronize access with it, not with play_effect method.

Does the following patch work for you?

Your patch is worked on TRATS board based on EXYNOS4210 but, you should apply following patch because 'chip->enabled' is used on max8997_haptic_configure() function to enable/disable haptic motor.

(quoted diff) +0 -0

b/drivers/haptic/max8997_haptic.c
index 806bcf3..0347404 100644

drivers/haptic/max8997_haptic.c +0 -0
@@ -182,11 +182,11 @@ static void max8997_haptic_enable(struct

max8997_haptic *chip)
}

if (!chip->enabled) {
+ chip->enabled = true;
regulator_enable(chip->regulator); max8997_haptic_configure(chip); if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_enable(chip->pwm);
- chip->enabled = true;
}

out:
@@ -198,11 +198,11 @@ static void max8997_haptic_disable(struct max8997_haptic *chip)
mutex_lock(&chip->mutex);

if (chip->enabled) {
+ chip->enabled = false;
max8997_haptic_configure(chip); if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_disable(chip->pwm);
regulator_disable(chip->regulator);
- chip->enabled = false;
}

mutex_unlock(&chip->mutex);

Signature · 4 lines
1.7.0.4

Thank you,
Chanwoo Choi
maintainer
#4 lore raw
Quoted 6 lines · Chanwoo Choi

Hi Dmitry,

Quoted 4 lines

This is not proper locking between playing effect and suspend. Now that you are using workqueue you need to synchronize access with it, not with play_effect method.

Quoted 6 lines
Quoted 2 lines

Does the following patch work for you?

Your patch is worked on TRATS board based on EXYNOS4210 but, you should apply following patch because 'chip->enabled' is used on max8997_haptic_configure() function to enable/disable haptic motor.

OK, excellent. I'll pick up this fix and apply the driver for 3.4 queue, thanks!

Signature · 1 line
Dmitry
#5 lore raw

Hi Dmitry,

Quoted 10 lines · Dmitry Torokhov
Quoted 9 lines · Chanwoo Choi

Hi Dmitry,

Quoted 6 lines

This is not proper locking between playing effect and suspend. Now that you are using workqueue you need to synchronize access with it, not with play_effect method.

Does the following patch work for you?

Quoted 6 lines
Quoted 3 lines

Your patch is worked on TRATS board based on EXYNOS4210 but, you should apply following patch because 'chip->enabled' is used on max8997_haptic_configure() function to enable/disable haptic motor.

OK, excellent. I'll pick up this fix and apply the driver for 3.4 queue, thanks!

Your patch depends on the MFD changes Choi sent along the input driver. I think it would make more sense for me to take it. What do you think ?

Cheers,
Samuel.

Signature · 2 lines
Intel Open Source Technology Centre
http://oss.intel.com/
maintainer
#6 lore raw
Quoted 13 lines · Samuel Ortiz

Hi Dmitry,

Quoted 10 lines · Dmitry Torokhov
Quoted 9 lines · Chanwoo Choi

Hi Dmitry,

Quoted 6 lines

This is not proper locking between playing effect and suspend. Now that you are using workqueue you need to synchronize access with it, not with play_effect method.

Does the following patch work for you?

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Your patch is worked on TRATS board based on EXYNOS4210 but, you should apply following patch because 'chip->enabled' is used on max8997_haptic_configure() function to enable/disable haptic motor.

OK, excellent. I'll pick up this fix and apply the driver for 3.4 queue, thanks!

Your patch depends on the MFD changes Choi sent along the input driver. I think it would make more sense for me to take it. What do you think ?

I think that splitting required platform data definitions from the driver into separate patch is quite pointless. I often see a driver split in 3+ patches - headers, the driver itself and Kconfig/makefile changes and I wonder what made them do it...

Anyway, below is the consolidated patch I was going to apply to my tree, but if you want to go through yours - feel free to apply it.

Thanks.

Signature · 22 lines
Dmitry


Input: add driver support for MAX8997-haptic

From: Donggeun Kim <[email protected]>

The MAX8997-haptic function can be used to control motor. User can
control the haptic driver by using force feedback framework.

Signed-off-by: Donggeun Kim <[email protected]>
Signed-off-by: MyungJoo Ham <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
---

 drivers/input/misc/Kconfig          |   12 +
 drivers/input/misc/Makefile         |    1 
 drivers/input/misc/max8997_haptic.c |  407 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/max8997.h         |   53 ++++-
 4 files changed, 472 insertions(+), 1 deletions(-)
 create mode 100644 drivers/input/misc/max8997_haptic.c
drivers/input/misc/Kconfig +12 -0
index 2337c3e..ee077a4 100644
@@ -134,6 +134,18 @@ config INPUT_MAX8925_ONKEY
 	  To compile this driver as a module, choose M here: the module
 	  will be called max8925_onkey.
 
+config INPUT_MAX8997_HAPTIC
+	tristate "MAXIM MAX8997 haptic controller support"
+	depends on HAVE_PWM && MFD_MAX8997
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the haptic controller
+	  on MAXIM MAX8997 chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called max8997-haptic.
+
 config INPUT_MC13783_PWRBUTTON
 	tristate "MC13783 ON buttons"
 	depends on MFD_MC13783
drivers/input/misc/Makefile +1 -0
index a6d8de0..f55cdf4 100644
@@ -31,6 +31,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_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_MPU3050)		+= mpu3050.o
drivers/input/misc/max8997_haptic.c new file +407 -0

407 lines not on this page · raw message

include/linux/mfd/max8997.h +52 -1

65 lines not on this page · raw message

Acked-by
#7 lore raw

Hi Dmitry,

Quoted 7 lines · Dmitry Torokhov
Quoted 4 lines
Quoted 2 lines

OK, excellent. I'll pick up this fix and apply the driver for 3.4 queue, thanks!

Your patch depends on the MFD changes Choi sent along the input driver. I think it would make more sense for me to take it. What do you think ?

I think that splitting required platform data definitions from the driver into separate patch is quite pointless.

Hmm, you're right on this one.

Quoted 6 lines

I often see a driver
split in 3+ patches - headers, the driver itself and Kconfig/makefile changes and I wonder what made them do it...

Anyway, below is the consolidated patch I was going to apply to my tree, but if you want to go through yours - feel free to apply it.

No, I think it makes sense for you to take it. Add my:

if you feel it's needed.

Cheers,
Samuel.

Signature · 2 lines
Intel Open Source Technology Centre
http://oss.intel.com/
maintainer
#8 lore raw
Quoted 16 lines · Samuel Ortiz

Hi Dmitry,

Quoted 7 lines · Dmitry Torokhov
Quoted 4 lines
Quoted 2 lines

OK, excellent. I'll pick up this fix and apply the driver for 3.4 queue, thanks!

Your patch depends on the MFD changes Choi sent along the input driver. I think it would make more sense for me to take it. What do you think ?

I think that splitting required platform data definitions from the driver into separate patch is quite pointless.

Hmm, you're right on this one.

Quoted 4 lines

I often see a driver
split in 3+ patches - headers, the driver itself and Kconfig/makefile changes and I wonder what made them do it...

Quoted 6 lines
Quoted 2 lines

Anyway, below is the consolidated patch I was going to apply to my tree, but if you want to go through yours - feel free to apply it.

No, I think it makes sense for you to take it. Add my:

if you feel it's needed.

I will, thank you.

Signature · 1 line
Dmitry