1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // simple-card-utils.c 4 // 5 // Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 7 #include <linux/clk.h> 8 #include <linux/gpio.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_gpio.h> 13 #include <linux/of_graph.h> 14 #include <sound/jack.h> 15 #include <sound/pcm_params.h> 16 #include <sound/simple_card_utils.h> 17 18 static void asoc_simple_fixup_sample_fmt(struct asoc_simple_data *data, 19 struct snd_pcm_hw_params *params) 20 { 21 int i; 22 struct snd_mask *mask = hw_param_mask(params, 23 SNDRV_PCM_HW_PARAM_FORMAT); 24 struct { 25 char *fmt; 26 u32 val; 27 } of_sample_fmt_table[] = { 28 { "s8", SNDRV_PCM_FORMAT_S8}, 29 { "s16_le", SNDRV_PCM_FORMAT_S16_LE}, 30 { "s24_le", SNDRV_PCM_FORMAT_S24_LE}, 31 { "s24_3le", SNDRV_PCM_FORMAT_S24_3LE}, 32 { "s32_le", SNDRV_PCM_FORMAT_S32_LE}, 33 }; 34 35 for (i = 0; i < ARRAY_SIZE(of_sample_fmt_table); i++) { 36 if (!strcmp(data->convert_sample_format, 37 of_sample_fmt_table[i].fmt)) { 38 snd_mask_none(mask); 39 snd_mask_set(mask, of_sample_fmt_table[i].val); 40 break; 41 } 42 } 43 } 44 45 void asoc_simple_convert_fixup(struct asoc_simple_data *data, 46 struct snd_pcm_hw_params *params) 47 { 48 struct snd_interval *rate = hw_param_interval(params, 49 SNDRV_PCM_HW_PARAM_RATE); 50 struct snd_interval *channels = hw_param_interval(params, 51 SNDRV_PCM_HW_PARAM_CHANNELS); 52 53 if (data->convert_rate) 54 rate->min = 55 rate->max = data->convert_rate; 56 57 if (data->convert_channels) 58 channels->min = 59 channels->max = data->convert_channels; 60 61 if (data->convert_sample_format) 62 asoc_simple_fixup_sample_fmt(data, params); 63 } 64 EXPORT_SYMBOL_GPL(asoc_simple_convert_fixup); 65 66 void asoc_simple_parse_convert(struct device_node *np, 67 char *prefix, 68 struct asoc_simple_data *data) 69 { 70 char prop[128]; 71 72 if (!prefix) 73 prefix = ""; 74 75 /* sampling rate convert */ 76 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate"); 77 of_property_read_u32(np, prop, &data->convert_rate); 78 79 /* channels transfer */ 80 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels"); 81 of_property_read_u32(np, prop, &data->convert_channels); 82 83 /* convert sample format */ 84 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-sample-format"); 85 of_property_read_string(np, prop, &data->convert_sample_format); 86 } 87 EXPORT_SYMBOL_GPL(asoc_simple_parse_convert); 88 89 int asoc_simple_parse_daifmt(struct device *dev, 90 struct device_node *node, 91 struct device_node *codec, 92 char *prefix, 93 unsigned int *retfmt) 94 { 95 struct device_node *bitclkmaster = NULL; 96 struct device_node *framemaster = NULL; 97 unsigned int daifmt; 98 99 daifmt = snd_soc_daifmt_parse_format(node, prefix); 100 101 snd_soc_daifmt_parse_clock_provider_as_phandle(node, prefix, &bitclkmaster, &framemaster); 102 if (!bitclkmaster && !framemaster) { 103 /* 104 * No dai-link level and master setting was not found from 105 * sound node level, revert back to legacy DT parsing and 106 * take the settings from codec node. 107 */ 108 dev_dbg(dev, "Revert to legacy daifmt parsing\n"); 109 110 daifmt |= snd_soc_daifmt_parse_clock_provider_as_flag(codec, NULL); 111 } else { 112 daifmt |= snd_soc_daifmt_clock_provider_from_bitmap( 113 ((codec == bitclkmaster) << 4) | (codec == framemaster)); 114 } 115 116 of_node_put(bitclkmaster); 117 of_node_put(framemaster); 118 119 *retfmt = daifmt; 120 121 return 0; 122 } 123 EXPORT_SYMBOL_GPL(asoc_simple_parse_daifmt); 124 125 int asoc_simple_parse_tdm_width_map(struct device *dev, struct device_node *np, 126 struct asoc_simple_dai *dai) 127 { 128 u32 *array_values, *p; 129 int n, i, ret; 130 131 if (!of_property_read_bool(np, "dai-tdm-slot-width-map")) 132 return 0; 133 134 n = of_property_count_elems_of_size(np, "dai-tdm-slot-width-map", sizeof(u32)); 135 if (n % 3) { 136 dev_err(dev, "Invalid number of cells for dai-tdm-slot-width-map\n"); 137 return -EINVAL; 138 } 139 140 dai->tdm_width_map = devm_kcalloc(dev, n, sizeof(*dai->tdm_width_map), GFP_KERNEL); 141 if (!dai->tdm_width_map) 142 return -ENOMEM; 143 144 array_values = kcalloc(n, sizeof(*array_values), GFP_KERNEL); 145 if (!array_values) 146 return -ENOMEM; 147 148 ret = of_property_read_u32_array(np, "dai-tdm-slot-width-map", array_values, n); 149 if (ret < 0) { 150 dev_err(dev, "Could not read dai-tdm-slot-width-map: %d\n", ret); 151 goto out; 152 } 153 154 p = array_values; 155 for (i = 0; i < n / 3; ++i) { 156 dai->tdm_width_map[i].sample_bits = *p++; 157 dai->tdm_width_map[i].slot_width = *p++; 158 dai->tdm_width_map[i].slot_count = *p++; 159 } 160 161 dai->n_tdm_widths = i; 162 ret = 0; 163 out: 164 kfree(array_values); 165 166 return ret; 167 } 168 EXPORT_SYMBOL_GPL(asoc_simple_parse_tdm_width_map); 169 170 int asoc_simple_set_dailink_name(struct device *dev, 171 struct snd_soc_dai_link *dai_link, 172 const char *fmt, ...) 173 { 174 va_list ap; 175 char *name = NULL; 176 int ret = -ENOMEM; 177 178 va_start(ap, fmt); 179 name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap); 180 va_end(ap); 181 182 if (name) { 183 ret = 0; 184 185 dai_link->name = name; 186 dai_link->stream_name = name; 187 } 188 189 return ret; 190 } 191 EXPORT_SYMBOL_GPL(asoc_simple_set_dailink_name); 192 193 int asoc_simple_parse_card_name(struct snd_soc_card *card, 194 char *prefix) 195 { 196 int ret; 197 198 if (!prefix) 199 prefix = ""; 200 201 /* Parse the card name from DT */ 202 ret = snd_soc_of_parse_card_name(card, "label"); 203 if (ret < 0 || !card->name) { 204 char prop[128]; 205 206 snprintf(prop, sizeof(prop), "%sname", prefix); 207 ret = snd_soc_of_parse_card_name(card, prop); 208 if (ret < 0) 209 return ret; 210 } 211 212 if (!card->name && card->dai_link) 213 card->name = card->dai_link->name; 214 215 return 0; 216 } 217 EXPORT_SYMBOL_GPL(asoc_simple_parse_card_name); 218 219 static int asoc_simple_clk_enable(struct asoc_simple_dai *dai) 220 { 221 if (dai) 222 return clk_prepare_enable(dai->clk); 223 224 return 0; 225 } 226 227 static void asoc_simple_clk_disable(struct asoc_simple_dai *dai) 228 { 229 if (dai) 230 clk_disable_unprepare(dai->clk); 231 } 232 233 int asoc_simple_parse_clk(struct device *dev, 234 struct device_node *node, 235 struct asoc_simple_dai *simple_dai, 236 struct snd_soc_dai_link_component *dlc) 237 { 238 struct clk *clk; 239 u32 val; 240 241 /* 242 * Parse dai->sysclk come from "clocks = <&xxx>" 243 * (if system has common clock) 244 * or "system-clock-frequency = <xxx>" 245 * or device's module clock. 246 */ 247 clk = devm_get_clk_from_child(dev, node, NULL); 248 simple_dai->clk_fixed = of_property_read_bool( 249 node, "system-clock-fixed"); 250 if (!IS_ERR(clk)) { 251 simple_dai->sysclk = clk_get_rate(clk); 252 253 simple_dai->clk = clk; 254 } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { 255 simple_dai->sysclk = val; 256 simple_dai->clk_fixed = true; 257 } else { 258 clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); 259 if (!IS_ERR(clk)) 260 simple_dai->sysclk = clk_get_rate(clk); 261 } 262 263 if (of_property_read_bool(node, "system-clock-direction-out")) 264 simple_dai->clk_direction = SND_SOC_CLOCK_OUT; 265 266 return 0; 267 } 268 EXPORT_SYMBOL_GPL(asoc_simple_parse_clk); 269 270 static int asoc_simple_check_fixed_sysclk(struct device *dev, 271 struct asoc_simple_dai *dai, 272 unsigned int *fixed_sysclk) 273 { 274 if (dai->clk_fixed) { 275 if (*fixed_sysclk && *fixed_sysclk != dai->sysclk) { 276 dev_err(dev, "inconsistent fixed sysclk rates (%u vs %u)\n", 277 *fixed_sysclk, dai->sysclk); 278 return -EINVAL; 279 } 280 *fixed_sysclk = dai->sysclk; 281 } 282 283 return 0; 284 } 285 286 int asoc_simple_startup(struct snd_pcm_substream *substream) 287 { 288 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 289 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); 290 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); 291 struct asoc_simple_dai *dai; 292 unsigned int fixed_sysclk = 0; 293 int i1, i2, i; 294 int ret; 295 296 for_each_prop_dai_cpu(props, i1, dai) { 297 ret = asoc_simple_clk_enable(dai); 298 if (ret) 299 goto cpu_err; 300 ret = asoc_simple_check_fixed_sysclk(rtd->dev, dai, &fixed_sysclk); 301 if (ret) 302 goto cpu_err; 303 } 304 305 for_each_prop_dai_codec(props, i2, dai) { 306 ret = asoc_simple_clk_enable(dai); 307 if (ret) 308 goto codec_err; 309 ret = asoc_simple_check_fixed_sysclk(rtd->dev, dai, &fixed_sysclk); 310 if (ret) 311 goto codec_err; 312 } 313 314 if (fixed_sysclk && props->mclk_fs) { 315 unsigned int fixed_rate = fixed_sysclk / props->mclk_fs; 316 317 if (fixed_sysclk % props->mclk_fs) { 318 dev_err(rtd->dev, "fixed sysclk %u not divisible by mclk_fs %u\n", 319 fixed_sysclk, props->mclk_fs); 320 return -EINVAL; 321 } 322 ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, 323 fixed_rate, fixed_rate); 324 if (ret) 325 goto codec_err; 326 } 327 328 return 0; 329 330 codec_err: 331 for_each_prop_dai_codec(props, i, dai) { 332 if (i >= i2) 333 break; 334 asoc_simple_clk_disable(dai); 335 } 336 cpu_err: 337 for_each_prop_dai_cpu(props, i, dai) { 338 if (i >= i1) 339 break; 340 asoc_simple_clk_disable(dai); 341 } 342 return ret; 343 } 344 EXPORT_SYMBOL_GPL(asoc_simple_startup); 345 346 void asoc_simple_shutdown(struct snd_pcm_substream *substream) 347 { 348 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 349 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); 350 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); 351 struct asoc_simple_dai *dai; 352 int i; 353 354 for_each_prop_dai_cpu(props, i, dai) { 355 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, i); 356 357 if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(cpu_dai)) 358 snd_soc_dai_set_sysclk(cpu_dai, 359 0, 0, SND_SOC_CLOCK_OUT); 360 361 asoc_simple_clk_disable(dai); 362 } 363 for_each_prop_dai_codec(props, i, dai) { 364 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, i); 365 366 if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(codec_dai)) 367 snd_soc_dai_set_sysclk(codec_dai, 368 0, 0, SND_SOC_CLOCK_IN); 369 370 asoc_simple_clk_disable(dai); 371 } 372 } 373 EXPORT_SYMBOL_GPL(asoc_simple_shutdown); 374 375 static int asoc_simple_set_clk_rate(struct device *dev, 376 struct asoc_simple_dai *simple_dai, 377 unsigned long rate) 378 { 379 if (!simple_dai) 380 return 0; 381 382 if (simple_dai->clk_fixed && rate != simple_dai->sysclk) { 383 dev_err(dev, "dai %s invalid clock rate %lu\n", simple_dai->name, rate); 384 return -EINVAL; 385 } 386 387 if (!simple_dai->clk) 388 return 0; 389 390 if (clk_get_rate(simple_dai->clk) == rate) 391 return 0; 392 393 return clk_set_rate(simple_dai->clk, rate); 394 } 395 396 static int asoc_simple_set_tdm(struct snd_soc_dai *dai, 397 struct asoc_simple_dai *simple_dai, 398 struct snd_pcm_hw_params *params) 399 { 400 int sample_bits = params_width(params); 401 int slot_width, slot_count; 402 int i, ret; 403 404 if (!simple_dai || !simple_dai->tdm_width_map) 405 return 0; 406 407 slot_width = simple_dai->slot_width; 408 slot_count = simple_dai->slots; 409 410 if (slot_width == 0) 411 slot_width = sample_bits; 412 413 for (i = 0; i < simple_dai->n_tdm_widths; ++i) { 414 if (simple_dai->tdm_width_map[i].sample_bits == sample_bits) { 415 slot_width = simple_dai->tdm_width_map[i].slot_width; 416 slot_count = simple_dai->tdm_width_map[i].slot_count; 417 break; 418 } 419 } 420 421 ret = snd_soc_dai_set_tdm_slot(dai, 422 simple_dai->tx_slot_mask, 423 simple_dai->rx_slot_mask, 424 slot_count, 425 slot_width); 426 if (ret && ret != -ENOTSUPP) { 427 dev_err(dai->dev, "simple-card: set_tdm_slot error: %d\n", ret); 428 return ret; 429 } 430 431 return 0; 432 } 433 434 int asoc_simple_hw_params(struct snd_pcm_substream *substream, 435 struct snd_pcm_hw_params *params) 436 { 437 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 438 struct asoc_simple_dai *pdai; 439 struct snd_soc_dai *sdai; 440 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); 441 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); 442 unsigned int mclk, mclk_fs = 0; 443 int i, ret; 444 445 if (props->mclk_fs) 446 mclk_fs = props->mclk_fs; 447 448 if (mclk_fs) { 449 struct snd_soc_component *component; 450 mclk = params_rate(params) * mclk_fs; 451 452 for_each_prop_dai_codec(props, i, pdai) { 453 ret = asoc_simple_set_clk_rate(rtd->dev, pdai, mclk); 454 if (ret < 0) 455 return ret; 456 } 457 458 for_each_prop_dai_cpu(props, i, pdai) { 459 ret = asoc_simple_set_clk_rate(rtd->dev, pdai, mclk); 460 if (ret < 0) 461 return ret; 462 } 463 464 /* Ensure sysclk is set on all components in case any 465 * (such as platform components) are missed by calls to 466 * snd_soc_dai_set_sysclk. 467 */ 468 for_each_rtd_components(rtd, i, component) { 469 ret = snd_soc_component_set_sysclk(component, 0, 0, 470 mclk, SND_SOC_CLOCK_IN); 471 if (ret && ret != -ENOTSUPP) 472 return ret; 473 } 474 475 for_each_rtd_codec_dais(rtd, i, sdai) { 476 ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_IN); 477 if (ret && ret != -ENOTSUPP) 478 return ret; 479 } 480 481 for_each_rtd_cpu_dais(rtd, i, sdai) { 482 ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_OUT); 483 if (ret && ret != -ENOTSUPP) 484 return ret; 485 } 486 } 487 488 for_each_prop_dai_codec(props, i, pdai) { 489 sdai = asoc_rtd_to_codec(rtd, i); 490 ret = asoc_simple_set_tdm(sdai, pdai, params); 491 if (ret < 0) 492 return ret; 493 } 494 495 for_each_prop_dai_cpu(props, i, pdai) { 496 sdai = asoc_rtd_to_cpu(rtd, i); 497 ret = asoc_simple_set_tdm(sdai, pdai, params); 498 if (ret < 0) 499 return ret; 500 } 501 502 return 0; 503 } 504 EXPORT_SYMBOL_GPL(asoc_simple_hw_params); 505 506 int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 507 struct snd_pcm_hw_params *params) 508 { 509 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); 510 struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); 511 512 asoc_simple_convert_fixup(&dai_props->adata, params); 513 514 return 0; 515 } 516 EXPORT_SYMBOL_GPL(asoc_simple_be_hw_params_fixup); 517 518 static int asoc_simple_init_dai(struct snd_soc_dai *dai, 519 struct asoc_simple_dai *simple_dai) 520 { 521 int ret; 522 523 if (!simple_dai) 524 return 0; 525 526 if (simple_dai->sysclk) { 527 ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 528 simple_dai->clk_direction); 529 if (ret && ret != -ENOTSUPP) { 530 dev_err(dai->dev, "simple-card: set_sysclk error\n"); 531 return ret; 532 } 533 } 534 535 if (simple_dai->slots) { 536 ret = snd_soc_dai_set_tdm_slot(dai, 537 simple_dai->tx_slot_mask, 538 simple_dai->rx_slot_mask, 539 simple_dai->slots, 540 simple_dai->slot_width); 541 if (ret && ret != -ENOTSUPP) { 542 dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); 543 return ret; 544 } 545 } 546 547 return 0; 548 } 549 550 static inline int asoc_simple_component_is_codec(struct snd_soc_component *component) 551 { 552 return component->driver->endianness; 553 } 554 555 static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, 556 struct simple_dai_props *dai_props) 557 { 558 struct snd_soc_dai_link *dai_link = rtd->dai_link; 559 struct snd_soc_component *component; 560 struct snd_soc_pcm_stream *params; 561 struct snd_pcm_hardware hw; 562 int i, ret, stream; 563 564 /* Do nothing if it already has Codec2Codec settings */ 565 if (dai_link->params) 566 return 0; 567 568 /* Do nothing if it was DPCM :: BE */ 569 if (dai_link->no_pcm) 570 return 0; 571 572 /* Only Codecs */ 573 for_each_rtd_components(rtd, i, component) { 574 if (!asoc_simple_component_is_codec(component)) 575 return 0; 576 } 577 578 /* Assumes the capabilities are the same for all supported streams */ 579 for_each_pcm_streams(stream) { 580 ret = snd_soc_runtime_calc_hw(rtd, &hw, stream); 581 if (ret == 0) 582 break; 583 } 584 585 if (ret < 0) { 586 dev_err(rtd->dev, "simple-card: no valid dai_link params\n"); 587 return ret; 588 } 589 590 params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL); 591 if (!params) 592 return -ENOMEM; 593 594 params->formats = hw.formats; 595 params->rates = hw.rates; 596 params->rate_min = hw.rate_min; 597 params->rate_max = hw.rate_max; 598 params->channels_min = hw.channels_min; 599 params->channels_max = hw.channels_max; 600 601 dai_link->params = params; 602 dai_link->num_params = 1; 603 604 return 0; 605 } 606 607 int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd) 608 { 609 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); 610 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); 611 struct asoc_simple_dai *dai; 612 int i, ret; 613 614 for_each_prop_dai_codec(props, i, dai) { 615 ret = asoc_simple_init_dai(asoc_rtd_to_codec(rtd, i), dai); 616 if (ret < 0) 617 return ret; 618 } 619 for_each_prop_dai_cpu(props, i, dai) { 620 ret = asoc_simple_init_dai(asoc_rtd_to_cpu(rtd, i), dai); 621 if (ret < 0) 622 return ret; 623 } 624 625 ret = asoc_simple_init_for_codec2codec(rtd, props); 626 if (ret < 0) 627 return ret; 628 629 return 0; 630 } 631 EXPORT_SYMBOL_GPL(asoc_simple_dai_init); 632 633 void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, 634 struct snd_soc_dai_link_component *cpus) 635 { 636 /* Assumes platform == cpu */ 637 if (!platforms->of_node) 638 platforms->of_node = cpus->of_node; 639 } 640 EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); 641 642 void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, 643 int is_single_links) 644 { 645 /* 646 * In soc_bind_dai_link() will check cpu name after 647 * of_node matching if dai_link has cpu_dai_name. 648 * but, it will never match if name was created by 649 * fmt_single_name() remove cpu_dai_name if cpu_args 650 * was 0. See: 651 * fmt_single_name() 652 * fmt_multiple_name() 653 */ 654 if (is_single_links) 655 cpus->dai_name = NULL; 656 } 657 EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu); 658 659 void asoc_simple_clean_reference(struct snd_soc_card *card) 660 { 661 struct snd_soc_dai_link *dai_link; 662 struct snd_soc_dai_link_component *cpu; 663 struct snd_soc_dai_link_component *codec; 664 int i, j; 665 666 for_each_card_prelinks(card, i, dai_link) { 667 for_each_link_cpus(dai_link, j, cpu) 668 of_node_put(cpu->of_node); 669 for_each_link_codecs(dai_link, j, codec) 670 of_node_put(codec->of_node); 671 } 672 } 673 EXPORT_SYMBOL_GPL(asoc_simple_clean_reference); 674 675 int asoc_simple_parse_routing(struct snd_soc_card *card, 676 char *prefix) 677 { 678 struct device_node *node = card->dev->of_node; 679 char prop[128]; 680 681 if (!prefix) 682 prefix = ""; 683 684 snprintf(prop, sizeof(prop), "%s%s", prefix, "routing"); 685 686 if (!of_property_read_bool(node, prop)) 687 return 0; 688 689 return snd_soc_of_parse_audio_routing(card, prop); 690 } 691 EXPORT_SYMBOL_GPL(asoc_simple_parse_routing); 692 693 int asoc_simple_parse_widgets(struct snd_soc_card *card, 694 char *prefix) 695 { 696 struct device_node *node = card->dev->of_node; 697 char prop[128]; 698 699 if (!prefix) 700 prefix = ""; 701 702 snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets"); 703 704 if (of_property_read_bool(node, prop)) 705 return snd_soc_of_parse_audio_simple_widgets(card, prop); 706 707 /* no widgets is not error */ 708 return 0; 709 } 710 EXPORT_SYMBOL_GPL(asoc_simple_parse_widgets); 711 712 int asoc_simple_parse_pin_switches(struct snd_soc_card *card, 713 char *prefix) 714 { 715 char prop[128]; 716 717 if (!prefix) 718 prefix = ""; 719 720 snprintf(prop, sizeof(prop), "%s%s", prefix, "pin-switches"); 721 722 return snd_soc_of_parse_pin_switches(card, prop); 723 } 724 EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches); 725 726 int asoc_simple_init_jack(struct snd_soc_card *card, 727 struct asoc_simple_jack *sjack, 728 int is_hp, char *prefix, 729 char *pin) 730 { 731 struct device *dev = card->dev; 732 enum of_gpio_flags flags; 733 char prop[128]; 734 char *pin_name; 735 char *gpio_name; 736 int mask; 737 int det; 738 739 if (!prefix) 740 prefix = ""; 741 742 sjack->gpio.gpio = -ENOENT; 743 744 if (is_hp) { 745 snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix); 746 pin_name = pin ? pin : "Headphones"; 747 gpio_name = "Headphone detection"; 748 mask = SND_JACK_HEADPHONE; 749 } else { 750 snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix); 751 pin_name = pin ? pin : "Mic Jack"; 752 gpio_name = "Mic detection"; 753 mask = SND_JACK_MICROPHONE; 754 } 755 756 det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags); 757 if (det == -EPROBE_DEFER) 758 return -EPROBE_DEFER; 759 760 if (gpio_is_valid(det)) { 761 sjack->pin.pin = pin_name; 762 sjack->pin.mask = mask; 763 764 sjack->gpio.name = gpio_name; 765 sjack->gpio.report = mask; 766 sjack->gpio.gpio = det; 767 sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW); 768 sjack->gpio.debounce_time = 150; 769 770 snd_soc_card_jack_new_pins(card, pin_name, mask, &sjack->jack, 771 &sjack->pin, 1); 772 773 snd_soc_jack_add_gpios(&sjack->jack, 1, 774 &sjack->gpio); 775 } 776 777 return 0; 778 } 779 EXPORT_SYMBOL_GPL(asoc_simple_init_jack); 780 781 int asoc_simple_init_priv(struct asoc_simple_priv *priv, 782 struct link_info *li) 783 { 784 struct snd_soc_card *card = simple_priv_to_card(priv); 785 struct device *dev = simple_priv_to_dev(priv); 786 struct snd_soc_dai_link *dai_link; 787 struct simple_dai_props *dai_props; 788 struct asoc_simple_dai *dais; 789 struct snd_soc_dai_link_component *dlcs; 790 struct snd_soc_codec_conf *cconf = NULL; 791 int i, dai_num = 0, dlc_num = 0, cnf_num = 0; 792 793 dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); 794 dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); 795 if (!dai_props || !dai_link) 796 return -ENOMEM; 797 798 /* 799 * dais (= CPU+Codec) 800 * dlcs (= CPU+Codec+Platform) 801 */ 802 for (i = 0; i < li->link; i++) { 803 int cc = li->num[i].cpus + li->num[i].codecs; 804 805 dai_num += cc; 806 dlc_num += cc + li->num[i].platforms; 807 808 if (!li->num[i].cpus) 809 cnf_num += li->num[i].codecs; 810 } 811 812 dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); 813 dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL); 814 if (!dais || !dlcs) 815 return -ENOMEM; 816 817 if (cnf_num) { 818 cconf = devm_kcalloc(dev, cnf_num, sizeof(*cconf), GFP_KERNEL); 819 if (!cconf) 820 return -ENOMEM; 821 } 822 823 dev_dbg(dev, "link %d, dais %d, ccnf %d\n", 824 li->link, dai_num, cnf_num); 825 826 /* dummy CPU/Codec */ 827 priv->dummy.of_node = NULL; 828 priv->dummy.dai_name = "snd-soc-dummy-dai"; 829 priv->dummy.name = "snd-soc-dummy"; 830 831 priv->dai_props = dai_props; 832 priv->dai_link = dai_link; 833 priv->dais = dais; 834 priv->dlcs = dlcs; 835 priv->codec_conf = cconf; 836 837 card->dai_link = priv->dai_link; 838 card->num_links = li->link; 839 card->codec_conf = cconf; 840 card->num_configs = cnf_num; 841 842 for (i = 0; i < li->link; i++) { 843 if (li->num[i].cpus) { 844 /* Normal CPU */ 845 dai_props[i].cpus = 846 dai_link[i].cpus = dlcs; 847 dai_props[i].num.cpus = 848 dai_link[i].num_cpus = li->num[i].cpus; 849 dai_props[i].cpu_dai = dais; 850 851 dlcs += li->num[i].cpus; 852 dais += li->num[i].cpus; 853 } else { 854 /* DPCM Be's CPU = dummy */ 855 dai_props[i].cpus = 856 dai_link[i].cpus = &priv->dummy; 857 dai_props[i].num.cpus = 858 dai_link[i].num_cpus = 1; 859 } 860 861 if (li->num[i].codecs) { 862 /* Normal Codec */ 863 dai_props[i].codecs = 864 dai_link[i].codecs = dlcs; 865 dai_props[i].num.codecs = 866 dai_link[i].num_codecs = li->num[i].codecs; 867 dai_props[i].codec_dai = dais; 868 869 dlcs += li->num[i].codecs; 870 dais += li->num[i].codecs; 871 872 if (!li->num[i].cpus) { 873 /* DPCM Be's Codec */ 874 dai_props[i].codec_conf = cconf; 875 cconf += li->num[i].codecs; 876 } 877 } else { 878 /* DPCM Fe's Codec = dummy */ 879 dai_props[i].codecs = 880 dai_link[i].codecs = &priv->dummy; 881 dai_props[i].num.codecs = 882 dai_link[i].num_codecs = 1; 883 } 884 885 if (li->num[i].platforms) { 886 /* Have Platform */ 887 dai_props[i].platforms = 888 dai_link[i].platforms = dlcs; 889 dai_props[i].num.platforms = 890 dai_link[i].num_platforms = li->num[i].platforms; 891 892 dlcs += li->num[i].platforms; 893 } else { 894 /* Doesn't have Platform */ 895 dai_props[i].platforms = 896 dai_link[i].platforms = NULL; 897 dai_props[i].num.platforms = 898 dai_link[i].num_platforms = 0; 899 } 900 } 901 902 return 0; 903 } 904 EXPORT_SYMBOL_GPL(asoc_simple_init_priv); 905 906 int asoc_simple_remove(struct platform_device *pdev) 907 { 908 struct snd_soc_card *card = platform_get_drvdata(pdev); 909 910 asoc_simple_clean_reference(card); 911 912 return 0; 913 } 914 EXPORT_SYMBOL_GPL(asoc_simple_remove); 915 916 int asoc_graph_card_probe(struct snd_soc_card *card) 917 { 918 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); 919 int ret; 920 921 ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL); 922 if (ret < 0) 923 return ret; 924 925 ret = asoc_simple_init_mic(card, &priv->mic_jack, NULL); 926 if (ret < 0) 927 return ret; 928 929 return 0; 930 } 931 EXPORT_SYMBOL_GPL(asoc_graph_card_probe); 932 933 int asoc_graph_is_ports0(struct device_node *np) 934 { 935 struct device_node *port, *ports, *ports0, *top; 936 int ret; 937 938 /* np is "endpoint" or "port" */ 939 if (of_node_name_eq(np, "endpoint")) { 940 port = of_get_parent(np); 941 } else { 942 port = np; 943 of_node_get(port); 944 } 945 946 ports = of_get_parent(port); 947 top = of_get_parent(ports); 948 ports0 = of_get_child_by_name(top, "ports"); 949 950 ret = ports0 == ports; 951 952 of_node_put(port); 953 of_node_put(ports); 954 of_node_put(ports0); 955 of_node_put(top); 956 957 return ret; 958 } 959 EXPORT_SYMBOL_GPL(asoc_graph_is_ports0); 960 961 /* Module information */ 962 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 963 MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); 964 MODULE_LICENSE("GPL v2"); 965