Added spinlock release in mr_alsa_audio_pcm_hw_params() and mr_alsa_audio_pcm_prepare() prior to call to set_sample_rate() This fixes issue #21
277 lines
11 KiB
Diff
277 lines
11 KiB
Diff
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,15 +885,19 @@ 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);
|
|
+ spin_unlock_irq(&chip->lock);
|
|
err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, runtime_dsd_rate);
|
|
+ spin_lock_irq(&chip->lock);
|
|
}
|
|
}
|
|
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);
|
|
+ spin_unlock_irq(&chip->lock);
|
|
err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, runtime->rate);
|
|
+ spin_lock_irq(&chip->lock);
|
|
//printk("### mr_alsa_audio_pcm_prepare: mr_alsa_audio_ops->set_sample_rate returned %d\n\n", err);
|
|
}
|
|
|
|
@@ -1825,14 +1526,18 @@ 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);
|
|
+ spin_unlock_irq(&chip->lock);
|
|
err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, dsd_rate);
|
|
+ spin_lock_irq(&chip->lock);
|
|
}
|
|
}
|
|
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);
|
|
+ spin_unlock_irq(&chip->lock);
|
|
err = chip->mr_alsa_audio_ops->set_sample_rate(chip->ravenna_peer, rate);
|
|
+ spin_lock_irq(&chip->lock);
|
|
}
|
|
|
|
if(chip->ravenna_peer)
|
|
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 = false;
|
|
+ }
|
|
+
|
|
+ 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:
|
|
@@ -1468,8 +1502,10 @@ void AudioFrameTIC(void* user)
|
|
frame_process_begin(&self->m_RTP_streams_manager);
|
|
if(self->m_pALSAChip && self->m_alsa_driver_frontend)
|
|
{
|
|
- self->m_alsa_driver_frontend->pcm_interrupt(self->m_pALSAChip, 1);
|
|
- self->m_alsa_driver_frontend->pcm_interrupt(self->m_pALSAChip, 0);
|
|
+ if (self->m_bIsRecordingIO)
|
|
+ self->m_alsa_driver_frontend->pcm_interrupt(self->m_pALSAChip, 1);
|
|
+ if (self->m_bIsPlaybackIO)
|
|
+ self->m_alsa_driver_frontend->pcm_interrupt(self->m_pALSAChip, 0);
|
|
}
|
|
frame_process_end(&self->m_RTP_streams_manager);
|
|
#endif
|
|
@@ -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
|