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