Loading Documentation/devicetree/bindings/sound/audio-graph-card.txt 0 → 100644 +124 −0 Original line number Diff line number Diff line Audio Graph Card: Audio Graph Card specifies audio DAI connections of SoC <-> codec. It is based on common bindings for device graphs. see ${LINUX}/Documentation/devicetree/bindings/graph.txt Basically, Audio Graph Card property is same as Simple Card. see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt Below are same as Simple-Card. - label - dai-format - frame-master - bitclock-master - bitclock-inversion - frame-inversion - dai-tdm-slot-num - dai-tdm-slot-width - clocks / system-clock-frequency Required properties: - compatible : "audio-graph-card"; - dais : list of CPU DAI port{s} Example: Single DAI case sound_card { compatible = "audio-graph-card"; dais = <&cpu_port>; }; dai-controller { ... cpu_port: port { cpu_endpoint: endpoint { remote-endpoint = <&codec_endpoint>; dai-format = "left_j"; ... }; }; }; audio-codec { ... port { codec_endpoint: endpoint { remote-endpoint = <&cpu_endpoint>; }; }; }; Example: Multi DAI case sound-card { compatible = "audio-graph-card"; label = "sound-card"; dais = <&cpu_port0 &cpu_port1 &cpu_port2>; }; audio-codec@0 { ... port { codec0_endpoint: endpoint { remote-endpoint = <&cpu_endpoint0>; }; }; }; audio-codec@1 { ... port { codec1_endpoint: endpoint { remote-endpoint = <&cpu_endpoint1>; }; }; }; audio-codec@2 { ... port { codec2_endpoint: endpoint { remote-endpoint = <&cpu_endpoint2>; }; }; }; dai-controller { ... ports { cpu_port0: port@0 { cpu_endpoint0: endpoint { remote-endpoint = <&codec0_endpoint>; dai-format = "left_j"; ... }; }; cpu_port1: port@1 { cpu_endpoint1: endpoint { remote-endpoint = <&codec1_endpoint>; dai-format = "i2s"; ... }; }; cpu_port2: port@2 { cpu_endpoint2: endpoint { remote-endpoint = <&codec2_endpoint>; dai-format = "i2s"; ... }; }; }; }; Documentation/devicetree/bindings/sound/simple-scu-card.txt +24 −41 Original line number Diff line number Diff line ASoC simple SCU Sound Card ASoC Simple SCU Sound Card Simple-Card specifies audio DAI connections of SoC <-> codec. Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM". For example, you can use this driver if you want to exchange sampling rate convert, Mixing, etc... Required properties: - compatible : "simple-scu-audio-card" "renesas,rsrc-card" Optional properties: - simple-audio-card,name : User specified audio sound card name, one string property. - simple-audio-card,cpu : CPU sub-node - simple-audio-card,codec : CODEC sub-node - simple-audio-card,name : see simple-audio-card.txt - simple-audio-card,cpu : see simple-audio-card.txt - simple-audio-card,codec : see simple-audio-card.txt Optional subnode properties: - simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" - simple-audio-card,frame-master : Indicates dai-link frame master. phandle to a cpu or codec subnode. - simple-audio-card,bitclock-master : Indicates dai-link bit clock master. phandle to a cpu or codec subnode. - simple-audio-card,bitclock-inversion : bool property. Add this if the dai-link uses bit clock inversion. - simple-audio-card,frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. - simple-audio-card,format : see simple-audio-card.txt - simple-audio-card,frame-master : see simple-audio-card.txt - simple-audio-card,bitclock-master : see simple-audio-card.txt - simple-audio-card,bitclock-inversion : see simple-audio-card.txt - simple-audio-card,frame-inversion : see simple-audio-card.txt - simple-audio-card,convert-rate : platform specified sampling rate convert - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) - simple-audio-card,prefix : see audio-routing - simple-audio-card,prefix : see routing - simple-audio-card,routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. Valid names for sources. Loading @@ -38,19 +32,11 @@ Optional subnode properties: Required CPU/CODEC subnodes properties: - sound-dai : phandle and port of CPU/CODEC - sound-dai : see simple-audio-card.txt Optional CPU/CODEC subnodes properties: - clocks / system-clock-frequency : specify subnode's clock if needed. it can be specified via "clocks" if system has clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) If a clock is specified, it is enabled with clk_prepare_enable() in dai startup() and disabled with clk_disable_unprepare() in dai shutdown(). - clocks / system-clock-frequency : see simple-audio-card.txt Example 1. Sampling Rate Covert Loading @@ -59,11 +45,10 @@ sound { simple-audio-card,name = "rsnd-ak4643"; simple-audio-card,format = "left_j"; simple-audio-card,format = "left_j"; simple-audio-card,bitclock-master = <&sndcodec>; simple-audio-card,frame-master = <&sndcodec>; simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ simple-audio-card,convert-rate = <48000>; simple-audio-card,prefix = "ak4642"; simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", Loading @@ -79,20 +64,18 @@ sound { }; }; Example 2. 2 CPU 1 Codec Example 2. 2 CPU 1 Codec (Mixing) sound { compatible = "renesas,rsrc-card"; card-name = "rsnd-ak4643"; format = "left_j"; bitclock-master = <&dpcmcpu>; frame-master = <&dpcmcpu>; compatible = "simple-scu-audio-card"; convert-rate = <48000>; /* see audio_clk_a */ simple-audio-card,name = "rsnd-ak4643"; simple-audio-card,format = "left_j"; simple-audio-card,bitclock-master = <&dpcmcpu>; simple-audio-card,frame-master = <&dpcmcpu>; audio-prefix = "ak4642"; audio-routing = "ak4642 Playback", "DAI0 Playback", simple-audio-card,prefix = "ak4642"; simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", "ak4642 Playback", "DAI1 Playback"; dpcmcpu: cpu@0 { Loading drivers/of/base.c +52 −10 Original line number Diff line number Diff line Loading @@ -1601,6 +1601,7 @@ int of_phandle_iterator_init(struct of_phandle_iterator *it, return 0; } EXPORT_SYMBOL_GPL(of_phandle_iterator_init); int of_phandle_iterator_next(struct of_phandle_iterator *it) { Loading Loading @@ -1670,6 +1671,7 @@ int of_phandle_iterator_next(struct of_phandle_iterator *it) return -EINVAL; } EXPORT_SYMBOL_GPL(of_phandle_iterator_next); int of_phandle_iterator_args(struct of_phandle_iterator *it, uint32_t *args, Loading Loading @@ -2484,6 +2486,41 @@ struct device_node *of_graph_get_endpoint_by_regs( } EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); /** * of_graph_get_remote_endpoint() - get remote endpoint node * @node: pointer to a local endpoint device_node * * Return: Remote endpoint node associated with remote endpoint node linked * to @node. Use of_node_put() on it when done. */ struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) { /* Get remote endpoint node. */ return of_parse_phandle(node, "remote-endpoint", 0); } EXPORT_SYMBOL(of_graph_get_remote_endpoint); /** * of_graph_get_port_parent() - get port's parent node * @node: pointer to a local endpoint device_node * * Return: device node associated with endpoint node linked * to @node. Use of_node_put() on it when done. */ struct device_node *of_graph_get_port_parent(struct device_node *node) { unsigned int depth; /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && node; depth--) { node = of_get_next_parent(node); if (depth == 2 && of_node_cmp(node->name, "ports")) break; } return node; } EXPORT_SYMBOL(of_graph_get_port_parent); /** * of_graph_get_remote_port_parent() - get remote port's parent node * @node: pointer to a local endpoint device_node Loading @@ -2495,18 +2532,11 @@ struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { struct device_node *np; unsigned int depth; /* Get remote endpoint node. */ np = of_parse_phandle(node, "remote-endpoint", 0); np = of_graph_get_remote_endpoint(node); /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && np; depth--) { np = of_get_next_parent(np); if (depth == 2 && of_node_cmp(np->name, "ports")) break; } return np; return of_graph_get_port_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port_parent); Loading @@ -2522,13 +2552,25 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) struct device_node *np; /* Get remote endpoint node. */ np = of_parse_phandle(node, "remote-endpoint", 0); np = of_graph_get_remote_endpoint(node); if (!np) return NULL; return of_get_next_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port); int of_graph_get_endpoint_count(const struct device_node *np) { struct device_node *endpoint; int num = 0; for_each_endpoint_of_node(np, endpoint) num++; return num; } EXPORT_SYMBOL(of_graph_get_endpoint_count); /** * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint * @node: pointer to parent device_node containing graph port/endpoint Loading include/linux/of_graph.h +21 −0 Original line number Diff line number Diff line Loading @@ -43,11 +43,15 @@ struct of_endpoint { #ifdef CONFIG_OF int of_graph_parse_endpoint(const struct device_node *node, struct of_endpoint *endpoint); int of_graph_get_endpoint_count(const struct device_node *np); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg); struct device_node *of_graph_get_remote_endpoint( const struct device_node *node); struct device_node *of_graph_get_port_parent(struct device_node *node); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node); struct device_node *of_graph_get_remote_port(const struct device_node *node); Loading @@ -61,6 +65,11 @@ static inline int of_graph_parse_endpoint(const struct device_node *node, return -ENOSYS; } static inline int of_graph_get_endpoint_count(const struct device_node *np) { return 0; } static inline struct device_node *of_graph_get_port_by_id( struct device_node *node, u32 id) { Loading @@ -80,6 +89,18 @@ static inline struct device_node *of_graph_get_endpoint_by_regs( return NULL; } static inline struct device_node *of_graph_get_remote_endpoint( const struct device_node *node) { return NULL; } static inline struct device_node *of_graph_get_port_parent( struct device_node *node) { return NULL; } static inline struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { Loading include/sound/simple_card_utils.h +10 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,16 @@ int asoc_simple_card_parse_dai(struct device_node *node, const char *cells_name, int *is_single_links); #define asoc_simple_card_parse_graph_cpu(ep, dai_link) \ asoc_simple_card_parse_graph_dai(ep, &dai_link->cpu_of_node, \ &dai_link->cpu_dai_name) #define asoc_simple_card_parse_graph_codec(ep, dai_link) \ asoc_simple_card_parse_graph_dai(ep, &dai_link->codec_of_node, \ &dai_link->codec_dai_name) int asoc_simple_card_parse_graph_dai(struct device_node *ep, struct device_node **endpoint_np, const char **dai_name); int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai); Loading Loading
Documentation/devicetree/bindings/sound/audio-graph-card.txt 0 → 100644 +124 −0 Original line number Diff line number Diff line Audio Graph Card: Audio Graph Card specifies audio DAI connections of SoC <-> codec. It is based on common bindings for device graphs. see ${LINUX}/Documentation/devicetree/bindings/graph.txt Basically, Audio Graph Card property is same as Simple Card. see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt Below are same as Simple-Card. - label - dai-format - frame-master - bitclock-master - bitclock-inversion - frame-inversion - dai-tdm-slot-num - dai-tdm-slot-width - clocks / system-clock-frequency Required properties: - compatible : "audio-graph-card"; - dais : list of CPU DAI port{s} Example: Single DAI case sound_card { compatible = "audio-graph-card"; dais = <&cpu_port>; }; dai-controller { ... cpu_port: port { cpu_endpoint: endpoint { remote-endpoint = <&codec_endpoint>; dai-format = "left_j"; ... }; }; }; audio-codec { ... port { codec_endpoint: endpoint { remote-endpoint = <&cpu_endpoint>; }; }; }; Example: Multi DAI case sound-card { compatible = "audio-graph-card"; label = "sound-card"; dais = <&cpu_port0 &cpu_port1 &cpu_port2>; }; audio-codec@0 { ... port { codec0_endpoint: endpoint { remote-endpoint = <&cpu_endpoint0>; }; }; }; audio-codec@1 { ... port { codec1_endpoint: endpoint { remote-endpoint = <&cpu_endpoint1>; }; }; }; audio-codec@2 { ... port { codec2_endpoint: endpoint { remote-endpoint = <&cpu_endpoint2>; }; }; }; dai-controller { ... ports { cpu_port0: port@0 { cpu_endpoint0: endpoint { remote-endpoint = <&codec0_endpoint>; dai-format = "left_j"; ... }; }; cpu_port1: port@1 { cpu_endpoint1: endpoint { remote-endpoint = <&codec1_endpoint>; dai-format = "i2s"; ... }; }; cpu_port2: port@2 { cpu_endpoint2: endpoint { remote-endpoint = <&codec2_endpoint>; dai-format = "i2s"; ... }; }; }; };
Documentation/devicetree/bindings/sound/simple-scu-card.txt +24 −41 Original line number Diff line number Diff line ASoC simple SCU Sound Card ASoC Simple SCU Sound Card Simple-Card specifies audio DAI connections of SoC <-> codec. Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM". For example, you can use this driver if you want to exchange sampling rate convert, Mixing, etc... Required properties: - compatible : "simple-scu-audio-card" "renesas,rsrc-card" Optional properties: - simple-audio-card,name : User specified audio sound card name, one string property. - simple-audio-card,cpu : CPU sub-node - simple-audio-card,codec : CODEC sub-node - simple-audio-card,name : see simple-audio-card.txt - simple-audio-card,cpu : see simple-audio-card.txt - simple-audio-card,codec : see simple-audio-card.txt Optional subnode properties: - simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" - simple-audio-card,frame-master : Indicates dai-link frame master. phandle to a cpu or codec subnode. - simple-audio-card,bitclock-master : Indicates dai-link bit clock master. phandle to a cpu or codec subnode. - simple-audio-card,bitclock-inversion : bool property. Add this if the dai-link uses bit clock inversion. - simple-audio-card,frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. - simple-audio-card,format : see simple-audio-card.txt - simple-audio-card,frame-master : see simple-audio-card.txt - simple-audio-card,bitclock-master : see simple-audio-card.txt - simple-audio-card,bitclock-inversion : see simple-audio-card.txt - simple-audio-card,frame-inversion : see simple-audio-card.txt - simple-audio-card,convert-rate : platform specified sampling rate convert - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) - simple-audio-card,prefix : see audio-routing - simple-audio-card,prefix : see routing - simple-audio-card,routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. Valid names for sources. Loading @@ -38,19 +32,11 @@ Optional subnode properties: Required CPU/CODEC subnodes properties: - sound-dai : phandle and port of CPU/CODEC - sound-dai : see simple-audio-card.txt Optional CPU/CODEC subnodes properties: - clocks / system-clock-frequency : specify subnode's clock if needed. it can be specified via "clocks" if system has clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) If a clock is specified, it is enabled with clk_prepare_enable() in dai startup() and disabled with clk_disable_unprepare() in dai shutdown(). - clocks / system-clock-frequency : see simple-audio-card.txt Example 1. Sampling Rate Covert Loading @@ -59,11 +45,10 @@ sound { simple-audio-card,name = "rsnd-ak4643"; simple-audio-card,format = "left_j"; simple-audio-card,format = "left_j"; simple-audio-card,bitclock-master = <&sndcodec>; simple-audio-card,frame-master = <&sndcodec>; simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ simple-audio-card,convert-rate = <48000>; simple-audio-card,prefix = "ak4642"; simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", Loading @@ -79,20 +64,18 @@ sound { }; }; Example 2. 2 CPU 1 Codec Example 2. 2 CPU 1 Codec (Mixing) sound { compatible = "renesas,rsrc-card"; card-name = "rsnd-ak4643"; format = "left_j"; bitclock-master = <&dpcmcpu>; frame-master = <&dpcmcpu>; compatible = "simple-scu-audio-card"; convert-rate = <48000>; /* see audio_clk_a */ simple-audio-card,name = "rsnd-ak4643"; simple-audio-card,format = "left_j"; simple-audio-card,bitclock-master = <&dpcmcpu>; simple-audio-card,frame-master = <&dpcmcpu>; audio-prefix = "ak4642"; audio-routing = "ak4642 Playback", "DAI0 Playback", simple-audio-card,prefix = "ak4642"; simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", "ak4642 Playback", "DAI1 Playback"; dpcmcpu: cpu@0 { Loading
drivers/of/base.c +52 −10 Original line number Diff line number Diff line Loading @@ -1601,6 +1601,7 @@ int of_phandle_iterator_init(struct of_phandle_iterator *it, return 0; } EXPORT_SYMBOL_GPL(of_phandle_iterator_init); int of_phandle_iterator_next(struct of_phandle_iterator *it) { Loading Loading @@ -1670,6 +1671,7 @@ int of_phandle_iterator_next(struct of_phandle_iterator *it) return -EINVAL; } EXPORT_SYMBOL_GPL(of_phandle_iterator_next); int of_phandle_iterator_args(struct of_phandle_iterator *it, uint32_t *args, Loading Loading @@ -2484,6 +2486,41 @@ struct device_node *of_graph_get_endpoint_by_regs( } EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); /** * of_graph_get_remote_endpoint() - get remote endpoint node * @node: pointer to a local endpoint device_node * * Return: Remote endpoint node associated with remote endpoint node linked * to @node. Use of_node_put() on it when done. */ struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) { /* Get remote endpoint node. */ return of_parse_phandle(node, "remote-endpoint", 0); } EXPORT_SYMBOL(of_graph_get_remote_endpoint); /** * of_graph_get_port_parent() - get port's parent node * @node: pointer to a local endpoint device_node * * Return: device node associated with endpoint node linked * to @node. Use of_node_put() on it when done. */ struct device_node *of_graph_get_port_parent(struct device_node *node) { unsigned int depth; /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && node; depth--) { node = of_get_next_parent(node); if (depth == 2 && of_node_cmp(node->name, "ports")) break; } return node; } EXPORT_SYMBOL(of_graph_get_port_parent); /** * of_graph_get_remote_port_parent() - get remote port's parent node * @node: pointer to a local endpoint device_node Loading @@ -2495,18 +2532,11 @@ struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { struct device_node *np; unsigned int depth; /* Get remote endpoint node. */ np = of_parse_phandle(node, "remote-endpoint", 0); np = of_graph_get_remote_endpoint(node); /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && np; depth--) { np = of_get_next_parent(np); if (depth == 2 && of_node_cmp(np->name, "ports")) break; } return np; return of_graph_get_port_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port_parent); Loading @@ -2522,13 +2552,25 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) struct device_node *np; /* Get remote endpoint node. */ np = of_parse_phandle(node, "remote-endpoint", 0); np = of_graph_get_remote_endpoint(node); if (!np) return NULL; return of_get_next_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port); int of_graph_get_endpoint_count(const struct device_node *np) { struct device_node *endpoint; int num = 0; for_each_endpoint_of_node(np, endpoint) num++; return num; } EXPORT_SYMBOL(of_graph_get_endpoint_count); /** * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint * @node: pointer to parent device_node containing graph port/endpoint Loading
include/linux/of_graph.h +21 −0 Original line number Diff line number Diff line Loading @@ -43,11 +43,15 @@ struct of_endpoint { #ifdef CONFIG_OF int of_graph_parse_endpoint(const struct device_node *node, struct of_endpoint *endpoint); int of_graph_get_endpoint_count(const struct device_node *np); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg); struct device_node *of_graph_get_remote_endpoint( const struct device_node *node); struct device_node *of_graph_get_port_parent(struct device_node *node); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node); struct device_node *of_graph_get_remote_port(const struct device_node *node); Loading @@ -61,6 +65,11 @@ static inline int of_graph_parse_endpoint(const struct device_node *node, return -ENOSYS; } static inline int of_graph_get_endpoint_count(const struct device_node *np) { return 0; } static inline struct device_node *of_graph_get_port_by_id( struct device_node *node, u32 id) { Loading @@ -80,6 +89,18 @@ static inline struct device_node *of_graph_get_endpoint_by_regs( return NULL; } static inline struct device_node *of_graph_get_remote_endpoint( const struct device_node *node) { return NULL; } static inline struct device_node *of_graph_get_port_parent( struct device_node *node) { return NULL; } static inline struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { Loading
include/sound/simple_card_utils.h +10 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,16 @@ int asoc_simple_card_parse_dai(struct device_node *node, const char *cells_name, int *is_single_links); #define asoc_simple_card_parse_graph_cpu(ep, dai_link) \ asoc_simple_card_parse_graph_dai(ep, &dai_link->cpu_of_node, \ &dai_link->cpu_dai_name) #define asoc_simple_card_parse_graph_codec(ep, dai_link) \ asoc_simple_card_parse_graph_dai(ep, &dai_link->codec_of_node, \ &dai_link->codec_dai_name) int asoc_simple_card_parse_graph_dai(struct device_node *ep, struct device_node **endpoint_np, const char **dai_name); int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai); Loading