[alsa-devel] [RFT v3 3/3] ASoC: core: Add support for DAI multicodec
Benoit Cousson
bcousson at baylibre.com
Mon Jun 23 16:26:17 CEST 2014
Hi Lars,
I finally got some BW to address your second email :-)
On 06/05/2014 13:24, Lars-Peter Clausen wrote:
> On 04/24/2014 02:01 PM, Benoit Cousson wrote:
>> DAI link assumes a one to one mapping between CPU DAI and CODEC. In
>> some cases, the same CPU DAI can be connected to several codecs.
>> This is the case for example, if you connect two mono codecs to the
>> same I2S link in order to have a stereo card.
>> The current ASoC implementation does not allow such setup.
>>
>> Add support for DAI links composed of a single CPU DAI and multiple
>> CODECs. Sound cards have to pass the CODECs array in the corresponding
>> DAI link through a new 'snd_soc_dai_link_component' struct. Each CODEC in
>> this array is described in the same manner single CODEC DAIs are
>> (either DT/OF node or codec_name).
>>
>> Fix a trailing space in the header as well.
>>
>> Based on an original code done by Misael.
>>
>> Signed-off-by: Benoit Cousson <bcousson at baylibre.com>
>> Signed-off-by: Misael Lopez Cruz <misael.lopez at ti.com>
>> Signed-off-by: Fabien Parent <fparent at baylibre.com>
>
> Some thoughts on the parameter fixup.
>
>> ---
>> include/sound/soc-dai.h | 5 +
>> include/sound/soc.h | 13 ++
>> sound/soc/soc-compress.c | 83 +++++---
>> sound/soc/soc-core.c | 364 ++++++++++++++++++++++-----------
>> sound/soc/soc-dapm.c | 71 ++++---
>> sound/soc/soc-pcm.c | 512
>> ++++++++++++++++++++++++++++++++---------------
>> 6 files changed, 715 insertions(+), 333 deletions(-)
>>
>> diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
>> index fad7676..6985851 100644
>> --- a/include/sound/soc-dai.h
>> +++ b/include/sound/soc-dai.h
>> @@ -274,6 +274,11 @@ struct snd_soc_dai {
>> struct snd_soc_codec *codec;
>> struct snd_soc_component *component;
>>
>> + /* CODEC TDM slot masks and params (for fixup) */
>> + unsigned int tx_mask;
>> + unsigned int rx_mask;
>> + struct snd_pcm_hw_params params[2];
>
> snd_pcm_hw_params is rather large, given that for a lot of setups we
> don't need it it might be better to make this a pointer and only
> allocate the params struct when needed.
OK.
>
> [...]
>> @@ -3624,17 +3697,26 @@ static int
>> snd_soc_xlate_tdm_slot_mask(unsigned int slots,
>> 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)
>> {
>> + int ret = 0;
>> +
>> if (dai->driver && dai->driver->ops->xlate_tdm_slot_mask)
>> dai->driver->ops->xlate_tdm_slot_mask(slots,
>> &tx_mask, &rx_mask);
>> else
>> snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
>>
>> + if (dai->codec) {
>> + dai->tx_mask = tx_mask;
>> + dai->rx_mask = rx_mask;
>> + }
>
> I don't think it makes sense to artificially limit this to just CODECs.
> While we do not support multiple CPU DAIs (yet?) adding the check for
> CODECs just makes the code more complex, but doesn't gain us anything.
OK, makes sense.
>
>
> [...]
>> + for (i = 0; i < rtd->num_codecs; i++) {
>> + struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>> + struct snd_pcm_hw_params *codec_params;
>> +
>> + codec_params = &codec_dai->params[substream->stream];
>
> The fixed up params are only ever used in here. Do we really need to
> keep two copies per CODEC DAI around?
Well, we can indeed, create a local copy that will be used for the
fixup. Moreover, it will avoid allocating the data dynamically.
>> +
>> + /* copy params for each codec */
>> + memcpy(codec_params, params, sizeof(struct snd_pcm_hw_params));
>> +
>> + /* fixup params based on TDM slot masks */
>> + if (codec_dai->tx_mask)
>> + soc_pcm_codec_params_fixup(codec_params,
>> + codec_dai->tx_mask);
>> + if (codec_dai->rx_mask)
>> + soc_pcm_codec_params_fixup(codec_params,
>> + codec_dai->rx_mask);
>> +
>
> If we fix-up the number of channels to be always the number of slots
> should we also setup a constraint for userspace that the number of
> channels must match the number of channels specified in the CPU DAI
> mask? Or should we check how many of the channels in the CODEC mask are
> actually active and fix-up the the number of channels according to that?
That's a pretty good question.
I've tried to check the current users of the snd_soc_dai_set_tdm_slot to
understand how it is used in cpu/codec dais.
There are only ~10 users, and it seems that the definition of the mask
is dependent of the user. I don't know if we can really enforce anything
because of that :-(
>> + if (codec_dai->driver->ops &&
>> + codec_dai->driver->ops->hw_params) {
>> + ret = codec_dai->driver->ops->hw_params(substream,
>> + codec_params, codec_dai);
>> + if (ret < 0) {
>> + dev_err(codec_dai->dev,
>> + "ASoC: can't set %s hw params: %d\n",
>> + codec_dai->name, ret);
>> + goto codec_err;
>> + }
>> }
>
> I think it makes sense to factor this whole block out into a helper
> function. E.g. soc_dai_hw_params(struct snd_soc_dai* dai, struct
> hw_params *params);. This will make it possible to also use it in other
> places like the dapm_dai_link_event() function.
OK, good point.
Thanks,
Benoit
--
Benoît Cousson
BayLibre
Embedded Linux Technology Lab
www.baylibre.com
More information about the Alsa-devel
mailing list