drm/panthor: Don't add write fences to the shared BOs
[drm/drm-misc.git] / sound / soc / generic / audio-graph-card2.c
blob4ad3d1b0714f6a4f0800b0fa2b01c52cb010379c
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>
19 /************************************
20 daifmt
21 ************************************
22 ports {
23 format = "left_j";
24 port@0 {
25 bitclock-master;
26 sample0: endpoint@0 {
27 frame-master;
29 sample1: endpoint@1 {
30 format = "i2s";
33 ...
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
42 If there was no settings, *Codec* will be
43 bitclock/frame provider as default.
44 see
45 graph_parse_daifmt().
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()
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
59 ************************************
60 Normal Audio-Graph
61 ************************************
63 CPU <---> Codec
65 sound {
66 compatible = "audio-graph-card2";
67 links = <&cpu>;
70 CPU {
71 cpu: port {
72 bitclock-master;
73 frame-master;
74 cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
77 Codec {
78 port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
81 ************************************
82 Multi-CPU/Codec
83 ************************************
85 It has link connection part (= X,x) and list part (= A,B,a,b).
86 "links" is connection part of CPU side (= @).
88 +----+ +---+
89 CPU1 --|A X| <-@----> |x a|-- Codec1
90 CPU2 --|B | | b|-- Codec2
91 +----+ +---+
93 sound {
94 compatible = "audio-graph-card2";
96 (@) links = <&mcpu>;
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
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
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>; }; };
121 Codec {
122 ports {
123 port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; };
124 port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; };
128 ************************************
129 DPCM
130 ************************************
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 ************
142 sound {
143 compatible = "audio-graph-card2";
145 // indicate routing
146 routing = "xxx Playback", "xxx Playback",
147 "xxx Playback", "xxx Playback",
148 "xxx Playback", "xxx Playback";
150 // indicate all Front-End, Back-End
151 links = <&fe0, &fe1, ...,
152 &be0, &be1, ...>;
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>; }; };
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>; }; };
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>; }; };
180 Codec {
181 ports {
182 port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
183 port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
188 ************************************
189 Codec to Codec
190 ************************************
192 +--+
193 | |<-- Codec0 <- IN
194 | |--> Codec1 -> OUT
195 +--+
197 sound {
198 compatible = "audio-graph-card2";
200 routing = "OUT" ,"DAI1 Playback",
201 "DAI0 Capture", "IN";
203 links = <&c2c>;
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>; }; };
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>; }; };
225 enum graph_type {
226 GRAPH_NORMAL,
227 GRAPH_DPCM,
228 GRAPH_C2C,
230 GRAPH_MULTI, /* don't use ! Use this only in __graph_get_type() */
233 #define GRAPH_NODENAME_MULTI "multi"
234 #define GRAPH_NODENAME_DPCM "dpcm"
235 #define GRAPH_NODENAME_C2C "codec2codec"
237 #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")
239 #define ep_to_port(ep) of_get_parent(ep)
240 static struct device_node *port_to_ports(struct device_node *port)
242 struct device_node *ports = of_get_parent(port);
244 if (!of_node_name_eq(ports, "ports")) {
245 of_node_put(ports);
246 return NULL;
248 return ports;
251 static enum graph_type __graph_get_type(struct device_node *lnk)
253 struct device_node *np, *parent_np;
254 enum graph_type ret;
257 * target {
258 * ports {
259 * => lnk: port@0 { ... };
260 * port@1 { ... };
261 * };
262 * };
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;
271 if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) {
272 ret = GRAPH_MULTI;
273 goto out_put;
276 if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) {
277 ret = GRAPH_DPCM;
278 goto out_put;
281 if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) {
282 ret = GRAPH_C2C;
283 goto out_put;
286 ret = GRAPH_NORMAL;
288 out_put:
289 of_node_put(np);
290 return ret;
294 static enum graph_type graph_get_type(struct simple_util_priv *priv,
295 struct device_node *lnk)
297 enum graph_type type = __graph_get_type(lnk);
299 /* GRAPH_MULTI here means GRAPH_NORMAL */
300 if (type == GRAPH_MULTI)
301 type = GRAPH_NORMAL;
303 #ifdef DEBUG
305 struct device *dev = simple_priv_to_dev(priv);
306 const char *str = "Normal";
308 switch (type) {
309 case GRAPH_DPCM:
310 if (graph_util_is_ports0(lnk))
311 str = "DPCM Front-End";
312 else
313 str = "DPCM Back-End";
314 break;
315 case GRAPH_C2C:
316 str = "Codec2Codec";
317 break;
318 default:
319 break;
322 dev_dbg(dev, "%pOF (%s)", lnk, str);
324 #endif
325 return type;
328 static int graph_lnk_is_multi(struct device_node *lnk)
330 return __graph_get_type(lnk) == GRAPH_MULTI;
333 static struct device_node *graph_get_next_multi_ep(struct device_node **port)
335 struct device_node *ports = port_to_ports(*port);
336 struct device_node *ep = NULL;
337 struct device_node *rep = NULL;
340 * multi {
341 * ports {
342 * => lnk: port@0 { ... }; // to pair
343 * port@1 { ep { ... = rep0 } }; // Multi Element
344 * port@2 { ep { ... = rep1 } }; // Multi Element
345 * ...
346 * };
347 * };
349 * xxx {
350 * port@0 { rep0 };
351 * port@1 { rep1 };
352 * };
354 do {
355 *port = of_get_next_child(ports, *port);
356 if (!*port)
357 break;
358 } while (!of_node_name_eq(*port, "port"));
360 if (*port) {
361 ep = port_to_endpoint(*port);
362 rep = of_graph_get_remote_endpoint(ep);
365 of_node_put(ep);
366 of_node_put(ports);
368 return rep;
371 static const struct snd_soc_ops graph_ops = {
372 .startup = simple_util_startup,
373 .shutdown = simple_util_shutdown,
374 .hw_params = simple_util_hw_params,
377 static void graph_parse_convert(struct device_node *ep,
378 struct simple_dai_props *props)
380 struct device_node *port = ep_to_port(ep);
381 struct device_node *ports = port_to_ports(port);
382 struct simple_util_data *adata = &props->adata;
384 simple_util_parse_convert(ports, NULL, adata);
385 simple_util_parse_convert(port, NULL, adata);
386 simple_util_parse_convert(ep, NULL, adata);
388 of_node_put(port);
389 of_node_put(ports);
392 static int __graph_parse_node(struct simple_util_priv *priv,
393 enum graph_type gtype,
394 struct device_node *ep,
395 struct link_info *li,
396 int is_cpu, int idx)
398 struct device *dev = simple_priv_to_dev(priv);
399 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
400 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
401 struct snd_soc_dai_link_component *dlc;
402 struct simple_util_dai *dai;
403 int ret, is_single_links = 0;
405 if (is_cpu) {
406 dlc = snd_soc_link_to_cpu(dai_link, idx);
407 dai = simple_props_to_dai_cpu(dai_props, idx);
408 } else {
409 dlc = snd_soc_link_to_codec(dai_link, idx);
410 dai = simple_props_to_dai_codec(dai_props, idx);
413 ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links);
414 if (ret < 0)
415 return ret;
417 ret = simple_util_parse_tdm(ep, dai);
418 if (ret < 0)
419 return ret;
421 ret = simple_util_parse_tdm_width_map(dev, ep, dai);
422 if (ret < 0)
423 return ret;
425 ret = simple_util_parse_clk(dev, ep, dai, dlc);
426 if (ret < 0)
427 return ret;
430 * set DAI Name
432 if (!dai_link->name) {
433 struct snd_soc_dai_link_component *cpus = dlc;
434 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx);
435 char *cpu_multi = "";
436 char *codec_multi = "";
438 if (dai_link->num_cpus > 1)
439 cpu_multi = "_multi";
440 if (dai_link->num_codecs > 1)
441 codec_multi = "_multi";
443 switch (gtype) {
444 case GRAPH_NORMAL:
445 /* run is_cpu only. see audio_graph2_link_normal() */
446 if (is_cpu)
447 simple_util_set_dailink_name(dev, dai_link, "%s%s-%s%s",
448 cpus->dai_name, cpu_multi,
449 codecs->dai_name, codec_multi);
450 break;
451 case GRAPH_DPCM:
452 if (is_cpu)
453 simple_util_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s",
454 cpus->of_node, cpus->dai_name, cpu_multi);
455 else
456 simple_util_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s",
457 codecs->of_node, codecs->dai_name, codec_multi);
458 break;
459 case GRAPH_C2C:
460 /* run is_cpu only. see audio_graph2_link_c2c() */
461 if (is_cpu)
462 simple_util_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s",
463 cpus->dai_name, cpu_multi,
464 codecs->dai_name, codec_multi);
465 break;
466 default:
467 break;
472 * Check "prefix" from top node
473 * if DPCM-BE case
475 if (!is_cpu && gtype == GRAPH_DPCM) {
476 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx);
477 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
478 struct device_node *rport = ep_to_port(ep);
479 struct device_node *rports = port_to_ports(rport);
481 snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
482 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix");
484 of_node_put(rport);
485 of_node_put(rports);
488 if (is_cpu) {
489 struct snd_soc_dai_link_component *cpus = dlc;
490 struct snd_soc_dai_link_component *platforms = snd_soc_link_to_platform(dai_link, idx);
492 simple_util_canonicalize_cpu(cpus, is_single_links);
493 simple_util_canonicalize_platform(platforms, cpus);
496 return 0;
499 static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link,
500 int *nm_idx, int cpu_idx,
501 struct device_node *mcpu_port)
504 * +---+ +---+
505 * | X|<-@------->|x |
506 * | | | |
507 * cpu0 <--|A 1|<--------->|4 a|-> codec0
508 * cpu1 <--|B 2|<-----+--->|5 b|-> codec1
509 * cpu2 <--|C 3|<----/ +---+
510 * +---+
512 * multi {
513 * ports {
514 * port@0 { mcpu_top_ep {... = mcodec_ep; }; }; // (X) to pair
515 * <mcpu_port> port@1 { mcpu0_ep { ... = cpu0_ep; }; // (A) Multi Element
516 * mcpu0_ep_0 { ... = mcodec0_ep_0; }; }; // (1) connected Codec
517 * port@2 { mcpu1_ep { ... = cpu1_ep; }; // (B) Multi Element
518 * mcpu1_ep_0 { ... = mcodec1_ep_0; }; }; // (2) connected Codec
519 * port@3 { mcpu2_ep { ... = cpu2_ep; }; // (C) Multi Element
520 * mcpu2_ep_0 { ... = mcodec1_ep_1; }; }; // (3) connected Codec
521 * };
523 * ports {
524 * port@0 { mcodec_top_ep {... = mcpu_ep; }; }; // (x) to pair
525 * <mcodec_port>port@1 { mcodec0_ep { ... = codec0_ep; }; // (a) Multi Element
526 * mcodec0_ep_0 { ... = mcpu0_ep_0; }; }; // (4) connected CPU
527 * port@2 { mcodec1_ep { ... = codec1_ep; }; // (b) Multi Element
528 * mcodec1_ep_0 { ... = mcpu1_ep_0; }; // (5) connected CPU
529 * mcodec1_ep_1 { ... = mcpu2_ep_0; }; }; // (5) connected CPU
530 * };
531 * };
533 struct device_node *mcpu_ep = port_to_endpoint(mcpu_port);
534 struct device_node *mcpu_ep_n = mcpu_ep;
535 struct device_node *mcpu_port_top = of_get_next_child(port_to_ports(mcpu_port), NULL);
536 struct device_node *mcpu_ep_top = port_to_endpoint(mcpu_port_top);
537 struct device_node *mcodec_ep_top = of_graph_get_remote_endpoint(mcpu_ep_top);
538 struct device_node *mcodec_port_top = ep_to_port(mcodec_ep_top);
539 struct device_node *mcodec_ports = port_to_ports(mcodec_port_top);
540 int nm_max = max(dai_link->num_cpus, dai_link->num_codecs);
541 int ret = -EINVAL;
543 if (cpu_idx > dai_link->num_cpus)
544 goto mcpu_err;
546 while (1) {
547 struct device_node *mcodec_ep_n;
548 struct device_node *mcodec_port_i;
549 struct device_node *mcodec_port;
550 int codec_idx;
552 if (*nm_idx > nm_max)
553 break;
555 mcpu_ep_n = of_get_next_child(mcpu_port, mcpu_ep_n);
556 if (!mcpu_ep_n) {
557 ret = 0;
558 break;
561 mcodec_ep_n = of_graph_get_remote_endpoint(mcpu_ep_n);
562 mcodec_port = ep_to_port(mcodec_ep_n);
564 if (mcodec_ports != port_to_ports(mcodec_port))
565 goto mcpu_err;
567 codec_idx = 0;
568 mcodec_port_i = of_get_next_child(mcodec_ports, NULL);
569 while (1) {
570 if (codec_idx > dai_link->num_codecs)
571 goto mcodec_err;
573 mcodec_port_i = of_get_next_child(mcodec_ports, mcodec_port_i);
575 if (!mcodec_port_i)
576 goto mcodec_err;
578 if (mcodec_port_i == mcodec_port)
579 break;
581 codec_idx++;
584 dai_link->ch_maps[*nm_idx].cpu = cpu_idx;
585 dai_link->ch_maps[*nm_idx].codec = codec_idx;
587 (*nm_idx)++;
589 of_node_put(mcodec_port_i);
590 mcodec_err:
591 of_node_put(mcodec_port);
592 of_node_put(mcpu_ep_n);
593 of_node_put(mcodec_ep_n);
595 mcpu_err:
596 of_node_put(mcpu_ep);
597 of_node_put(mcpu_port_top);
598 of_node_put(mcpu_ep_top);
599 of_node_put(mcodec_ep_top);
600 of_node_put(mcodec_port_top);
601 of_node_put(mcodec_ports);
603 return ret;
606 static int graph_parse_node_multi(struct simple_util_priv *priv,
607 enum graph_type gtype,
608 struct device_node *port,
609 struct link_info *li, int is_cpu)
611 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
612 struct device *dev = simple_priv_to_dev(priv);
613 struct device_node *ep;
614 int ret = -ENOMEM;
615 int nm_idx = 0;
616 int nm_max = max(dai_link->num_cpus, dai_link->num_codecs);
619 * create ch_maps if CPU:Codec = N:M
620 * DPCM is out of scope
622 if (gtype != GRAPH_DPCM && !dai_link->ch_maps &&
623 dai_link->num_cpus > 1 && dai_link->num_codecs > 1 &&
624 dai_link->num_cpus != dai_link->num_codecs) {
626 dai_link->ch_maps = devm_kcalloc(dev, nm_max,
627 sizeof(struct snd_soc_dai_link_ch_map), GFP_KERNEL);
628 if (!dai_link->ch_maps)
629 goto multi_err;
632 for (int idx = 0;; idx++) {
634 * multi {
635 * ports {
636 * <port> port@0 { ... }; // to pair
637 * port@1 { mcpu1_ep { ... = cpu1_ep };}; // Multi Element
638 * port@2 { mcpu2_ep { ... = cpu2_ep };}; // Multi Element
639 * };
640 * };
642 * cpu {
643 * ports {
644 * <ep> port@0 { cpu1_ep { ... = mcpu1_ep };};
645 * };
646 * };
648 ep = graph_get_next_multi_ep(&port);
649 if (!ep)
650 break;
652 ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, idx);
653 of_node_put(ep);
654 if (ret < 0)
655 goto multi_err;
657 /* CPU:Codec = N:M */
658 if (is_cpu && dai_link->ch_maps) {
659 ret = graph_parse_node_multi_nm(dai_link, &nm_idx, idx, port);
660 if (ret < 0)
661 goto multi_err;
665 if (is_cpu && dai_link->ch_maps && (nm_idx != nm_max))
666 ret = -EINVAL;
668 multi_err:
669 return ret;
672 static int graph_parse_node_single(struct simple_util_priv *priv,
673 enum graph_type gtype,
674 struct device_node *port,
675 struct link_info *li, int is_cpu)
677 struct device_node *ep = port_to_endpoint(port);
678 int ret = __graph_parse_node(priv, gtype, ep, li, is_cpu, 0);
680 of_node_put(ep);
682 return ret;
685 static int graph_parse_node(struct simple_util_priv *priv,
686 enum graph_type gtype,
687 struct device_node *port,
688 struct link_info *li, int is_cpu)
690 if (graph_lnk_is_multi(port))
691 return graph_parse_node_multi(priv, gtype, port, li, is_cpu);
692 else
693 return graph_parse_node_single(priv, gtype, port, li, is_cpu);
696 static void graph_parse_daifmt(struct device_node *node,
697 unsigned int *daifmt, unsigned int *bit_frame)
699 unsigned int fmt;
701 if (!node)
702 return;
705 * see also above "daifmt" explanation
706 * and samples.
710 * ports {
711 * (A)
712 * port {
713 * (B)
714 * endpoint {
715 * (C)
716 * };
717 * };
718 * };
719 * };
723 * clock_provider:
725 * It can be judged it is provider
726 * if (A) or (B) or (C) has bitclock-master / frame-master flag.
728 * use "or"
730 *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
732 #define update_daifmt(name) \
733 if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \
734 (fmt & SND_SOC_DAIFMT_##name##_MASK)) \
735 *daifmt |= fmt & SND_SOC_DAIFMT_##name##_MASK
738 * format
740 * This function is called by (C) -> (B) -> (A) order.
741 * Set if applicable part was not yet set.
743 fmt = snd_soc_daifmt_parse_format(node, NULL);
744 update_daifmt(FORMAT);
745 update_daifmt(CLOCK);
746 update_daifmt(INV);
749 static void graph_link_init(struct simple_util_priv *priv,
750 struct device_node *lnk,
751 struct device_node *port_cpu,
752 struct device_node *port_codec,
753 struct link_info *li,
754 int is_cpu_node)
756 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
757 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
758 struct device_node *ep_cpu, *ep_codec;
759 struct device_node *ports_cpu, *ports_codec;
760 unsigned int daifmt = 0, daiclk = 0;
761 bool playback_only = 0, capture_only = 0;
762 enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT;
763 enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT;
764 unsigned int bit_frame = 0;
766 of_node_get(port_cpu);
767 if (graph_lnk_is_multi(port_cpu)) {
768 ep_cpu = graph_get_next_multi_ep(&port_cpu);
769 of_node_put(port_cpu);
770 port_cpu = ep_to_port(ep_cpu);
771 } else {
772 ep_cpu = port_to_endpoint(port_cpu);
774 ports_cpu = port_to_ports(port_cpu);
776 of_node_get(port_codec);
777 if (graph_lnk_is_multi(port_codec)) {
778 ep_codec = graph_get_next_multi_ep(&port_codec);
779 of_node_put(port_cpu);
780 port_codec = ep_to_port(ep_codec);
781 } else {
782 ep_codec = port_to_endpoint(port_codec);
784 ports_codec = port_to_ports(port_codec);
787 graph_parse_daifmt(ep_cpu, &daifmt, &bit_frame);
788 graph_parse_daifmt(ep_codec, &daifmt, &bit_frame);
789 graph_parse_daifmt(port_cpu, &daifmt, &bit_frame);
790 graph_parse_daifmt(port_codec, &daifmt, &bit_frame);
791 graph_parse_daifmt(ports_cpu, &daifmt, &bit_frame);
792 graph_parse_daifmt(ports_codec, &daifmt, &bit_frame);
793 graph_parse_daifmt(lnk, &daifmt, &bit_frame);
795 graph_util_parse_link_direction(lnk, &playback_only, &capture_only);
796 graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only);
797 graph_util_parse_link_direction(ports_codec, &playback_only, &capture_only);
798 graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only);
799 graph_util_parse_link_direction(port_codec, &playback_only, &capture_only);
800 graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only);
801 graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only);
803 of_property_read_u32(lnk, "mclk-fs", &dai_props->mclk_fs);
804 of_property_read_u32(ports_cpu, "mclk-fs", &dai_props->mclk_fs);
805 of_property_read_u32(ports_codec, "mclk-fs", &dai_props->mclk_fs);
806 of_property_read_u32(port_cpu, "mclk-fs", &dai_props->mclk_fs);
807 of_property_read_u32(port_codec, "mclk-fs", &dai_props->mclk_fs);
808 of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs);
809 of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs);
811 graph_util_parse_trigger_order(priv, lnk, &trigger_start, &trigger_stop);
812 graph_util_parse_trigger_order(priv, ports_cpu, &trigger_start, &trigger_stop);
813 graph_util_parse_trigger_order(priv, ports_codec, &trigger_start, &trigger_stop);
814 graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
815 graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
816 graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop);
817 graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop);
820 * convert bit_frame
821 * We need to flip clock_provider if it was CPU node,
822 * because it is Codec base.
824 daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
825 if (is_cpu_node)
826 daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);
828 dai_link->playback_only = playback_only;
829 dai_link->capture_only = capture_only;
831 dai_link->trigger_start = trigger_start;
832 dai_link->trigger_stop = trigger_stop;
834 dai_link->dai_fmt = daifmt | daiclk;
835 dai_link->init = simple_util_dai_init;
836 dai_link->ops = &graph_ops;
837 if (priv->ops)
838 dai_link->ops = priv->ops;
840 of_node_put(ports_cpu);
841 of_node_put(ports_codec);
842 of_node_put(port_cpu);
843 of_node_put(port_codec);
844 of_node_put(ep_cpu);
845 of_node_put(ep_codec);
848 int audio_graph2_link_normal(struct simple_util_priv *priv,
849 struct device_node *lnk,
850 struct link_info *li)
852 struct device_node *cpu_port = lnk;
853 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
854 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
855 int ret;
858 * call Codec first.
859 * see
860 * __graph_parse_node() :: DAI Naming
862 ret = graph_parse_node(priv, GRAPH_NORMAL, codec_port, li, 0);
863 if (ret < 0)
864 goto err;
867 * call CPU, and set DAI Name
869 ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_port, li, 1);
870 if (ret < 0)
871 goto err;
873 graph_link_init(priv, lnk, cpu_port, codec_port, li, 1);
874 err:
875 of_node_put(codec_port);
876 of_node_put(cpu_ep);
878 return ret;
880 EXPORT_SYMBOL_GPL(audio_graph2_link_normal);
882 int audio_graph2_link_dpcm(struct simple_util_priv *priv,
883 struct device_node *lnk,
884 struct link_info *li)
886 struct device_node *ep = port_to_endpoint(lnk);
887 struct device_node *rep = of_graph_get_remote_endpoint(ep);
888 struct device_node *cpu_port = NULL;
889 struct device_node *codec_port = NULL;
890 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
891 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
892 int is_cpu = graph_util_is_ports0(lnk);
893 int ret;
895 if (is_cpu) {
896 cpu_port = of_graph_get_remote_port(ep); /* rport */
899 * dpcm {
900 * // Front-End
901 * ports@0 {
902 * => lnk: port@0 { ep: { ... = rep }; };
903 * ...
904 * };
905 * // Back-End
906 * ports@0 {
907 * ...
908 * };
909 * };
911 * CPU {
912 * rports: ports {
913 * rport: port@0 { rep: { ... = ep } };
918 * setup CPU here, Codec is already set as dummy.
919 * see
920 * simple_util_init_priv()
922 dai_link->dynamic = 1;
923 dai_link->dpcm_merged_format = 1;
925 ret = graph_parse_node(priv, GRAPH_DPCM, cpu_port, li, 1);
926 if (ret)
927 goto err;
929 } else {
930 codec_port = of_graph_get_remote_port(ep); /* rport */
933 * dpcm {
934 * // Front-End
935 * ports@0 {
936 * ...
937 * };
938 * // Back-End
939 * ports@0 {
940 * => lnk: port@0 { ep: { ... = rep; }; };
941 * ...
942 * };
943 * };
945 * Codec {
946 * rports: ports {
947 * rport: port@0 { rep: { ... = ep; }; };
952 * setup Codec here, CPU is already set as dummy.
953 * see
954 * simple_util_init_priv()
957 /* BE settings */
958 dai_link->no_pcm = 1;
959 dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup;
961 ret = graph_parse_node(priv, GRAPH_DPCM, codec_port, li, 0);
962 if (ret < 0)
963 goto err;
966 graph_parse_convert(ep, dai_props); /* at node of <dpcm> */
967 graph_parse_convert(rep, dai_props); /* at node of <CPU/Codec> */
969 graph_link_init(priv, lnk, cpu_port, codec_port, li, is_cpu);
970 err:
971 of_node_put(ep);
972 of_node_put(rep);
973 of_node_put(cpu_port);
974 of_node_put(codec_port);
976 return ret;
978 EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm);
980 int audio_graph2_link_c2c(struct simple_util_priv *priv,
981 struct device_node *lnk,
982 struct link_info *li)
984 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
985 struct device_node *port0, *port1, *ports;
986 struct device_node *codec0_port, *codec1_port;
987 struct device_node *ep0, *ep1;
988 u32 val = 0;
989 int ret = -EINVAL;
992 * codec2codec {
993 * ports {
994 * rate = <48000>;
995 * => lnk: port@0 { c2c0_ep: { ... = codec0_ep; }; };
996 * port@1 { c2c1_ep: { ... = codec1_ep; }; };
997 * };
998 * };
1000 * Codec {
1001 * ports {
1002 * port@0 { codec0_ep: ... }; };
1003 * port@1 { codec1_ep: ... }; };
1004 * };
1005 * };
1007 of_node_get(lnk);
1008 port0 = lnk;
1009 ports = port_to_ports(port0);
1010 port1 = of_get_next_child(ports, lnk);
1013 * Card2 can use original Codec2Codec settings if DT has.
1014 * It will use default settings if no settings on DT.
1015 * see
1016 * simple_util_init_for_codec2codec()
1018 * Add more settings here if needed
1020 of_property_read_u32(ports, "rate", &val);
1021 if (val) {
1022 struct device *dev = simple_priv_to_dev(priv);
1023 struct snd_soc_pcm_stream *c2c_conf;
1025 c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL);
1026 if (!c2c_conf)
1027 goto err1;
1029 c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */
1030 c2c_conf->rates = SNDRV_PCM_RATE_8000_384000;
1031 c2c_conf->rate_min =
1032 c2c_conf->rate_max = val;
1033 c2c_conf->channels_min =
1034 c2c_conf->channels_max = 2; /* update ME */
1036 dai_link->c2c_params = c2c_conf;
1037 dai_link->num_c2c_params = 1;
1040 ep0 = port_to_endpoint(port0);
1041 ep1 = port_to_endpoint(port1);
1043 codec0_port = of_graph_get_remote_port(ep0);
1044 codec1_port = of_graph_get_remote_port(ep1);
1047 * call Codec first.
1048 * see
1049 * __graph_parse_node() :: DAI Naming
1051 ret = graph_parse_node(priv, GRAPH_C2C, codec1_port, li, 0);
1052 if (ret < 0)
1053 goto err2;
1056 * call CPU, and set DAI Name
1058 ret = graph_parse_node(priv, GRAPH_C2C, codec0_port, li, 1);
1059 if (ret < 0)
1060 goto err2;
1062 graph_link_init(priv, lnk, codec0_port, codec1_port, li, 1);
1063 err2:
1064 of_node_put(ep0);
1065 of_node_put(ep1);
1066 of_node_put(codec0_port);
1067 of_node_put(codec1_port);
1068 err1:
1069 of_node_put(ports);
1070 of_node_put(port0);
1071 of_node_put(port1);
1073 return ret;
1075 EXPORT_SYMBOL_GPL(audio_graph2_link_c2c);
1077 static int graph_link(struct simple_util_priv *priv,
1078 struct graph2_custom_hooks *hooks,
1079 enum graph_type gtype,
1080 struct device_node *lnk,
1081 struct link_info *li)
1083 struct device *dev = simple_priv_to_dev(priv);
1084 GRAPH2_CUSTOM func = NULL;
1085 int ret = -EINVAL;
1087 switch (gtype) {
1088 case GRAPH_NORMAL:
1089 if (hooks && hooks->custom_normal)
1090 func = hooks->custom_normal;
1091 else
1092 func = audio_graph2_link_normal;
1093 break;
1094 case GRAPH_DPCM:
1095 if (hooks && hooks->custom_dpcm)
1096 func = hooks->custom_dpcm;
1097 else
1098 func = audio_graph2_link_dpcm;
1099 break;
1100 case GRAPH_C2C:
1101 if (hooks && hooks->custom_c2c)
1102 func = hooks->custom_c2c;
1103 else
1104 func = audio_graph2_link_c2c;
1105 break;
1106 default:
1107 break;
1110 if (!func) {
1111 dev_err(dev, "non supported gtype (%d)\n", gtype);
1112 goto err;
1115 ret = func(priv, lnk, li);
1116 if (ret < 0)
1117 goto err;
1119 li->link++;
1120 err:
1121 return ret;
1124 static int graph_counter(struct device_node *lnk)
1127 * Multi CPU / Codec
1129 * multi {
1130 * ports {
1131 * => lnk: port@0 { ... }; // to pair
1132 * port@1 { ... }; // Multi Element
1133 * port@2 { ... }; // Multi Element
1134 * ...
1135 * };
1136 * };
1138 * ignore first lnk part
1140 if (graph_lnk_is_multi(lnk)) {
1141 struct device_node *ports = port_to_ports(lnk);
1144 * CPU/Codec = N:M case has many endpoints.
1145 * We can't use of_graph_get_endpoint_count() here
1147 return of_get_child_count(ports) - 1;
1150 * Single CPU / Codec
1152 else
1153 return 1;
1156 static int graph_count_normal(struct simple_util_priv *priv,
1157 struct device_node *lnk,
1158 struct link_info *li)
1160 struct device_node *cpu_port = lnk;
1161 struct device_node *cpu_ep = port_to_endpoint(cpu_port);
1162 struct device_node *codec_port = of_graph_get_remote_port(cpu_ep);
1165 * CPU {
1166 * => lnk: port { endpoint { .. }; };
1167 * };
1170 * DON'T REMOVE platforms
1171 * see
1172 * simple-card.c :: simple_count_noml()
1174 li->num[li->link].cpus =
1175 li->num[li->link].platforms = graph_counter(cpu_port);
1177 li->num[li->link].codecs = graph_counter(codec_port);
1179 of_node_put(cpu_ep);
1180 of_node_put(codec_port);
1182 return 0;
1185 static int graph_count_dpcm(struct simple_util_priv *priv,
1186 struct device_node *lnk,
1187 struct link_info *li)
1189 struct device_node *ep = port_to_endpoint(lnk);
1190 struct device_node *rport = of_graph_get_remote_port(ep);
1193 * dpcm {
1194 * // Front-End
1195 * ports@0 {
1196 * => lnk: port@0 { endpoint { ... }; };
1197 * ...
1198 * };
1199 * // Back-End
1200 * ports@1 {
1201 * => lnk: port@0 { endpoint { ... }; };
1202 * ...
1203 * };
1204 * };
1207 if (graph_util_is_ports0(lnk)) {
1209 * DON'T REMOVE platforms
1210 * see
1211 * simple-card.c :: simple_count_noml()
1213 li->num[li->link].cpus = graph_counter(rport); /* FE */
1214 li->num[li->link].platforms = graph_counter(rport);
1215 } else {
1216 li->num[li->link].codecs = graph_counter(rport); /* BE */
1219 of_node_put(ep);
1220 of_node_put(rport);
1222 return 0;
1225 static int graph_count_c2c(struct simple_util_priv *priv,
1226 struct device_node *lnk,
1227 struct link_info *li)
1229 struct device_node *ports = port_to_ports(lnk);
1230 struct device_node *port0 = lnk;
1231 struct device_node *port1 = of_get_next_child(ports, of_node_get(lnk));
1232 struct device_node *ep0 = port_to_endpoint(port0);
1233 struct device_node *ep1 = port_to_endpoint(port1);
1234 struct device_node *codec0 = of_graph_get_remote_port(ep0);
1235 struct device_node *codec1 = of_graph_get_remote_port(ep1);
1238 * codec2codec {
1239 * ports {
1240 * => lnk: port@0 { endpoint { ... }; };
1241 * port@1 { endpoint { ... }; };
1242 * };
1243 * };
1246 * DON'T REMOVE platforms
1247 * see
1248 * simple-card.c :: simple_count_noml()
1250 li->num[li->link].cpus =
1251 li->num[li->link].platforms = graph_counter(codec0);
1253 li->num[li->link].codecs = graph_counter(codec1);
1255 of_node_put(ports);
1256 of_node_put(port1);
1257 of_node_put(ep0);
1258 of_node_put(ep1);
1259 of_node_put(codec0);
1260 of_node_put(codec1);
1262 return 0;
1265 static int graph_count(struct simple_util_priv *priv,
1266 struct graph2_custom_hooks *hooks,
1267 enum graph_type gtype,
1268 struct device_node *lnk,
1269 struct link_info *li)
1271 struct device *dev = simple_priv_to_dev(priv);
1272 GRAPH2_CUSTOM func = NULL;
1273 int ret = -EINVAL;
1275 if (li->link >= SNDRV_MAX_LINKS) {
1276 dev_err(dev, "too many links\n");
1277 return ret;
1280 switch (gtype) {
1281 case GRAPH_NORMAL:
1282 func = graph_count_normal;
1283 break;
1284 case GRAPH_DPCM:
1285 func = graph_count_dpcm;
1286 break;
1287 case GRAPH_C2C:
1288 func = graph_count_c2c;
1289 break;
1290 default:
1291 break;
1294 if (!func) {
1295 dev_err(dev, "non supported gtype (%d)\n", gtype);
1296 goto err;
1299 ret = func(priv, lnk, li);
1300 if (ret < 0)
1301 goto err;
1303 li->link++;
1304 err:
1305 return ret;
1308 static int graph_for_each_link(struct simple_util_priv *priv,
1309 struct graph2_custom_hooks *hooks,
1310 struct link_info *li,
1311 int (*func)(struct simple_util_priv *priv,
1312 struct graph2_custom_hooks *hooks,
1313 enum graph_type gtype,
1314 struct device_node *lnk,
1315 struct link_info *li))
1317 struct of_phandle_iterator it;
1318 struct device *dev = simple_priv_to_dev(priv);
1319 struct device_node *node = dev->of_node;
1320 struct device_node *lnk;
1321 enum graph_type gtype;
1322 int rc, ret;
1324 /* loop for all listed CPU port */
1325 of_for_each_phandle(&it, rc, node, "links", NULL, 0) {
1326 lnk = it.node;
1328 gtype = graph_get_type(priv, lnk);
1330 ret = func(priv, hooks, gtype, lnk, li);
1331 if (ret < 0)
1332 return ret;
1335 return 0;
1338 int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
1339 struct graph2_custom_hooks *hooks)
1341 struct snd_soc_card *card = simple_priv_to_card(priv);
1342 int ret;
1344 struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL);
1345 if (!li)
1346 return -ENOMEM;
1348 card->probe = graph_util_card_probe;
1349 card->owner = THIS_MODULE;
1350 card->dev = dev;
1352 if ((hooks) && (hooks)->hook_pre) {
1353 ret = (hooks)->hook_pre(priv);
1354 if (ret < 0)
1355 goto err;
1358 ret = graph_for_each_link(priv, hooks, li, graph_count);
1359 if (!li->link)
1360 ret = -EINVAL;
1361 if (ret < 0)
1362 goto err;
1364 ret = simple_util_init_priv(priv, li);
1365 if (ret < 0)
1366 goto err;
1368 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
1369 if (IS_ERR(priv->pa_gpio)) {
1370 ret = PTR_ERR(priv->pa_gpio);
1371 dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
1372 goto err;
1375 ret = simple_util_parse_widgets(card, NULL);
1376 if (ret < 0)
1377 goto err;
1379 ret = simple_util_parse_routing(card, NULL);
1380 if (ret < 0)
1381 goto err;
1383 memset(li, 0, sizeof(*li));
1384 ret = graph_for_each_link(priv, hooks, li, graph_link);
1385 if (ret < 0)
1386 goto err;
1388 ret = simple_util_parse_card_name(card, NULL);
1389 if (ret < 0)
1390 goto err;
1392 snd_soc_card_set_drvdata(card, priv);
1394 if ((hooks) && (hooks)->hook_post) {
1395 ret = (hooks)->hook_post(priv);
1396 if (ret < 0)
1397 goto err;
1400 simple_util_debug_info(priv);
1402 ret = snd_soc_of_parse_aux_devs(card, "aux-devs");
1403 if (ret < 0)
1404 goto err;
1406 ret = devm_snd_soc_register_card(dev, card);
1407 err:
1408 if (ret < 0)
1409 dev_err_probe(dev, ret, "parse error\n");
1411 return ret;
1413 EXPORT_SYMBOL_GPL(audio_graph2_parse_of);
1415 static int graph_probe(struct platform_device *pdev)
1417 struct simple_util_priv *priv;
1418 struct device *dev = &pdev->dev;
1420 /* Allocate the private data and the DAI link array */
1421 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1422 if (!priv)
1423 return -ENOMEM;
1425 return audio_graph2_parse_of(priv, dev, NULL);
1428 static const struct of_device_id graph_of_match[] = {
1429 { .compatible = "audio-graph-card2", },
1432 MODULE_DEVICE_TABLE(of, graph_of_match);
1434 static struct platform_driver graph_card = {
1435 .driver = {
1436 .name = "asoc-audio-graph-card2",
1437 .pm = &snd_soc_pm_ops,
1438 .of_match_table = graph_of_match,
1440 .probe = graph_probe,
1441 .remove = simple_util_remove,
1443 module_platform_driver(graph_card);
1445 MODULE_ALIAS("platform:asoc-audio-graph-card2");
1446 MODULE_LICENSE("GPL v2");
1447 MODULE_DESCRIPTION("ASoC Audio Graph Card2");
1448 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");