[alsa-devel] [PATCH v3 0/3] Add TDM slot info OF parsing supports
Change in v3: - Add .of_xlate_tdm_slot_mask(). - Add snd_soc_of_xlate_tdm_slot_mask(). - Remove TDM slot masks OF parsing... - Split the TDM infomation into two properties.
Xiubo Li (3): ASoC: binding: add tdm-slot.txt ASoC: core: add TDM slot parsing from DT supports ASoC: simple-card: add slot information parsing supports
.../devicetree/bindings/sound/simple-card.txt | 5 ++ .../devicetree/bindings/sound/tdm-slot.txt | 20 ++++++++ include/sound/simple_card.h | 2 + include/sound/soc-dai.h | 2 + include/sound/soc.h | 3 ++ sound/soc/generic/simple-card.c | 18 +++++++ sound/soc/soc-core.c | 59 ++++++++++++++++++++++ 7 files changed, 109 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tdm-slot.txt
Signed-off-by: Xiubo Li Li.Xiubo@freescale.com Cc: Lars-Peter Clausen lars@metafoo.de Cc: Mark Brown broonie@linaro.org --- Documentation/devicetree/bindings/sound/tdm-slot.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tdm-slot.txt
diff --git a/Documentation/devicetree/bindings/sound/tdm-slot.txt b/Documentation/devicetree/bindings/sound/tdm-slot.txt new file mode 100644 index 0000000..6a2c842 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tdm-slot.txt @@ -0,0 +1,20 @@ +TDM slot: + +This specifies audio DAI's TDM slot. + +TDM slot properties: +dai-tdm-slot-num : Number of slots in use. +dai-tdm-slot-width : Width in bits for each slot. + +For instance: + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + +And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() +to specify a explicit mapping of the channels and the slots. If it's absent +the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the +tx and rx masks. + +For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit +for an active slot as default, and the default active bits are at the LSB of +the masks.
For some CPU/CODEC DAI devices the TDM slot infomation maybe needed. This patch adds the slot parsing from DT supports.
TDM slot properties: dai-tdm-slot-num : Number of slots in use. dai-tdm-slot-width : Width in bits for each slot.
For instance: dai-tdm-slot-num = <2>; dai-tdm-slot-width = <8>;
And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() to specify a explicit mapping of the channels and the slots. If it's absent the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the tx and rx masks.
For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit for an active slot as default, and the default active bits are at the LSB of the masks.
Signed-off-by: Xiubo Li Li.Xiubo@freescale.com Cc: Lars-Peter Clausen lars@metafoo.de Cc: Mark Brown broonie@linaro.org --- include/sound/soc-dai.h | 2 ++ include/sound/soc.h | 3 +++ sound/soc/soc-core.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+)
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c4..d86e0fc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -142,6 +142,8 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); + int (*of_xlate_tdm_slot_mask)(unsigned int slots, + unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); diff --git a/include/sound/soc.h b/include/sound/soc.h index 21d025e..759db05 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1190,6 +1190,9 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index abee5f4..bc3d090 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3663,6 +3663,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
/** + * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * Generates the TDM tx and rx slot default masks for DAI. + */ +static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (*tx_mask || *rx_mask) + return 0; + + if (!slots) + return -EINVAL; + + *tx_mask = (1 << slots) - 1; + *rx_mask = (1 << slots) - 1; + + return 0; +} + +/** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI * @tx_mask: bitmask representing active TX slots. @@ -3676,6 +3700,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { + if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) + dai->driver->ops->of_xlate_tdm_slot_mask(slots, + &tx_mask, &rx_mask); + else + snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (dai->driver && dai->driver->ops->set_tdm_slot) return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); @@ -4558,6 +4588,35 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);
+int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width) +{ + u32 val; + int ret; + + if (of_property_read_bool(np, "dai-tdm-slot-num")) { + ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); + if (ret) + return ret; + + if (slots) + *slots = val; + } + + if (of_property_read_bool(np, "dai-tdm-slot-width")) { + ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); + if (ret) + return ret; + + if (slot_width) + *slot_width = val; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) {
For some CPU/CODEC DAI devices the slot information maybe needed. This patch adds the slot information parsing for simple-card driver.
Signed-off-by: Xiubo Li Li.Xiubo@freescale.com Cc: Lars-Peter Clausen lars@metafoo.de Cc: Mark Brown broonie@linaro.org --- .../devicetree/bindings/sound/simple-card.txt | 5 +++++ include/sound/simple_card.h | 2 ++ sound/soc/generic/simple-card.c | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 0527358..b30c222 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -18,6 +18,8 @@ Optional properties: Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. +- dai-tdm-slot-num : Please refer to tdm-slot.txt. +- dai-tdm-slot-width : Please refer to tdm-slot.txt.
Required subnodes:
@@ -56,6 +58,9 @@ sound { "Headphone Jack", "HP_OUT", "External Speaker", "LINE_OUT";
+ dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + simple-audio-card,cpu { sound-dai = <&sh_fsi2 0>; }; diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index e1ac996..9b0ac77 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -18,6 +18,8 @@ struct asoc_simple_dai { const char *name; unsigned int fmt; unsigned int sysclk; + int slots; + int slot_width; };
struct asoc_simple_card_info { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 4fe8abc..bdd176d 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -9,11 +9,14 @@ * published by the Free Software Foundation. */ #include <linux/clk.h> +#include <linux/device.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/string.h> #include <sound/simple_card.h> +#include <sound/soc-dai.h> +#include <sound/soc.h>
struct simple_card_data { struct snd_soc_card snd_card; @@ -44,6 +47,16 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, } }
+ if (set->slots) { + ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, + set->slots, + set->slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); + goto err; + } + } + ret = 0;
err: @@ -94,6 +107,11 @@ asoc_simple_card_sub_parse_of(struct device_node *np, if (ret < 0) goto parse_error;
+ /* parse TDM slot */ + ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); + if (ret) + goto parse_error; + /* * bitclock-inversion, frame-inversion * bitclock-master, frame-master
On Fri, Feb 14, 2014 at 09:34:33AM +0800, Xiubo Li wrote:
Change in v3:
- Add .of_xlate_tdm_slot_mask().
- Add snd_soc_of_xlate_tdm_slot_mask().
- Remove TDM slot masks OF parsing...
- Split the TDM infomation into two properties.
Applied all, thanks - this is a really nice, clear binding though I think we will need to extend it in future to support specifying which slots are in use by a given device.
participants (2)
-
Mark Brown
-
Xiubo Li