[alsa-devel] ALSA hw sample rate conversion support

Liam Girdwood lrg at slimlogic.co.uk
Wed Mar 30 21:09:53 CEST 2011


On Wed, 2011-03-30 at 21:02 +0530, Koul, Vinod wrote:
> Aisheng Dong wrote:
> > Hi ALL,
> > 
> > Does ALSA core support hw sample rate conversion now?
> > Our soc has a HW sample rate converter module inside,
> > I wonder if current ALSA core provide interface to support hw sample
> > rate conversion?
> > 
> Assuming the SRC is inside SoC and you are converting sampling rate of stream
> and sending at different rate, then I have a patch for you.
> Basically the soc side hw_params should call a new API which call
> codec_set_params() and sets the matching rate.
> 
> Something like this in soc-core
> 
> +int snd_soc_codec_set_params(struct snd_soc_codec *codec, unsigned int param)
> +{
> +       if (codec->driver->set_params)
> +               return codec->driver->set_params(codec, param);
> +       else
> +               return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(snd_soc_codec_set_params);
> 
> Mark,
> Would you okay with such a patch where DSP is doing some conversion and codec
> will get different params from what stream is set up? And we make sure 
> conversion is synced

Fwiw, I've already implemented a hw_params() fixup between the DSP and
CODEC drivers. This is in my dsp branch atm here :-

http://git.kernel.org/?p=linux/kernel/git/lrg/asoc-2.6.git;a=shortlog;h=refs/heads/topic/dsp-upstream

This allows us to rewrite channels, rates, formats etc. depending on the
use case and can be part of the machine driver e.g. (from sdp4430.c)

static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
			struct snd_pcm_hw_params *params)
{
	struct snd_interval *channels = hw_param_interval(params,
                                       SNDRV_PCM_HW_PARAM_CHANNELS);
	unsigned int be_id = rtd->dai_link->be_id;

	if (be_id == OMAP_ABE_DAI_MM_FM)
		channels->min = 2;
	else if (be_id == OMAP_ABE_DAI_BT_VX)
		channels->min = 1;
	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
	                            SNDRV_PCM_HW_PARAM_FIRST_MASK],
	                            SNDRV_PCM_FORMAT_S16_LE);
	return 0;
}

static int dmic_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
			struct snd_pcm_hw_params *params)
{
	struct snd_interval *rate = hw_param_interval(params,
			SNDRV_PCM_HW_PARAM_RATE);

	/* The ABE will covert the FE rate to 96k */
	rate->min = rate->max = 96000;

	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
	                            SNDRV_PCM_HW_PARAM_FIRST_MASK],
	                            SNDRV_PCM_FORMAT_S32_LE);
	return 0;
}

I intend to start upstreaming all this stuff when I return from holiday
on the 11th April (in time for 2.6.40).

Liam



More information about the Alsa-devel mailing list