1 // SPDX-License-Identifier: GPL-2.0
3 // ASoC Audio Graph Card2 support
5 // Copyright (C) 2020 Renesas Electronics Corp.
6 // Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
8 // based on ${LINUX}/sound/soc/generic/audio-graph-card.c
10 #include <linux/device.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/module.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 /************************************
21 ************************************
36 You can set daifmt at ports/port/endpoint.
37 It uses *latest* format, and *share* master settings.
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.
47 "format" property is no longer needed on DT if both CPU/Codec drivers are
48 supporting snd_soc_dai_ops :: .auto_selectable_formats.
50 snd_soc_runtime_get_dai_fmt()
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 ************************************
61 ************************************
66 compatible = "audio-graph-card2";
74 cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
78 port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
81 ************************************
83 ************************************
85 It has link connection part (= X,x) and list part (= A,B,a,b).
86 "links" is connection part of CPU side (= @).
89 CPU1 --|A X| <-@----> |x a|-- Codec1
90 CPU2 --|B | | b|-- Codec2
94 compatible = "audio-graph-card2";
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
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
116 port@0 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; };
117 port@1 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; };
123 port@0 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; };
124 port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; };
128 ************************************
130 ************************************
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
143 compatible = "audio-graph-card2";
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, ...,
157 fe0: port@0 { fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; };
158 fe1: port@1 { fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; };
163 be0: port@0 { be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; };
164 be1: port@1 { be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; };
174 port@0 { pcm0_ep: endpoint { remote-endpoint = <&fe0_ep>; }; };
175 port@1 { pcm1_ep: endpoint { remote-endpoint = <&fe1_ep>; }; };
182 port@0 { dai0_ep: endpoint { remote-endpoint = <&be0_ep>; }; };
183 port@1 { dai1_ep: endpoint { remote-endpoint = <&be1_ep>; }; };
188 ************************************
190 ************************************
198 compatible = "audio-graph-card2";
200 routing = "OUT" ,"DAI1 Playback",
201 "DAI0 Capture", "IN";
208 c2c: port@0 { c2cf_ep: endpoint { remote-endpoint = <&codec0_ep>; }; };
209 port@1 { c2cb_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
218 codec0_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; };
219 port@1 { codec1_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; };
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")) {
251 static enum graph_type
__graph_get_type(struct device_node
*lnk
)
253 struct device_node
*np
, *parent_np
;
259 * => lnk: port@0 { ... };
264 np
= of_get_parent(lnk
);
265 if (of_node_name_eq(np
, "ports")) {
266 parent_np
= of_get_parent(np
);
271 if (of_node_name_eq(np
, GRAPH_NODENAME_MULTI
)) {
276 if (of_node_name_eq(np
, GRAPH_NODENAME_DPCM
)) {
281 if (of_node_name_eq(np
, GRAPH_NODENAME_C2C
)) {
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
)
305 struct device
*dev
= simple_priv_to_dev(priv
);
306 const char *str
= "Normal";
310 if (graph_util_is_ports0(lnk
))
311 str
= "DPCM Front-End";
313 str
= "DPCM Back-End";
322 dev_dbg(dev
, "%pOF (%s)", lnk
, str
);
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
;
342 * => lnk: port@0 { ... }; // to pair
343 * port@1 { ep { ... = rep0 } }; // Multi Element
344 * port@2 { ep { ... = rep1 } }; // Multi Element
355 *port
= of_get_next_child(ports
, *port
);
358 } while (!of_node_name_eq(*port
, "port"));
361 ep
= port_to_endpoint(*port
);
362 rep
= of_graph_get_remote_endpoint(ep
);
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
);
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
,
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;
406 dlc
= snd_soc_link_to_cpu(dai_link
, idx
);
407 dai
= simple_props_to_dai_cpu(dai_props
, idx
);
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
);
417 ret
= simple_util_parse_tdm(ep
, dai
);
421 ret
= simple_util_parse_tdm_width_map(dev
, ep
, dai
);
425 ret
= simple_util_parse_clk(dev
, ep
, dai
, dlc
);
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";
445 /* run is_cpu only. see audio_graph2_link_normal() */
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
);
453 simple_util_set_dailink_name(dev
, dai_link
, "fe.%pOFP.%s%s",
454 cpus
->of_node
, cpus
->dai_name
, cpu_multi
);
456 simple_util_set_dailink_name(dev
, dai_link
, "be.%pOFP.%s%s",
457 codecs
->of_node
, codecs
->dai_name
, codec_multi
);
460 /* run is_cpu only. see audio_graph2_link_c2c() */
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
);
472 * Check "prefix" from top node
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");
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
);
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
)
505 * | X|<-@------->|x |
507 * cpu0 <--|A 1|<--------->|4 a|-> codec0
508 * cpu1 <--|B 2|<-----+--->|5 b|-> codec1
509 * cpu2 <--|C 3|<----/ +---+
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
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
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
);
543 if (cpu_idx
> dai_link
->num_cpus
)
547 struct device_node
*mcodec_ep_n
;
548 struct device_node
*mcodec_port_i
;
549 struct device_node
*mcodec_port
;
552 if (*nm_idx
> nm_max
)
555 mcpu_ep_n
= of_get_next_child(mcpu_port
, mcpu_ep_n
);
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
))
568 mcodec_port_i
= of_get_next_child(mcodec_ports
, NULL
);
570 if (codec_idx
> dai_link
->num_codecs
)
573 mcodec_port_i
= of_get_next_child(mcodec_ports
, mcodec_port_i
);
578 if (mcodec_port_i
== mcodec_port
)
584 dai_link
->ch_maps
[*nm_idx
].cpu
= cpu_idx
;
585 dai_link
->ch_maps
[*nm_idx
].codec
= codec_idx
;
589 of_node_put(mcodec_port_i
);
591 of_node_put(mcodec_port
);
592 of_node_put(mcpu_ep_n
);
593 of_node_put(mcodec_ep_n
);
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
);
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
;
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
)
632 for (int idx
= 0;; idx
++) {
636 * <port> port@0 { ... }; // to pair
637 * port@1 { mcpu1_ep { ... = cpu1_ep };}; // Multi Element
638 * port@2 { mcpu2_ep { ... = cpu2_ep };}; // Multi Element
644 * <ep> port@0 { cpu1_ep { ... = mcpu1_ep };};
648 ep
= graph_get_next_multi_ep(&port
);
652 ret
= __graph_parse_node(priv
, gtype
, ep
, li
, is_cpu
, idx
);
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
);
665 if (is_cpu
&& dai_link
->ch_maps
&& (nm_idx
!= nm_max
))
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);
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
);
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
)
705 * see also above "daifmt" explanation
725 * It can be judged it is provider
726 * if (A) or (B) or (C) has bitclock-master / frame-master flag.
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
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
);
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
,
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
);
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
);
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
);
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
);
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
;
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
);
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
);
860 * __graph_parse_node() :: DAI Naming
862 ret
= graph_parse_node(priv
, GRAPH_NORMAL
, codec_port
, li
, 0);
867 * call CPU, and set DAI Name
869 ret
= graph_parse_node(priv
, GRAPH_NORMAL
, cpu_port
, li
, 1);
873 graph_link_init(priv
, lnk
, cpu_port
, codec_port
, li
, 1);
875 of_node_put(codec_port
);
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
);
896 cpu_port
= of_graph_get_remote_port(ep
); /* rport */
902 * => lnk: port@0 { ep: { ... = rep }; };
913 * rport: port@0 { rep: { ... = ep } };
918 * setup CPU here, Codec is already set as dummy.
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);
930 codec_port
= of_graph_get_remote_port(ep
); /* rport */
940 * => lnk: port@0 { ep: { ... = rep; }; };
947 * rport: port@0 { rep: { ... = ep; }; };
952 * setup Codec here, CPU is already set as dummy.
954 * simple_util_init_priv()
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);
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
);
973 of_node_put(cpu_port
);
974 of_node_put(codec_port
);
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
;
995 * => lnk: port@0 { c2c0_ep: { ... = codec0_ep; }; };
996 * port@1 { c2c1_ep: { ... = codec1_ep; }; };
1002 * port@0 { codec0_ep: ... }; };
1003 * port@1 { codec1_ep: ... }; };
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.
1016 * simple_util_init_for_codec2codec()
1018 * Add more settings here if needed
1020 of_property_read_u32(ports
, "rate", &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
);
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
);
1049 * __graph_parse_node() :: DAI Naming
1051 ret
= graph_parse_node(priv
, GRAPH_C2C
, codec1_port
, li
, 0);
1056 * call CPU, and set DAI Name
1058 ret
= graph_parse_node(priv
, GRAPH_C2C
, codec0_port
, li
, 1);
1062 graph_link_init(priv
, lnk
, codec0_port
, codec1_port
, li
, 1);
1066 of_node_put(codec0_port
);
1067 of_node_put(codec1_port
);
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
;
1089 if (hooks
&& hooks
->custom_normal
)
1090 func
= hooks
->custom_normal
;
1092 func
= audio_graph2_link_normal
;
1095 if (hooks
&& hooks
->custom_dpcm
)
1096 func
= hooks
->custom_dpcm
;
1098 func
= audio_graph2_link_dpcm
;
1101 if (hooks
&& hooks
->custom_c2c
)
1102 func
= hooks
->custom_c2c
;
1104 func
= audio_graph2_link_c2c
;
1111 dev_err(dev
, "non supported gtype (%d)\n", gtype
);
1115 ret
= func(priv
, lnk
, li
);
1124 static int graph_counter(struct device_node
*lnk
)
1131 * => lnk: port@0 { ... }; // to pair
1132 * port@1 { ... }; // Multi Element
1133 * port@2 { ... }; // Multi Element
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
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
);
1166 * => lnk: port { endpoint { .. }; };
1170 * DON'T REMOVE platforms
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
);
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
);
1196 * => lnk: port@0 { endpoint { ... }; };
1201 * => lnk: port@0 { endpoint { ... }; };
1207 if (graph_util_is_ports0(lnk
)) {
1209 * DON'T REMOVE platforms
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
);
1216 li
->num
[li
->link
].codecs
= graph_counter(rport
); /* BE */
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
);
1240 * => lnk: port@0 { endpoint { ... }; };
1241 * port@1 { endpoint { ... }; };
1246 * DON'T REMOVE platforms
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
);
1259 of_node_put(codec0
);
1260 of_node_put(codec1
);
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
;
1275 if (li
->link
>= SNDRV_MAX_LINKS
) {
1276 dev_err(dev
, "too many links\n");
1282 func
= graph_count_normal
;
1285 func
= graph_count_dpcm
;
1288 func
= graph_count_c2c
;
1295 dev_err(dev
, "non supported gtype (%d)\n", gtype
);
1299 ret
= func(priv
, lnk
, li
);
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
;
1324 /* loop for all listed CPU port */
1325 of_for_each_phandle(&it
, rc
, node
, "links", NULL
, 0) {
1328 gtype
= graph_get_type(priv
, lnk
);
1330 ret
= func(priv
, hooks
, gtype
, lnk
, li
);
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
);
1344 struct link_info
*li
__free(kfree
) = kzalloc(sizeof(*li
), GFP_KERNEL
);
1348 card
->probe
= graph_util_card_probe
;
1349 card
->owner
= THIS_MODULE
;
1352 if ((hooks
) && (hooks
)->hook_pre
) {
1353 ret
= (hooks
)->hook_pre(priv
);
1358 ret
= graph_for_each_link(priv
, hooks
, li
, graph_count
);
1364 ret
= simple_util_init_priv(priv
, li
);
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
);
1375 ret
= simple_util_parse_widgets(card
, NULL
);
1379 ret
= simple_util_parse_routing(card
, NULL
);
1383 memset(li
, 0, sizeof(*li
));
1384 ret
= graph_for_each_link(priv
, hooks
, li
, graph_link
);
1388 ret
= simple_util_parse_card_name(card
, NULL
);
1392 snd_soc_card_set_drvdata(card
, priv
);
1394 if ((hooks
) && (hooks
)->hook_post
) {
1395 ret
= (hooks
)->hook_post(priv
);
1400 simple_util_debug_info(priv
);
1402 ret
= snd_soc_of_parse_aux_devs(card
, "aux-devs");
1406 ret
= devm_snd_soc_register_card(dev
, card
);
1409 dev_err_probe(dev
, ret
, "parse error\n");
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
);
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
= {
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>");