| From 0063caf83ab43e26efc2c1b9e829b1a7a024e7c0 Mon Sep 17 00:00:00 2001 |
| From: Xiubo Li <Li.Xiubo@freescale.com> |
| Date: Fri, 14 Feb 2014 09:34:35 +0800 |
| Subject: ASoC: core: add TDM slot parsing from DT supports |
| |
| 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> |
| Signed-off-by: Mark Brown <broonie@linaro.org> |
| (cherry picked from commit 89c6785715592a6b082b3f9f28c27bb14b041c7d) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| 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 71f27c403194..d86e0fc41e80 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 465dc6e0674d..2a878d03c147 100644 |
| --- a/include/sound/soc.h |
| +++ b/include/sound/soc.h |
| @@ -1175,6 +1175,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 0540cb08e0ea..5b7d3ba87c7a 100644 |
| --- a/sound/soc/soc-core.c |
| +++ b/sound/soc/soc-core.c |
| @@ -3609,6 +3609,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. |
| @@ -3622,6 +3646,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); |
| @@ -4504,6 +4534,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) |
| { |
| -- |
| 2.1.2 |
| |