1 // SPDX-License-Identifier: GPL-2.0-only
3 * Regulator haptic driver
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 * Author: Jaewon Kim <jaewon02.kim@samsung.com>
7 * Author: Hyunhee Kim <hyunhee.kim@samsung.com>
10 #include <linux/input.h>
11 #include <linux/module.h>
13 #include <linux/platform_data/regulator-haptic.h>
14 #include <linux/platform_device.h>
15 #include <linux/regulator/consumer.h>
16 #include <linux/slab.h>
18 #define MAX_MAGNITUDE_SHIFT 16
20 struct regulator_haptic
{
22 struct input_dev
*input_dev
;
23 struct regulator
*regulator
;
25 struct work_struct work
;
31 unsigned int max_volt
;
32 unsigned int min_volt
;
33 unsigned int magnitude
;
36 static int regulator_haptic_toggle(struct regulator_haptic
*haptic
, bool on
)
40 if (haptic
->active
!= on
) {
42 error
= on
? regulator_enable(haptic
->regulator
) :
43 regulator_disable(haptic
->regulator
);
46 "failed to switch regulator %s: %d\n",
47 on
? "on" : "off", error
);
57 static int regulator_haptic_set_voltage(struct regulator_haptic
*haptic
,
58 unsigned int magnitude
)
61 unsigned int intensity
;
64 volt_mag_multi
= (u64
)(haptic
->max_volt
- haptic
->min_volt
) * magnitude
;
65 intensity
= (unsigned int)(volt_mag_multi
>> MAX_MAGNITUDE_SHIFT
);
67 error
= regulator_set_voltage(haptic
->regulator
,
68 intensity
+ haptic
->min_volt
,
71 dev_err(haptic
->dev
, "cannot set regulator voltage to %d: %d\n",
72 intensity
+ haptic
->min_volt
, error
);
76 regulator_haptic_toggle(haptic
, !!magnitude
);
81 static void regulator_haptic_work(struct work_struct
*work
)
83 struct regulator_haptic
*haptic
= container_of(work
,
84 struct regulator_haptic
, work
);
86 guard(mutex
)(&haptic
->mutex
);
88 if (!haptic
->suspended
)
89 regulator_haptic_set_voltage(haptic
, haptic
->magnitude
);
92 static int regulator_haptic_play_effect(struct input_dev
*input
, void *data
,
93 struct ff_effect
*effect
)
95 struct regulator_haptic
*haptic
= input_get_drvdata(input
);
97 haptic
->magnitude
= effect
->u
.rumble
.strong_magnitude
;
98 if (!haptic
->magnitude
)
99 haptic
->magnitude
= effect
->u
.rumble
.weak_magnitude
;
101 schedule_work(&haptic
->work
);
106 static void regulator_haptic_close(struct input_dev
*input
)
108 struct regulator_haptic
*haptic
= input_get_drvdata(input
);
110 cancel_work_sync(&haptic
->work
);
111 regulator_haptic_set_voltage(haptic
, 0);
114 static int __maybe_unused
115 regulator_haptic_parse_dt(struct device
*dev
, struct regulator_haptic
*haptic
)
117 struct device_node
*node
;
122 dev_err(dev
, "Missing device tree data\n");
126 error
= of_property_read_u32(node
, "max-microvolt", &haptic
->max_volt
);
128 dev_err(dev
, "cannot parse max-microvolt\n");
132 error
= of_property_read_u32(node
, "min-microvolt", &haptic
->min_volt
);
134 dev_err(dev
, "cannot parse min-microvolt\n");
141 static int regulator_haptic_probe(struct platform_device
*pdev
)
143 const struct regulator_haptic_data
*pdata
= dev_get_platdata(&pdev
->dev
);
144 struct regulator_haptic
*haptic
;
145 struct input_dev
*input_dev
;
148 haptic
= devm_kzalloc(&pdev
->dev
, sizeof(*haptic
), GFP_KERNEL
);
152 platform_set_drvdata(pdev
, haptic
);
153 haptic
->dev
= &pdev
->dev
;
154 mutex_init(&haptic
->mutex
);
155 INIT_WORK(&haptic
->work
, regulator_haptic_work
);
158 haptic
->max_volt
= pdata
->max_volt
;
159 haptic
->min_volt
= pdata
->min_volt
;
160 } else if (IS_ENABLED(CONFIG_OF
)) {
161 error
= regulator_haptic_parse_dt(&pdev
->dev
, haptic
);
165 dev_err(&pdev
->dev
, "Missing platform data\n");
169 haptic
->regulator
= devm_regulator_get_exclusive(&pdev
->dev
, "haptic");
170 if (IS_ERR(haptic
->regulator
)) {
171 dev_err(&pdev
->dev
, "failed to get regulator\n");
172 return PTR_ERR(haptic
->regulator
);
175 input_dev
= devm_input_allocate_device(&pdev
->dev
);
179 haptic
->input_dev
= input_dev
;
180 haptic
->input_dev
->name
= "regulator-haptic";
181 haptic
->input_dev
->dev
.parent
= &pdev
->dev
;
182 haptic
->input_dev
->close
= regulator_haptic_close
;
183 input_set_drvdata(haptic
->input_dev
, haptic
);
184 input_set_capability(haptic
->input_dev
, EV_FF
, FF_RUMBLE
);
186 error
= input_ff_create_memless(input_dev
, NULL
,
187 regulator_haptic_play_effect
);
189 dev_err(&pdev
->dev
, "failed to create force-feedback\n");
193 error
= input_register_device(haptic
->input_dev
);
195 dev_err(&pdev
->dev
, "failed to register input device\n");
202 static int regulator_haptic_suspend(struct device
*dev
)
204 struct platform_device
*pdev
= to_platform_device(dev
);
205 struct regulator_haptic
*haptic
= platform_get_drvdata(pdev
);
207 scoped_guard(mutex_intr
, &haptic
->mutex
) {
208 regulator_haptic_set_voltage(haptic
, 0);
209 haptic
->suspended
= true;
217 static int regulator_haptic_resume(struct device
*dev
)
219 struct platform_device
*pdev
= to_platform_device(dev
);
220 struct regulator_haptic
*haptic
= platform_get_drvdata(pdev
);
221 unsigned int magnitude
;
223 guard(mutex
)(&haptic
->mutex
);
225 haptic
->suspended
= false;
227 magnitude
= READ_ONCE(haptic
->magnitude
);
229 regulator_haptic_set_voltage(haptic
, magnitude
);
234 static DEFINE_SIMPLE_DEV_PM_OPS(regulator_haptic_pm_ops
,
235 regulator_haptic_suspend
, regulator_haptic_resume
);
237 static const struct of_device_id regulator_haptic_dt_match
[] = {
238 { .compatible
= "regulator-haptic" },
241 MODULE_DEVICE_TABLE(of
, regulator_haptic_dt_match
);
243 static struct platform_driver regulator_haptic_driver
= {
244 .probe
= regulator_haptic_probe
,
246 .name
= "regulator-haptic",
247 .of_match_table
= regulator_haptic_dt_match
,
248 .pm
= pm_sleep_ptr(®ulator_haptic_pm_ops
),
251 module_platform_driver(regulator_haptic_driver
);
253 MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
254 MODULE_AUTHOR("Hyunhee Kim <hyunhee.kim@samsung.com>");
255 MODULE_DESCRIPTION("Regulator haptic driver");
256 MODULE_LICENSE("GPL");