[alsa-devel] ALSA device with slave clock
Hi,
I've been fighting with some devices for the case where ALSA device is a clock slave. I'm also working on some patches/quirks to make some of these things work.
I have couple of questions in this domain I didn't find documented:
1) How is application supposed to use ALSA capture device when it doesn't know the sampling rate? For example with ASIO on Windows application sets sampling rate to 0 to indicate slave and then starts the device and retrieves the rate using ASIOGetSampleRate(). There are typically also reset request messages when the rate changes.
2) Some USB devices have indicator for lock status between set sampling rate and detected input rate. One such device I have is Motu 8D (UAC2 device): Simple mixer control 'Internal Clock Validity',0 Capabilities: pswitch pswitch-joined Playback channels: Mono Mono: Playback [on] As long as the status is valid, I can set sampling rate to the same, or something else. When the status becomes invalid due to rate mismatch, ALSA fails to set any of the sampling rates, even correct one and there's an error message in dmesg: "usb 3-14: clock source 1 is not valid, cannot use". So the clock source cannot be made valid again by changing sampling rate once it has become invalid, because it is currently invalid...
3) What is the correct way to deal with clock slave device from both driver and application perspective? So that application can retrieve the current sampling rate, instead of setting one... UAC2 has provisions for this, but this doesn't seem to be supported by the current driver. I have also some hardware where I would like to do the same with I2S - where clock generator is outside of the SoC and the SoC is just a slave (for example S/PDIF or AES/EBU input to a SoC where clock is generated from the input stream using PLL).
Best regards,
- Jussi
Hi,
On Jan 15 2018 05:37, Jussi Laako wrote:
- How is application supposed to use ALSA capture device when it
doesn't know the sampling rate? For example with ASIO on Windows application sets sampling rate to 0 to indicate slave and then starts the device and retrieves the rate using ASIOGetSampleRate(). There are typically also reset request messages when the rate changes.
When delegating the desicion to ALSA PCM core, applications should set 'struct snd_pcm_hw_params.intervals[SNDRV_PCM_HW_PARAM_RATE]' for 'any' state (see 'snd_interval_any()' in 'src/pcm/interval_inline.h' of alsa-lib), then call ioctl(2) with 'SNDRV_PCM_IOCTL_HW_PARAMS' command. In this case, ALSA PCM core select the _minimum_ value of available sampling rates supported by the driver. You can see the selection process in 'snd_pcm_hw_params_choose()' in 'sound/core/pcm_native.c' of kernel source.
When applying restrictions to the available sampling rates, ALSA PCM drivers are expected to describe relevant parameters on 'struct snd_pcm_hardware' properly when handling calls of open(2) to any ALSA PCM character devices.
``` (include/sound/pcm.h) struct snd_pcm_hardware { ... unsigned int rates; unsigned int rate_min; unsigned int rate_max; ... }; ```
Below is an example to limit available sampling rates just to 44100.
``` (In an implementation of 'struct snd_pcm_ops.open') struct snd_pcm_hardware info; ... info.rate_min = 44100; info.rate_max = 44100; info.rates = snd_pcm_rate_to_rate_bit(44100); substream->runtime.hw = info; ... ```
You can see actual example in snd-dice driver in 'sound/firewire/dice/dice-pcm.c' ('limit_channels_and_rates()'). For several reasons, this driver reads registers on target devices, then limit sampling rate for ALSA PCM substream to actual supported sampling rate. The state of device can be changed by the other applications, so the driver dynamically change the restriction.
- Some USB devices have indicator for lock status between set sampling
rate and detected input rate. One such device I have is Motu 8D (UAC2 device): Simple mixer control 'Internal Clock Validity',0 Capabilities: pswitch pswitch-joined Playback channels: Mono Mono: Playback [on] As long as the status is valid, I can set sampling rate to the same, or something else. When the status becomes invalid due to rate mismatch, ALSA fails to set any of the sampling rates, even correct one and there's an error message in dmesg: "usb 3-14: clock source 1 is not valid, cannot use". So the clock source cannot be made valid again by changing sampling rate once it has become invalid, because it is currently invalid...
I've never read related codes for your device. In my opinion, current 'snd-usb-audio' doesn't handle such restriction correctly. In theory, the driver should read state of the device, then applying the restriction to runtime of the PCM substream when handling open(2) from userspace applications, as I described.
- What is the correct way to deal with clock slave device from both
driver and application perspective? So that application can retrieve the current sampling rate, instead of setting one... UAC2 has provisions for this, but this doesn't seem to be supported by the current driver. I have also some hardware where I would like to do the same with I2S - where clock generator is outside of the SoC and the SoC is just a slave (for example S/PDIF or AES/EBU input to a SoC where clock is generated from the input stream using PLL).
It's better for your driver to describe 'struct snd_pcm_hardware' correctly, as I noted.
For the interaction between application/kernel-stuffs, this low-level sample program may be good information to you. https://github.com/takaswie/alsa-ioctl-test/blob/master/refine-pcm-params.c
Regards
Takashi Sakamoto
participants (2)
-
Jussi Laako
-
Takashi Sakamoto