Loading Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt→Documentation/devicetree/bindings/sound/simple-scu-card.txt +110 −0 Original line number Diff line number Diff line Renesas Sampling Rate Convert Sound Card: ASoC simple SCU Sound Card Renesas Sampling Rate Convert Sound Card specifies audio DAI connections of SoC <-> codec. Simple-Card specifies audio DAI connections of SoC <-> codec. Required properties: - compatible : "renesas,rsrc-card{,<board>}" Examples with boards are: - "renesas,rsrc-card" - "renesas,rsrc-card,lager" - "renesas,rsrc-card,koelsch" - compatible : "simple-scu-audio-card" "renesas,rsrc-card" Optional properties: - card_name : User specified audio sound card name, one string - simple-audio-card,name : User specified audio sound card name, one string property. - cpu : CPU sub-node - codec : CODEC sub-node - simple-audio-card,cpu : CPU sub-node - simple-audio-card,codec : CODEC sub-node Optional subnode properties: - format : CPU/CODEC common audio format. - simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" - frame-master : Indicates dai-link frame master. - simple-audio-card,frame-master : Indicates dai-link frame master. phandle to a cpu or codec subnode. - bitclock-master : Indicates dai-link bit clock master. - simple-audio-card,bitclock-master : Indicates dai-link bit clock master. phandle to a cpu or codec subnode. - bitclock-inversion : bool property. Add this if the - simple-audio-card,bitclock-inversion : bool property. Add this if the dai-link uses bit clock inversion. - frame-inversion : bool property. Add this if the - simple-audio-card,frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. - convert-rate : platform specified sampling rate convert - convert-channels : platform specified converted channel size (2 - 8 ch) - audio-prefix : see audio-routing - audio-routing : A list of the connections between audio components. - 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,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. use audio-prefix if some components is using same sink/sources naming. Loading @@ -54,22 +52,59 @@ Optional CPU/CODEC subnodes properties: clk_disable_unprepare() in dai shutdown(). Example Example 1. Sampling Rate Covert sound { compatible = "renesas,rsrc-card,lager"; compatible = "simple-scu-audio-card"; card-name = "rsnd-ak4643"; format = "left_j"; bitclock-master = <&sndcodec>; frame-master = <&sndcodec>; 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>; sndcpu: cpu { simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ simple-audio-card,prefix = "ak4642"; simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", "DAI0 Capture", "ak4642 Capture"; sndcpu: simple-audio-card,cpu { sound-dai = <&rcar_sound>; }; sndcodec: codec { sndcodec: simple-audio-card,codec { sound-dai = <&ak4643>; system-clock-frequency = <11289600>; }; }; Example 2. 2 CPU 1 Codec sound { compatible = "renesas,rsrc-card"; card-name = "rsnd-ak4643"; format = "left_j"; bitclock-master = <&dpcmcpu>; frame-master = <&dpcmcpu>; convert-rate = <48000>; /* see audio_clk_a */ audio-prefix = "ak4642"; audio-routing = "ak4642 Playback", "DAI0 Playback", "ak4642 Playback", "DAI1 Playback"; dpcmcpu: cpu@0 { sound-dai = <&rcar_sound 0>; }; cpu@1 { sound-dai = <&rcar_sound 1>; }; codec { sound-dai = <&ak4643>; clocks = <&audio_clock>; }; }; include/sound/simple_card_utils.h +34 −0 Original line number Diff line number Diff line Loading @@ -33,4 +33,38 @@ int asoc_simple_card_set_dailink_name(struct device *dev, int asoc_simple_card_parse_card_name(struct snd_soc_card *card, char *prefix); #define asoc_simple_card_parse_clk_cpu(node, dai_link, simple_dai) \ asoc_simple_card_parse_clk(node, dai_link->cpu_of_node, simple_dai) #define asoc_simple_card_parse_clk_codec(node, dai_link, simple_dai) \ asoc_simple_card_parse_clk(node, dai_link->codec_of_node, simple_dai) int asoc_simple_card_parse_clk(struct device_node *node, struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai); #define asoc_simple_card_parse_cpu(node, dai_link, \ list_name, cells_name, is_single_link) \ asoc_simple_card_parse_dai(node, &dai_link->cpu_of_node, \ &dai_link->cpu_dai_name, list_name, cells_name, is_single_link) #define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name) \ asoc_simple_card_parse_dai(node, &dai_link->codec_of_node, \ &dai_link->codec_dai_name, list_name, cells_name, NULL) #define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \ asoc_simple_card_parse_dai(node, &dai_link->platform_of_node, \ NULL, list_name, cells_name, NULL) int asoc_simple_card_parse_dai(struct device_node *node, struct device_node **endpoint_np, const char **dai_name, const char *list_name, const char *cells_name, int *is_single_links); int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai); int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link); void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, int is_single_links); int asoc_simple_card_clean_reference(struct snd_soc_card *card); #endif /* __SIMPLE_CARD_CORE_H */ sound/soc/generic/Kconfig +8 −0 Original line number Diff line number Diff line Loading @@ -6,3 +6,11 @@ config SND_SIMPLE_CARD select SND_SIMPLE_CARD_UTILS help This option enables generic simple sound card support config SND_SIMPLE_SCU_CARD tristate "ASoC Simple SCU sound card support" depends on OF select SND_SIMPLE_CARD_UTILS help This option enables generic simple SCU sound card support. It supports DPCM of multi CPU single Codec system. sound/soc/generic/Makefile +2 −0 Original line number Diff line number Diff line snd-soc-simple-card-utils-objs := simple-card-utils.o snd-soc-simple-card-objs := simple-card.o snd-soc-simple-scu-card-objs := simple-scu-card.o obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o sound/soc/generic/simple-card-utils.c +141 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/clk.h> #include <linux/module.h> #include <linux/of.h> #include <sound/simple_card_utils.h> Loading Loading @@ -97,6 +98,146 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); int asoc_simple_card_parse_clk(struct device_node *node, struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai) { struct clk *clk; u32 val; /* * Parse dai->sysclk come from "clocks = <&xxx>" * (if system has common clock) * or "system-clock-frequency = <xxx>" * or device's module clock. */ clk = of_clk_get(node, 0); if (!IS_ERR(clk)) { simple_dai->sysclk = clk_get_rate(clk); simple_dai->clk = clk; } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { simple_dai->sysclk = val; } else { clk = of_clk_get(dai_of_node, 0); if (!IS_ERR(clk)) simple_dai->sysclk = clk_get_rate(clk); } return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); int asoc_simple_card_parse_dai(struct device_node *node, struct device_node **dai_of_node, const char **dai_name, const char *list_name, const char *cells_name, int *is_single_link) { struct of_phandle_args args; int ret; if (!node) return 0; /* * Get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() */ ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args); if (ret) return ret; /* Get dai->name */ if (dai_name) { ret = snd_soc_of_get_dai_name(node, dai_name); if (ret < 0) return ret; } *dai_of_node = args.np; if (is_single_link) *is_single_link = !args.args_count; return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai) { int ret; if (simple_dai->sysclk) { ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); return ret; } } if (simple_dai->slots) { ret = snd_soc_dai_set_tdm_slot(dai, simple_dai->tx_slot_mask, simple_dai->rx_slot_mask, simple_dai->slots, simple_dai->slot_width); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); return ret; } } return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) { if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; /* Assumes platform == cpu */ if (!dai_link->platform_of_node) dai_link->platform_of_node = dai_link->cpu_of_node; return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, int is_single_links) { /* * In soc_bind_dai_link() will check cpu name after * of_node matching if dai_link has cpu_dai_name. * but, it will never match if name was created by * fmt_single_name() remove cpu_dai_name if cpu_args * was 0. See: * fmt_single_name() * fmt_multiple_name() */ if (is_single_links) dai_link->cpu_dai_name = NULL; } EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu); int asoc_simple_card_clean_reference(struct snd_soc_card *card) { struct snd_soc_dai_link *dai_link; int num_links; for (num_links = 0, dai_link = card->dai_link; num_links < card->num_links; num_links++, dai_link++) { of_node_put(dai_link->cpu_of_node); of_node_put(dai_link->codec_of_node); } return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); /* Module information */ MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); Loading Loading
Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt→Documentation/devicetree/bindings/sound/simple-scu-card.txt +110 −0 Original line number Diff line number Diff line Renesas Sampling Rate Convert Sound Card: ASoC simple SCU Sound Card Renesas Sampling Rate Convert Sound Card specifies audio DAI connections of SoC <-> codec. Simple-Card specifies audio DAI connections of SoC <-> codec. Required properties: - compatible : "renesas,rsrc-card{,<board>}" Examples with boards are: - "renesas,rsrc-card" - "renesas,rsrc-card,lager" - "renesas,rsrc-card,koelsch" - compatible : "simple-scu-audio-card" "renesas,rsrc-card" Optional properties: - card_name : User specified audio sound card name, one string - simple-audio-card,name : User specified audio sound card name, one string property. - cpu : CPU sub-node - codec : CODEC sub-node - simple-audio-card,cpu : CPU sub-node - simple-audio-card,codec : CODEC sub-node Optional subnode properties: - format : CPU/CODEC common audio format. - simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" - frame-master : Indicates dai-link frame master. - simple-audio-card,frame-master : Indicates dai-link frame master. phandle to a cpu or codec subnode. - bitclock-master : Indicates dai-link bit clock master. - simple-audio-card,bitclock-master : Indicates dai-link bit clock master. phandle to a cpu or codec subnode. - bitclock-inversion : bool property. Add this if the - simple-audio-card,bitclock-inversion : bool property. Add this if the dai-link uses bit clock inversion. - frame-inversion : bool property. Add this if the - simple-audio-card,frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. - convert-rate : platform specified sampling rate convert - convert-channels : platform specified converted channel size (2 - 8 ch) - audio-prefix : see audio-routing - audio-routing : A list of the connections between audio components. - 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,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. use audio-prefix if some components is using same sink/sources naming. Loading @@ -54,22 +52,59 @@ Optional CPU/CODEC subnodes properties: clk_disable_unprepare() in dai shutdown(). Example Example 1. Sampling Rate Covert sound { compatible = "renesas,rsrc-card,lager"; compatible = "simple-scu-audio-card"; card-name = "rsnd-ak4643"; format = "left_j"; bitclock-master = <&sndcodec>; frame-master = <&sndcodec>; 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>; sndcpu: cpu { simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ simple-audio-card,prefix = "ak4642"; simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", "DAI0 Capture", "ak4642 Capture"; sndcpu: simple-audio-card,cpu { sound-dai = <&rcar_sound>; }; sndcodec: codec { sndcodec: simple-audio-card,codec { sound-dai = <&ak4643>; system-clock-frequency = <11289600>; }; }; Example 2. 2 CPU 1 Codec sound { compatible = "renesas,rsrc-card"; card-name = "rsnd-ak4643"; format = "left_j"; bitclock-master = <&dpcmcpu>; frame-master = <&dpcmcpu>; convert-rate = <48000>; /* see audio_clk_a */ audio-prefix = "ak4642"; audio-routing = "ak4642 Playback", "DAI0 Playback", "ak4642 Playback", "DAI1 Playback"; dpcmcpu: cpu@0 { sound-dai = <&rcar_sound 0>; }; cpu@1 { sound-dai = <&rcar_sound 1>; }; codec { sound-dai = <&ak4643>; clocks = <&audio_clock>; }; };
include/sound/simple_card_utils.h +34 −0 Original line number Diff line number Diff line Loading @@ -33,4 +33,38 @@ int asoc_simple_card_set_dailink_name(struct device *dev, int asoc_simple_card_parse_card_name(struct snd_soc_card *card, char *prefix); #define asoc_simple_card_parse_clk_cpu(node, dai_link, simple_dai) \ asoc_simple_card_parse_clk(node, dai_link->cpu_of_node, simple_dai) #define asoc_simple_card_parse_clk_codec(node, dai_link, simple_dai) \ asoc_simple_card_parse_clk(node, dai_link->codec_of_node, simple_dai) int asoc_simple_card_parse_clk(struct device_node *node, struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai); #define asoc_simple_card_parse_cpu(node, dai_link, \ list_name, cells_name, is_single_link) \ asoc_simple_card_parse_dai(node, &dai_link->cpu_of_node, \ &dai_link->cpu_dai_name, list_name, cells_name, is_single_link) #define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name) \ asoc_simple_card_parse_dai(node, &dai_link->codec_of_node, \ &dai_link->codec_dai_name, list_name, cells_name, NULL) #define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \ asoc_simple_card_parse_dai(node, &dai_link->platform_of_node, \ NULL, list_name, cells_name, NULL) int asoc_simple_card_parse_dai(struct device_node *node, struct device_node **endpoint_np, const char **dai_name, const char *list_name, const char *cells_name, int *is_single_links); int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai); int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link); void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, int is_single_links); int asoc_simple_card_clean_reference(struct snd_soc_card *card); #endif /* __SIMPLE_CARD_CORE_H */
sound/soc/generic/Kconfig +8 −0 Original line number Diff line number Diff line Loading @@ -6,3 +6,11 @@ config SND_SIMPLE_CARD select SND_SIMPLE_CARD_UTILS help This option enables generic simple sound card support config SND_SIMPLE_SCU_CARD tristate "ASoC Simple SCU sound card support" depends on OF select SND_SIMPLE_CARD_UTILS help This option enables generic simple SCU sound card support. It supports DPCM of multi CPU single Codec system.
sound/soc/generic/Makefile +2 −0 Original line number Diff line number Diff line snd-soc-simple-card-utils-objs := simple-card-utils.o snd-soc-simple-card-objs := simple-card.o snd-soc-simple-scu-card-objs := simple-scu-card.o obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o
sound/soc/generic/simple-card-utils.c +141 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/clk.h> #include <linux/module.h> #include <linux/of.h> #include <sound/simple_card_utils.h> Loading Loading @@ -97,6 +98,146 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); int asoc_simple_card_parse_clk(struct device_node *node, struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai) { struct clk *clk; u32 val; /* * Parse dai->sysclk come from "clocks = <&xxx>" * (if system has common clock) * or "system-clock-frequency = <xxx>" * or device's module clock. */ clk = of_clk_get(node, 0); if (!IS_ERR(clk)) { simple_dai->sysclk = clk_get_rate(clk); simple_dai->clk = clk; } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { simple_dai->sysclk = val; } else { clk = of_clk_get(dai_of_node, 0); if (!IS_ERR(clk)) simple_dai->sysclk = clk_get_rate(clk); } return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); int asoc_simple_card_parse_dai(struct device_node *node, struct device_node **dai_of_node, const char **dai_name, const char *list_name, const char *cells_name, int *is_single_link) { struct of_phandle_args args; int ret; if (!node) return 0; /* * Get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() */ ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args); if (ret) return ret; /* Get dai->name */ if (dai_name) { ret = snd_soc_of_get_dai_name(node, dai_name); if (ret < 0) return ret; } *dai_of_node = args.np; if (is_single_link) *is_single_link = !args.args_count; return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai) { int ret; if (simple_dai->sysclk) { ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); return ret; } } if (simple_dai->slots) { ret = snd_soc_dai_set_tdm_slot(dai, simple_dai->tx_slot_mask, simple_dai->rx_slot_mask, simple_dai->slots, simple_dai->slot_width); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); return ret; } } return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) { if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; /* Assumes platform == cpu */ if (!dai_link->platform_of_node) dai_link->platform_of_node = dai_link->cpu_of_node; return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, int is_single_links) { /* * In soc_bind_dai_link() will check cpu name after * of_node matching if dai_link has cpu_dai_name. * but, it will never match if name was created by * fmt_single_name() remove cpu_dai_name if cpu_args * was 0. See: * fmt_single_name() * fmt_multiple_name() */ if (is_single_links) dai_link->cpu_dai_name = NULL; } EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu); int asoc_simple_card_clean_reference(struct snd_soc_card *card) { struct snd_soc_dai_link *dai_link; int num_links; for (num_links = 0, dai_link = card->dai_link; num_links < card->num_links; num_links++, dai_link++) { of_node_put(dai_link->cpu_of_node); of_node_put(dai_link->codec_of_node); } return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); /* Module information */ MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); Loading