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