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 mutex_lock(&haptic
->mutex
);
88 if (!haptic
->suspended
)
89 regulator_haptic_set_voltage(haptic
, haptic
->magnitude
);
91 mutex_unlock(&haptic
->mutex
);
94 static int regulator_haptic_play_effect(struct input_dev
*input
, void *data
,
95 struct ff_effect
*effect
)
97 struct regulator_haptic
*haptic
= input_get_drvdata(input
);
99 haptic
->magnitude
= effect
->u
.rumble
.strong_magnitude
;
100 if (!haptic
->magnitude
)
101 haptic
->magnitude
= effect
->u
.rumble
.weak_magnitude
;
103 schedule_work(&haptic
->work
);
108 static void regulator_haptic_close(struct input_dev
*input
)
110 struct regulator_haptic
*haptic
= input_get_drvdata(input
);
112 cancel_work_sync(&haptic
->work
);
113 regulator_haptic_set_voltage(haptic
, 0);
116 static int __maybe_unused
117 regulator_haptic_parse_dt(struct device
*dev
, struct regulator_haptic
*haptic
)
119 struct device_node
*node
;
124 dev_err(dev
, "Missing device tree data\n");
128 error
= of_property_read_u32(node
, "max-microvolt", &haptic
->max_volt
);
130 dev_err(dev
, "cannot parse max-microvolt\n");
134 error
= of_property_read_u32(node
, "min-microvolt", &haptic
->min_volt
);
136 dev_err(dev
, "cannot parse min-microvolt\n");
143 static int regulator_haptic_probe(struct platform_device
*pdev
)
145 const struct regulator_haptic_data
*pdata
= dev_get_platdata(&pdev
->dev
);
146 struct regulator_haptic
*haptic
;
147 struct input_dev
*input_dev
;
150 haptic
= devm_kzalloc(&pdev
->dev
, sizeof(*haptic
), GFP_KERNEL
);
154 platform_set_drvdata(pdev
, haptic
);
155 haptic
->dev
= &pdev
->dev
;
156 mutex_init(&haptic
->mutex
);
157 INIT_WORK(&haptic
->work
, regulator_haptic_work
);
160 haptic
->max_volt
= pdata
->max_volt
;
161 haptic
->min_volt
= pdata
->min_volt
;
162 } else if (IS_ENABLED(CONFIG_OF
)) {
163 error
= regulator_haptic_parse_dt(&pdev
->dev
, haptic
);
167 dev_err(&pdev
->dev
, "Missing platform data\n");
171 haptic
->regulator
= devm_regulator_get_exclusive(&pdev
->dev
, "haptic");
172 if (IS_ERR(haptic
->regulator
)) {
173 dev_err(&pdev
->dev
, "failed to get regulator\n");
174 return PTR_ERR(haptic
->regulator
);
177 input_dev
= devm_input_allocate_device(&pdev
->dev
);
181 haptic
->input_dev
= input_dev
;
182 haptic
->input_dev
->name
= "regulator-haptic";
183 haptic
->input_dev
->dev
.parent
= &pdev
->dev
;
184 haptic
->input_dev
->close
= regulator_haptic_close
;
185 input_set_drvdata(haptic
->input_dev
, haptic
);
186 input_set_capability(haptic
->input_dev
, EV_FF
, FF_RUMBLE
);
188 error
= input_ff_create_memless(input_dev
, NULL
,
189 regulator_haptic_play_effect
);
191 dev_err(&pdev
->dev
, "failed to create force-feedback\n");
195 error
= input_register_device(haptic
->input_dev
);
197 dev_err(&pdev
->dev
, "failed to register input device\n");
204 static int __maybe_unused
regulator_haptic_suspend(struct device
*dev
)
206 struct platform_device
*pdev
= to_platform_device(dev
);
207 struct regulator_haptic
*haptic
= platform_get_drvdata(pdev
);
210 error
= mutex_lock_interruptible(&haptic
->mutex
);
214 regulator_haptic_set_voltage(haptic
, 0);
216 haptic
->suspended
= true;
218 mutex_unlock(&haptic
->mutex
);
223 static int __maybe_unused
regulator_haptic_resume(struct device
*dev
)
225 struct platform_device
*pdev
= to_platform_device(dev
);
226 struct regulator_haptic
*haptic
= platform_get_drvdata(pdev
);
227 unsigned int magnitude
;
229 mutex_lock(&haptic
->mutex
);
231 haptic
->suspended
= false;
233 magnitude
= READ_ONCE(haptic
->magnitude
);
235 regulator_haptic_set_voltage(haptic
, magnitude
);
237 mutex_unlock(&haptic
->mutex
);
242 static SIMPLE_DEV_PM_OPS(regulator_haptic_pm_ops
,
243 regulator_haptic_suspend
, regulator_haptic_resume
);
245 static const struct of_device_id regulator_haptic_dt_match
[] = {
246 { .compatible
= "regulator-haptic" },
249 MODULE_DEVICE_TABLE(of
, regulator_haptic_dt_match
);
251 static struct platform_driver regulator_haptic_driver
= {
252 .probe
= regulator_haptic_probe
,
254 .name
= "regulator-haptic",
255 .of_match_table
= regulator_haptic_dt_match
,
256 .pm
= ®ulator_haptic_pm_ops
,
259 module_platform_driver(regulator_haptic_driver
);
261 MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
262 MODULE_AUTHOR("Hyunhee Kim <hyunhee.kim@samsung.com>");
263 MODULE_DESCRIPTION("Regulator haptic driver");
264 MODULE_LICENSE("GPL");