From 3aeed93856f74b5bb90f2ae18823a0b68a5f3bac Mon Sep 17 00:00:00 2001 From: Andrea Bondavalli Date: Fri, 26 Jun 2020 19:31:23 +0200 Subject: [PATCH] Added patch to the ALSA RAVENNA/AES67 driver to handle independent playback and capture I/O startup and termination. This fixes issue #11 --- ...alsa-lkm-independent-playback-capture.path | 252 ++++++++++++++++++ build.sh | 1 + 2 files changed, 253 insertions(+) create mode 100644 3rdparty/patches/ravenna-alsa-lkm-independent-playback-capture.path diff --git a/3rdparty/patches/ravenna-alsa-lkm-independent-playback-capture.path b/3rdparty/patches/ravenna-alsa-lkm-independent-playback-capture.path new file mode 100644 index 0000000..1561cce --- /dev/null +++ b/3rdparty/patches/ravenna-alsa-lkm-independent-playback-capture.path @@ -0,0 +1,252 @@ +diff --git a/driver/audio_driver.c b/driver/audio_driver.c +index 3d9debd..169348b 100644 +--- a/driver/audio_driver.c ++++ b/driver/audio_driver.c +@@ -824,13 +824,13 @@ static int mr_alsa_audio_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd + n = snd_pcm_playback_hw_avail(runtime); + n += runtime->delay; + } +- chip->mr_alsa_audio_ops->start_interrupts(chip->ravenna_peer); ++ chip->mr_alsa_audio_ops->start_interrupts(chip->ravenna_peer, alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK); + return 0; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: +- chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer); ++ chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer, alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK); + return 0; + default: + return -EINVAL; +@@ -870,13 +870,13 @@ static int mr_alsa_audio_pcm_prepare(struct snd_pcm_substream *substream) + { + if(runtime_dsd_mode != chip->current_dsd) + { +- chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer); ++ chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer, substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, runtime_dsd_rate); + } + } + else if(chip->current_rate != runtime->rate) + { +- chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer); ++ chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer, substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + //printk("\n### mr_alsa_audio_pcm_prepare: mr_alsa_audio_ops->set_sample_rate to %u\n", runtime->rate); + err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, runtime->rate); + //printk("### mr_alsa_audio_pcm_prepare: mr_alsa_audio_ops->set_sample_rate returned %d\n\n", err); +@@ -1825,13 +1825,13 @@ static int mr_alsa_audio_pcm_hw_params( struct snd_pcm_substream *substream, + { + if(dsd_mode != chip->current_dsd) + { +- chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer); ++ chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer, substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, dsd_rate); + } + } + else if(rate != chip->current_rate) + { +- chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer); ++ chip->mr_alsa_audio_ops->stop_interrupts(chip->ravenna_peer, substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, rate); + } + +diff --git a/driver/manager.c b/driver/manager.c +index 25b77dc..ec62624 100644 +--- a/driver/manager.c ++++ b/driver/manager.c +@@ -133,6 +133,8 @@ bool init(struct TManager* self, int* errorCode) + self->m_bIORunning = false; + self->m_pALSAChip = NULL; + self->m_alsa_driver_frontend = NULL; ++ self->m_bIsPlaybackIO = false; ++ self->m_bIsRecordingIO = false; + + memset(self->m_cInterfaceName, 0, MAX_INTERFACE_NAME); + +@@ -249,8 +251,10 @@ bool start(struct TManager* self) + bool stop(struct TManager* self) + { + MTAL_DP("entering CManager::stop..\n"); +- if(self->m_bIORunning) +- stopIO(self); ++ if(self->m_bIORunning) { ++ stopIO(self, false); ++ stopIO(self, true); ++ } + EnableEtherTube(&self->m_EthernetFilter, 0); + + StopAudioFrameTICTimer(&self->m_PTP); +@@ -261,14 +265,23 @@ bool stop(struct TManager* self) + } + + ////////////////////////////////////////////////////////////////////////////////// +-bool startIO(struct TManager* self) ++bool startIO(struct TManager* self, bool is_playback) + { + if(!self->m_bIsStarted) + return false; ++ + MTAL_DP("MergingRAVENNAAudioDriver::startIO\n"); + +- MuteInputBuffer(self); +- MuteOutputBuffer(self); ++ if (!is_playback) { ++ printk(KERN_DEBUG "starting capture I/O\n"); ++ MuteInputBuffer(self); ++ self->m_bIsRecordingIO = true; ++ } ++ else { ++ printk(KERN_DEBUG "starting playback I/O\n"); ++ MuteOutputBuffer(self); ++ self->m_bIsPlaybackIO = true; ++ } + + #if defined(MT_TONE_TEST) + self->m_tone_test_phase = 0; +@@ -283,12 +296,27 @@ bool startIO(struct TManager* self) + } + + ////////////////////////////////////////////////////////////////////////////////// +-bool stopIO(struct TManager* self) ++bool stopIO(struct TManager* self, bool is_playback) + { + MTAL_DP("MergingRAVENNAAudioDriver::stopIO\n"); +- self->m_bIORunning = false; +- MuteInputBuffer(self); +- MuteOutputBuffer(self); ++ ++ if (is_playback && !self->m_bIsPlaybackIO) ++ return true; ++ if (!is_playback && !self->m_bIsRecordingIO) ++ return true; ++ ++ if (!is_playback) { ++ printk(KERN_DEBUG "stopping capture I/O\n"); ++ MuteInputBuffer(self); ++ self->m_bIsRecordingIO = false; ++ } else { ++ printk(KERN_DEBUG "stopping playback I/O\n"); ++ MuteOutputBuffer(self); ++ self->m_bIsPlaybackIO = true; ++ } ++ ++ self->m_bIORunning = self->m_bIsRecordingIO || self->m_bIsPlaybackIO; ++ + return true; + } + +@@ -613,7 +641,8 @@ void OnNewMessage(struct TManager* self, struct MT_ALSA_msg* msg_rcv) + case MT_ALSA_Msg_StartIO: + { + MTAL_DP("CManager::OnNewMessage MT_ALSA_Msg_StartIO..\n"); +- if (!startIO(self)) ++ /* ++ if (!startIO(self) ) + { + MTAL_DP("CManager::OnNewMessage MT_ALSA_Msg_StartIO.. failed\n"); + msg_reply.errCode = -401; +@@ -623,11 +652,14 @@ void OnNewMessage(struct TManager* self, struct MT_ALSA_msg* msg_rcv) + MTAL_DP("CManager::OnNewMessage MT_ALSA_Msg_StartIO.. succeeded\n"); + msg_reply.errCode = 0; + } ++ */ ++ msg_reply.errCode = -401; + break; + } + case MT_ALSA_Msg_StopIO: + { + MTAL_DP("CManager::OnNewMessage MT_ALSA_Msg_StopIO..\n"); ++ /* + if (!stopIO(self)) + { + MTAL_DP("CManager::OnNewMessage MT_ALSA_Msg_StopIO.. failed\n"); +@@ -638,6 +670,8 @@ void OnNewMessage(struct TManager* self, struct MT_ALSA_msg* msg_rcv) + MTAL_DP("CManager::OnNewMessage MT_ALSA_Msg_StopIO.. succeeded\n"); + msg_reply.errCode = 0; + } ++ */ ++ msg_reply.errCode = -401; + break; + } + case MT_ALSA_Msg_SetSampleRate: +@@ -1680,20 +1714,25 @@ int get_interrupts_frame_size(void* user, uint32_t *framesize) + return -EINVAL; + } + +-int start_interrupts(void* user) ++int start_interrupts(void* user, bool is_playback) + { + struct TManager* self = (struct TManager*)user; +- if(startIO(self)) ++ ++ MTAL_DP("entering CManager::start_interrupts..\n"); ++ if(startIO(self, is_playback)) { + return 0; ++ } + return -1; + } + +-int stop_interrupts(void* user) ++int stop_interrupts(void* user, bool is_playback) + { + struct TManager* self = (struct TManager*)user; ++ + MTAL_DP("entering CManager::stop_interrupts..\n"); +- if(stopIO(self)) ++ if (stopIO(self, is_playback)) { + return 0; ++ } + return -1; + } + +diff --git a/driver/manager.h b/driver/manager.h +index a5b2fc2..3306bc9 100644 +--- a/driver/manager.h ++++ b/driver/manager.h +@@ -86,6 +86,9 @@ struct TManager + int32_t m_nPlayoutDelay; + int32_t m_nCaptureDelay; + ++ bool m_bIsPlaybackIO; ++ bool m_bIsRecordingIO; ++ + volatile bool m_bIsStarted; + volatile bool m_bIORunning; + +@@ -144,8 +147,8 @@ void destroy(struct TManager* self); + bool start(struct TManager* self); + bool stop(struct TManager* self); + +-bool startIO(struct TManager* self); +-bool stopIO(struct TManager* self); ++bool startIO(struct TManager* self, bool is_playback); ++bool stopIO(struct TManager* self, bool is_playback); + + bool SetInterfaceName(struct TManager* self, const char* cInterfaceName); + bool SetSamplingRate(struct TManager* self, uint32_t SamplingRate); +@@ -242,8 +245,8 @@ int get_nb_inputs(void* user, uint32_t *nb_Channels); + int get_nb_outputs(void* user, uint32_t *nb_Channels); + int get_playout_delay(void* user, snd_pcm_sframes_t *delay_in_sample); + int get_capture_delay(void* user, snd_pcm_sframes_t *delay_in_sample); +-int start_interrupts(void* user); +-int stop_interrupts(void* user); ++int start_interrupts(void* user, bool is_playback); ++int stop_interrupts(void* user, bool is_playback); + int notify_master_volume_change(void* user, int direction, int32_t value); + int notify_master_switch_change(void* user, int direction, int32_t value); + int get_master_volume_value(void* user, int direction, int32_t* value); +diff --git a/driver/audio_driver.h b/driver/audio_driver.h +index 930e429..3f2c76d 100644 +--- a/driver/audio_driver.h ++++ b/driver/audio_driver.h +@@ -74,8 +74,8 @@ struct alsa_ops + int (*get_nb_outputs)(void* ravenna_peer, uint32_t *nb_channels); + int (*get_playout_delay)(void* ravenna_peer, snd_pcm_sframes_t *delay_in_sample); + int (*get_capture_delay)(void* ravenna_peer, snd_pcm_sframes_t *delay_in_sample); +- int (*start_interrupts)(void* ravenna_peer); /// starts IO +- int (*stop_interrupts)(void* ravenna_peer); /// stops IO ++ int (*start_interrupts)(void* ravenna_peer, bool is_playback); /// starts IO ++ int (*stop_interrupts)(void* ravenna_peer, bool is_playback); /// stops IO + + int (*notify_master_volume_change)(void* ravenna_peer, int direction, int32_t value); /// direction: 0 for playback, 1 for capture. value: from -99 to 0 + int (*notify_master_switch_change)(void* ravenna_peer, int direction, int32_t value); /// direction: 0 for playback, 1 for capture. value: 0 for mute, 1 for enable diff --git a/build.sh b/build.sh index 9ce5491..12a4165 100755 --- a/build.sh +++ b/build.sh @@ -20,6 +20,7 @@ if [ ! -d ravenna-alsa-lkm.git ]; then git apply ../../patches/ravenna-alsa-lkm-arm-32bit.patch git apply ../../patches/ravenna-alsa-lkm-add-codec-am824.patch git apply ../../patches/ravenna-alsa-lkm-disable-ptp-checksum.patch + git apply ../../patches/ravenna-alsa-lkm-independent-playback-capture.path echo "Building ravenna-alsa-lkm kernel module ..." make cd ../..