bcm2835-pcm: Numerous enhancements
bcm2835: extend allowed range of channels and samplerates Allow everything the videocore accepts. bcm2835: restrict channels*rate to 8*960000 This is required at least for SPDIF. If the bitrate goes above, videocore will either resample the audio or corrupt it due to underruns. Supposedly the hardware isn't designed to output higher rates, but it can still resample it down to supported rates. Some code is based on ac97_pcm.c. rpi: update vc_vchi_audioserv_defs.h Add audioserv 3 extensions. The changes were taken from the paste linked here: https://github.com/raspberrypi/linux/pull/1166#issuecomment-151917067 bcm2835: implement channel map API Report all layouts supported by the HDMI protocol to userspace. Make the videocore set the correct layout according to the userspace request. Some code taken from patch_hdmi.c. In particular, the HDMI channel layout table was copied without changes - with the idea in mind that hopefully it can be shared one day. Or at least updating it will be simpler. In my tests, everything appears to work, except when outputting FL FR RL RR. Then my receiver outputs RL on both the RL and RR speakers, while RR is never heard. bcm2835: access controls under the audio mutex I don't think the ALSA framework provides any kind of automatic synchronization within the control callbacks. We most likely need to ensure this manually, so add locking around all access to shared mutable data. In particular, bcm2835_audio_set_ctls() should probably always be called under our own audio lock. bcm2835: always use 2/4/8 channels for multichannel layouts Pad the unused channels with NA. This means userspace needs to write additional, silent padding channels, which is not ideal, but better than noise. Works around noise at the following channel counts: 3, 5, 6, 7 bcm2835: only allow stereo if analogue jack is selected Sending more than 2 channels to videocore while outputting to analogue mysteriously outputs heavy artifacts. So just paint it over with a hack: if analogue is explicitly selected as destination, do not reporting support for anything other than stereo. I'm not sure how to deal with the auto case (destination 0). There's probably way to retrieve this and even to listen to plug events, but I didn't find one yet, and it's probably not worth the trouble. Just don't use this setting, I guess. Unless you like noise. Changing the setting while an audio stream is active also doesn't work properly. We could probably interrupt running streams by returning ENODEV or using kernel hotplug stuff (maybe), but that also doesn't seem worth the trouble. bcm2835: interpolate audio delay It appears the GPU only sends us a message all 10ms to update the playback progress. Other than this, the playback position (what SNDRV_PCM_IOCTL_DELAY will return) is not updated at all. Userspace will see jitter up to 10ms in the audio position. Make this a bit nicer for userspace by interpolating the position using the CPU clock. I'm not sure if setting snd_pcm_runtime.delay is the right approach for this. Or if there is maybe an already existing mechanism for position interpolation in the ALSA core. I only set SNDRV_PCM_INFO_BATCH because this appears to remove at least one situation snd_pcm_runtime.delay is used, so I have to worry less in which place I have to update this field, or how it interacts with the rest of ALSA. In the future, it might be nice to use VC_AUDIO_MSG_TYPE_LATENCY. One problem is that it requires sending a videocore message, and waiting for a reply, which could make the implementation much harder due to locking and synchronization requirements.
Loading
Please sign in to comment