xref: /linux/drivers/input/misc/cs40l50-vibra.c (revision d46971e0b6f574059d167ddda1355ed301a0bae6)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * CS40L50 Advanced Haptic Driver with waveform memory,
4  * integrated DSP, and closed-loop algorithms
5  *
6  * Copyright 2024 Cirrus Logic, Inc.
7  *
8  * Author: James Ogletree <james.ogletree@cirrus.com>
9  */
10 
11 #include <linux/bitfield.h>
12 #include <linux/input.h>
13 #include <linux/mfd/cs40l50.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 
17 /* Wavetables */
18 #define CS40L50_RAM_INDEX_START		0x1000000
19 #define CS40L50_RAM_INDEX_END		0x100007F
20 #define CS40L50_RTH_INDEX_START		0x1400000
21 #define CS40L50_RTH_INDEX_END		0x1400001
22 #define CS40L50_ROM_INDEX_START		0x1800000
23 #define CS40L50_ROM_INDEX_END		0x180001A
24 #define CS40L50_TYPE_PCM		8
25 #define CS40L50_TYPE_PWLE		12
26 #define CS40L50_PCM_ID			0x0
27 #define CS40L50_OWT_CUSTOM_DATA_SIZE	2
28 #define CS40L50_CUSTOM_DATA_MASK	0xFFFFU
29 
30 /* DSP */
31 #define CS40L50_GPIO_BASE		0x2804140
32 #define CS40L50_OWT_BASE		0x2805C34
33 #define CS40L50_OWT_SIZE		0x2805C38
34 #define CS40L50_OWT_NEXT		0x2805C3C
35 #define CS40L50_EFFECTS_MAX		1
36 
37 /* GPIO */
38 #define CS40L50_GPIO_NUM_MASK		GENMASK(14, 12)
39 #define CS40L50_GPIO_EDGE_MASK		BIT(15)
40 #define CS40L50_GPIO_MAPPING_NONE	0
41 #define CS40L50_GPIO_DISABLE		0x1FF
42 
43 enum cs40l50_bank_type {
44 	CS40L50_WVFRM_BANK_RAM,
45 	CS40L50_WVFRM_BANK_ROM,
46 	CS40L50_WVFRM_BANK_OWT,
47 	CS40L50_WVFRM_BANK_NUM,
48 };
49 
50 /* Describes an area in DSP memory populated by effects */
51 struct cs40l50_bank {
52 	enum cs40l50_bank_type type;
53 	u32 base_index;
54 	u32 max_index;
55 };
56 
57 struct cs40l50_effect {
58 	enum cs40l50_bank_type type;
59 	struct list_head list;
60 	u32 gpio_reg;
61 	u32 index;
62 	int id;
63 };
64 
65 /* Describes haptic interface of loaded DSP firmware */
66 struct cs40l50_vibra_dsp {
67 	struct cs40l50_bank *banks;
68 	u32 gpio_base_reg;
69 	u32 owt_offset_reg;
70 	u32 owt_size_reg;
71 	u32 owt_base_reg;
72 	u32 push_owt_cmd;
73 	u32 delete_owt_cmd;
74 	u32 stop_cmd;
75 	int (*write)(struct device *dev, struct regmap *regmap, u32 val);
76 };
77 
78 /* Describes configuration and state of haptic operations */
79 struct cs40l50_vibra {
80 	struct device *dev;
81 	struct regmap *regmap;
82 	struct input_dev *input;
83 	struct workqueue_struct *vib_wq;
84 	struct list_head effect_head;
85 	struct cs40l50_vibra_dsp dsp;
86 };
87 
88 struct cs40l50_work {
89 	struct cs40l50_vibra *vib;
90 	struct ff_effect *effect;
91 	struct work_struct work;
92 	s16 *custom_data;
93 	int custom_len;
94 	int count;
95 	int error;
96 };
97 
98 static struct cs40l50_bank cs40l50_banks[] = {
99 	{
100 		.type =		CS40L50_WVFRM_BANK_RAM,
101 		.base_index =	CS40L50_RAM_INDEX_START,
102 		.max_index =	CS40L50_RAM_INDEX_END,
103 	},
104 	{
105 		.type =		CS40L50_WVFRM_BANK_ROM,
106 		.base_index =	CS40L50_ROM_INDEX_START,
107 		.max_index =	CS40L50_ROM_INDEX_END,
108 	},
109 	{
110 		.type =		CS40L50_WVFRM_BANK_OWT,
111 		.base_index =	CS40L50_RTH_INDEX_START,
112 		.max_index =	CS40L50_RTH_INDEX_END,
113 	},
114 };
115 
116 static struct cs40l50_vibra_dsp cs40l50_dsp = {
117 	.banks =		cs40l50_banks,
118 	.gpio_base_reg =	CS40L50_GPIO_BASE,
119 	.owt_base_reg =		CS40L50_OWT_BASE,
120 	.owt_offset_reg =	CS40L50_OWT_NEXT,
121 	.owt_size_reg =		CS40L50_OWT_SIZE,
122 	.push_owt_cmd =		CS40L50_OWT_PUSH,
123 	.delete_owt_cmd =	CS40L50_OWT_DELETE,
124 	.stop_cmd =		CS40L50_STOP_PLAYBACK,
125 	.write =		cs40l50_dsp_write,
126 };
127 
cs40l50_find_effect(int id,struct list_head * effect_head)128 static struct cs40l50_effect *cs40l50_find_effect(int id, struct list_head *effect_head)
129 {
130 	struct cs40l50_effect *effect;
131 
132 	list_for_each_entry(effect, effect_head, list)
133 		if (effect->id == id)
134 			return effect;
135 
136 	return NULL;
137 }
138 
cs40l50_effect_bank_set(struct cs40l50_work * work_data,struct cs40l50_effect * effect)139 static int cs40l50_effect_bank_set(struct cs40l50_work *work_data,
140 				   struct cs40l50_effect *effect)
141 {
142 	s16 bank_type = work_data->custom_data[0] & CS40L50_CUSTOM_DATA_MASK;
143 
144 	if (bank_type >= CS40L50_WVFRM_BANK_NUM) {
145 		dev_err(work_data->vib->dev, "Invalid bank (%d)\n", bank_type);
146 		return -EINVAL;
147 	}
148 
149 	if (work_data->custom_len > CS40L50_OWT_CUSTOM_DATA_SIZE)
150 		effect->type = CS40L50_WVFRM_BANK_OWT;
151 	else
152 		effect->type = bank_type;
153 
154 	return 0;
155 }
156 
cs40l50_effect_index_set(struct cs40l50_work * work_data,struct cs40l50_effect * effect)157 static int cs40l50_effect_index_set(struct cs40l50_work *work_data,
158 				    struct cs40l50_effect *effect)
159 {
160 	struct cs40l50_vibra *vib = work_data->vib;
161 	struct cs40l50_effect *owt_effect;
162 	u32 base_index, max_index;
163 
164 	base_index = vib->dsp.banks[effect->type].base_index;
165 	max_index = vib->dsp.banks[effect->type].max_index;
166 
167 	effect->index = base_index;
168 
169 	switch (effect->type) {
170 	case CS40L50_WVFRM_BANK_OWT:
171 		list_for_each_entry(owt_effect, &vib->effect_head, list)
172 			if (owt_effect->type == CS40L50_WVFRM_BANK_OWT)
173 				effect->index++;
174 		break;
175 	case CS40L50_WVFRM_BANK_ROM:
176 	case CS40L50_WVFRM_BANK_RAM:
177 		effect->index += work_data->custom_data[1] & CS40L50_CUSTOM_DATA_MASK;
178 		break;
179 	default:
180 		dev_err(vib->dev, "Bank type %d not supported\n", effect->type);
181 		return -EINVAL;
182 	}
183 
184 	if (effect->index > max_index || effect->index < base_index) {
185 		dev_err(vib->dev, "Index out of bounds: %u\n", effect->index);
186 		return -ENOSPC;
187 	}
188 
189 	return 0;
190 }
191 
cs40l50_effect_gpio_mapping_set(struct cs40l50_work * work_data,struct cs40l50_effect * effect)192 static int cs40l50_effect_gpio_mapping_set(struct cs40l50_work *work_data,
193 					   struct cs40l50_effect *effect)
194 {
195 	u16 gpio_edge, gpio_num, button = work_data->effect->trigger.button;
196 	struct cs40l50_vibra *vib = work_data->vib;
197 
198 	if (button) {
199 		gpio_num = FIELD_GET(CS40L50_GPIO_NUM_MASK, button);
200 		gpio_edge = FIELD_GET(CS40L50_GPIO_EDGE_MASK, button);
201 		effect->gpio_reg = vib->dsp.gpio_base_reg + (gpio_num * 8) - gpio_edge;
202 
203 		return regmap_write(vib->regmap, effect->gpio_reg, button);
204 	}
205 
206 	effect->gpio_reg = CS40L50_GPIO_MAPPING_NONE;
207 
208 	return 0;
209 }
210 
211 struct cs40l50_owt_header {
212 	u32 type;
213 	u32 data_words;
214 	u32 offset;
215 } __packed;
216 
cs40l50_upload_owt(struct cs40l50_work * work_data)217 static int cs40l50_upload_owt(struct cs40l50_work *work_data)
218 {
219 	u8 *new_owt_effect_data __free(kfree) = NULL;
220 	struct cs40l50_vibra *vib = work_data->vib;
221 	size_t len = work_data->custom_len * 2;
222 	struct cs40l50_owt_header header;
223 	u32 offset, size;
224 	int error;
225 
226 	error = regmap_read(vib->regmap, vib->dsp.owt_size_reg, &size);
227 	if (error)
228 		return error;
229 
230 	if ((size * sizeof(u32)) < sizeof(header) + len) {
231 		dev_err(vib->dev, "No space in open wavetable for effect\n");
232 		return -ENOSPC;
233 	}
234 
235 	header.type = work_data->custom_data[0] == CS40L50_PCM_ID ? CS40L50_TYPE_PCM :
236 								    CS40L50_TYPE_PWLE;
237 	header.offset = sizeof(header) / sizeof(u32);
238 	header.data_words = len / sizeof(u32);
239 
240 	new_owt_effect_data = kmalloc(sizeof(header) + len, GFP_KERNEL);
241 	if (!new_owt_effect_data)
242 		return -ENOMEM;
243 
244 	memcpy(new_owt_effect_data, &header, sizeof(header));
245 	memcpy(new_owt_effect_data + sizeof(header), work_data->custom_data, len);
246 
247 	error = regmap_read(vib->regmap, vib->dsp.owt_offset_reg, &offset);
248 	if (error)
249 		return error;
250 
251 	error = regmap_bulk_write(vib->regmap, vib->dsp.owt_base_reg +
252 				  (offset * sizeof(u32)), new_owt_effect_data,
253 				  sizeof(header) + len);
254 	if (error)
255 		return error;
256 
257 	error = vib->dsp.write(vib->dev, vib->regmap, vib->dsp.push_owt_cmd);
258 	if (error)
259 		return error;
260 
261 	return 0;
262 }
263 
cs40l50_add_worker(struct work_struct * work)264 static void cs40l50_add_worker(struct work_struct *work)
265 {
266 	struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work);
267 	struct cs40l50_vibra *vib = work_data->vib;
268 	struct cs40l50_effect *effect;
269 	bool is_new = false;
270 	int error;
271 
272 	error = pm_runtime_resume_and_get(vib->dev);
273 	if (error)
274 		goto err_exit;
275 
276 	/* Update effect if already uploaded, otherwise create new effect */
277 	effect = cs40l50_find_effect(work_data->effect->id, &vib->effect_head);
278 	if (!effect) {
279 		effect = kzalloc(sizeof(*effect), GFP_KERNEL);
280 		if (!effect) {
281 			error = -ENOMEM;
282 			goto err_pm;
283 		}
284 
285 		effect->id = work_data->effect->id;
286 		is_new = true;
287 	}
288 
289 	error = cs40l50_effect_bank_set(work_data, effect);
290 	if (error)
291 		goto err_free;
292 
293 	error = cs40l50_effect_index_set(work_data, effect);
294 	if (error)
295 		goto err_free;
296 
297 	error = cs40l50_effect_gpio_mapping_set(work_data, effect);
298 	if (error)
299 		goto err_free;
300 
301 	if (effect->type == CS40L50_WVFRM_BANK_OWT)
302 		error = cs40l50_upload_owt(work_data);
303 err_free:
304 	if (is_new) {
305 		if (error)
306 			kfree(effect);
307 		else
308 			list_add(&effect->list, &vib->effect_head);
309 	}
310 err_pm:
311 	pm_runtime_mark_last_busy(vib->dev);
312 	pm_runtime_put_autosuspend(vib->dev);
313 err_exit:
314 	work_data->error = error;
315 }
316 
cs40l50_add(struct input_dev * dev,struct ff_effect * effect,struct ff_effect * old)317 static int cs40l50_add(struct input_dev *dev, struct ff_effect *effect,
318 		       struct ff_effect *old)
319 {
320 	struct ff_periodic_effect *periodic = &effect->u.periodic;
321 	struct cs40l50_vibra *vib = input_get_drvdata(dev);
322 	struct cs40l50_work work_data;
323 
324 	if (effect->type != FF_PERIODIC || periodic->waveform != FF_CUSTOM) {
325 		dev_err(vib->dev, "Type (%#X) or waveform (%#X) unsupported\n",
326 			effect->type, periodic->waveform);
327 		return -EINVAL;
328 	}
329 
330 	work_data.custom_data = memdup_array_user(effect->u.periodic.custom_data,
331 						  effect->u.periodic.custom_len,
332 						  sizeof(s16));
333 	if (IS_ERR(work_data.custom_data))
334 		return PTR_ERR(work_data.custom_data);
335 
336 	work_data.custom_len = effect->u.periodic.custom_len;
337 	work_data.vib = vib;
338 	work_data.effect = effect;
339 	INIT_WORK_ONSTACK(&work_data.work, cs40l50_add_worker);
340 
341 	/* Push to the workqueue to serialize with playbacks */
342 	queue_work(vib->vib_wq, &work_data.work);
343 	flush_work(&work_data.work);
344 	destroy_work_on_stack(&work_data.work);
345 
346 	kfree(work_data.custom_data);
347 
348 	return work_data.error;
349 }
350 
cs40l50_start_worker(struct work_struct * work)351 static void cs40l50_start_worker(struct work_struct *work)
352 {
353 	struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work);
354 	struct cs40l50_vibra *vib = work_data->vib;
355 	struct cs40l50_effect *start_effect;
356 
357 	if (pm_runtime_resume_and_get(vib->dev) < 0)
358 		goto err_free;
359 
360 	start_effect = cs40l50_find_effect(work_data->effect->id, &vib->effect_head);
361 	if (start_effect) {
362 		while (--work_data->count >= 0) {
363 			vib->dsp.write(vib->dev, vib->regmap, start_effect->index);
364 			usleep_range(work_data->effect->replay.length,
365 				     work_data->effect->replay.length + 100);
366 		}
367 	} else {
368 		dev_err(vib->dev, "Effect to play not found\n");
369 	}
370 
371 	pm_runtime_mark_last_busy(vib->dev);
372 	pm_runtime_put_autosuspend(vib->dev);
373 err_free:
374 	kfree(work_data);
375 }
376 
cs40l50_stop_worker(struct work_struct * work)377 static void cs40l50_stop_worker(struct work_struct *work)
378 {
379 	struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work);
380 	struct cs40l50_vibra *vib = work_data->vib;
381 
382 	if (pm_runtime_resume_and_get(vib->dev) < 0)
383 		return;
384 
385 	vib->dsp.write(vib->dev, vib->regmap, vib->dsp.stop_cmd);
386 
387 	pm_runtime_mark_last_busy(vib->dev);
388 	pm_runtime_put_autosuspend(vib->dev);
389 
390 	kfree(work_data);
391 }
392 
cs40l50_playback(struct input_dev * dev,int effect_id,int val)393 static int cs40l50_playback(struct input_dev *dev, int effect_id, int val)
394 {
395 	struct cs40l50_vibra *vib = input_get_drvdata(dev);
396 	struct cs40l50_work *work_data;
397 
398 	work_data = kzalloc(sizeof(*work_data), GFP_ATOMIC);
399 	if (!work_data)
400 		return -ENOMEM;
401 
402 	work_data->vib = vib;
403 
404 	if (val > 0) {
405 		work_data->effect = &dev->ff->effects[effect_id];
406 		work_data->count = val;
407 		INIT_WORK(&work_data->work, cs40l50_start_worker);
408 	} else {
409 		/* Stop the amplifier as device drives only one effect */
410 		INIT_WORK(&work_data->work, cs40l50_stop_worker);
411 	}
412 
413 	queue_work(vib->vib_wq, &work_data->work);
414 
415 	return 0;
416 }
417 
cs40l50_erase_worker(struct work_struct * work)418 static void cs40l50_erase_worker(struct work_struct *work)
419 {
420 	struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work);
421 	struct cs40l50_effect *erase_effect, *owt_effect;
422 	struct cs40l50_vibra *vib = work_data->vib;
423 	int error;
424 
425 	error = pm_runtime_resume_and_get(vib->dev);
426 	if (error)
427 		goto err_exit;
428 
429 	erase_effect = cs40l50_find_effect(work_data->effect->id, &vib->effect_head);
430 	if (!erase_effect) {
431 		dev_err(vib->dev, "Effect to erase not found\n");
432 		error = -EINVAL;
433 		goto err_pm;
434 	}
435 
436 	if (erase_effect->gpio_reg != CS40L50_GPIO_MAPPING_NONE) {
437 		error = regmap_write(vib->regmap, erase_effect->gpio_reg,
438 				     CS40L50_GPIO_DISABLE);
439 		if (error)
440 			goto err_pm;
441 	}
442 
443 	if (erase_effect->type == CS40L50_WVFRM_BANK_OWT) {
444 		error = vib->dsp.write(vib->dev, vib->regmap,
445 				       vib->dsp.delete_owt_cmd |
446 				       (erase_effect->index & 0xFF));
447 		if (error)
448 			goto err_pm;
449 
450 		list_for_each_entry(owt_effect, &vib->effect_head, list)
451 			if (owt_effect->type == CS40L50_WVFRM_BANK_OWT &&
452 			    owt_effect->index > erase_effect->index)
453 				owt_effect->index--;
454 	}
455 
456 	list_del(&erase_effect->list);
457 	kfree(erase_effect);
458 err_pm:
459 	pm_runtime_mark_last_busy(vib->dev);
460 	pm_runtime_put_autosuspend(vib->dev);
461 err_exit:
462 	work_data->error = error;
463 }
464 
cs40l50_erase(struct input_dev * dev,int effect_id)465 static int cs40l50_erase(struct input_dev *dev, int effect_id)
466 {
467 	struct cs40l50_vibra *vib = input_get_drvdata(dev);
468 	struct cs40l50_work work_data;
469 
470 	work_data.vib = vib;
471 	work_data.effect = &dev->ff->effects[effect_id];
472 
473 	INIT_WORK_ONSTACK(&work_data.work, cs40l50_erase_worker);
474 
475 	/* Push to workqueue to serialize with playbacks */
476 	queue_work(vib->vib_wq, &work_data.work);
477 	flush_work(&work_data.work);
478 	destroy_work_on_stack(&work_data.work);
479 
480 	return work_data.error;
481 }
482 
cs40l50_remove_wq(void * data)483 static void cs40l50_remove_wq(void *data)
484 {
485 	flush_workqueue(data);
486 	destroy_workqueue(data);
487 }
488 
cs40l50_vibra_probe(struct platform_device * pdev)489 static int cs40l50_vibra_probe(struct platform_device *pdev)
490 {
491 	struct cs40l50 *cs40l50 = dev_get_drvdata(pdev->dev.parent);
492 	struct cs40l50_vibra *vib;
493 	int error;
494 
495 	vib = devm_kzalloc(pdev->dev.parent, sizeof(*vib), GFP_KERNEL);
496 	if (!vib)
497 		return -ENOMEM;
498 
499 	vib->dev = cs40l50->dev;
500 	vib->regmap = cs40l50->regmap;
501 	vib->dsp = cs40l50_dsp;
502 
503 	vib->input = devm_input_allocate_device(vib->dev);
504 	if (!vib->input)
505 		return -ENOMEM;
506 
507 	vib->input->id.product = cs40l50->devid;
508 	vib->input->id.version = cs40l50->revid;
509 	vib->input->name = "cs40l50_vibra";
510 
511 	input_set_drvdata(vib->input, vib);
512 	input_set_capability(vib->input, EV_FF, FF_PERIODIC);
513 	input_set_capability(vib->input, EV_FF, FF_CUSTOM);
514 
515 	error = input_ff_create(vib->input, CS40L50_EFFECTS_MAX);
516 	if (error) {
517 		dev_err(vib->dev, "Failed to create input device\n");
518 		return error;
519 	}
520 
521 	vib->input->ff->upload = cs40l50_add;
522 	vib->input->ff->playback = cs40l50_playback;
523 	vib->input->ff->erase = cs40l50_erase;
524 
525 	INIT_LIST_HEAD(&vib->effect_head);
526 
527 	vib->vib_wq = alloc_ordered_workqueue("vib_wq", WQ_HIGHPRI);
528 	if (!vib->vib_wq)
529 		return -ENOMEM;
530 
531 	error = devm_add_action_or_reset(vib->dev, cs40l50_remove_wq, vib->vib_wq);
532 	if (error)
533 		return error;
534 
535 	error = input_register_device(vib->input);
536 	if (error)
537 		return error;
538 
539 	return 0;
540 }
541 
542 static const struct platform_device_id cs40l50_vibra_id_match[] = {
543 	{ "cs40l50-vibra", },
544 	{}
545 };
546 MODULE_DEVICE_TABLE(platform, cs40l50_vibra_id_match);
547 
548 static struct platform_driver cs40l50_vibra_driver = {
549 	.probe		= cs40l50_vibra_probe,
550 	.id_table	= cs40l50_vibra_id_match,
551 	.driver		= {
552 		.name	= "cs40l50-vibra",
553 	},
554 };
555 module_platform_driver(cs40l50_vibra_driver);
556 
557 MODULE_DESCRIPTION("CS40L50 Advanced Haptic Driver");
558 MODULE_AUTHOR("James Ogletree, Cirrus Logic Inc. <james.ogletree@cirrus.com>");
559 MODULE_LICENSE("GPL");
560