From d7a79bea8ca63c955bd436adbf571fe5eda0ad76 Mon Sep 17 00:00:00 2001 From: Long Wang Date: Tue, 7 Feb 2023 00:44:01 -0800 Subject: [PATCH] smart_amp: eliminat pops when switch device between speaker and headphone. There are two pops caused by SOF Firmware. Pop occurs when switch from headphone to speaker: When switch to headphone, audio playback data still remains in DSM internal processing buffer and not consumed by DMA. So when switch back to speaker, the DSM processing buffer is not clean, then pop noise occurs. We can clean and reset the point for DSM internal processing buffer by called this function 'smart_amp_init' in function 'smart_amp_prepare'. Pop occurs when switch from speaker to headphone: The feedback and feed-forward buffer processing should be independent. But the number of frames processed by DSM feedforward is corrupted by feedback buffer calculation. When capture pipeline exists, the number of frames for feedforward is always same as feedback. And the number of frames for feedback is zero at the first time when the capture pipeline setup. Then the number of frames processed by DSM feed forward is also zero though there are many frames in playback buffer. So the available frames will become larger. It is easy to exceed the limit size of DSM input. Then it will cause the buffer overflow and we could hear obvious pop noise from speaker. We fix it by calculating the number of frames for feedforward and feedback respectively. Signed-off-by: Long Wang --- src/audio/smart_amp/smart_amp.c | 35 +++++++++++++++------------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/audio/smart_amp/smart_amp.c b/src/audio/smart_amp/smart_amp.c index bc15b350a392..0a4903d8e609 100644 --- a/src/audio/smart_amp/smart_amp.c +++ b/src/audio/smart_amp/smart_amp.c @@ -598,19 +598,19 @@ static int smart_amp_copy(struct comp_dev *dev) avail_feedback_frames = audio_stream_get_avail_frames(&feedback_buf->stream); - avail_frames = MIN(avail_passthrough_frames, - avail_feedback_frames); + avail_feedback_frames = MIN(avail_passthrough_frames, + avail_feedback_frames); - feedback_bytes = avail_frames * + feedback_bytes = avail_feedback_frames * audio_stream_frame_bytes(&feedback_buf->stream); comp_dbg(dev, "smart_amp_copy(): processing %d feedback frames (avail_passthrough_frames: %d)", - avail_frames, avail_passthrough_frames); + avail_feedback_frames, avail_passthrough_frames); /* perform buffer writeback after source_buf process */ buffer_stream_invalidate(feedback_buf, feedback_bytes); sad->process(dev, &feedback_buf->stream, - &sink_buf->stream, avail_frames, + &sink_buf->stream, avail_feedback_frames, sad->config.feedback_ch_map, true); comp_update_buffer_consume(feedback_buf, feedback_bytes); @@ -621,7 +621,6 @@ static int smart_amp_copy(struct comp_dev *dev) /* bytes calculation */ source_bytes = avail_frames * audio_stream_frame_bytes(&source_buf->stream); - sink_bytes = avail_frames * audio_stream_frame_bytes(&sink_buf->stream); /* process data */ @@ -727,20 +726,18 @@ static int smart_amp_prepare(struct comp_dev *dev) goto error; } - if (sad->mod_handle->bitwidth != bitwidth) { - sad->mod_handle->bitwidth = bitwidth; - comp_info(dev, "[DSM] Re-initialized for %d bit processing", bitwidth); + sad->mod_handle->bitwidth = bitwidth; + comp_info(dev, "[DSM] Re-initialized for %d bit processing", bitwidth); - ret = smart_amp_init(sad->mod_handle, dev); - if (ret) { - comp_err(dev, "[DSM] Re-initialization error."); - goto error; - } - ret = maxim_dsm_restore_param(sad->mod_handle, dev); - if (ret) { - comp_err(dev, "[DSM] Restoration error."); - goto error; - } + ret = smart_amp_init(sad->mod_handle, dev); + if (ret) { + comp_err(dev, "[DSM] Re-initialization error."); + goto error; + } + ret = maxim_dsm_restore_param(sad->mod_handle, dev); + if (ret) { + comp_err(dev, "[DSM] Restoration error."); + goto error; } sad->process = get_smart_amp_process(dev);