aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/misc
diff options
context:
space:
mode:
authorJaewon Kim <jaewon02.kim@samsung.com>2014-09-12 02:15:01 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-09-12 02:40:28 -0400
commita3b3ca753cdc92c7d5f57404afed3115b3b79cc6 (patch)
treede26e862cd43b9c2cb78eb06749145d3726b8e5c /drivers/input/misc
parentadff5962fdd2f29bac943bc014ebd529444b2153 (diff)
Input: add haptic driver on max77693
This driver to supports the haptic controller on MAX77693 Multifunction device with PMIC, CHARGER, LED, MUIC, HAPTIC. This driver supports external pwm and LRA (Linear Resonant Actuator) motor. User can control the haptic device via force feedback framework. Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com> Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/misc')
-rw-r--r--drivers/input/misc/Kconfig11
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/max77693-haptic.c357
3 files changed, 369 insertions, 0 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 36382e5b7703..23297ab6163f 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -144,6 +144,17 @@ config INPUT_M68K_BEEP
144 tristate "M68k Beeper support" 144 tristate "M68k Beeper support"
145 depends on M68K 145 depends on M68K
146 146
147config INPUT_MAX77693_HAPTIC
148 tristate "MAXIM MAX77693 haptic controller support"
149 depends on MFD_MAX77693 && PWM
150 select INPUT_FF_MEMLESS
151 help
152 This option enables support for the haptic controller on
153 MAXIM MAX77693 chip.
154
155 To compile this driver as module, choose M here: the
156 module will be called max77693-haptic.
157
147config INPUT_MAX8925_ONKEY 158config INPUT_MAX8925_ONKEY
148 tristate "MAX8925 ONKEY support" 159 tristate "MAX8925 ONKEY support"
149 depends on MFD_MAX8925 160 depends on MFD_MAX8925
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index e8b84d2c845f..19c760361f80 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
37obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o 37obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
38obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o 38obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
39obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o 39obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
40obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
40obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o 41obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
41obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o 42obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
42obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o 43obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
new file mode 100644
index 000000000000..d605db4d2f39
--- /dev/null
+++ b/drivers/input/misc/max77693-haptic.c
@@ -0,0 +1,357 @@
1/*
2 * MAXIM MAX77693 Haptic device driver
3 *
4 * Copyright (C) 2014 Samsung Electronics
5 * Jaewon Kim <jaewon02.kim@samsung.com>
6 *
7 * This program is not provided / owned by Maxim Integrated Products.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/i2c.h>
18#include <linux/regmap.h>
19#include <linux/input.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/pwm.h>
23#include <linux/slab.h>
24#include <linux/workqueue.h>
25#include <linux/regulator/consumer.h>
26#include <linux/mfd/max77693.h>
27#include <linux/mfd/max77693-private.h>
28
29#define MAX_MAGNITUDE_SHIFT 16
30
31enum max77693_haptic_motor_type {
32 MAX77693_HAPTIC_ERM = 0,
33 MAX77693_HAPTIC_LRA,
34};
35
36enum max77693_haptic_pulse_mode {
37 MAX77693_HAPTIC_EXTERNAL_MODE = 0,
38 MAX77693_HAPTIC_INTERNAL_MODE,
39};
40
41enum max77693_haptic_pwm_divisor {
42 MAX77693_HAPTIC_PWM_DIVISOR_32 = 0,
43 MAX77693_HAPTIC_PWM_DIVISOR_64,
44 MAX77693_HAPTIC_PWM_DIVISOR_128,
45 MAX77693_HAPTIC_PWM_DIVISOR_256,
46};
47
48struct max77693_haptic {
49 struct regmap *regmap_pmic;
50 struct regmap *regmap_haptic;
51 struct device *dev;
52 struct input_dev *input_dev;
53 struct pwm_device *pwm_dev;
54 struct regulator *motor_reg;
55
56 bool enabled;
57 bool suspend_state;
58 unsigned int magnitude;
59 unsigned int pwm_duty;
60 enum max77693_haptic_motor_type type;
61 enum max77693_haptic_pulse_mode mode;
62 enum max77693_haptic_pwm_divisor pwm_divisor;
63
64 struct work_struct work;
65};
66
67static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)
68{
69 int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2;
70 int error;
71
72 error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
73 if (error) {
74 dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
75 return error;
76 }
77
78 return 0;
79}
80
81static int max77693_haptic_configure(struct max77693_haptic *haptic,
82 bool enable)
83{
84 unsigned int value;
85 int error;
86
87 value = ((haptic->type << MAX77693_CONFIG2_MODE) |
88 (enable << MAX77693_CONFIG2_MEN) |
89 (haptic->mode << MAX77693_CONFIG2_HTYP) |
90 (haptic->pwm_divisor));
91
92 error = regmap_write(haptic->regmap_haptic,
93 MAX77693_HAPTIC_REG_CONFIG2, value);
94 if (error) {
95 dev_err(haptic->dev,
96 "failed to update haptic config: %d\n", error);
97 return error;
98 }
99
100 return 0;
101}
102
103static int max77693_haptic_lowsys(struct max77693_haptic *haptic, bool enable)
104{
105 int error;
106
107 error = regmap_update_bits(haptic->regmap_pmic,
108 MAX77693_PMIC_REG_LSCNFG,
109 MAX77693_PMIC_LOW_SYS_MASK,
110 enable << MAX77693_PMIC_LOW_SYS_SHIFT);
111 if (error) {
112 dev_err(haptic->dev, "cannot update pmic regmap: %d\n", error);
113 return error;
114 }
115
116 return 0;
117}
118
119static void max77693_haptic_enable(struct max77693_haptic *haptic)
120{
121 int error;
122
123 if (haptic->enabled)
124 return;
125
126 error = pwm_enable(haptic->pwm_dev);
127 if (error) {
128 dev_err(haptic->dev,
129 "failed to enable haptic pwm device: %d\n", error);
130 return;
131 }
132
133 error = max77693_haptic_lowsys(haptic, true);
134 if (error)
135 goto err_enable_lowsys;
136
137 error = max77693_haptic_configure(haptic, true);
138 if (error)
139 goto err_enable_config;
140
141 haptic->enabled = true;
142
143 return;
144
145err_enable_config:
146 max77693_haptic_lowsys(haptic, false);
147err_enable_lowsys:
148 pwm_disable(haptic->pwm_dev);
149}
150
151static void max77693_haptic_disable(struct max77693_haptic *haptic)
152{
153 int error;
154
155 if (haptic->enabled)
156 return;
157
158 error = max77693_haptic_configure(haptic, false);
159 if (error)
160 return;
161
162 error = max77693_haptic_lowsys(haptic, false);
163 if (error)
164 goto err_disable_lowsys;
165