Added patch to the ALSA RAVENNA/AES67 driver to handle independent playback and capture I/O startup and termination.

This fixes issue #11
This commit is contained in:
Andrea Bondavalli 2020-06-26 19:31:23 +02:00
parent 9062a82033
commit 3aeed93856
2 changed files with 253 additions and 0 deletions

View File

@ -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

View File

@ -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 ../..