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