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