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