1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // ASoC simple sound card support 4 // 5 // Copyright (C) 2012 Renesas Solutions Corp. 6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 8 #include <linux/cleanup.h> 9 #include <linux/clk.h> 10 #include <linux/device.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_platform.h> 14 #include <linux/platform_device.h> 15 #include <linux/string.h> 16 #include <sound/simple_card_utils.h> 17 #include <sound/soc.h> 18 #include <sound/soc-dai.h> 19 20 #define DPCM_SELECTABLE 1 21 22 #define DAI "sound-dai" 23 #define CELL "#sound-dai-cells" 24 #define PREFIX "simple-audio-card," 25 26 static const struct snd_soc_ops simple_ops = { 27 .startup = simple_util_startup, 28 .shutdown = simple_util_shutdown, 29 .hw_params = simple_util_hw_params, 30 }; 31 32 #define simple_ret(priv, ret) _simple_ret(priv, __func__, ret) 33 static inline int _simple_ret(struct simple_util_priv *priv, 34 const char *func, int ret) 35 { 36 return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); 37 } 38 39 static int simple_parse_platform(struct simple_util_priv *priv, 40 struct device_node *node, 41 struct snd_soc_dai_link_component *dlc) 42 { 43 struct of_phandle_args args; 44 int ret; 45 46 if (!node) 47 return 0; 48 49 /* 50 * Get node via "sound-dai = <&phandle port>" 51 * It will be used as the of_node for component matching during 52 * snd_soc_add_pcm_runtime(). 53 */ 54 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); 55 if (ret) 56 return simple_ret(priv, ret); 57 58 /* dai_name is not required and may not exist for plat component */ 59 60 dlc->of_node = args.np; 61 62 return 0; 63 } 64 65 static int simple_parse_dai(struct simple_util_priv *priv, 66 struct device_node *node, 67 struct snd_soc_dai_link_component *dlc, 68 int *is_single_link) 69 { 70 struct device *dev = simple_priv_to_dev(priv); 71 struct of_phandle_args args; 72 struct snd_soc_dai_link_component resolved_dlc = {}; 73 struct snd_soc_dai *dai; 74 const char *fallback_dai_name; 75 int ret; 76 77 if (!node) 78 return 0; 79 80 /* 81 * Get node via "sound-dai = <&phandle port>" 82 * It will be used as the of_node for component matching during 83 * snd_soc_add_pcm_runtime(). 84 */ 85 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); 86 if (ret) 87 goto end; 88 89 /* 90 * Try to find from DAI args 91 */ 92 dai = snd_soc_get_dai_via_args(&args); 93 if (dai) { 94 ret = -ENOMEM; 95 dlc->dai_name = snd_soc_dai_name_get(dai); 96 dlc->dai_args = snd_soc_copy_dai_args(dev, &args); 97 if (!dlc->dai_args) 98 goto end; 99 } else { 100 ret = snd_soc_get_dlc(&args, &resolved_dlc); 101 if (ret < 0) 102 goto end; 103 104 /* Keep fallback dai_name valid across component rebind */ 105 fallback_dai_name = resolved_dlc.dai_name; 106 if (fallback_dai_name) { 107 fallback_dai_name = devm_kstrdup_const(dev, fallback_dai_name, 108 GFP_KERNEL); 109 ret = -ENOMEM; 110 if (!fallback_dai_name) { 111 of_node_put(resolved_dlc.of_node); 112 goto end; 113 } 114 } 115 116 dlc->of_node = resolved_dlc.of_node; 117 dlc->dai_name = fallback_dai_name; 118 dlc->dai_args = resolved_dlc.dai_args; 119 } 120 121 if (is_single_link) 122 *is_single_link = !args.args_count; 123 ret = 0; 124 end: 125 return simple_ret(priv, ret); 126 } 127 128 static void simple_parse_convert(struct device *dev, 129 struct device_node *np, 130 struct simple_util_data *adata) 131 { 132 struct device_node *top = dev->of_node; 133 struct device_node *node __free(device_node) = of_get_parent(np); 134 135 simple_util_parse_convert(top, PREFIX, adata); 136 simple_util_parse_convert(node, PREFIX, adata); 137 simple_util_parse_convert(node, NULL, adata); 138 simple_util_parse_convert(np, NULL, adata); 139 } 140 141 static int simple_parse_node(struct simple_util_priv *priv, 142 struct device_node *np, 143 struct link_info *li, 144 char *prefix, 145 int *cpu) 146 { 147 struct device *dev = simple_priv_to_dev(priv); 148 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 149 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 150 struct snd_soc_dai_link_component *dlc; 151 struct simple_util_dai *dai; 152 int ret; 153 154 if (cpu) { 155 dlc = snd_soc_link_to_cpu(dai_link, 0); 156 dai = simple_props_to_dai_cpu(dai_props, 0); 157 } else { 158 dlc = snd_soc_link_to_codec(dai_link, 0); 159 dai = simple_props_to_dai_codec(dai_props, 0); 160 } 161 162 ret = simple_parse_dai(priv, np, dlc, cpu); 163 if (ret) 164 goto end; 165 166 ret = simple_util_parse_clk(dev, np, dai, dlc); 167 if (ret) 168 goto end; 169 170 ret = simple_util_parse_tdm(np, dai); 171 end: 172 return simple_ret(priv, ret); 173 } 174 175 static int simple_link_init(struct simple_util_priv *priv, 176 struct device_node *cpu, 177 struct device_node *codec, 178 struct link_info *li, 179 char *prefix, char *name) 180 { 181 struct device *dev = simple_priv_to_dev(priv); 182 struct device_node *top = dev->of_node; 183 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 184 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 185 struct device_node *node __free(device_node) = of_get_parent(cpu); 186 enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT; 187 enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT; 188 bool playback_only = 0, capture_only = 0; 189 int ret; 190 191 ret = simple_util_parse_daifmt(dev, node, codec, 192 prefix, &dai_link->dai_fmt); 193 if (ret < 0) 194 goto end; 195 196 graph_util_parse_link_direction(top, &playback_only, &capture_only); 197 graph_util_parse_link_direction(node, &playback_only, &capture_only); 198 graph_util_parse_link_direction(cpu, &playback_only, &capture_only); 199 graph_util_parse_link_direction(codec, &playback_only, &capture_only); 200 201 of_property_read_u32(top, "mclk-fs", &dai_props->mclk_fs); 202 of_property_read_u32(top, PREFIX "mclk-fs", &dai_props->mclk_fs); 203 of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs); 204 of_property_read_u32(node, PREFIX "mclk-fs", &dai_props->mclk_fs); 205 of_property_read_u32(cpu, "mclk-fs", &dai_props->mclk_fs); 206 of_property_read_u32(cpu, PREFIX "mclk-fs", &dai_props->mclk_fs); 207 of_property_read_u32(codec, "mclk-fs", &dai_props->mclk_fs); 208 of_property_read_u32(codec, PREFIX "mclk-fs", &dai_props->mclk_fs); 209 210 graph_util_parse_trigger_order(priv, top, &trigger_start, &trigger_stop); 211 graph_util_parse_trigger_order(priv, node, &trigger_start, &trigger_stop); 212 graph_util_parse_trigger_order(priv, cpu, &trigger_start, &trigger_stop); 213 graph_util_parse_trigger_order(priv, codec, &trigger_start, &trigger_stop); 214 215 dai_link->playback_only = playback_only; 216 dai_link->capture_only = capture_only; 217 218 dai_link->trigger_start = trigger_start; 219 dai_link->trigger_stop = trigger_stop; 220 221 dai_link->init = simple_util_dai_init; 222 dai_link->ops = &simple_ops; 223 224 ret = simple_util_set_dailink_name(priv, dai_link, name); 225 end: 226 return simple_ret(priv, ret); 227 } 228 229 static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, 230 struct device_node *np, 231 struct device_node *codec, 232 struct link_info *li, 233 bool is_top) 234 { 235 struct device *dev = simple_priv_to_dev(priv); 236 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 237 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 238 struct device_node *top = dev->of_node; 239 struct device_node *node __free(device_node) = of_get_parent(np); 240 char *prefix = ""; 241 char dai_name[64]; 242 int ret; 243 244 dev_dbg(dev, "link_of DPCM (%pOF)\n", np); 245 246 /* For single DAI link & old style of DT node */ 247 if (is_top) 248 prefix = PREFIX; 249 250 if (li->cpu) { 251 struct snd_soc_dai_link_component *cpus = snd_soc_link_to_cpu(dai_link, 0); 252 struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, 0); 253 int is_single_links = 0; 254 255 /* Codec is dummy */ 256 257 /* FE settings */ 258 dai_link->dynamic = 1; 259 dai_link->dpcm_merged_format = 1; 260 261 ret = simple_parse_node(priv, np, li, prefix, &is_single_links); 262 if (ret < 0) 263 goto out_put_node; 264 265 snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name); 266 267 simple_util_canonicalize_cpu(cpus, is_single_links); 268 simple_util_canonicalize_platform(platforms, cpus); 269 } else { 270 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, 0); 271 struct snd_soc_codec_conf *cconf; 272 273 /* CPU is dummy */ 274 275 /* BE settings */ 276 dai_link->no_pcm = 1; 277 dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup; 278 279 cconf = simple_props_to_codec_conf(dai_props, 0); 280 281 ret = simple_parse_node(priv, np, li, prefix, NULL); 282 if (ret < 0) 283 goto out_put_node; 284 285 snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name); 286 287 /* check "prefix" from top node */ 288 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, 289 PREFIX "prefix"); 290 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node, 291 "prefix"); 292 snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node, 293 "prefix"); 294 } 295 296 simple_parse_convert(dev, np, &dai_props->adata); 297 298 ret = simple_link_init(priv, np, codec, li, prefix, dai_name); 299 300 out_put_node: 301 li->link++; 302 303 return simple_ret(priv, ret); 304 } 305 306 static int simple_dai_link_of(struct simple_util_priv *priv, 307 struct device_node *np, 308 struct device_node *codec, 309 struct link_info *li, 310 bool is_top) 311 { 312 struct device *dev = simple_priv_to_dev(priv); 313 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 314 struct snd_soc_dai_link_component *cpus = snd_soc_link_to_cpu(dai_link, 0); 315 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, 0); 316 struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, 0); 317 struct device_node *cpu = NULL; 318 char dai_name[64]; 319 char prop[128]; 320 char *prefix = ""; 321 int ret, single_cpu = 0; 322 323 cpu = np; 324 struct device_node *node __free(device_node) = of_get_parent(np); 325 326 dev_dbg(dev, "link_of (%pOF)\n", node); 327 328 /* For single DAI link & old style of DT node */ 329 if (is_top) 330 prefix = PREFIX; 331 332 snprintf(prop, sizeof(prop), "%splat", prefix); 333 struct device_node *plat __free(device_node) = of_get_child_by_name(node, prop); 334 335 ret = simple_parse_node(priv, cpu, li, prefix, &single_cpu); 336 if (ret < 0) 337 goto dai_link_of_err; 338 339 ret = simple_parse_node(priv, codec, li, prefix, NULL); 340 if (ret < 0) 341 goto dai_link_of_err; 342 343 ret = simple_parse_platform(priv, plat, platforms); 344 if (ret < 0) 345 goto dai_link_of_err; 346 347 snprintf(dai_name, sizeof(dai_name), 348 "%s-%s", cpus->dai_name, codecs->dai_name); 349 350 simple_util_canonicalize_cpu(cpus, single_cpu); 351 simple_util_canonicalize_platform(platforms, cpus); 352 353 ret = simple_link_init(priv, cpu, codec, li, prefix, dai_name); 354 355 dai_link_of_err: 356 li->link++; 357 358 return simple_ret(priv, ret); 359 } 360 361 static int __simple_for_each_link(struct simple_util_priv *priv, 362 struct link_info *li, 363 int (*func_noml)(struct simple_util_priv *priv, 364 struct device_node *np, 365 struct device_node *codec, 366 struct link_info *li, bool is_top), 367 int (*func_dpcm)(struct simple_util_priv *priv, 368 struct device_node *np, 369 struct device_node *codec, 370 struct link_info *li, bool is_top)) 371 { 372 struct device *dev = simple_priv_to_dev(priv); 373 struct device_node *top = dev->of_node; 374 struct device_node *node; 375 uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev); 376 bool is_top = 0; 377 int ret = 0; 378 379 /* Check if it has dai-link */ 380 node = of_get_child_by_name(top, PREFIX "dai-link"); 381 if (!node) { 382 node = of_node_get(top); 383 is_top = 1; 384 } 385 386 struct device_node *add_devs __free(device_node) = of_get_child_by_name(top, PREFIX "additional-devs"); 387 388 /* loop for all dai-link */ 389 do { 390 struct simple_util_data adata; 391 int num = of_get_child_count(node); 392 393 /* Skip additional-devs node */ 394 if (node == add_devs) { 395 node = of_get_next_child(top, node); 396 continue; 397 } 398 399 /* get codec */ 400 struct device_node *codec __free(device_node) = 401 of_get_child_by_name(node, is_top ? PREFIX "codec" : "codec"); 402 if (!codec) { 403 ret = -ENODEV; 404 goto error; 405 } 406 /* get platform */ 407 struct device_node *plat __free(device_node) = 408 of_get_child_by_name(node, is_top ? PREFIX "plat" : "plat"); 409 410 /* get convert-xxx property */ 411 memset(&adata, 0, sizeof(adata)); 412 for_each_child_of_node_scoped(node, np) { 413 if (np == add_devs) 414 continue; 415 simple_parse_convert(dev, np, &adata); 416 } 417 418 /* loop for all CPU/Codec node */ 419 for_each_child_of_node_scoped(node, np) { 420 if (plat == np || add_devs == np) 421 continue; 422 /* 423 * It is DPCM 424 * if it has many CPUs, 425 * or has convert-xxx property 426 */ 427 if (dpcm_selectable && 428 (num > 2 || simple_util_is_convert_required(&adata))) { 429 /* 430 * np 431 * |1(CPU)|0(Codec) li->cpu 432 * CPU |Pass |return 433 * Codec |return|Pass 434 */ 435 if (li->cpu != (np == codec)) 436 ret = func_dpcm(priv, np, codec, li, is_top); 437 /* else normal sound */ 438 } else { 439 /* 440 * np 441 * |1(CPU)|0(Codec) li->cpu 442 * CPU |Pass |return 443 * Codec |return|return 444 */ 445 if (li->cpu && (np != codec)) 446 ret = func_noml(priv, np, codec, li, is_top); 447 } 448 449 if (ret < 0) 450 goto error; 451 } 452 453 node = of_get_next_child(top, node); 454 } while (!is_top && node); 455 456 error: 457 of_node_put(node); 458 459 return simple_ret(priv, ret); 460 } 461 462 static int simple_for_each_link(struct simple_util_priv *priv, 463 struct link_info *li, 464 int (*func_noml)(struct simple_util_priv *priv, 465 struct device_node *np, 466 struct device_node *codec, 467 struct link_info *li, bool is_top), 468 int (*func_dpcm)(struct simple_util_priv *priv, 469 struct device_node *np, 470 struct device_node *codec, 471 struct link_info *li, bool is_top)) 472 { 473 int ret; 474 /* 475 * Detect all CPU first, and Detect all Codec 2nd. 476 * 477 * In Normal sound case, all DAIs are detected 478 * as "CPU-Codec". 479 * 480 * In DPCM sound case, 481 * all CPUs are detected as "CPU-dummy", and 482 * all Codecs are detected as "dummy-Codec". 483 * To avoid random sub-device numbering, 484 * detect "dummy-Codec" in last; 485 */ 486 for (li->cpu = 1; li->cpu >= 0; li->cpu--) { 487 ret = __simple_for_each_link(priv, li, func_noml, func_dpcm); 488 if (ret < 0) 489 break; 490 } 491 492 return simple_ret(priv, ret); 493 } 494 495 static void simple_depopulate_aux(void *data) 496 { 497 struct simple_util_priv *priv = data; 498 499 of_platform_depopulate(simple_priv_to_dev(priv)); 500 } 501 502 static int simple_populate_aux(struct simple_util_priv *priv) 503 { 504 struct device *dev = simple_priv_to_dev(priv); 505 struct device_node *node __free(device_node) = of_get_child_by_name(dev->of_node, PREFIX "additional-devs"); 506 int ret; 507 508 if (!node) 509 return 0; 510 511 ret = of_platform_populate(node, NULL, NULL, dev); 512 if (ret) 513 goto end; 514 515 ret = devm_add_action_or_reset(dev, simple_depopulate_aux, priv); 516 end: 517 return simple_ret(priv, ret); 518 } 519 520 static int simple_count_noml(struct simple_util_priv *priv, 521 struct device_node *np, 522 struct device_node *codec, 523 struct link_info *li, bool is_top) 524 { 525 int ret = -EINVAL; 526 527 if (li->link >= SNDRV_MAX_LINKS) 528 goto end; 529 530 /* 531 * DON'T REMOVE platforms 532 * 533 * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform 534 * are different Component, but are sharing same component->dev. 535 * Simple Card had been supported it without special Platform selection. 536 * We need platforms here. 537 * 538 * In case of no Platform, it will be Platform == CPU, but Platform will be 539 * ignored by snd_soc_rtd_add_component(). 540 * 541 * see 542 * simple-card-utils.c :: simple_util_canonicalize_platform() 543 */ 544 li->num[li->link].cpus = 1; 545 li->num[li->link].platforms = 1; 546 547 li->num[li->link].codecs = 1; 548 549 li->link += 1; 550 ret = 0; 551 end: 552 return simple_ret(priv, ret); 553 } 554 555 static int simple_count_dpcm(struct simple_util_priv *priv, 556 struct device_node *np, 557 struct device_node *codec, 558 struct link_info *li, bool is_top) 559 { 560 int ret = -EINVAL; 561 562 if (li->link >= SNDRV_MAX_LINKS) 563 goto end; 564 565 if (li->cpu) { 566 /* 567 * DON'T REMOVE platforms 568 * see 569 * simple_count_noml() 570 */ 571 li->num[li->link].cpus = 1; 572 li->num[li->link].platforms = 1; 573 574 li->link++; /* CPU-dummy */ 575 } else { 576 li->num[li->link].codecs = 1; 577 578 li->link++; /* dummy-Codec */ 579 } 580 ret = 0; 581 end: 582 return simple_ret(priv, ret); 583 } 584 585 static int simple_get_dais_count(struct simple_util_priv *priv, 586 struct link_info *li) 587 { 588 struct device *dev = simple_priv_to_dev(priv); 589 struct device_node *top = dev->of_node; 590 591 /* 592 * link_num : number of links. 593 * CPU-Codec / CPU-dummy / dummy-Codec 594 * dais_num : number of DAIs 595 * ccnf_num : number of codec_conf 596 * same number for "dummy-Codec" 597 * 598 * ex1) 599 * CPU0 --- Codec0 link : 5 600 * CPU1 --- Codec1 dais : 7 601 * CPU2 -/ ccnf : 1 602 * CPU3 --- Codec2 603 * 604 * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec 605 * => 7 DAIs = 4xCPU + 3xCodec 606 * => 1 ccnf = 1xdummy-Codec 607 * 608 * ex2) 609 * CPU0 --- Codec0 link : 5 610 * CPU1 --- Codec1 dais : 6 611 * CPU2 -/ ccnf : 1 612 * CPU3 -/ 613 * 614 * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec 615 * => 6 DAIs = 4xCPU + 2xCodec 616 * => 1 ccnf = 1xdummy-Codec 617 * 618 * ex3) 619 * CPU0 --- Codec0 link : 6 620 * CPU1 -/ dais : 6 621 * CPU2 --- Codec1 ccnf : 2 622 * CPU3 -/ 623 * 624 * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec 625 * => 6 DAIs = 4xCPU + 2xCodec 626 * => 2 ccnf = 2xdummy-Codec 627 * 628 * ex4) 629 * CPU0 --- Codec0 (convert-rate) link : 3 630 * CPU1 --- Codec1 dais : 4 631 * ccnf : 1 632 * 633 * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec 634 * => 4 DAIs = 2xCPU + 2xCodec 635 * => 1 ccnf = 1xdummy-Codec 636 */ 637 if (!top) { 638 li->num[0].cpus = 1; 639 li->num[0].codecs = 1; 640 li->num[0].platforms = 1; 641 642 li->link = 1; 643 return 0; 644 } 645 646 return simple_for_each_link(priv, li, 647 simple_count_noml, 648 simple_count_dpcm); 649 } 650 651 static int simple_soc_probe(struct snd_soc_card *card) 652 { 653 struct simple_util_priv *priv = snd_soc_card_get_drvdata(card); 654 int ret; 655 656 ret = simple_util_init_hp(card, &priv->hp_jack, PREFIX); 657 if (ret < 0) 658 goto end; 659 660 ret = simple_util_init_mic(card, &priv->mic_jack, PREFIX); 661 if (ret < 0) 662 goto end; 663 664 ret = simple_util_init_aux_jacks(card, PREFIX); 665 end: 666 return simple_ret(priv, ret); 667 } 668 669 static int simple_parse_of(struct simple_util_priv *priv) 670 { 671 struct snd_soc_card *card = simple_priv_to_card(priv); 672 struct device *dev = card->dev; 673 int ret = -EINVAL; 674 675 if (!dev) 676 return simple_ret(priv, ret); 677 678 ret = -ENOMEM; 679 struct link_info *li __free(kfree) = kzalloc_obj(*li); 680 if (!li) 681 goto end; 682 683 ret = simple_get_dais_count(priv, li); 684 if (ret < 0) 685 goto end; 686 687 ret = -EINVAL; 688 if (!li->link) 689 goto end; 690 691 ret = simple_util_init_priv(priv, li); 692 if (ret < 0) 693 goto end; 694 695 ret = simple_util_parse_widgets(priv, PREFIX); 696 if (ret < 0) 697 goto end; 698 699 ret = simple_util_parse_routing(priv, PREFIX); 700 if (ret < 0) 701 goto end; 702 703 ret = simple_util_parse_pin_switches(priv, PREFIX); 704 if (ret < 0) 705 goto end; 706 707 ret = simple_util_parse_aux_devs(priv, PREFIX); 708 if (ret < 0) 709 goto err; 710 711 /* Single/Muti DAI link(s) & New style of DT node */ 712 memset(li, 0, sizeof(*li)); 713 ret = simple_for_each_link(priv, li, 714 simple_dai_link_of, 715 simple_dai_link_of_dpcm); 716 if (ret < 0) 717 goto err; 718 719 /* Card name should be set after simple_for_each_link() */ 720 ret = simple_util_parse_card_name(priv, PREFIX); 721 if (ret < 0) 722 goto err; 723 724 ret = simple_populate_aux(priv); 725 if (ret < 0) 726 goto err; 727 728 snd_soc_card_set_drvdata(card, priv); 729 730 simple_util_debug_info(priv); 731 732 ret = devm_snd_soc_register_card(dev, card); 733 err: 734 if (ret < 0) { 735 simple_util_clean_reference(priv); 736 return dev_err_probe(dev, ret, "parse error\n"); 737 } 738 end: 739 return simple_ret(priv, ret); 740 } 741 742 static int simple_probe(struct platform_device *pdev) 743 { 744 struct simple_util_priv *priv; 745 struct device *dev = &pdev->dev; 746 struct snd_soc_card *card; 747 748 /* Allocate the private data and the DAI link array */ 749 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 750 if (!priv) 751 return -ENOMEM; 752 753 card = simple_priv_to_card(priv); 754 card->owner = THIS_MODULE; 755 card->dev = dev; 756 card->probe = simple_soc_probe; 757 card->driver_name = "simple-card"; 758 759 return simple_parse_of(priv); 760 } 761 762 static const struct of_device_id simple_of_match[] = { 763 { .compatible = "simple-audio-card", }, 764 { .compatible = "simple-scu-audio-card", 765 .data = (void *)DPCM_SELECTABLE }, 766 {}, 767 }; 768 MODULE_DEVICE_TABLE(of, simple_of_match); 769 770 static struct platform_driver simple_card = { 771 .driver = { 772 .name = "asoc-simple-card", 773 .pm = &snd_soc_pm_ops, 774 .of_match_table = simple_of_match, 775 }, 776 .probe = simple_probe, 777 .remove = simple_util_remove, 778 }; 779 780 module_platform_driver(simple_card); 781 782 MODULE_ALIAS("platform:asoc-simple-card"); 783 MODULE_LICENSE("GPL v2"); 784 MODULE_DESCRIPTION("ASoC Simple Sound Card"); 785 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 786