1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // ASoC Audio Graph Card2 support 4 // 5 // Copyright (C) 2020 Renesas Electronics Corp. 6 // Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 // 8 // based on ${LINUX}/sound/soc/generic/audio-graph-card.c 9 #include <linux/clk.h> 10 #include <linux/device.h> 11 #include <linux/gpio.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/of_device.h> 16 #include <linux/of_gpio.h> 17 #include <linux/of_graph.h> 18 #include <linux/platform_device.h> 19 #include <linux/string.h> 20 #include <sound/graph_card.h> 21 22 /************************************ 23 daifmt 24 ************************************ 25 ports { 26 format = "left_j"; 27 port@0 { 28 bitclock-master; 29 sample0: endpoint@0 { 30 frame-master; 31 }; 32 sample1: endpoint@1 { 33 format = "i2s"; 34 }; 35 }; 36 ... 37 }; 38 39 You can set daifmt at ports/port/endpoint. 40 It uses *latest* format, and *share* master settings. 41 In above case, 42 sample0: left_j, bitclock-master, frame-master 43 sample1: i2s, bitclock-master 44 45 If there was no settings, *Codec* will be 46 bitclock/frame provider as default. 47 see 48 graph_parse_daifmt(). 49 50 "format" property is no longer needed on DT if both CPU/Codec drivers are 51 supporting snd_soc_dai_ops :: .auto_selectable_formats. 52 see 53 snd_soc_runtime_get_dai_fmt() 54 55 sample driver 56 linux/sound/soc/sh/rcar/core.c 57 linux/sound/soc/codecs/ak4613.c 58 linux/sound/soc/codecs/pcm3168a.c 59 linux/sound/soc/soc-utils.c 60 linux/sound/soc/generic/test-component.c 61 62 ************************************ 63 Normal Audio-Graph 64 ************************************ 65 66 CPU <---> Codec 67 68 sound { 69 compatible = "audio-graph-card2"; 70 links = <&cpu>; 71 }; 72 73 CPU { 74 cpu: port { 75 bitclock-master; 76 frame-master; 77 cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; }; 78 }; 79 80 Codec { 81 port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; }; 82 }; 83 84 ************************************ 85 Multi-CPU/Codec 86 ************************************ 87 88 It has connection part (= X) and list part (= y). 89 links indicates connection part of CPU side (= A). 90 91 +-+ (A) +-+ 92 CPU1 --(y) | | <-(X)--(X)-> | | (y)-- Codec1 93 CPU2 --(y) | | | | (y)-- Codec2 94 +-+ +-+ 95 96 sound { 97 compatible = "audio-graph-card2"; 98 99 (A) links = <&mcpu>; 100 101 multi { 102 ports@0 { 103 (X) (A) mcpu: port@0 { mcpu0_ep: endpoint { remote-endpoint = <&mcodec0_ep>; }; }; 104 (y) port@1 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; }; 105 (y) port@2 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; }; 106 }; 107 ports@1 { 108 (X) port@0 { mcodec0_ep: endpoint { remote-endpoint = <&mcpu0_ep>; }; }; 109 (y) port@1 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; 110 (y) port@2 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; }; 111 }; 112 }; 113 }; 114 115 CPU { 116 ports { 117 bitclock-master; 118 frame-master; 119 port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; }; 120 port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; }; 121 }; 122 }; 123 124 Codec { 125 ports { 126 port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; }; 127 port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; }; 128 }; 129 }; 130 131 ************************************ 132 DPCM 133 ************************************ 134 135 DSP 136 ************ 137 PCM0 <--> * fe0 be0 * <--> DAI0: Codec Headset 138 PCM1 <--> * fe1 be1 * <--> DAI1: Codec Speakers 139 PCM2 <--> * fe2 be2 * <--> DAI2: MODEM 140 PCM3 <--> * fe3 be3 * <--> DAI3: BT 141 * be4 * <--> DAI4: DMIC 142 * be5 * <--> DAI5: FM 143 ************ 144 145 sound { 146 compatible = "audio-graph-card2"; 147 148 // indicate routing 149 routing = "xxx Playback", "xxx Playback", 150 "xxx Playback", "xxx Playback", 151 "xxx Playback", "xxx Playback"; 152 153 // indicate all Front-End, Back-End 154 links = <&fe0, &fe1, ..., 155 &be0, &be1, ...>; 156 157 dpcm { 158 // Front-End 159 ports@0 { 160 fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; }; 161 fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; }; 162 ... 163 }; 164 // Back-End 165 ports@1 { 166 be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; }; 167 be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; }; 168 ... 169 }; 170 }; 171 }; 172 173 CPU { 174 ports { 175 bitclock-master; 176 frame-master; 177 port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; }; 178 port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; }; 179 ... 180 }; 181 }; 182 183 Codec { 184 ports { 185 port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; }; 186 port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; }; 187 ... 188 }; 189 }; 190 191 ************************************ 192 Codec to Codec 193 ************************************ 194 195 +--+ 196 | |<-- Codec0 <- IN 197 | |--> Codec1 -> OUT 198 +--+ 199 200 sound { 201 compatible = "audio-graph-card2"; 202 203 routing = "OUT" ,"DAI1 Playback", 204 "DAI0 Capture", "IN"; 205 206 links = <&c2c>; 207 208 codec2codec { 209 ports { 210 rate = <48000>; 211 c2c: port@0 { c2cf_ep: endpoint { remote-endpoint = <&codec0_ep>; }; }; 212 port@1 { c2cb_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; 213 }; 214 }; 215 216 Codec { 217 ports { 218 port@0 { 219 bitclock-master; 220 frame-master; 221 codec0_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; }; 222 port@1 { codec1_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; }; 223 }; 224 }; 225 226 */ 227 228 enum graph_type { 229 GRAPH_NORMAL, 230 GRAPH_DPCM, 231 GRAPH_C2C, 232 233 GRAPH_MULTI, /* don't use ! Use this only in __graph_get_type() */ 234 }; 235 236 #define GRAPH_NODENAME_MULTI "multi" 237 #define GRAPH_NODENAME_DPCM "dpcm" 238 #define GRAPH_NODENAME_C2C "codec2codec" 239 240 #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint") 241 242 static enum graph_type __graph_get_type(struct device_node *lnk) 243 { 244 struct device_node *np, *parent_np; 245 enum graph_type ret; 246 247 /* 248 * target { 249 * ports { 250 * => lnk: port@0 { ... }; 251 * port@1 { ... }; 252 * }; 253 * }; 254 */ 255 np = of_get_parent(lnk); 256 if (of_node_name_eq(np, "ports")) { 257 parent_np = of_get_parent(np); 258 of_node_put(np); 259 np = parent_np; 260 } 261 262 if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) { 263 ret = GRAPH_MULTI; 264 goto out_put; 265 } 266 267 if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) { 268 ret = GRAPH_DPCM; 269 goto out_put; 270 } 271 272 if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) { 273 ret = GRAPH_C2C; 274 goto out_put; 275 } 276 277 ret = GRAPH_NORMAL; 278 279 out_put: 280 of_node_put(np); 281 return ret; 282 283 } 284 285 static enum graph_type graph_get_type(struct asoc_simple_priv *priv, 286 struct device_node *lnk) 287 { 288 enum graph_type type = __graph_get_type(lnk); 289 290 /* GRAPH_MULTI here means GRAPH_NORMAL */ 291 if (type == GRAPH_MULTI) 292 type = GRAPH_NORMAL; 293 294 #ifdef DEBUG 295 { 296 struct device *dev = simple_priv_to_dev(priv); 297 const char *str = "Normal"; 298 299 switch (type) { 300 case GRAPH_DPCM: 301 if (asoc_graph_is_ports0(lnk)) 302 str = "DPCM Front-End"; 303 else 304 str = "DPCM Back-End"; 305 break; 306 case GRAPH_C2C: 307 str = "Codec2Codec"; 308 break; 309 default: 310 break; 311 } 312 313 dev_dbg(dev, "%pOF (%s)", lnk, str); 314 } 315 #endif 316 return type; 317 } 318 319 static int graph_lnk_is_multi(struct device_node *lnk) 320 { 321 return __graph_get_type(lnk) == GRAPH_MULTI; 322 } 323 324 static struct device_node *graph_get_next_multi_ep(struct device_node **port) 325 { 326 struct device_node *ports = of_get_parent(*port); 327 struct device_node *ep = NULL; 328 struct device_node *rep = NULL; 329 330 /* 331 * multi { 332 * ports { 333 * => lnk: port@0 { ... }; 334 * port@1 { ep { ... = rep0 } }; 335 * port@2 { ep { ... = rep1 } }; 336 * ... 337 * }; 338 * }; 339 * 340 * xxx { 341 * port@0 { rep0 }; 342 * port@1 { rep1 }; 343 * }; 344 */ 345 do { 346 *port = of_get_next_child(ports, *port); 347 if (!*port) 348 break; 349 } while (!of_node_name_eq(*port, "port")); 350 351 if (*port) { 352 ep = port_to_endpoint(*port); 353 rep = of_graph_get_remote_endpoint(ep); 354 } 355 356 of_node_put(ep); 357 of_node_put(ports); 358 359 return rep; 360 } 361 362 static const struct snd_soc_ops graph_ops = { 363 .startup = asoc_simple_startup, 364 .shutdown = asoc_simple_shutdown, 365 .hw_params = asoc_simple_hw_params, 366 }; 367 368 static void graph_parse_convert(struct device_node *ep, 369 struct simple_dai_props *props) 370 { 371 struct device_node *port = of_get_parent(ep); 372 struct device_node *ports = of_get_parent(port); 373 struct asoc_simple_data *adata = &props->adata; 374 375 if (of_node_name_eq(ports, "ports")) 376 asoc_simple_parse_convert(ports, NULL, adata); 377 asoc_simple_parse_convert(port, NULL, adata); 378 asoc_simple_parse_convert(ep, NULL, adata); 379 380 of_node_put(port); 381 of_node_put(ports); 382 } 383 384 static void graph_parse_mclk_fs(struct device_node *ep, 385 struct simple_dai_props *props) 386 { 387 struct device_node *port = of_get_parent(ep); 388 struct device_node *ports = of_get_parent(port); 389 390 if (of_node_name_eq(ports, "ports")) 391 of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); 392 of_property_read_u32(port, "mclk-fs", &props->mclk_fs); 393 of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); 394 395 of_node_put(port); 396 of_node_put(ports); 397 } 398 399 static int __graph_parse_node(struct asoc_simple_priv *priv, 400 enum graph_type gtype, 401 struct device_node *ep, 402 struct link_info *li, 403 int is_cpu, int idx) 404 { 405 struct device *dev = simple_priv_to_dev(priv); 406 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 407 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 408 struct snd_soc_dai_link_component *dlc; 409 struct asoc_simple_dai *dai; 410 int ret, is_single_links = 0; 411 412 if (is_cpu) { 413 dlc = asoc_link_to_cpu(dai_link, idx); 414 dai = simple_props_to_dai_cpu(dai_props, idx); 415 } else { 416 dlc = asoc_link_to_codec(dai_link, idx); 417 dai = simple_props_to_dai_codec(dai_props, idx); 418 } 419 420 graph_parse_mclk_fs(ep, dai_props); 421 422 ret = asoc_graph_parse_dai(dev, ep, dlc, &is_single_links); 423 if (ret < 0) 424 return ret; 425 426 ret = asoc_simple_parse_tdm(ep, dai); 427 if (ret < 0) 428 return ret; 429 430 ret = asoc_simple_parse_tdm_width_map(dev, ep, dai); 431 if (ret < 0) 432 return ret; 433 434 ret = asoc_simple_parse_clk(dev, ep, dai, dlc); 435 if (ret < 0) 436 return ret; 437 438 /* 439 * set DAI Name 440 */ 441 if (!dai_link->name) { 442 struct snd_soc_dai_link_component *cpus = dlc; 443 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx); 444 char *cpu_multi = ""; 445 char *codec_multi = ""; 446 447 if (dai_link->num_cpus > 1) 448 cpu_multi = "_multi"; 449 if (dai_link->num_codecs > 1) 450 codec_multi = "_multi"; 451 452 switch (gtype) { 453 case GRAPH_NORMAL: 454 /* run is_cpu only. see audio_graph2_link_normal() */ 455 if (is_cpu) 456 asoc_simple_set_dailink_name(dev, dai_link, "%s%s-%s%s", 457 cpus->dai_name, cpu_multi, 458 codecs->dai_name, codec_multi); 459 break; 460 case GRAPH_DPCM: 461 if (is_cpu) 462 asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s", 463 cpus->of_node, cpus->dai_name, cpu_multi); 464 else 465 asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s", 466 codecs->of_node, codecs->dai_name, codec_multi); 467 break; 468 case GRAPH_C2C: 469 /* run is_cpu only. see audio_graph2_link_c2c() */ 470 if (is_cpu) 471 asoc_simple_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s", 472 cpus->dai_name, cpu_multi, 473 codecs->dai_name, codec_multi); 474 break; 475 default: 476 break; 477 } 478 } 479 480 /* 481 * Check "prefix" from top node 482 * if DPCM-BE case 483 */ 484 if (!is_cpu && gtype == GRAPH_DPCM) { 485 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx); 486 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx); 487 struct device_node *rport = of_get_parent(ep); 488 struct device_node *rports = of_get_parent(rport); 489 490 if (of_node_name_eq(rports, "ports")) 491 snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); 492 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix"); 493 494 of_node_put(rport); 495 of_node_put(rports); 496 } 497 498 if (is_cpu) { 499 struct snd_soc_dai_link_component *cpus = dlc; 500 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx); 501 502 asoc_simple_canonicalize_cpu(cpus, is_single_links); 503 asoc_simple_canonicalize_platform(platforms, cpus); 504 } 505 506 return 0; 507 } 508 509 static int graph_parse_node(struct asoc_simple_priv *priv, 510 enum graph_type gtype, 511 struct device_node *port, 512 struct link_info *li, int is_cpu) 513 { 514 struct device_node *ep; 515 int ret = 0; 516 517 if (graph_lnk_is_multi(port)) { 518 int idx; 519 520 of_node_get(port); 521 522 for (idx = 0;; idx++) { 523 ep = graph_get_next_multi_ep(&port); 524 if (!ep) 525 break; 526 527 ret = __graph_parse_node(priv, gtype, ep, 528 li, is_cpu, idx); 529 of_node_put(ep); 530 if (ret < 0) 531 break; 532 } 533 } else { 534 /* Single CPU / Codec */ 535 ep = port_to_endpoint(port); 536 ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0); 537 of_node_put(ep); 538 } 539 540 return ret; 541 } 542 543 static void graph_parse_daifmt(struct device_node *node, 544 unsigned int *daifmt, unsigned int *bit_frame) 545 { 546 unsigned int fmt; 547 548 /* 549 * see also above "daifmt" explanation 550 * and samples. 551 */ 552 553 /* 554 * ports { 555 * (A) 556 * port { 557 * (B) 558 * endpoint { 559 * (C) 560 * }; 561 * }; 562 * }; 563 * }; 564 */ 565 566 /* 567 * clock_provider: 568 * 569 * It can be judged it is provider 570 * if (A) or (B) or (C) has bitclock-master / frame-master flag. 571 * 572 * use "or" 573 */ 574 *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL); 575 576 #define update_daifmt(name) \ 577 if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \ 578 (fmt & SND_SOC_DAIFMT_##name##_MASK)) \ 579 *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK 580 581 /* 582 * format 583 * 584 * This function is called by (C) -> (B) -> (A) order. 585 * Set if applicable part was not yet set. 586 */ 587 fmt = snd_soc_daifmt_parse_format(node, NULL); 588 update_daifmt(FORMAT); 589 update_daifmt(CLOCK); 590 update_daifmt(INV); 591 } 592 593 static void graph_link_init(struct asoc_simple_priv *priv, 594 struct device_node *port, 595 struct link_info *li, 596 int is_cpu_node) 597 { 598 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 599 struct device_node *ep; 600 struct device_node *ports; 601 unsigned int daifmt = 0, daiclk = 0; 602 unsigned int bit_frame = 0; 603 604 if (graph_lnk_is_multi(port)) { 605 of_node_get(port); 606 ep = graph_get_next_multi_ep(&port); 607 port = of_get_parent(ep); 608 } else { 609 ep = port_to_endpoint(port); 610 } 611 612 ports = of_get_parent(port); 613 614 /* 615 * ports { 616 * (A) 617 * port { 618 * (B) 619 * endpoint { 620 * (C) 621 * }; 622 * }; 623 * }; 624 * }; 625 */ 626 graph_parse_daifmt(ep, &daifmt, &bit_frame); /* (C) */ 627 graph_parse_daifmt(port, &daifmt, &bit_frame); /* (B) */ 628 if (of_node_name_eq(ports, "ports")) 629 graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */ 630 631 /* 632 * convert bit_frame 633 * We need to flip clock_provider if it was CPU node, 634 * because it is Codec base. 635 */ 636 daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame); 637 if (is_cpu_node) 638 daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk); 639 640 dai_link->dai_fmt = daifmt | daiclk; 641 dai_link->init = asoc_simple_dai_init; 642 dai_link->ops = &graph_ops; 643 if (priv->ops) 644 dai_link->ops = priv->ops; 645 } 646 647 int audio_graph2_link_normal(struct asoc_simple_priv *priv, 648 struct device_node *lnk, 649 struct link_info *li) 650 { 651 struct device_node *cpu_port = lnk; 652 struct device_node *cpu_ep = port_to_endpoint(cpu_port); 653 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep); 654 int ret; 655 656 /* 657 * call Codec first. 658 * see 659 * __graph_parse_node() :: DAI Naming 660 */ 661 ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0); 662 if (ret < 0) 663 goto err; 664 665 /* 666 * call CPU, and set DAI Name 667 */ 668 ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1); 669 if (ret < 0) 670 goto err; 671 672 graph_link_init(priv, cpu_port, li, 1); 673 err: 674 of_node_put(codec_port); 675 of_node_put(cpu_ep); 676 677 return ret; 678 } 679 EXPORT_SYMBOL_GPL(audio_graph2_link_normal); 680 681 int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, 682 struct device_node *lnk, 683 struct link_info *li) 684 { 685 struct device_node *ep = port_to_endpoint(lnk); 686 struct device_node *rep = of_graph_get_remote_endpoint(ep); 687 struct device_node *rport = of_graph_get_remote_port(ep); 688 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 689 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 690 int is_cpu = asoc_graph_is_ports0(lnk); 691 int ret; 692 693 if (is_cpu) { 694 /* 695 * dpcm { 696 * // Front-End 697 * ports@0 { 698 * => lnk: port@0 { ep: { ... = rep }; }; 699 * ... 700 * }; 701 * // Back-End 702 * ports@0 { 703 * ... 704 * }; 705 * }; 706 * 707 * CPU { 708 * rports: ports { 709 * rport: port@0 { rep: { ... = ep } }; 710 * } 711 * } 712 */ 713 /* 714 * setup CPU here, Codec is already set as dummy. 715 * see 716 * asoc_simple_init_priv() 717 */ 718 dai_link->dynamic = 1; 719 dai_link->dpcm_merged_format = 1; 720 721 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1); 722 if (ret) 723 goto err; 724 } else { 725 /* 726 * dpcm { 727 * // Front-End 728 * ports@0 { 729 * ... 730 * }; 731 * // Back-End 732 * ports@0 { 733 * => lnk: port@0 { ep: { ... = rep; }; }; 734 * ... 735 * }; 736 * }; 737 * 738 * Codec { 739 * rports: ports { 740 * rport: port@0 { rep: { ... = ep; }; }; 741 * } 742 * } 743 */ 744 /* 745 * setup Codec here, CPU is already set as dummy. 746 * see 747 * asoc_simple_init_priv() 748 */ 749 750 /* BE settings */ 751 dai_link->no_pcm = 1; 752 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; 753 754 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0); 755 if (ret < 0) 756 goto err; 757 } 758 759 graph_parse_convert(ep, dai_props); /* at node of <dpcm> */ 760 graph_parse_convert(rep, dai_props); /* at node of <CPU/Codec> */ 761 762 snd_soc_dai_link_set_capabilities(dai_link); 763 764 graph_link_init(priv, rport, li, is_cpu); 765 err: 766 of_node_put(ep); 767 of_node_put(rep); 768 of_node_put(rport); 769 770 return ret; 771 } 772 EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm); 773 774 int audio_graph2_link_c2c(struct asoc_simple_priv *priv, 775 struct device_node *lnk, 776 struct link_info *li) 777 { 778 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 779 struct device_node *port0, *port1, *ports; 780 struct device_node *codec0_port, *codec1_port; 781 struct device_node *ep0, *ep1; 782 u32 val = 0; 783 int ret = -EINVAL; 784 785 /* 786 * codec2codec { 787 * ports { 788 * rate = <48000>; 789 * => lnk: port@0 { c2c0_ep: { ... = codec0_ep; }; }; 790 * port@1 { c2c1_ep: { ... = codec1_ep; }; }; 791 * }; 792 * }; 793 * 794 * Codec { 795 * ports { 796 * port@0 { codec0_ep: ... }; }; 797 * port@1 { codec1_ep: ... }; }; 798 * }; 799 * }; 800 */ 801 of_node_get(lnk); 802 port0 = lnk; 803 ports = of_get_parent(port0); 804 port1 = of_get_next_child(ports, lnk); 805 806 /* 807 * Card2 can use original Codec2Codec settings if DT has. 808 * It will use default settings if no settings on DT. 809 * see 810 * asoc_simple_init_for_codec2codec() 811 * 812 * Add more settings here if needed 813 */ 814 of_property_read_u32(ports, "rate", &val); 815 if (val) { 816 struct device *dev = simple_priv_to_dev(priv); 817 struct snd_soc_pcm_stream *c2c_conf; 818 819 c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL); 820 if (!c2c_conf) 821 goto err1; 822 823 c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */ 824 c2c_conf->rates = SNDRV_PCM_RATE_8000_384000; 825 c2c_conf->rate_min = 826 c2c_conf->rate_max = val; 827 c2c_conf->channels_min = 828 c2c_conf->channels_max = 2; /* update ME */ 829 830 dai_link->c2c_params = c2c_conf; 831 dai_link->num_c2c_params = 1; 832 } 833 834 ep0 = port_to_endpoint(port0); 835 ep1 = port_to_endpoint(port1); 836 837 codec0_port = of_graph_get_remote_port(ep0); 838 codec1_port = of_graph_get_remote_port(ep1); 839 840 /* 841 * call Codec first. 842 * see 843 * __graph_parse_node() :: DAI Naming 844 */ 845 ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0); 846 if (ret < 0) 847 goto err2; 848 849 /* 850 * call CPU, and set DAI Name 851 */ 852 ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1); 853 if (ret < 0) 854 goto err2; 855 856 graph_link_init(priv, codec0_port, li, 1); 857 err2: 858 of_node_put(ep0); 859 of_node_put(ep1); 860 of_node_put(codec0_port); 861 of_node_put(codec1_port); 862 err1: 863 of_node_put(ports); 864 of_node_put(port0); 865 of_node_put(port1); 866 867 return ret; 868 } 869 EXPORT_SYMBOL_GPL(audio_graph2_link_c2c); 870 871 static int graph_link(struct asoc_simple_priv *priv, 872 struct graph2_custom_hooks *hooks, 873 enum graph_type gtype, 874 struct device_node *lnk, 875 struct link_info *li) 876 { 877 struct device *dev = simple_priv_to_dev(priv); 878 GRAPH2_CUSTOM func = NULL; 879 int ret = -EINVAL; 880 881 switch (gtype) { 882 case GRAPH_NORMAL: 883 if (hooks && hooks->custom_normal) 884 func = hooks->custom_normal; 885 else 886 func = audio_graph2_link_normal; 887 break; 888 case GRAPH_DPCM: 889 if (hooks && hooks->custom_dpcm) 890 func = hooks->custom_dpcm; 891 else 892 func = audio_graph2_link_dpcm; 893 break; 894 case GRAPH_C2C: 895 if (hooks && hooks->custom_c2c) 896 func = hooks->custom_c2c; 897 else 898 func = audio_graph2_link_c2c; 899 break; 900 default: 901 break; 902 } 903 904 if (!func) { 905 dev_err(dev, "non supported gtype (%d)\n", gtype); 906 goto err; 907 } 908 909 ret = func(priv, lnk, li); 910 if (ret < 0) 911 goto err; 912 913 li->link++; 914 err: 915 return ret; 916 } 917 918 static int graph_counter(struct device_node *lnk) 919 { 920 /* 921 * Multi CPU / Codec 922 * 923 * multi { 924 * ports { 925 * => lnk: port@0 { ... }; 926 * port@1 { ... }; 927 * port@2 { ... }; 928 * ... 929 * }; 930 * }; 931 * 932 * ignore first lnk part 933 */ 934 if (graph_lnk_is_multi(lnk)) 935 return of_graph_get_endpoint_count(of_get_parent(lnk)) - 1; 936 /* 937 * Single CPU / Codec 938 */ 939 else 940 return 1; 941 } 942 943 static int graph_count_normal(struct asoc_simple_priv *priv, 944 struct device_node *lnk, 945 struct link_info *li) 946 { 947 struct device_node *cpu_port = lnk; 948 struct device_node *cpu_ep = port_to_endpoint(cpu_port); 949 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep); 950 951 /* 952 * CPU { 953 * => lnk: port { endpoint { .. }; }; 954 * }; 955 */ 956 /* 957 * DON'T REMOVE platforms 958 * see 959 * simple-card.c :: simple_count_noml() 960 */ 961 li->num[li->link].cpus = 962 li->num[li->link].platforms = graph_counter(cpu_port); 963 964 li->num[li->link].codecs = graph_counter(codec_port); 965 966 of_node_put(cpu_ep); 967 of_node_put(codec_port); 968 969 return 0; 970 } 971 972 static int graph_count_dpcm(struct asoc_simple_priv *priv, 973 struct device_node *lnk, 974 struct link_info *li) 975 { 976 struct device_node *ep = port_to_endpoint(lnk); 977 struct device_node *rport = of_graph_get_remote_port(ep); 978 979 /* 980 * dpcm { 981 * // Front-End 982 * ports@0 { 983 * => lnk: port@0 { endpoint { ... }; }; 984 * ... 985 * }; 986 * // Back-End 987 * ports@1 { 988 * => lnk: port@0 { endpoint { ... }; }; 989 * ... 990 * }; 991 * }; 992 */ 993 994 if (asoc_graph_is_ports0(lnk)) { 995 /* 996 * DON'T REMOVE platforms 997 * see 998 * simple-card.c :: simple_count_noml() 999 */ 1000 li->num[li->link].cpus = graph_counter(rport); /* FE */ 1001 li->num[li->link].platforms = graph_counter(rport); 1002 } else { 1003 li->num[li->link].codecs = graph_counter(rport); /* BE */ 1004 } 1005 1006 of_node_put(ep); 1007 of_node_put(rport); 1008 1009 return 0; 1010 } 1011 1012 static int graph_count_c2c(struct asoc_simple_priv *priv, 1013 struct device_node *lnk, 1014 struct link_info *li) 1015 { 1016 struct device_node *ports = of_get_parent(lnk); 1017 struct device_node *port0 = lnk; 1018 struct device_node *port1 = of_get_next_child(ports, lnk); 1019 struct device_node *ep0 = port_to_endpoint(port0); 1020 struct device_node *ep1 = port_to_endpoint(port1); 1021 struct device_node *codec0 = of_graph_get_remote_port(ep0); 1022 struct device_node *codec1 = of_graph_get_remote_port(ep1); 1023 1024 of_node_get(lnk); 1025 1026 /* 1027 * codec2codec { 1028 * ports { 1029 * => lnk: port@0 { endpoint { ... }; }; 1030 * port@1 { endpoint { ... }; }; 1031 * }; 1032 * }; 1033 */ 1034 /* 1035 * DON'T REMOVE platforms 1036 * see 1037 * simple-card.c :: simple_count_noml() 1038 */ 1039 li->num[li->link].cpus = 1040 li->num[li->link].platforms = graph_counter(codec0); 1041 1042 li->num[li->link].codecs = graph_counter(codec1); 1043 1044 of_node_put(ports); 1045 of_node_put(port1); 1046 of_node_put(ep0); 1047 of_node_put(ep1); 1048 of_node_put(codec0); 1049 of_node_put(codec1); 1050 1051 return 0; 1052 } 1053 1054 static int graph_count(struct asoc_simple_priv *priv, 1055 struct graph2_custom_hooks *hooks, 1056 enum graph_type gtype, 1057 struct device_node *lnk, 1058 struct link_info *li) 1059 { 1060 struct device *dev = simple_priv_to_dev(priv); 1061 GRAPH2_CUSTOM func = NULL; 1062 int ret = -EINVAL; 1063 1064 if (li->link >= SNDRV_MAX_LINKS) { 1065 dev_err(dev, "too many links\n"); 1066 return ret; 1067 } 1068 1069 switch (gtype) { 1070 case GRAPH_NORMAL: 1071 func = graph_count_normal; 1072 break; 1073 case GRAPH_DPCM: 1074 func = graph_count_dpcm; 1075 break; 1076 case GRAPH_C2C: 1077 func = graph_count_c2c; 1078 break; 1079 default: 1080 break; 1081 } 1082 1083 if (!func) { 1084 dev_err(dev, "non supported gtype (%d)\n", gtype); 1085 goto err; 1086 } 1087 1088 ret = func(priv, lnk, li); 1089 if (ret < 0) 1090 goto err; 1091 1092 li->link++; 1093 err: 1094 return ret; 1095 } 1096 1097 static int graph_for_each_link(struct asoc_simple_priv *priv, 1098 struct graph2_custom_hooks *hooks, 1099 struct link_info *li, 1100 int (*func)(struct asoc_simple_priv *priv, 1101 struct graph2_custom_hooks *hooks, 1102 enum graph_type gtype, 1103 struct device_node *lnk, 1104 struct link_info *li)) 1105 { 1106 struct of_phandle_iterator it; 1107 struct device *dev = simple_priv_to_dev(priv); 1108 struct device_node *node = dev->of_node; 1109 struct device_node *lnk; 1110 enum graph_type gtype; 1111 int rc, ret; 1112 1113 /* loop for all listed CPU port */ 1114 of_for_each_phandle(&it, rc, node, "links", NULL, 0) { 1115 lnk = it.node; 1116 1117 gtype = graph_get_type(priv, lnk); 1118 1119 ret = func(priv, hooks, gtype, lnk, li); 1120 if (ret < 0) 1121 return ret; 1122 } 1123 1124 return 0; 1125 } 1126 1127 int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev, 1128 struct graph2_custom_hooks *hooks) 1129 { 1130 struct snd_soc_card *card = simple_priv_to_card(priv); 1131 struct link_info *li; 1132 int ret; 1133 1134 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); 1135 if (!li) 1136 return -ENOMEM; 1137 1138 card->probe = asoc_graph_card_probe; 1139 card->owner = THIS_MODULE; 1140 card->dev = dev; 1141 1142 if ((hooks) && (hooks)->hook_pre) { 1143 ret = (hooks)->hook_pre(priv); 1144 if (ret < 0) 1145 goto err; 1146 } 1147 1148 ret = graph_for_each_link(priv, hooks, li, graph_count); 1149 if (!li->link) 1150 ret = -EINVAL; 1151 if (ret < 0) 1152 goto err; 1153 1154 ret = asoc_simple_init_priv(priv, li); 1155 if (ret < 0) 1156 goto err; 1157 1158 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); 1159 if (IS_ERR(priv->pa_gpio)) { 1160 ret = PTR_ERR(priv->pa_gpio); 1161 dev_err(dev, "failed to get amplifier gpio: %d\n", ret); 1162 goto err; 1163 } 1164 1165 ret = asoc_simple_parse_widgets(card, NULL); 1166 if (ret < 0) 1167 goto err; 1168 1169 ret = asoc_simple_parse_routing(card, NULL); 1170 if (ret < 0) 1171 goto err; 1172 1173 memset(li, 0, sizeof(*li)); 1174 ret = graph_for_each_link(priv, hooks, li, graph_link); 1175 if (ret < 0) 1176 goto err; 1177 1178 ret = asoc_simple_parse_card_name(card, NULL); 1179 if (ret < 0) 1180 goto err; 1181 1182 snd_soc_card_set_drvdata(card, priv); 1183 1184 if ((hooks) && (hooks)->hook_post) { 1185 ret = (hooks)->hook_post(priv); 1186 if (ret < 0) 1187 goto err; 1188 } 1189 1190 asoc_simple_debug_info(priv); 1191 1192 ret = devm_snd_soc_register_card(dev, card); 1193 err: 1194 devm_kfree(dev, li); 1195 1196 if (ret < 0) 1197 dev_err_probe(dev, ret, "parse error\n"); 1198 1199 return ret; 1200 } 1201 EXPORT_SYMBOL_GPL(audio_graph2_parse_of); 1202 1203 static int graph_probe(struct platform_device *pdev) 1204 { 1205 struct asoc_simple_priv *priv; 1206 struct device *dev = &pdev->dev; 1207 1208 /* Allocate the private data and the DAI link array */ 1209 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 1210 if (!priv) 1211 return -ENOMEM; 1212 1213 return audio_graph2_parse_of(priv, dev, NULL); 1214 } 1215 1216 static const struct of_device_id graph_of_match[] = { 1217 { .compatible = "audio-graph-card2", }, 1218 {}, 1219 }; 1220 MODULE_DEVICE_TABLE(of, graph_of_match); 1221 1222 static struct platform_driver graph_card = { 1223 .driver = { 1224 .name = "asoc-audio-graph-card2", 1225 .pm = &snd_soc_pm_ops, 1226 .of_match_table = graph_of_match, 1227 }, 1228 .probe = graph_probe, 1229 .remove = asoc_simple_remove, 1230 }; 1231 module_platform_driver(graph_card); 1232 1233 MODULE_ALIAS("platform:asoc-audio-graph-card2"); 1234 MODULE_LICENSE("GPL v2"); 1235 MODULE_DESCRIPTION("ASoC Audio Graph Card2"); 1236 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 1237