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(np); 420 goto error; 421 } 422 } 423 424 of_node_put(codec); 425 of_node_put(plat); 426 node = of_get_next_child(top, node); 427 } while (!is_top && node); 428 429 error: 430 of_node_put(node); 431 return ret; 432 } 433 434 static int simple_for_each_link(struct asoc_simple_priv *priv, 435 struct link_info *li, 436 int (*func_noml)(struct asoc_simple_priv *priv, 437 struct device_node *np, 438 struct device_node *codec, 439 struct link_info *li, bool is_top), 440 int (*func_dpcm)(struct asoc_simple_priv *priv, 441 struct device_node *np, 442 struct device_node *codec, 443 struct link_info *li, bool is_top)) 444 { 445 int ret; 446 /* 447 * Detect all CPU first, and Detect all Codec 2nd. 448 * 449 * In Normal sound case, all DAIs are detected 450 * as "CPU-Codec". 451 * 452 * In DPCM sound case, 453 * all CPUs are detected as "CPU-dummy", and 454 * all Codecs are detected as "dummy-Codec". 455 * To avoid random sub-device numbering, 456 * detect "dummy-Codec" in last; 457 */ 458 for (li->cpu = 1; li->cpu >= 0; li->cpu--) { 459 ret = __simple_for_each_link(priv, li, func_noml, func_dpcm); 460 if (ret < 0) 461 break; 462 } 463 464 return ret; 465 } 466 467 static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li) 468 { 469 struct snd_soc_card *card = simple_priv_to_card(priv); 470 int ret; 471 472 ret = asoc_simple_parse_widgets(card, PREFIX); 473 if (ret < 0) 474 return ret; 475 476 ret = asoc_simple_parse_routing(card, PREFIX); 477 if (ret < 0) 478 return ret; 479 480 ret = asoc_simple_parse_pin_switches(card, PREFIX); 481 if (ret < 0) 482 return ret; 483 484 /* Single/Muti DAI link(s) & New style of DT node */ 485 memset(li, 0, sizeof(*li)); 486 ret = simple_for_each_link(priv, li, 487 simple_dai_link_of, 488 simple_dai_link_of_dpcm); 489 if (ret < 0) 490 return ret; 491 492 ret = asoc_simple_parse_card_name(card, PREFIX); 493 if (ret < 0) 494 return ret; 495 496 ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs"); 497 498 return ret; 499 } 500 501 static int simple_count_noml(struct asoc_simple_priv *priv, 502 struct device_node *np, 503 struct device_node *codec, 504 struct link_info *li, bool is_top) 505 { 506 if (li->link >= SNDRV_MAX_LINKS) { 507 struct device *dev = simple_priv_to_dev(priv); 508 509 dev_err(dev, "too many links\n"); 510 return -EINVAL; 511 } 512 513 /* 514 * DON'T REMOVE platforms 515 * 516 * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform 517 * are different Component, but are sharing same component->dev. 518 * Simple Card had been supported it without special Platform selection. 519 * We need platforms here. 520 * 521 * In case of no Platform, it will be Platform == CPU, but Platform will be 522 * ignored by snd_soc_rtd_add_component(). 523 * 524 * see 525 * simple-card-utils.c :: asoc_simple_canonicalize_platform() 526 */ 527 li->num[li->link].cpus = 1; 528 li->num[li->link].platforms = 1; 529 530 li->num[li->link].codecs = 1; 531 532 li->link += 1; 533 534 return 0; 535 } 536 537 static int simple_count_dpcm(struct asoc_simple_priv *priv, 538 struct device_node *np, 539 struct device_node *codec, 540 struct link_info *li, bool is_top) 541 { 542 if (li->link >= SNDRV_MAX_LINKS) { 543 struct device *dev = simple_priv_to_dev(priv); 544 545 dev_err(dev, "too many links\n"); 546 return -EINVAL; 547 } 548 549 if (li->cpu) { 550 /* 551 * DON'T REMOVE platforms 552 * see 553 * simple_count_noml() 554 */ 555 li->num[li->link].cpus = 1; 556 li->num[li->link].platforms = 1; 557 558 li->link++; /* CPU-dummy */ 559 } else { 560 li->num[li->link].codecs = 1; 561 562 li->link++; /* dummy-Codec */ 563 } 564 565 return 0; 566 } 567 568 static int simple_get_dais_count(struct asoc_simple_priv *priv, 569 struct link_info *li) 570 { 571 struct device *dev = simple_priv_to_dev(priv); 572 struct device_node *top = dev->of_node; 573 574 /* 575 * link_num : number of links. 576 * CPU-Codec / CPU-dummy / dummy-Codec 577 * dais_num : number of DAIs 578 * ccnf_num : number of codec_conf 579 * same number for "dummy-Codec" 580 * 581 * ex1) 582 * CPU0 --- Codec0 link : 5 583 * CPU1 --- Codec1 dais : 7 584 * CPU2 -/ ccnf : 1 585 * CPU3 --- Codec2 586 * 587 * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec 588 * => 7 DAIs = 4xCPU + 3xCodec 589 * => 1 ccnf = 1xdummy-Codec 590 * 591 * ex2) 592 * CPU0 --- Codec0 link : 5 593 * CPU1 --- Codec1 dais : 6 594 * CPU2 -/ ccnf : 1 595 * CPU3 -/ 596 * 597 * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec 598 * => 6 DAIs = 4xCPU + 2xCodec 599 * => 1 ccnf = 1xdummy-Codec 600 * 601 * ex3) 602 * CPU0 --- Codec0 link : 6 603 * CPU1 -/ dais : 6 604 * CPU2 --- Codec1 ccnf : 2 605 * CPU3 -/ 606 * 607 * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec 608 * => 6 DAIs = 4xCPU + 2xCodec 609 * => 2 ccnf = 2xdummy-Codec 610 * 611 * ex4) 612 * CPU0 --- Codec0 (convert-rate) link : 3 613 * CPU1 --- Codec1 dais : 4 614 * ccnf : 1 615 * 616 * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec 617 * => 4 DAIs = 2xCPU + 2xCodec 618 * => 1 ccnf = 1xdummy-Codec 619 */ 620 if (!top) { 621 li->num[0].cpus = 1; 622 li->num[0].codecs = 1; 623 li->num[0].platforms = 1; 624 625 li->link = 1; 626 return 0; 627 } 628 629 return simple_for_each_link(priv, li, 630 simple_count_noml, 631 simple_count_dpcm); 632 } 633 634 static int simple_soc_probe(struct snd_soc_card *card) 635 { 636 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); 637 int ret; 638 639 ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX); 640 if (ret < 0) 641 return ret; 642 643 ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX); 644 if (ret < 0) 645 return ret; 646 647 ret = asoc_simple_init_aux_jacks(priv, PREFIX); 648 if (ret < 0) 649 return ret; 650 651 return 0; 652 } 653 654 static int asoc_simple_probe(struct platform_device *pdev) 655 { 656 struct asoc_simple_priv *priv; 657 struct device *dev = &pdev->dev; 658 struct device_node *np = dev->of_node; 659 struct snd_soc_card *card; 660 struct link_info *li; 661 int ret; 662 663 /* Allocate the private data and the DAI link array */ 664 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 665 if (!priv) 666 return -ENOMEM; 667 668 card = simple_priv_to_card(priv); 669 card->owner = THIS_MODULE; 670 card->dev = dev; 671 card->probe = simple_soc_probe; 672 card->driver_name = "simple-card"; 673 674 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); 675 if (!li) 676 return -ENOMEM; 677 678 ret = simple_get_dais_count(priv, li); 679 if (ret < 0) 680 return ret; 681 682 if (!li->link) 683 return -EINVAL; 684 685 ret = asoc_simple_init_priv(priv, li); 686 if (ret < 0) 687 return ret; 688 689 if (np && of_device_is_available(np)) { 690 691 ret = simple_parse_of(priv, li); 692 if (ret < 0) { 693 dev_err_probe(dev, ret, "parse error\n"); 694 goto err; 695 } 696 697 } else { 698 struct asoc_simple_card_info *cinfo; 699 struct snd_soc_dai_link_component *cpus; 700 struct snd_soc_dai_link_component *codecs; 701 struct snd_soc_dai_link_component *platform; 702 struct snd_soc_dai_link *dai_link = priv->dai_link; 703 struct simple_dai_props *dai_props = priv->dai_props; 704 705 cinfo = dev->platform_data; 706 if (!cinfo) { 707 dev_err(dev, "no info for asoc-simple-card\n"); 708 return -EINVAL; 709 } 710 711 if (!cinfo->name || 712 !cinfo->codec_dai.name || 713 !cinfo->codec || 714 !cinfo->platform || 715 !cinfo->cpu_dai.name) { 716 dev_err(dev, "insufficient asoc_simple_card_info settings\n"); 717 return -EINVAL; 718 } 719 720 cpus = dai_link->cpus; 721 cpus->dai_name = cinfo->cpu_dai.name; 722 723 codecs = dai_link->codecs; 724 codecs->name = cinfo->codec; 725 codecs->dai_name = cinfo->codec_dai.name; 726 727 platform = dai_link->platforms; 728 platform->name = cinfo->platform; 729 730 card->name = (cinfo->card) ? cinfo->card : cinfo->name; 731 dai_link->name = cinfo->name; 732 dai_link->stream_name = cinfo->name; 733 dai_link->dai_fmt = cinfo->daifmt; 734 dai_link->init = asoc_simple_dai_init; 735 memcpy(dai_props->cpu_dai, &cinfo->cpu_dai, 736 sizeof(*dai_props->cpu_dai)); 737 memcpy(dai_props->codec_dai, &cinfo->codec_dai, 738 sizeof(*dai_props->codec_dai)); 739 } 740 741 snd_soc_card_set_drvdata(card, priv); 742 743 asoc_simple_debug_info(priv); 744 745 ret = devm_snd_soc_register_card(dev, card); 746 if (ret < 0) 747 goto err; 748 749 devm_kfree(dev, li); 750 return 0; 751 err: 752 asoc_simple_clean_reference(card); 753 754 return ret; 755 } 756 757 static const struct of_device_id simple_of_match[] = { 758 { .compatible = "simple-audio-card", }, 759 { .compatible = "simple-scu-audio-card", 760 .data = (void *)DPCM_SELECTABLE }, 761 {}, 762 }; 763 MODULE_DEVICE_TABLE(of, simple_of_match); 764 765 static struct platform_driver asoc_simple_card = { 766 .driver = { 767 .name = "asoc-simple-card", 768 .pm = &snd_soc_pm_ops, 769 .of_match_table = simple_of_match, 770 }, 771 .probe = asoc_simple_probe, 772 .remove = asoc_simple_remove, 773 }; 774 775 module_platform_driver(asoc_simple_card); 776 777 MODULE_ALIAS("platform:asoc-simple-card"); 778 MODULE_LICENSE("GPL v2"); 779 MODULE_DESCRIPTION("ASoC Simple Sound Card"); 780 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 781