1 // SPDX-License-Identifier: GPL-2.0
3 * CS40L50 Advanced Haptic Driver with waveform memory,
4 * integrated DSP, and closed-loop algorithms
6 * Copyright 2024 Cirrus Logic, Inc.
8 * Author: James Ogletree <james.ogletree@cirrus.com>
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>
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
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
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
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
,
50 /* Describes an area in DSP memory populated by effects */
52 enum cs40l50_bank_type type
;
57 struct cs40l50_effect
{
58 enum cs40l50_bank_type type
;
59 struct list_head list
;
65 /* Describes haptic interface of loaded DSP firmware */
66 struct cs40l50_vibra_dsp
{
67 struct cs40l50_bank
*banks
;
75 int (*write
)(struct device
*dev
, struct regmap
*regmap
, u32 val
);
78 /* Describes configuration and state of haptic operations */
79 struct cs40l50_vibra
{
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
;
89 struct cs40l50_vibra
*vib
;
90 struct ff_effect
*effect
;
91 struct work_struct work
;
98 static struct cs40l50_bank cs40l50_banks
[] = {
100 .type
= CS40L50_WVFRM_BANK_RAM
,
101 .base_index
= CS40L50_RAM_INDEX_START
,
102 .max_index
= CS40L50_RAM_INDEX_END
,
105 .type
= CS40L50_WVFRM_BANK_ROM
,
106 .base_index
= CS40L50_ROM_INDEX_START
,
107 .max_index
= CS40L50_ROM_INDEX_END
,
110 .type
= CS40L50_WVFRM_BANK_OWT
,
111 .base_index
= CS40L50_RTH_INDEX_START
,
112 .max_index
= CS40L50_RTH_INDEX_END
,
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
,
128 static struct cs40l50_effect
*cs40l50_find_effect(int id
, struct list_head
*effect_head
)
130 struct cs40l50_effect
*effect
;
132 list_for_each_entry(effect
, effect_head
, list
)
133 if (effect
->id
== id
)
139 static int cs40l50_effect_bank_set(struct cs40l50_work
*work_data
,
140 struct cs40l50_effect
*effect
)
142 s16 bank_type
= work_data
->custom_data
[0] & CS40L50_CUSTOM_DATA_MASK
;
144 if (bank_type
>= CS40L50_WVFRM_BANK_NUM
) {
145 dev_err(work_data
->vib
->dev
, "Invalid bank (%d)\n", bank_type
);
149 if (work_data
->custom_len
> CS40L50_OWT_CUSTOM_DATA_SIZE
)
150 effect
->type
= CS40L50_WVFRM_BANK_OWT
;
152 effect
->type
= bank_type
;
157 static int cs40l50_effect_index_set(struct cs40l50_work
*work_data
,
158 struct cs40l50_effect
*effect
)
160 struct cs40l50_vibra
*vib
= work_data
->vib
;
161 struct cs40l50_effect
*owt_effect
;
162 u32 base_index
, max_index
;
164 base_index
= vib
->dsp
.banks
[effect
->type
].base_index
;
165 max_index
= vib
->dsp
.banks
[effect
->type
].max_index
;
167 effect
->index
= base_index
;
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
)
175 case CS40L50_WVFRM_BANK_ROM
:
176 case CS40L50_WVFRM_BANK_RAM
:
177 effect
->index
+= work_data
->custom_data
[1] & CS40L50_CUSTOM_DATA_MASK
;
180 dev_err(vib
->dev
, "Bank type %d not supported\n", effect
->type
);
184 if (effect
->index
> max_index
|| effect
->index
< base_index
) {
185 dev_err(vib
->dev
, "Index out of bounds: %u\n", effect
->index
);
192 static int cs40l50_effect_gpio_mapping_set(struct cs40l50_work
*work_data
,
193 struct cs40l50_effect
*effect
)
195 u16 gpio_edge
, gpio_num
, button
= work_data
->effect
->trigger
.button
;
196 struct cs40l50_vibra
*vib
= work_data
->vib
;
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
;
203 return regmap_write(vib
->regmap
, effect
->gpio_reg
, button
);
206 effect
->gpio_reg
= CS40L50_GPIO_MAPPING_NONE
;
211 struct cs40l50_owt_header
{
217 static int cs40l50_upload_owt(struct cs40l50_work
*work_data
)
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
;
226 error
= regmap_read(vib
->regmap
, vib
->dsp
.owt_size_reg
, &size
);
230 if ((size
* sizeof(u32
)) < sizeof(header
) + len
) {
231 dev_err(vib
->dev
, "No space in open wavetable for effect\n");
235 header
.type
= work_data
->custom_data
[0] == CS40L50_PCM_ID
? CS40L50_TYPE_PCM
:
237 header
.offset
= sizeof(header
) / sizeof(u32
);
238 header
.data_words
= len
/ sizeof(u32
);
240 new_owt_effect_data
= kmalloc(sizeof(header
) + len
, GFP_KERNEL
);
242 memcpy(new_owt_effect_data
, &header
, sizeof(header
));
243 memcpy(new_owt_effect_data
+ sizeof(header
), work_data
->custom_data
, len
);
245 error
= regmap_read(vib
->regmap
, vib
->dsp
.owt_offset_reg
, &offset
);
249 error
= regmap_bulk_write(vib
->regmap
, vib
->dsp
.owt_base_reg
+
250 (offset
* sizeof(u32
)), new_owt_effect_data
,
251 sizeof(header
) + len
);
255 error
= vib
->dsp
.write(vib
->dev
, vib
->regmap
, vib
->dsp
.push_owt_cmd
);
262 static void cs40l50_add_worker(struct work_struct
*work
)
264 struct cs40l50_work
*work_data
= container_of(work
, struct cs40l50_work
, work
);
265 struct cs40l50_vibra
*vib
= work_data
->vib
;
266 struct cs40l50_effect
*effect
;
270 error
= pm_runtime_resume_and_get(vib
->dev
);
274 /* Update effect if already uploaded, otherwise create new effect */
275 effect
= cs40l50_find_effect(work_data
->effect
->id
, &vib
->effect_head
);
277 effect
= kzalloc(sizeof(*effect
), GFP_KERNEL
);
283 effect
->id
= work_data
->effect
->id
;
287 error
= cs40l50_effect_bank_set(work_data
, effect
);
291 error
= cs40l50_effect_index_set(work_data
, effect
);
295 error
= cs40l50_effect_gpio_mapping_set(work_data
, effect
);
299 if (effect
->type
== CS40L50_WVFRM_BANK_OWT
)
300 error
= cs40l50_upload_owt(work_data
);
306 list_add(&effect
->list
, &vib
->effect_head
);
309 pm_runtime_mark_last_busy(vib
->dev
);
310 pm_runtime_put_autosuspend(vib
->dev
);
312 work_data
->error
= error
;
315 static int cs40l50_add(struct input_dev
*dev
, struct ff_effect
*effect
,
316 struct ff_effect
*old
)
318 struct ff_periodic_effect
*periodic
= &effect
->u
.periodic
;
319 struct cs40l50_vibra
*vib
= input_get_drvdata(dev
);
320 struct cs40l50_work work_data
;
322 if (effect
->type
!= FF_PERIODIC
|| periodic
->waveform
!= FF_CUSTOM
) {
323 dev_err(vib
->dev
, "Type (%#X) or waveform (%#X) unsupported\n",
324 effect
->type
, periodic
->waveform
);
328 work_data
.custom_data
= memdup_array_user(effect
->u
.periodic
.custom_data
,
329 effect
->u
.periodic
.custom_len
,
331 if (IS_ERR(work_data
.custom_data
))
332 return PTR_ERR(work_data
.custom_data
);
334 work_data
.custom_len
= effect
->u
.periodic
.custom_len
;
336 work_data
.effect
= effect
;
337 INIT_WORK_ONSTACK(&work_data
.work
, cs40l50_add_worker
);
339 /* Push to the workqueue to serialize with playbacks */
340 queue_work(vib
->vib_wq
, &work_data
.work
);
341 flush_work(&work_data
.work
);
342 destroy_work_on_stack(&work_data
.work
);
344 kfree(work_data
.custom_data
);
346 return work_data
.error
;
349 static void cs40l50_start_worker(struct work_struct
*work
)
351 struct cs40l50_work
*work_data
= container_of(work
, struct cs40l50_work
, work
);
352 struct cs40l50_vibra
*vib
= work_data
->vib
;
353 struct cs40l50_effect
*start_effect
;
355 if (pm_runtime_resume_and_get(vib
->dev
) < 0)
358 start_effect
= cs40l50_find_effect(work_data
->effect
->id
, &vib
->effect_head
);
360 while (--work_data
->count
>= 0) {
361 vib
->dsp
.write(vib
->dev
, vib
->regmap
, start_effect
->index
);
362 usleep_range(work_data
->effect
->replay
.length
,
363 work_data
->effect
->replay
.length
+ 100);
366 dev_err(vib
->dev
, "Effect to play not found\n");
369 pm_runtime_mark_last_busy(vib
->dev
);
370 pm_runtime_put_autosuspend(vib
->dev
);
375 static void cs40l50_stop_worker(struct work_struct
*work
)
377 struct cs40l50_work
*work_data
= container_of(work
, struct cs40l50_work
, work
);
378 struct cs40l50_vibra
*vib
= work_data
->vib
;
380 if (pm_runtime_resume_and_get(vib
->dev
) < 0)
383 vib
->dsp
.write(vib
->dev
, vib
->regmap
, vib
->dsp
.stop_cmd
);
385 pm_runtime_mark_last_busy(vib
->dev
);
386 pm_runtime_put_autosuspend(vib
->dev
);
391 static int cs40l50_playback(struct input_dev
*dev
, int effect_id
, int val
)
393 struct cs40l50_vibra
*vib
= input_get_drvdata(dev
);
394 struct cs40l50_work
*work_data
;
396 work_data
= kzalloc(sizeof(*work_data
), GFP_ATOMIC
);
400 work_data
->vib
= vib
;
403 work_data
->effect
= &dev
->ff
->effects
[effect_id
];
404 work_data
->count
= val
;
405 INIT_WORK(&work_data
->work
, cs40l50_start_worker
);
407 /* Stop the amplifier as device drives only one effect */
408 INIT_WORK(&work_data
->work
, cs40l50_stop_worker
);
411 queue_work(vib
->vib_wq
, &work_data
->work
);
416 static void cs40l50_erase_worker(struct work_struct
*work
)
418 struct cs40l50_work
*work_data
= container_of(work
, struct cs40l50_work
, work
);
419 struct cs40l50_effect
*erase_effect
, *owt_effect
;
420 struct cs40l50_vibra
*vib
= work_data
->vib
;
423 error
= pm_runtime_resume_and_get(vib
->dev
);
427 erase_effect
= cs40l50_find_effect(work_data
->effect
->id
, &vib
->effect_head
);
429 dev_err(vib
->dev
, "Effect to erase not found\n");
434 if (erase_effect
->gpio_reg
!= CS40L50_GPIO_MAPPING_NONE
) {
435 error
= regmap_write(vib
->regmap
, erase_effect
->gpio_reg
,
436 CS40L50_GPIO_DISABLE
);
441 if (erase_effect
->type
== CS40L50_WVFRM_BANK_OWT
) {
442 error
= vib
->dsp
.write(vib
->dev
, vib
->regmap
,
443 vib
->dsp
.delete_owt_cmd
|
444 (erase_effect
->index
& 0xFF));
448 list_for_each_entry(owt_effect
, &vib
->effect_head
, list
)
449 if (owt_effect
->type
== CS40L50_WVFRM_BANK_OWT
&&
450 owt_effect
->index
> erase_effect
->index
)
454 list_del(&erase_effect
->list
);
457 pm_runtime_mark_last_busy(vib
->dev
);
458 pm_runtime_put_autosuspend(vib
->dev
);
460 work_data
->error
= error
;
463 static int cs40l50_erase(struct input_dev
*dev
, int effect_id
)
465 struct cs40l50_vibra
*vib
= input_get_drvdata(dev
);
466 struct cs40l50_work work_data
;
469 work_data
.effect
= &dev
->ff
->effects
[effect_id
];
471 INIT_WORK_ONSTACK(&work_data
.work
, cs40l50_erase_worker
);
473 /* Push to workqueue to serialize with playbacks */
474 queue_work(vib
->vib_wq
, &work_data
.work
);
475 flush_work(&work_data
.work
);
476 destroy_work_on_stack(&work_data
.work
);
478 return work_data
.error
;
481 static void cs40l50_remove_wq(void *data
)
483 flush_workqueue(data
);
484 destroy_workqueue(data
);
487 static int cs40l50_vibra_probe(struct platform_device
*pdev
)
489 struct cs40l50
*cs40l50
= dev_get_drvdata(pdev
->dev
.parent
);
490 struct cs40l50_vibra
*vib
;
493 vib
= devm_kzalloc(pdev
->dev
.parent
, sizeof(*vib
), GFP_KERNEL
);
497 vib
->dev
= cs40l50
->dev
;
498 vib
->regmap
= cs40l50
->regmap
;
499 vib
->dsp
= cs40l50_dsp
;
501 vib
->input
= devm_input_allocate_device(vib
->dev
);
505 vib
->input
->id
.product
= cs40l50
->devid
;
506 vib
->input
->id
.version
= cs40l50
->revid
;
507 vib
->input
->name
= "cs40l50_vibra";
509 input_set_drvdata(vib
->input
, vib
);
510 input_set_capability(vib
->input
, EV_FF
, FF_PERIODIC
);
511 input_set_capability(vib
->input
, EV_FF
, FF_CUSTOM
);
513 error
= input_ff_create(vib
->input
, CS40L50_EFFECTS_MAX
);
515 dev_err(vib
->dev
, "Failed to create input device\n");
519 vib
->input
->ff
->upload
= cs40l50_add
;
520 vib
->input
->ff
->playback
= cs40l50_playback
;
521 vib
->input
->ff
->erase
= cs40l50_erase
;
523 INIT_LIST_HEAD(&vib
->effect_head
);
525 vib
->vib_wq
= alloc_ordered_workqueue("vib_wq", WQ_HIGHPRI
);
529 error
= devm_add_action_or_reset(vib
->dev
, cs40l50_remove_wq
, vib
->vib_wq
);
533 error
= input_register_device(vib
->input
);
540 static const struct platform_device_id cs40l50_vibra_id_match
[] = {
541 { "cs40l50-vibra", },
544 MODULE_DEVICE_TABLE(platform
, cs40l50_vibra_id_match
);
546 static struct platform_driver cs40l50_vibra_driver
= {
547 .probe
= cs40l50_vibra_probe
,
548 .id_table
= cs40l50_vibra_id_match
,
550 .name
= "cs40l50-vibra",
553 module_platform_driver(cs40l50_vibra_driver
);
555 MODULE_DESCRIPTION("CS40L50 Advanced Haptic Driver");
556 MODULE_AUTHOR("James Ogletree, Cirrus Logic Inc. <james.ogletree@cirrus.com>");
557 MODULE_LICENSE("GPL");