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