1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Support for gpio amplifier
4 * Copyright 2026 CS GROUP France
5 * Author: Herve Codina <herve.codina@bootlin.com>
6 *
7 * Basic simple amplifier driver
8 * Copyright (c) 2017 BayLibre, SAS.
9 * Author: Jerome Brunet <jbrunet@baylibre.com>
10 */
11
12 #include <linux/bitmap.h>
13 #include <linux/bits.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/math.h>
16 #include <linux/minmax.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/slab.h>
21 #include <sound/soc.h>
22 #include <linux/sort.h>
23 #include <sound/tlv.h>
24
25 struct simple_amp_single {
26 struct gpio_desc *gpio;
27 bool is_inverted;
28 int kctrl_val;
29 const char *control_name;
30 };
31
32 struct simple_amp_point {
33 u32 gpio_val;
34 int gain_db;
35 };
36
37 struct simple_amp_range {
38 unsigned int nb_points;
39 struct simple_amp_point min;
40 struct simple_amp_point max;
41 };
42
43 struct simple_amp_ranges {
44 unsigned int nb_ranges;
45 struct simple_amp_range *tab_ranges;
46 };
47
48 struct simple_amp_labels {
49 unsigned int nb_labels;
50 const char **tab_labels;
51 };
52
53 enum simple_amp_mode {
54 SIMPLE_AMP_MODE_NONE,
55 SIMPLE_AMP_MODE_RANGES,
56 SIMPLE_AMP_MODE_LABELS,
57 };
58
59 struct simple_amp_multi {
60 struct gpio_descs *gpios;
61 u32 kctrl_val;
62 u32 kctrl_max;
63 const char *control_name;
64 unsigned int *tlv_array;
65 enum simple_amp_mode mode;
66 union {
67 struct simple_amp_ranges ranges;
68 struct simple_amp_labels labels;
69 };
70 };
71
72 struct simple_amp_data {
73 unsigned int supports;
74 #define SIMPLE_AUDIO_SUPPORT_PGA BIT(0)
75 #define SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES BIT(1)
76 #define SIMPLE_AUDIO_SUPPORT_MUTE BIT(2)
77 #define SIMPLE_AUDIO_SUPPORT_BYPASS BIT(3)
78
79 const struct snd_soc_dapm_widget *dapm_widgets;
80 unsigned int num_dapm_widgets;
81 const struct snd_soc_dapm_route *dapm_routes;
82 unsigned int num_dapm_routes;
83 };
84
85 struct simple_amp {
86 const struct simple_amp_data *data;
87 struct gpio_desc *gpiod_enable;
88 struct simple_amp_single mute;
89 struct simple_amp_single bypass;
90 struct simple_amp_multi gain;
91 };
92
simple_amp_power_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * control,int event)93 static int simple_amp_power_event(struct snd_soc_dapm_widget *w,
94 struct snd_kcontrol *control, int event)
95 {
96 struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
97 struct simple_amp *simple_amp = snd_soc_component_get_drvdata(c);
98 int val;
99
100 switch (event) {
101 case SND_SOC_DAPM_POST_PMU:
102 val = 1;
103 break;
104 case SND_SOC_DAPM_PRE_PMD:
105 val = 0;
106 break;
107 default:
108 WARN(1, "Unexpected event");
109 return -EINVAL;
110 }
111
112 gpiod_set_value_cansleep(simple_amp->gpiod_enable, val);
113
114 return 0;
115 }
116
117 static const struct snd_soc_dapm_widget simple_amp_dapm_widgets[] = {
118 SND_SOC_DAPM_INPUT("INL"),
119 SND_SOC_DAPM_INPUT("INR"),
120 SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event,
121 (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)),
122 SND_SOC_DAPM_OUTPUT("OUTL"),
123 SND_SOC_DAPM_OUTPUT("OUTR"),
124 SND_SOC_DAPM_REGULATOR_SUPPLY("VCC", 20, 0),
125 };
126
127 static const struct snd_soc_dapm_route simple_amp_dapm_routes[] = {
128 { "DRV", NULL, "INL" },
129 { "DRV", NULL, "INR" },
130 { "OUTL", NULL, "VCC" },
131 { "OUTR", NULL, "VCC" },
132 { "OUTL", NULL, "DRV" },
133 { "OUTR", NULL, "DRV" },
134 };
135
136 static const struct snd_soc_dapm_widget simple_amp_mono_pga_dapm_widgets[] = {
137 SND_SOC_DAPM_INPUT("IN"),
138 SND_SOC_DAPM_OUTPUT("OUT"),
139 SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event,
140 (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)),
141 SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0),
142 };
143
144 static const struct snd_soc_dapm_route simple_amp_mono_pga_dapm_routes[] = {
145 { "PGA", NULL, "IN" },
146 { "PGA", NULL, "vdd" },
147 { "OUT", NULL, "PGA" },
148 };
149
150 static const struct snd_soc_dapm_widget simple_amp_stereo_pga_dapm_widgets[] = {
151 SND_SOC_DAPM_INPUT("INL"),
152 SND_SOC_DAPM_INPUT("INR"),
153 SND_SOC_DAPM_OUTPUT("OUTL"),
154 SND_SOC_DAPM_OUTPUT("OUTR"),
155 SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event,
156 (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)),
157 SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0),
158 };
159
160 static const struct snd_soc_dapm_route simple_amp_stereo_pga_dapm_routes[] = {
161 { "PGA", NULL, "INL" },
162 { "PGA", NULL, "INR" },
163 { "PGA", NULL, "vdd" },
164 { "OUTL", NULL, "PGA" },
165 { "OUTR", NULL, "PGA" },
166 };
167
simple_amp_single_kctrl_write_gpio(struct simple_amp_single * single,int kctrl_val)168 static int simple_amp_single_kctrl_write_gpio(struct simple_amp_single *single,
169 int kctrl_val)
170 {
171 int gpio_val;
172
173 gpio_val = single->is_inverted ? !kctrl_val : kctrl_val;
174
175 return gpiod_set_value_cansleep(single->gpio, gpio_val);
176 }
177
simple_amp_single_kctrl_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)178 static int simple_amp_single_kctrl_info(struct snd_kcontrol *kcontrol,
179 struct snd_ctl_elem_info *uinfo)
180 {
181 uinfo->count = 1;
182 uinfo->value.integer.min = 0;
183 uinfo->value.integer.max = 1;
184 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
185 return 0;
186 }
187
simple_amp_single_kctrl_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)188 static int simple_amp_single_kctrl_get(struct snd_kcontrol *kcontrol,
189 struct snd_ctl_elem_value *ucontrol)
190 {
191 struct simple_amp_single *single = (struct simple_amp_single *)kcontrol->private_value;
192
193 ucontrol->value.integer.value[0] = single->kctrl_val;
194
195 return 0;
196 }
197
simple_amp_single_kctrl_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)198 static int simple_amp_single_kctrl_put(struct snd_kcontrol *kcontrol,
199 struct snd_ctl_elem_value *ucontrol)
200 {
201 struct simple_amp_single *single = (struct simple_amp_single *)kcontrol->private_value;
202 int kctrl_val;
203 int err;
204
205 kctrl_val = ucontrol->value.integer.value[0] ? 1 : 0;
206
207 if (kctrl_val == single->kctrl_val)
208 return 0;
209
210 err = simple_amp_single_kctrl_write_gpio(single, kctrl_val);
211 if (err)
212 return err;
213
214 single->kctrl_val = kctrl_val;
215
216 return 1; /* The value changed */
217 }
218
simple_amp_single_add_kcontrol(struct snd_soc_component * component,struct simple_amp_single * single)219 static int simple_amp_single_add_kcontrol(struct snd_soc_component *component,
220 struct simple_amp_single *single)
221 {
222 struct snd_kcontrol_new control = {
223 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
224 .name = single->control_name,
225 .info = simple_amp_single_kctrl_info,
226 .get = simple_amp_single_kctrl_get,
227 .put = simple_amp_single_kctrl_put,
228 .private_value = (unsigned long)single,
229 };
230 int ret;
231
232 /* Be consistent between single->kctrl_val value and the GPIO value */
233 ret = simple_amp_single_kctrl_write_gpio(single, single->kctrl_val);
234 if (ret)
235 return ret;
236
237 return snd_soc_add_component_controls(component, &control, 1);
238 }
239
simple_amp_multi_ranges_kctrl_to_gpio(u32 kctrl_val,struct simple_amp_ranges * ranges)240 static u32 simple_amp_multi_ranges_kctrl_to_gpio(u32 kctrl_val,
241 struct simple_amp_ranges *ranges)
242 {
243 struct simple_amp_range *range;
244 u32 index = kctrl_val;
245 unsigned int i;
246
247 for (i = 0; i < ranges->nb_ranges; i++) {
248 range = &ranges->tab_ranges[i];
249
250 if (index < range->nb_points)
251 return (range->max.gpio_val >= range->min.gpio_val) ?
252 range->min.gpio_val + index :
253 range->min.gpio_val - index;
254
255 index -= range->nb_points;
256 }
257
258 /*
259 * Given index out of possible ranges. This is shouldn't happen.
260 * Signal the issue and return the maximum value
261 */
262 WARN(1, "kctrl_val %u out of ranges\n", kctrl_val);
263 return ranges->tab_ranges[ranges->nb_ranges - 1].max.gpio_val;
264 }
265
simple_amp_multi_kctrl_write_gpios(struct simple_amp_multi * multi,u32 kctrl_val)266 static int simple_amp_multi_kctrl_write_gpios(struct simple_amp_multi *multi,
267 u32 kctrl_val)
268 {
269 DECLARE_BITMAP(bm, 32);
270 u32 gpio_val;
271
272 if (kctrl_val > multi->kctrl_max)
273 return -EINVAL;
274
275 if (multi->mode == SIMPLE_AMP_MODE_RANGES)
276 gpio_val = simple_amp_multi_ranges_kctrl_to_gpio(kctrl_val,
277 &multi->ranges);
278 else
279 gpio_val = kctrl_val;
280
281 bitmap_from_arr32(bm, &gpio_val, multi->gpios->ndescs);
282
283 return gpiod_multi_set_value_cansleep(multi->gpios, bm);
284 }
285
simple_amp_multi_kctrl_int_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)286 static int simple_amp_multi_kctrl_int_info(struct snd_kcontrol *kcontrol,
287 struct snd_ctl_elem_info *uinfo)
288 {
289 struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
290
291 uinfo->count = 1;
292 uinfo->value.integer.min = 0;
293 uinfo->value.integer.max = multi->kctrl_max;
294 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
295 return 0;
296 }
297
simple_amp_multi_kctrl_int_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)298 static int simple_amp_multi_kctrl_int_get(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol)
300 {
301 struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
302
303 ucontrol->value.integer.value[0] = multi->kctrl_val;
304 return 0;
305 }
306
simple_amp_multi_kctrl_int_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)307 static int simple_amp_multi_kctrl_int_put(struct snd_kcontrol *kcontrol,
308 struct snd_ctl_elem_value *ucontrol)
309 {
310 struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
311 u32 kctrl_val;
312 int ret;
313
314 kctrl_val = ucontrol->value.integer.value[0];
315
316 if (kctrl_val == multi->kctrl_val)
317 return 0;
318
319 ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val);
320 if (ret)
321 return ret;
322
323 multi->kctrl_val = kctrl_val;
324
325 return 1; /* The value changed */
326 }
327
simple_amp_multi_kctrl_enum_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)328 static int simple_amp_multi_kctrl_enum_info(struct snd_kcontrol *kcontrol,
329 struct snd_ctl_elem_info *uinfo)
330 {
331 struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
332
333 return snd_ctl_enum_info(uinfo, 1, multi->labels.nb_labels,
334 multi->labels.tab_labels);
335 }
336
simple_amp_multi_kctrl_enum_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)337 static int simple_amp_multi_kctrl_enum_get(struct snd_kcontrol *kcontrol,
338 struct snd_ctl_elem_value *ucontrol)
339 {
340 struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
341
342 ucontrol->value.enumerated.item[0] = multi->kctrl_val;
343 return 0;
344 }
345
simple_amp_multi_kctrl_enum_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)346 static int simple_amp_multi_kctrl_enum_put(struct snd_kcontrol *kcontrol,
347 struct snd_ctl_elem_value *ucontrol)
348 {
349 struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
350 u32 kctrl_val;
351 int ret;
352
353 kctrl_val = ucontrol->value.enumerated.item[0];
354
355 if (kctrl_val == multi->kctrl_val)
356 return 0;
357
358 ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val);
359 if (ret)
360 return ret;
361
362 multi->kctrl_val = kctrl_val;
363
364 return 1; /* The value changed */
365 }
366
simple_amp_alloc_tlv_ranges(const struct simple_amp_ranges * ranges)367 static unsigned int *simple_amp_alloc_tlv_ranges(const struct simple_amp_ranges *ranges)
368 {
369 unsigned int index;
370 unsigned int *tlv;
371 unsigned int *t;
372 unsigned int i;
373
374 tlv = kzalloc_objs(*tlv, 2 + ranges->nb_ranges * 6, GFP_KERNEL);
375 if (!tlv)
376 return NULL;
377
378 t = tlv;
379
380 /* Fill first TLV */
381 *t++ = SNDRV_CTL_TLVT_DB_RANGE; /* Tag */
382 *t++ = ranges->nb_ranges * 6 * sizeof(*tlv); /* Len */
383 /* Ranges are sorted from lower to higher value */
384 index = 0;
385 for (i = 0; i < ranges->nb_ranges; i++) {
386 /* Fill range item i */
387 *t++ = index; /* min */
388 index += ranges->tab_ranges[i].nb_points;
389 *t++ = index - 1; /* max */
390 *t++ = SNDRV_CTL_TLVT_DB_MINMAX; /* Tag */
391 *t++ = 2 * sizeof(*tlv); /* Len */
392 *t++ = ranges->tab_ranges[i].min.gain_db; /* min_dB */
393 *t++ = ranges->tab_ranges[i].max.gain_db; /* max_dB */
394 }
395
396 return tlv;
397 }
398
simple_amp_multi_add_kcontrol(struct snd_soc_component * component,struct simple_amp_multi * multi)399 static int simple_amp_multi_add_kcontrol(struct snd_soc_component *component,
400 struct simple_amp_multi *multi)
401 {
402 struct snd_kcontrol_new control = {
403 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
404 .name = multi->control_name,
405 .info = simple_amp_multi_kctrl_int_info,
406 .get = simple_amp_multi_kctrl_int_get,
407 .put = simple_amp_multi_kctrl_int_put,
408 .private_value = (unsigned long)multi,
409 };
410 int ret;
411
412 switch (multi->mode) {
413 case SIMPLE_AMP_MODE_RANGES:
414 multi->tlv_array = simple_amp_alloc_tlv_ranges(&multi->ranges);
415 if (!multi->tlv_array)
416 return -ENOMEM;
417
418 control.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
419 SNDRV_CTL_ELEM_ACCESS_READWRITE;
420 control.tlv.p = multi->tlv_array;
421 break;
422
423 case SIMPLE_AMP_MODE_LABELS:
424 /* Use enumerated values */
425 control.info = simple_amp_multi_kctrl_enum_info;
426 control.get = simple_amp_multi_kctrl_enum_get;
427 control.put = simple_amp_multi_kctrl_enum_put;
428 break;
429
430 case SIMPLE_AMP_MODE_NONE:
431 /* Already set control configuration is enough */
432 break;
433
434 default:
435 return -EINVAL;
436 }
437
438 /* Be consistent between multi->kctrl_val value and the GPIOs value */
439 ret = simple_amp_multi_kctrl_write_gpios(multi, multi->kctrl_val);
440 if (ret)
441 goto err_free_tlv_array;
442
443 ret = snd_soc_add_component_controls(component, &control, 1);
444 if (ret)
445 goto err_free_tlv_array;
446
447 return 0;
448
449 err_free_tlv_array:
450 kfree(multi->tlv_array);
451 return ret;
452 }
453
simple_amp_add_basic_dapm(struct snd_soc_component * component)454 static int simple_amp_add_basic_dapm(struct snd_soc_component *component)
455 {
456 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
457 struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
458 struct device *dev = component->dev;
459 int ret;
460
461 /* Add basic dapm widgets and routes */
462 ret = snd_soc_dapm_new_controls(dapm, simple_amp->data->dapm_widgets,
463 simple_amp->data->num_dapm_widgets);
464 if (ret) {
465 dev_err(dev, "Failed to add basic dapm widgets (%d)\n", ret);
466 return ret;
467 }
468
469 ret = snd_soc_dapm_add_routes(dapm, simple_amp->data->dapm_routes,
470 simple_amp->data->num_dapm_routes);
471 if (ret) {
472 dev_err(dev, "Failed to add basic dapm routes (%d)\n", ret);
473 return ret;
474 }
475
476 return 0;
477 }
478
479 struct simple_amp_supply {
480 const char *prop_name;
481 const struct snd_soc_dapm_widget dapm_widget;
482 const struct snd_soc_dapm_route dapm_route;
483 };
484
485 static const struct simple_amp_supply simple_amp_supplies[] = {
486 {
487 .prop_name = "vddio-supply",
488 .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vddio", 0, 0),
489 .dapm_route = { "PGA", NULL, "vddio" },
490 }, {
491 .prop_name = "vdda1-supply",
492 .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda1", 0, 0),
493 .dapm_route = { "PGA", NULL, "vdda1" },
494 }, {
495 .prop_name = "vdda2-supply",
496 .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda2", 0, 0),
497 .dapm_route = { "PGA", NULL, "vdda2" },
498 },
499 { /* End of list */}
500 };
501
simple_amp_add_power_supplies(struct snd_soc_component * component)502 static int simple_amp_add_power_supplies(struct snd_soc_component *component)
503 {
504 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
505 struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
506 const struct simple_amp_supply *supply;
507 struct device *dev = component->dev;
508 int ret;
509
510 /*
511 * Those additional power supplies are attached to the PGA.
512 * If PGA is not supported, simply skipped them.
513 */
514 if (!(simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA)) {
515 dev_err(dev, "Extra power supplied need PGA\n");
516 return -EINVAL;
517 }
518
519 supply = simple_amp_supplies;
520 do {
521 if (!of_property_present(dev->of_node, supply->prop_name))
522 continue;
523
524 ret = snd_soc_dapm_new_controls(dapm, &supply->dapm_widget, 1);
525 if (ret) {
526 dev_err(dev, "Failed to add control for '%s' (%d)\n",
527 supply->prop_name, ret);
528 return ret;
529 }
530 ret = snd_soc_dapm_add_routes(dapm, &supply->dapm_route, 1);
531 if (ret) {
532 dev_err(dev, "Failed to add route for '%s' (%d)\n",
533 supply->prop_name, ret);
534 return ret;
535 }
536 } while ((++supply)->prop_name);
537
538 return 0;
539 }
540
simple_amp_component_probe(struct snd_soc_component * component)541 static int simple_amp_component_probe(struct snd_soc_component *component)
542 {
543 struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
544 int ret;
545
546 /* Add basic dapm widgets and routes */
547 ret = simple_amp_add_basic_dapm(component);
548 if (ret)
549 return ret;
550
551 /* Add additional power supplies */
552 if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES) {
553 ret = simple_amp_add_power_supplies(component);
554 if (ret)
555 return ret;
556 }
557
558 if (simple_amp->mute.gpio) {
559 /*
560 * The name of the GPIO used is mute. According to this name, 1
561 * means muted and 0 means un-muted.
562 *
563 * An inversion is expected by ALSA. Indeed from ALSA point of
564 * view, 1 means 'on' (un-muted) and 0 means 'off' (muted).
565 */
566 simple_amp->mute.is_inverted = true;
567 simple_amp->mute.kctrl_val = 1; /* Un-muted */
568 ret = simple_amp_single_add_kcontrol(component, &simple_amp->mute);
569 if (ret)
570 return ret;
571 }
572
573 if (simple_amp->bypass.gpio) {
574 ret = simple_amp_single_add_kcontrol(component, &simple_amp->bypass);
575 if (ret)
576 return ret;
577 }
578
579 if (simple_amp->gain.gpios) {
580 ret = simple_amp_multi_add_kcontrol(component, &simple_amp->gain);
581 if (ret)
582 return ret;
583 }
584
585 return 0;
586 }
587
simple_amp_component_remove(struct snd_soc_component * component)588 static void simple_amp_component_remove(struct snd_soc_component *component)
589 {
590 struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
591
592 kfree(simple_amp->gain.tlv_array);
593 simple_amp->gain.tlv_array = NULL;
594 }
595
596 static const struct snd_soc_component_driver simple_amp_component_driver = {
597 .probe = simple_amp_component_probe,
598 .remove = simple_amp_component_remove,
599 };
600
simple_amp_parse_single_gpio(struct device * dev,struct simple_amp_single * single,const char * gpio_property)601 static int simple_amp_parse_single_gpio(struct device *dev,
602 struct simple_amp_single *single,
603 const char *gpio_property)
604 {
605 /* Start with the inactive value */
606 single->is_inverted = false;
607 single->kctrl_val = 0;
608 single->gpio = devm_gpiod_get_optional(dev, gpio_property, GPIOD_OUT_LOW);
609 if (IS_ERR(single->gpio))
610 return dev_err_probe(dev, PTR_ERR(single->gpio),
611 "Failed to get '%s' gpio\n",
612 gpio_property);
613 return 0;
614 }
615
simple_amp_cmp_ranges(const void * a,const void * b)616 static int simple_amp_cmp_ranges(const void *a, const void *b)
617 {
618 const struct simple_amp_range *a_range = a;
619 const struct simple_amp_range *b_range = b;
620
621 /* Ranges a and b don't overlap. This has been already checked */
622
623 return a_range->min.gain_db - b_range->max.gain_db;
624 }
625
simple_amp_check_new_range(const struct simple_amp_range * new_range,const struct simple_amp_range * tab_ranges,unsigned int nb_ranges)626 static int simple_amp_check_new_range(const struct simple_amp_range *new_range,
627 const struct simple_amp_range *tab_ranges,
628 unsigned int nb_ranges)
629 {
630 unsigned int i;
631
632 for (i = 0; i < nb_ranges; i++) {
633 /* Check for range overlaps */
634 if (new_range->min.gain_db >= tab_ranges[i].min.gain_db &&
635 new_range->min.gain_db <= tab_ranges[i].max.gain_db)
636 return -EINVAL;
637
638 if (new_range->max.gain_db >= tab_ranges[i].min.gain_db &&
639 new_range->max.gain_db <= tab_ranges[i].max.gain_db)
640 return -EINVAL;
641
642 if (new_range->min.gain_db <= tab_ranges[i].min.gain_db &&
643 new_range->max.gain_db >= tab_ranges[i].max.gain_db)
644 return -EINVAL;
645 }
646 return 0;
647 }
648
simple_amp_parse_ranges(struct device * dev,struct simple_amp_multi * multi,const char * ranges_property)649 static int simple_amp_parse_ranges(struct device *dev,
650 struct simple_amp_multi *multi,
651 const char *ranges_property)
652 {
653 struct simple_amp_ranges *ranges = &multi->ranges;
654 struct simple_amp_range *range;
655 struct device_node *np = dev->of_node;
656 struct simple_amp_point first_point;
657 unsigned int max_gpio_val;
658 unsigned int i;
659 int ret;
660 u32 u;
661 s32 s;
662
663 max_gpio_val = (1 << multi->gpios->ndescs) - 1;
664
665 ret = of_property_count_u32_elems(np, ranges_property);
666 if (ret < 0)
667 return ret;
668
669 /* The ranges array cannot be empty */
670 if (ret == 0)
671 return -EINVAL;
672 /*
673 * One range item is composed of 2 points and each point is composed of
674 * 2 values.
675 */
676 if (ret % 4)
677 return -EINVAL;
678
679 ranges->nb_ranges = ret / 4;
680
681 /* The worst case is one range per possible gpio value */
682 if (ranges->nb_ranges > max_gpio_val + 1)
683 return -EINVAL;
684
685 ranges->tab_ranges = devm_kcalloc(dev, ranges->nb_ranges,
686 sizeof(*ranges->tab_ranges),
687 GFP_KERNEL);
688 if (!ranges->tab_ranges)
689 return -ENOMEM;
690
691 multi->kctrl_max = 0;
692 for (i = 0; i < ranges->nb_ranges; i++) {
693 range = &ranges->tab_ranges[i];
694
695 /* First gpios value */
696 ret = of_property_read_u32_index(np, ranges_property, i * 4, &u);
697 if (ret)
698 return ret;
699 if (u > max_gpio_val)
700 return -EINVAL;
701
702 range->min.gpio_val = u;
703
704 /* First Gain value */
705 ret = of_property_read_s32_index(np, ranges_property, i * 4 + 1, &s);
706 if (ret)
707 return ret;
708
709 range->min.gain_db = s;
710
711 /* Second gpios value */
712 ret = of_property_read_u32_index(np, ranges_property, i * 4 + 2, &u);
713 if (ret)
714 return ret;
715 if (u > max_gpio_val)
716 return -EINVAL;
717
718 range->max.gpio_val = u;
719
720 /* Second Gain value */
721 ret = of_property_read_s32_index(np, ranges_property, i * 4 + 3, &s);
722 if (ret)
723 return ret;
724
725 range->max.gain_db = s;
726
727 /* Save the first point for later usage */
728 if (i == 0)
729 first_point = range->min;
730
731 /* Fix min and max if needed */
732 if (range->min.gain_db > range->max.gain_db)
733 swap(range->min, range->max);
734
735 ret = simple_amp_check_new_range(range, ranges->tab_ranges, i);
736 if (ret)
737 return ret;
738
739 range->nb_points = abs_diff(range->min.gpio_val,
740 range->max.gpio_val) + 1;
741
742 multi->kctrl_max += range->nb_points;
743 }
744
745 multi->kctrl_max -= 1;
746
747 /* Sort the tab_range array by gain_db value */
748 sort(ranges->tab_ranges, ranges->nb_ranges, sizeof(*ranges->tab_ranges),
749 simple_amp_cmp_ranges, NULL);
750
751 /*
752 * multi->kctrl_val is the index in tab_ranges.
753 *
754 * Choose to have the initial amplification value set to the first point
755 * available in the first range available in the tab_ranges array before
756 * sorting.
757 *
758 * This first point has been identified before sorting. Search for it in
759 * the sorted array in order to set the multi->kctrl_val initial value.
760 */
761 multi->kctrl_val = 0;
762 for (i = 0; i < ranges->nb_ranges; i++) {
763 range = &ranges->tab_ranges[i];
764
765 if (range->min.gpio_val == first_point.gpio_val &&
766 range->min.gain_db == first_point.gain_db)
767 break;
768
769 multi->kctrl_val += range->nb_points;
770
771 if (range->max.gpio_val == first_point.gpio_val &&
772 range->max.gain_db == first_point.gain_db) {
773 multi->kctrl_val--;
774 break;
775 }
776 }
777
778 return 0;
779 }
780
simple_amp_parse_labels(struct device * dev,struct simple_amp_multi * multi,const char * labels_property)781 static int simple_amp_parse_labels(struct device *dev,
782 struct simple_amp_multi *multi,
783 const char *labels_property)
784 {
785 struct simple_amp_labels *labels = &multi->labels;
786 struct device_node *np = dev->of_node;
787 int ret;
788
789 ret = of_property_count_strings(np, labels_property);
790 if (ret < 0)
791 return ret;
792
793 /* The labels array cannot be empty */
794 if (ret == 0)
795 return -EINVAL;
796
797 labels->nb_labels = ret;
798 if (labels->nb_labels > (1 << multi->gpios->ndescs))
799 return -EINVAL;
800
801 labels->tab_labels = devm_kcalloc(dev, labels->nb_labels,
802 sizeof(*labels->tab_labels),
803 GFP_KERNEL);
804 if (!labels->tab_labels)
805 return -ENOMEM;
806
807 multi->kctrl_max = labels->nb_labels - 1;
808 multi->kctrl_val = 0;
809
810 return of_property_read_string_array(np, labels_property, labels->tab_labels,
811 labels->nb_labels);
812 }
813
simple_amp_parse_multi_gpio(struct device * dev,struct simple_amp_multi * multi,const char * gpios_property,const char * ranges_property,const char * labels_property)814 static int simple_amp_parse_multi_gpio(struct device *dev,
815 struct simple_amp_multi *multi,
816 const char *gpios_property,
817 const char *ranges_property,
818 const char *labels_property)
819 {
820 struct device_node *np = dev->of_node;
821 int ret;
822
823 /* Start with the value 0 (GPIO inactive). Can be changed later */
824 multi->kctrl_val = 0;
825 multi->gpios = devm_gpiod_get_array_optional(dev, gpios_property, GPIOD_OUT_LOW);
826 if (IS_ERR(multi->gpios))
827 return dev_err_probe(dev, PTR_ERR(multi->gpios),
828 "Failed to get '%s' gpios\n",
829 gpios_property);
830 if (!multi->gpios)
831 return 0;
832
833 if (multi->gpios->ndescs > 16)
834 return dev_err_probe(dev, -EINVAL,
835 "Number of '%s' gpios limited to 16\n",
836 gpios_property);
837
838 /* Set default value for the kctrl_max. Can be changed later */
839 multi->kctrl_max = (1 << multi->gpios->ndescs) - 1;
840
841 multi->mode = SIMPLE_AMP_MODE_NONE;
842 if (of_property_present(np, ranges_property)) {
843 ret = simple_amp_parse_ranges(dev, multi, ranges_property);
844 if (ret < 0)
845 return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
846 ranges_property);
847 multi->mode = SIMPLE_AMP_MODE_RANGES;
848 } else if (of_property_present(np, labels_property)) {
849 ret = simple_amp_parse_labels(dev, multi, labels_property);
850 if (ret < 0)
851 return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
852 labels_property);
853
854 multi->mode = SIMPLE_AMP_MODE_LABELS;
855 }
856
857 return 0;
858 }
859
simple_amp_probe(struct platform_device * pdev)860 static int simple_amp_probe(struct platform_device *pdev)
861 {
862 struct device *dev = &pdev->dev;
863 struct simple_amp *simple_amp;
864 int ret;
865
866 simple_amp = devm_kzalloc(dev, sizeof(*simple_amp), GFP_KERNEL);
867 if (!simple_amp)
868 return -ENOMEM;
869 platform_set_drvdata(pdev, simple_amp);
870
871 simple_amp->data = of_device_get_match_data(dev);
872 if (!simple_amp->data)
873 return -EINVAL;
874
875 simple_amp->gpiod_enable = devm_gpiod_get_optional(dev, "enable",
876 GPIOD_OUT_LOW);
877 if (IS_ERR(simple_amp->gpiod_enable))
878 return dev_err_probe(dev, PTR_ERR(simple_amp->gpiod_enable),
879 "Failed to get 'enable' gpio");
880
881 if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_MUTE) {
882 ret = simple_amp_parse_single_gpio(dev, &simple_amp->mute, "mute");
883 if (ret)
884 return ret;
885 }
886
887 if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_BYPASS) {
888 ret = simple_amp_parse_single_gpio(dev, &simple_amp->bypass, "bypass");
889 if (ret)
890 return ret;
891 }
892
893 if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA) {
894 ret = simple_amp_parse_multi_gpio(dev, &simple_amp->gain, "gain",
895 "gain-ranges", "gain-labels");
896 if (ret)
897 return ret;
898 }
899
900 /* Set controls name */
901 simple_amp->gain.control_name = "Volume";
902 simple_amp->mute.control_name = "Switch";
903 simple_amp->bypass.control_name = "Bypass Switch";
904
905 if (simple_amp->gain.mode == SIMPLE_AMP_MODE_LABELS) {
906 /*
907 * The gain widget control will use enumerated values.
908 *
909 * Having just "Voltage" and "Switch" widget names with
910 * enumerated values and boolean value can confuse ALSA in terms
911 * of possible values (strings).
912 *
913 * Make things clear and avoid the just "Switch" name in that
914 * case.
915 */
916 simple_amp->mute.control_name = "Out Switch";
917 }
918
919 return devm_snd_soc_register_component(dev,
920 &simple_amp_component_driver,
921 NULL, 0);
922 }
923
924 static const struct simple_amp_data simple_audio_amplifier_data = {
925 .dapm_widgets = simple_amp_dapm_widgets,
926 .num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets),
927 .dapm_routes = simple_amp_dapm_routes,
928 .num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes),
929 };
930
931 static const struct simple_amp_data simple_audio_mono_pga_data = {
932 .supports = SIMPLE_AUDIO_SUPPORT_PGA |
933 SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES |
934 SIMPLE_AUDIO_SUPPORT_MUTE |
935 SIMPLE_AUDIO_SUPPORT_BYPASS,
936 .dapm_widgets = simple_amp_mono_pga_dapm_widgets,
937 .num_dapm_widgets = ARRAY_SIZE(simple_amp_mono_pga_dapm_widgets),
938 .dapm_routes = simple_amp_mono_pga_dapm_routes,
939 .num_dapm_routes = ARRAY_SIZE(simple_amp_mono_pga_dapm_routes),
940 };
941
942 static const struct simple_amp_data simple_audio_stereo_pga_data = {
943 .supports = SIMPLE_AUDIO_SUPPORT_PGA |
944 SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES |
945 SIMPLE_AUDIO_SUPPORT_MUTE |
946 SIMPLE_AUDIO_SUPPORT_BYPASS,
947 .dapm_widgets = simple_amp_stereo_pga_dapm_widgets,
948 .num_dapm_widgets = ARRAY_SIZE(simple_amp_stereo_pga_dapm_widgets),
949 .dapm_routes = simple_amp_stereo_pga_dapm_routes,
950 .num_dapm_routes = ARRAY_SIZE(simple_amp_stereo_pga_dapm_routes),
951 };
952
953 static const struct of_device_id simple_amp_ids[] = {
954 { .compatible = "dioo,dio2125", .data = &simple_audio_amplifier_data},
955 { .compatible = "simple-audio-amplifier", .data = &simple_audio_amplifier_data},
956 { .compatible = "gpio-audio-amp-mono", .data = &simple_audio_mono_pga_data},
957 { .compatible = "gpio-audio-amp-stereo", .data = &simple_audio_stereo_pga_data},
958 { }
959 };
960 MODULE_DEVICE_TABLE(of, simple_amp_ids);
961
962 static struct platform_driver simple_amp_driver = {
963 .driver = {
964 .name = "simple-amplifier",
965 .of_match_table = simple_amp_ids,
966 },
967 .probe = simple_amp_probe,
968 };
969
970 module_platform_driver(simple_amp_driver);
971
972 MODULE_DESCRIPTION("ASoC Simple Audio Amplifier driver");
973 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
974 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
975 MODULE_LICENSE("GPL");
976