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 fw_devlink_purge_absent_suppliers(&np->fwnode); 265 goto out_put; 266 } 267 268 if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) { 269 ret = GRAPH_DPCM; 270 fw_devlink_purge_absent_suppliers(&np->fwnode); 271 goto out_put; 272 } 273 274 if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) { 275 ret = GRAPH_C2C; 276 fw_devlink_purge_absent_suppliers(&np->fwnode); 277 goto out_put; 278 } 279 280 ret = GRAPH_NORMAL; 281 282 out_put: 283 of_node_put(np); 284 return ret; 285 286 } 287 288 static enum graph_type graph_get_type(struct asoc_simple_priv *priv, 289 struct device_node *lnk) 290 { 291 enum graph_type type = __graph_get_type(lnk); 292 293 /* GRAPH_MULTI here means GRAPH_NORMAL */ 294 if (type == GRAPH_MULTI) 295 type = GRAPH_NORMAL; 296 297 #ifdef DEBUG 298 { 299 struct device *dev = simple_priv_to_dev(priv); 300 const char *str = "Normal"; 301 302 switch (type) { 303 case GRAPH_DPCM: 304 if (asoc_graph_is_ports0(lnk)) 305 str = "DPCM Front-End"; 306 else 307 str = "DPCM Back-End"; 308 break; 309 case GRAPH_C2C: 310 str = "Codec2Codec"; 311 break; 312 default: 313 break; 314 } 315 316 dev_dbg(dev, "%pOF (%s)", lnk, str); 317 } 318 #endif 319 return type; 320 } 321 322 static int graph_lnk_is_multi(struct device_node *lnk) 323 { 324 return __graph_get_type(lnk) == GRAPH_MULTI; 325 } 326 327 static struct device_node *graph_get_next_multi_ep(struct device_node **port) 328 { 329 struct device_node *ports = of_get_parent(*port); 330 struct device_node *ep = NULL; 331 struct device_node *rep = NULL; 332 333 /* 334 * multi { 335 * ports { 336 * => lnk: port@0 { ... }; 337 * port@1 { ep { ... = rep0 } }; 338 * port@2 { ep { ... = rep1 } }; 339 * ... 340 * }; 341 * }; 342 * 343 * xxx { 344 * port@0 { rep0 }; 345 * port@1 { rep1 }; 346 * }; 347 */ 348 do { 349 *port = of_get_next_child(ports, *port); 350 if (!*port) 351 break; 352 } while (!of_node_name_eq(*port, "port")); 353 354 if (*port) { 355 ep = port_to_endpoint(*port); 356 rep = of_graph_get_remote_endpoint(ep); 357 } 358 359 of_node_put(ep); 360 of_node_put(ports); 361 362 return rep; 363 } 364 365 static const struct snd_soc_ops graph_ops = { 366 .startup = asoc_simple_startup, 367 .shutdown = asoc_simple_shutdown, 368 .hw_params = asoc_simple_hw_params, 369 }; 370 371 static void graph_parse_convert(struct device_node *ep, 372 struct simple_dai_props *props) 373 { 374 struct device_node *port = of_get_parent(ep); 375 struct device_node *ports = of_get_parent(port); 376 struct asoc_simple_data *adata = &props->adata; 377 378 if (of_node_name_eq(ports, "ports")) 379 asoc_simple_parse_convert(ports, NULL, adata); 380 asoc_simple_parse_convert(port, NULL, adata); 381 asoc_simple_parse_convert(ep, NULL, adata); 382 383 of_node_put(port); 384 of_node_put(ports); 385 } 386 387 static void graph_parse_mclk_fs(struct device_node *ep, 388 struct simple_dai_props *props) 389 { 390 struct device_node *port = of_get_parent(ep); 391 struct device_node *ports = of_get_parent(port); 392 393 if (of_node_name_eq(ports, "ports")) 394 of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); 395 of_property_read_u32(port, "mclk-fs", &props->mclk_fs); 396 of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); 397 398 of_node_put(port); 399 of_node_put(ports); 400 } 401 402 static int __graph_parse_node(struct asoc_simple_priv *priv, 403 enum graph_type gtype, 404 struct device_node *ep, 405 struct link_info *li, 406 int is_cpu, int idx) 407 { 408 struct device *dev = simple_priv_to_dev(priv); 409 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 410 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 411 struct snd_soc_dai_link_component *dlc; 412 struct asoc_simple_dai *dai; 413 int ret, is_single_links = 0; 414 415 if (is_cpu) { 416 dlc = asoc_link_to_cpu(dai_link, idx); 417 dai = simple_props_to_dai_cpu(dai_props, idx); 418 } else { 419 dlc = asoc_link_to_codec(dai_link, idx); 420 dai = simple_props_to_dai_codec(dai_props, idx); 421 } 422 423 graph_parse_mclk_fs(ep, dai_props); 424 425 ret = asoc_graph_parse_dai(dev, ep, dlc, &is_single_links); 426 if (ret < 0) 427 return ret; 428 429 ret = asoc_simple_parse_tdm(ep, dai); 430 if (ret < 0) 431 return ret; 432 433 ret = asoc_simple_parse_tdm_width_map(dev, ep, dai); 434 if (ret < 0) 435 return ret; 436 437 ret = asoc_simple_parse_clk(dev, ep, dai, dlc); 438 if (ret < 0) 439 return ret; 440 441 /* 442 * set DAI Name 443 */ 444 if (!dai_link->name) { 445 struct snd_soc_dai_link_component *cpus = dlc; 446 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx); 447 char *cpu_multi = ""; 448 char *codec_multi = ""; 449 450 if (dai_link->num_cpus > 1) 451 cpu_multi = "_multi"; 452 if (dai_link->num_codecs > 1) 453 codec_multi = "_multi"; 454 455 switch (gtype) { 456 case GRAPH_NORMAL: 457 /* run is_cpu only. see audio_graph2_link_normal() */ 458 if (is_cpu) 459 asoc_simple_set_dailink_name(dev, dai_link, "%s%s-%s%s", 460 cpus->dai_name, cpu_multi, 461 codecs->dai_name, codec_multi); 462 break; 463 case GRAPH_DPCM: 464 if (is_cpu) 465 asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s", 466 cpus->of_node, cpus->dai_name, cpu_multi); 467 else 468 asoc_simple_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s", 469 codecs->of_node, codecs->dai_name, codec_multi); 470 break; 471 case GRAPH_C2C: 472 /* run is_cpu only. see audio_graph2_link_c2c() */ 473 if (is_cpu) 474 asoc_simple_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s", 475 cpus->dai_name, cpu_multi, 476 codecs->dai_name, codec_multi); 477 break; 478 default: 479 break; 480 } 481 } 482 483 /* 484 * Check "prefix" from top node 485 * if DPCM-BE case 486 */ 487 if (!is_cpu && gtype == GRAPH_DPCM) { 488 struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, idx); 489 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx); 490 struct device_node *rport = of_get_parent(ep); 491 struct device_node *rports = of_get_parent(rport); 492 493 if (of_node_name_eq(rports, "ports")) 494 snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); 495 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix"); 496 497 of_node_put(rport); 498 of_node_put(rports); 499 } 500 501 if (is_cpu) { 502 struct snd_soc_dai_link_component *cpus = dlc; 503 struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, idx); 504 505 asoc_simple_canonicalize_cpu(cpus, is_single_links); 506 asoc_simple_canonicalize_platform(platforms, cpus); 507 } 508 509 return 0; 510 } 511 512 static int graph_parse_node(struct asoc_simple_priv *priv, 513 enum graph_type gtype, 514 struct device_node *port, 515 struct link_info *li, int is_cpu) 516 { 517 struct device_node *ep; 518 int ret = 0; 519 520 if (graph_lnk_is_multi(port)) { 521 int idx; 522 523 of_node_get(port); 524 525 for (idx = 0;; idx++) { 526 ep = graph_get_next_multi_ep(&port); 527 if (!ep) 528 break; 529 530 ret = __graph_parse_node(priv, gtype, ep, 531 li, is_cpu, idx); 532 of_node_put(ep); 533 if (ret < 0) 534 break; 535 } 536 } else { 537 /* Single CPU / Codec */ 538 ep = port_to_endpoint(port); 539 ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0); 540 of_node_put(ep); 541 } 542 543 return ret; 544 } 545 546 static void graph_parse_daifmt(struct device_node *node, 547 unsigned int *daifmt, unsigned int *bit_frame) 548 { 549 unsigned int fmt; 550 551 /* 552 * see also above "daifmt" explanation 553 * and samples. 554 */ 555 556 /* 557 * ports { 558 * (A) 559 * port { 560 * (B) 561 * endpoint { 562 * (C) 563 * }; 564 * }; 565 * }; 566 * }; 567 */ 568 569 /* 570 * clock_provider: 571 * 572 * It can be judged it is provider 573 * if (A) or (B) or (C) has bitclock-master / frame-master flag. 574 * 575 * use "or" 576 */ 577 *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL); 578 579 #define update_daifmt(name) \ 580 if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \ 581 (fmt & SND_SOC_DAIFMT_##name##_MASK)) \ 582 *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK 583 584 /* 585 * format 586 * 587 * This function is called by (C) -> (B) -> (A) order. 588 * Set if applicable part was not yet set. 589 */ 590 fmt = snd_soc_daifmt_parse_format(node, NULL); 591 update_daifmt(FORMAT); 592 update_daifmt(CLOCK); 593 update_daifmt(INV); 594 } 595 596 static void graph_link_init(struct asoc_simple_priv *priv, 597 struct device_node *port, 598 struct link_info *li, 599 int is_cpu_node) 600 { 601 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 602 struct device_node *ep; 603 struct device_node *ports; 604 unsigned int daifmt = 0, daiclk = 0; 605 unsigned int bit_frame = 0; 606 607 if (graph_lnk_is_multi(port)) { 608 of_node_get(port); 609 ep = graph_get_next_multi_ep(&port); 610 port = of_get_parent(ep); 611 } else { 612 ep = port_to_endpoint(port); 613 } 614 615 ports = of_get_parent(port); 616 617 /* 618 * ports { 619 * (A) 620 * port { 621 * (B) 622 * endpoint { 623 * (C) 624 * }; 625 * }; 626 * }; 627 * }; 628 */ 629 graph_parse_daifmt(ep, &daifmt, &bit_frame); /* (C) */ 630 graph_parse_daifmt(port, &daifmt, &bit_frame); /* (B) */ 631 if (of_node_name_eq(ports, "ports")) 632 graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */ 633 634 /* 635 * convert bit_frame 636 * We need to flip clock_provider if it was CPU node, 637 * because it is Codec base. 638 */ 639 daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame); 640 if (is_cpu_node) 641 daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk); 642 643 dai_link->dai_fmt = daifmt | daiclk; 644 dai_link->init = asoc_simple_dai_init; 645 dai_link->ops = &graph_ops; 646 if (priv->ops) 647 dai_link->ops = priv->ops; 648 } 649 650 int audio_graph2_link_normal(struct asoc_simple_priv *priv, 651 struct device_node *lnk, 652 struct link_info *li) 653 { 654 struct device_node *cpu_port = lnk; 655 struct device_node *cpu_ep = port_to_endpoint(cpu_port); 656 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep); 657 int ret; 658 659 /* 660 * call Codec first. 661 * see 662 * __graph_parse_node() :: DAI Naming 663 */ 664 ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0); 665 if (ret < 0) 666 goto err; 667 668 /* 669 * call CPU, and set DAI Name 670 */ 671 ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1); 672 if (ret < 0) 673 goto err; 674 675 graph_link_init(priv, cpu_port, li, 1); 676 err: 677 of_node_put(codec_port); 678 of_node_put(cpu_ep); 679 680 return ret; 681 } 682 EXPORT_SYMBOL_GPL(audio_graph2_link_normal); 683 684 int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, 685 struct device_node *lnk, 686 struct link_info *li) 687 { 688 struct device_node *ep = port_to_endpoint(lnk); 689 struct device_node *rep = of_graph_get_remote_endpoint(ep); 690 struct device_node *rport = of_graph_get_remote_port(ep); 691 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 692 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 693 int is_cpu = asoc_graph_is_ports0(lnk); 694 int ret; 695 696 if (is_cpu) { 697 /* 698 * dpcm { 699 * // Front-End 700 * ports@0 { 701 * => lnk: port@0 { ep: { ... = rep }; }; 702 * ... 703 * }; 704 * // Back-End 705 * ports@0 { 706 * ... 707 * }; 708 * }; 709 * 710 * CPU { 711 * rports: ports { 712 * rport: port@0 { rep: { ... = ep } }; 713 * } 714 * } 715 */ 716 /* 717 * setup CPU here, Codec is already set as dummy. 718 * see 719 * asoc_simple_init_priv() 720 */ 721 dai_link->dynamic = 1; 722 dai_link->dpcm_merged_format = 1; 723 724 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1); 725 if (ret) 726 goto err; 727 } else { 728 /* 729 * dpcm { 730 * // Front-End 731 * ports@0 { 732 * ... 733 * }; 734 * // Back-End 735 * ports@0 { 736 * => lnk: port@0 { ep: { ... = rep; }; }; 737 * ... 738 * }; 739 * }; 740 * 741 * Codec { 742 * rports: ports { 743 * rport: port@0 { rep: { ... = ep; }; }; 744 * } 745 * } 746 */ 747 /* 748 * setup Codec here, CPU is already set as dummy. 749 * see 750 * asoc_simple_init_priv() 751 */ 752 753 /* BE settings */ 754 dai_link->no_pcm = 1; 755 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; 756 757 ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0); 758 if (ret < 0) 759 goto err; 760 } 761 762 graph_parse_convert(ep, dai_props); /* at node of <dpcm> */ 763 graph_parse_convert(rep, dai_props); /* at node of <CPU/Codec> */ 764 765 snd_soc_dai_link_set_capabilities(dai_link); 766 767 graph_link_init(priv, rport, li, is_cpu); 768 err: 769 of_node_put(ep); 770 of_node_put(rep); 771 of_node_put(rport); 772 773 return ret; 774 } 775 EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm); 776 777 int audio_graph2_link_c2c(struct asoc_simple_priv *priv, 778 struct device_node *lnk, 779 struct link_info *li) 780 { 781 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 782 struct device_node *port0, *port1, *ports; 783 struct device_node *codec0_port, *codec1_port; 784 struct device_node *ep0, *ep1; 785 u32 val = 0; 786 int ret = -EINVAL; 787 788 /* 789 * codec2codec { 790 * ports { 791 * rate = <48000>; 792 * => lnk: port@0 { c2c0_ep: { ... = codec0_ep; }; }; 793 * port@1 { c2c1_ep: { ... = codec1_ep; }; }; 794 * }; 795 * }; 796 * 797 * Codec { 798 * ports { 799 * port@0 { codec0_ep: ... }; }; 800 * port@1 { codec1_ep: ... }; }; 801 * }; 802 * }; 803 */ 804 of_node_get(lnk); 805 port0 = lnk; 806 ports = of_get_parent(port0); 807 port1 = of_get_next_child(ports, lnk); 808 809 /* 810 * Card2 can use original Codec2Codec settings if DT has. 811 * It will use default settings if no settings on DT. 812 * see 813 * asoc_simple_init_for_codec2codec() 814 * 815 * Add more settings here if needed 816 */ 817 of_property_read_u32(ports, "rate", &val); 818 if (val) { 819 struct device *dev = simple_priv_to_dev(priv); 820 struct snd_soc_pcm_stream *c2c_conf; 821 822 c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL); 823 if (!c2c_conf) 824 goto err1; 825 826 c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */ 827 c2c_conf->rates = SNDRV_PCM_RATE_8000_384000; 828 c2c_conf->rate_min = 829 c2c_conf->rate_max = val; 830 c2c_conf->channels_min = 831 c2c_conf->channels_max = 2; /* update ME */ 832 833 dai_link->c2c_params = c2c_conf; 834 dai_link->num_c2c_params = 1; 835 } 836 837 ep0 = port_to_endpoint(port0); 838 ep1 = port_to_endpoint(port1); 839 840 codec0_port = of_graph_get_remote_port(ep0); 841 codec1_port = of_graph_get_remote_port(ep1); 842 843 /* 844 * call Codec first. 845 * see 846 * __graph_parse_node() :: DAI Naming 847 */ 848 ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0); 849 if (ret < 0) 850 goto err2; 851 852 /* 853 * call CPU, and set DAI Name 854 */ 855 ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1); 856 if (ret < 0) 857 goto err2; 858 859 graph_link_init(priv, codec0_port, li, 1); 860 err2: 861 of_node_put(ep0); 862 of_node_put(ep1); 863 of_node_put(codec0_port); 864 of_node_put(codec1_port); 865 err1: 866 of_node_put(ports); 867 of_node_put(port0); 868 of_node_put(port1); 869 870 return ret; 871 } 872 EXPORT_SYMBOL_GPL(audio_graph2_link_c2c); 873 874 static int graph_link(struct asoc_simple_priv *priv, 875 struct graph2_custom_hooks *hooks, 876 enum graph_type gtype, 877 struct device_node *lnk, 878 struct link_info *li) 879 { 880 struct device *dev = simple_priv_to_dev(priv); 881 GRAPH2_CUSTOM func = NULL; 882 int ret = -EINVAL; 883 884 switch (gtype) { 885 case GRAPH_NORMAL: 886 if (hooks && hooks->custom_normal) 887 func = hooks->custom_normal; 888 else 889 func = audio_graph2_link_normal; 890 break; 891 case GRAPH_DPCM: 892 if (hooks && hooks->custom_dpcm) 893 func = hooks->custom_dpcm; 894 else 895 func = audio_graph2_link_dpcm; 896 break; 897 case GRAPH_C2C: 898 if (hooks && hooks->custom_c2c) 899 func = hooks->custom_c2c; 900 else 901 func = audio_graph2_link_c2c; 902 break; 903 default: 904 break; 905 } 906 907 if (!func) { 908 dev_err(dev, "non supported gtype (%d)\n", gtype); 909 goto err; 910 } 911 912 ret = func(priv, lnk, li); 913 if (ret < 0) 914 goto err; 915 916 li->link++; 917 err: 918 return ret; 919 } 920 921 static int graph_counter(struct device_node *lnk) 922 { 923 /* 924 * Multi CPU / Codec 925 * 926 * multi { 927 * ports { 928 * => lnk: port@0 { ... }; 929 * port@1 { ... }; 930 * port@2 { ... }; 931 * ... 932 * }; 933 * }; 934 * 935 * ignore first lnk part 936 */ 937 if (graph_lnk_is_multi(lnk)) 938 return of_graph_get_endpoint_count(of_get_parent(lnk)) - 1; 939 /* 940 * Single CPU / Codec 941 */ 942 else 943 return 1; 944 } 945 946 static int graph_count_normal(struct asoc_simple_priv *priv, 947 struct device_node *lnk, 948 struct link_info *li) 949 { 950 struct device_node *cpu_port = lnk; 951 struct device_node *cpu_ep = port_to_endpoint(cpu_port); 952 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep); 953 954 /* 955 * CPU { 956 * => lnk: port { endpoint { .. }; }; 957 * }; 958 */ 959 /* 960 * DON'T REMOVE platforms 961 * see 962 * simple-card.c :: simple_count_noml() 963 */ 964 li->num[li->link].cpus = 965 li->num[li->link].platforms = graph_counter(cpu_port); 966 967 li->num[li->link].codecs = graph_counter(codec_port); 968 969 of_node_put(cpu_ep); 970 of_node_put(codec_port); 971 972 return 0; 973 } 974 975 static int graph_count_dpcm(struct asoc_simple_priv *priv, 976 struct device_node *lnk, 977 struct link_info *li) 978 { 979 struct device_node *ep = port_to_endpoint(lnk); 980 struct device_node *rport = of_graph_get_remote_port(ep); 981 982 /* 983 * dpcm { 984 * // Front-End 985 * ports@0 { 986 * => lnk: port@0 { endpoint { ... }; }; 987 * ... 988 * }; 989 * // Back-End 990 * ports@1 { 991 * => lnk: port@0 { endpoint { ... }; }; 992 * ... 993 * }; 994 * }; 995 */ 996 997 if (asoc_graph_is_ports0(lnk)) { 998 /* 999 * DON'T REMOVE platforms 1000 * see 1001 * simple-card.c :: simple_count_noml() 1002 */ 1003 li->num[li->link].cpus = graph_counter(rport); /* FE */ 1004 li->num[li->link].platforms = graph_counter(rport); 1005 } else { 1006 li->num[li->link].codecs = graph_counter(rport); /* BE */ 1007 } 1008 1009 of_node_put(ep); 1010 of_node_put(rport); 1011 1012 return 0; 1013 } 1014 1015 static int graph_count_c2c(struct asoc_simple_priv *priv, 1016 struct device_node *lnk, 1017 struct link_info *li) 1018 { 1019 struct device_node *ports = of_get_parent(lnk); 1020 struct device_node *port0 = lnk; 1021 struct device_node *port1 = of_get_next_child(ports, lnk); 1022 struct device_node *ep0 = port_to_endpoint(port0); 1023 struct device_node *ep1 = port_to_endpoint(port1); 1024 struct device_node *codec0 = of_graph_get_remote_port(ep0); 1025 struct device_node *codec1 = of_graph_get_remote_port(ep1); 1026 1027 of_node_get(lnk); 1028 1029 /* 1030 * codec2codec { 1031 * ports { 1032 * => lnk: port@0 { endpoint { ... }; }; 1033 * port@1 { endpoint { ... }; }; 1034 * }; 1035 * }; 1036 */ 1037 /* 1038 * DON'T REMOVE platforms 1039 * see 1040 * simple-card.c :: simple_count_noml() 1041 */ 1042 li->num[li->link].cpus = 1043 li->num[li->link].platforms = graph_counter(codec0); 1044 1045 li->num[li->link].codecs = graph_counter(codec1); 1046 1047 of_node_put(ports); 1048 of_node_put(port1); 1049 of_node_put(ep0); 1050 of_node_put(ep1); 1051 of_node_put(codec0); 1052 of_node_put(codec1); 1053 1054 return 0; 1055 } 1056 1057 static int graph_count(struct asoc_simple_priv *priv, 1058 struct graph2_custom_hooks *hooks, 1059 enum graph_type gtype, 1060 struct device_node *lnk, 1061 struct link_info *li) 1062 { 1063 struct device *dev = simple_priv_to_dev(priv); 1064 GRAPH2_CUSTOM func = NULL; 1065 int ret = -EINVAL; 1066 1067 if (li->link >= SNDRV_MAX_LINKS) { 1068 dev_err(dev, "too many links\n"); 1069 return ret; 1070 } 1071 1072 switch (gtype) { 1073 case GRAPH_NORMAL: 1074 func = graph_count_normal; 1075 break; 1076 case GRAPH_DPCM: 1077 func = graph_count_dpcm; 1078 break; 1079 case GRAPH_C2C: 1080 func = graph_count_c2c; 1081 break; 1082 default: 1083 break; 1084 } 1085 1086 if (!func) { 1087 dev_err(dev, "non supported gtype (%d)\n", gtype); 1088 goto err; 1089 } 1090 1091 ret = func(priv, lnk, li); 1092 if (ret < 0) 1093 goto err; 1094 1095 li->link++; 1096 err: 1097 return ret; 1098 } 1099 1100 static int graph_for_each_link(struct asoc_simple_priv *priv, 1101 struct graph2_custom_hooks *hooks, 1102 struct link_info *li, 1103 int (*func)(struct asoc_simple_priv *priv, 1104 struct graph2_custom_hooks *hooks, 1105 enum graph_type gtype, 1106 struct device_node *lnk, 1107 struct link_info *li)) 1108 { 1109 struct of_phandle_iterator it; 1110 struct device *dev = simple_priv_to_dev(priv); 1111 struct device_node *node = dev->of_node; 1112 struct device_node *lnk; 1113 enum graph_type gtype; 1114 int rc, ret; 1115 1116 /* loop for all listed CPU port */ 1117 of_for_each_phandle(&it, rc, node, "links", NULL, 0) { 1118 lnk = it.node; 1119 1120 gtype = graph_get_type(priv, lnk); 1121 1122 ret = func(priv, hooks, gtype, lnk, li); 1123 if (ret < 0) 1124 return ret; 1125 } 1126 1127 return 0; 1128 } 1129 1130 int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev, 1131 struct graph2_custom_hooks *hooks) 1132 { 1133 struct snd_soc_card *card = simple_priv_to_card(priv); 1134 struct link_info *li; 1135 int ret; 1136 1137 li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); 1138 if (!li) 1139 return -ENOMEM; 1140 1141 card->probe = asoc_graph_card_probe; 1142 card->owner = THIS_MODULE; 1143 card->dev = dev; 1144 1145 if ((hooks) && (hooks)->hook_pre) { 1146 ret = (hooks)->hook_pre(priv); 1147 if (ret < 0) 1148 goto err; 1149 } 1150 1151 ret = graph_for_each_link(priv, hooks, li, graph_count); 1152 if (!li->link) 1153 ret = -EINVAL; 1154 if (ret < 0) 1155 goto err; 1156 1157 ret = asoc_simple_init_priv(priv, li); 1158 if (ret < 0) 1159 goto err; 1160 1161 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); 1162 if (IS_ERR(priv->pa_gpio)) { 1163 ret = PTR_ERR(priv->pa_gpio); 1164 dev_err(dev, "failed to get amplifier gpio: %d\n", ret); 1165 goto err; 1166 } 1167 1168 ret = asoc_simple_parse_widgets(card, NULL); 1169 if (ret < 0) 1170 goto err; 1171 1172 ret = asoc_simple_parse_routing(card, NULL); 1173 if (ret < 0) 1174 goto err; 1175 1176 memset(li, 0, sizeof(*li)); 1177 ret = graph_for_each_link(priv, hooks, li, graph_link); 1178 if (ret < 0) 1179 goto err; 1180 1181 ret = asoc_simple_parse_card_name(card, NULL); 1182 if (ret < 0) 1183 goto err; 1184 1185 snd_soc_card_set_drvdata(card, priv); 1186 1187 if ((hooks) && (hooks)->hook_post) { 1188 ret = (hooks)->hook_post(priv); 1189 if (ret < 0) 1190 goto err; 1191 } 1192 1193 asoc_simple_debug_info(priv); 1194 1195 ret = devm_snd_soc_register_card(dev, card); 1196 err: 1197 devm_kfree(dev, li); 1198 1199 if (ret < 0) 1200 dev_err_probe(dev, ret, "parse error\n"); 1201 1202 return ret; 1203 } 1204 EXPORT_SYMBOL_GPL(audio_graph2_parse_of); 1205 1206 static int graph_probe(struct platform_device *pdev) 1207 { 1208 struct asoc_simple_priv *priv; 1209 struct device *dev = &pdev->dev; 1210 1211 /* Allocate the private data and the DAI link array */ 1212 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 1213 if (!priv) 1214 return -ENOMEM; 1215 1216 return audio_graph2_parse_of(priv, dev, NULL); 1217 } 1218 1219 static const struct of_device_id graph_of_match[] = { 1220 { .compatible = "audio-graph-card2", }, 1221 {}, 1222 }; 1223 MODULE_DEVICE_TABLE(of, graph_of_match); 1224 1225 static struct platform_driver graph_card = { 1226 .driver = { 1227 .name = "asoc-audio-graph-card2", 1228 .pm = &snd_soc_pm_ops, 1229 .of_match_table = graph_of_match, 1230 }, 1231 .probe = graph_probe, 1232 .remove = asoc_simple_remove, 1233 }; 1234 module_platform_driver(graph_card); 1235 1236 MODULE_ALIAS("platform:asoc-audio-graph-card2"); 1237 MODULE_LICENSE("GPL v2"); 1238 MODULE_DESCRIPTION("ASoC Audio Graph Card2"); 1239 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 1240