[alsa-devel] ALSA hw sample rate conversion support
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?
Thanks
Regards Aisheng
Aisheng Dong wrote:
Does ALSA core support hw sample rate conversion now?
Yes; this has always been supported for chips like Emu10k1.
I wonder if current ALSA core provide interface to support hw sample rate conversion?
In your driver, set the ..._CONTINUOUS flag in the rates field (see the section "Hardware Description" in the doc), and in the hw_params callback, program the SRC according to the selected rate.
Regards, Clemens
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
~Vinod
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...
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(¶ms->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(¶ms->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
Change subject
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(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S32_LE); return 0; }
Liam,
For sample rate conversion case, supplying back-end hw_params_fixup function would work. However, I am looking for run-time configuration of back-end channel mode. For scenario of multi-channel microphone input, I need to have a mean to specify channel mode of back-end depending on algorithm running on DSP while front-end channel mode is mono. Is there a hook in the framework to do that?
Thanks Patrick
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
On Thu, 2011-03-31 at 10:45 -0700, Patrick Lai wrote:
Change subject
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(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S32_LE); return 0; }
Liam,
For sample rate conversion case, supplying back-end hw_params_fixup function would work. However, I am looking for run-time configuration of back-end channel mode. For scenario of multi-channel microphone input, I need to have a mean to specify channel mode of back-end depending on algorithm running on DSP while front-end channel mode is mono. Is there a hook in the framework to do that?
Not atm, but it does sound like we need to add such a hook.
I'll add this to the conference agenda.
Thanks
Liam
participants (5)
-
Aisheng Dong
-
Clemens Ladisch
-
Koul, Vinod
-
Liam Girdwood
-
Patrick Lai