From: Vanitha Channaiah vanitha.channaiah@in.bosch.com
For buffer size equal to two period size, the start position of slave_hw_ptr is rounded down in order to avoid xruns
For e.g.: Considering below parameters and its values: Period size = 96 (0x60) Buffer size = 192 (0xC0) Timer ticks = 1 avail_min = 0x60 slave_hw_ptr = unaligned value during dmix_start()
Issue: - Initial, app_ptr = hw_ptr = 0 - Application fills buffer size of data. so app_ptr = 0xC0, hw_ptr = 0 - During dmix_start(), current slave_hw_ptr is not rounded down. current slave_hw_ptr would be 0x66 - slave_hw_ptr is keep on updating at the hardware 0x67, 0x68, 0x69 - The diff calculation between old_slave_hw_ptr(0x66) and new_slave_hw_ptr(0x69) results in avail = 0x6 - After 1 snd_pcm_period_elapsed(), slave_hw_ptr = 0xC0 - The result of avail = 0x5A which is less than avail_min(0x60) - Here, xruns will be observed
Fix: - Initial, app_ptr = hw_ptr = 0 - Application fills buffer size of data. so app_ptr = 0xC0, hw_ptr = 0 - Round down of slave_hw_ptr during dmix_start() leads to below calculation: - During dmix_start(), slave_hw_ptr rounded to 0x60 (old slave_hw_ptr) - The diff calculation between old_slave_hw_ptr(0x60) and new_slave_hw_ptr(0x69) results in avail = 0x9 - After 1 snd_pcm_period_elapsed(), slave_hw_ptr = 0xC0 - The result of avail = 0x60 which is avail_min(0x60) - Here, xruns can be avoided
Signed-off-by: Vanitha Channaiah vanitha.channaiah@in.bosch.com
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 54d9900..a201fa3 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -2043,10 +2043,14 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix) { + /* + * For buffer size equal to two period size, slave_hw_ptr is rounded down + * to avoid xruns + */
if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP || (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && - pcm->buffer_size <= pcm->period_size * 2)) + pcm->buffer_size < pcm->period_size * 2)) dmix->slave_appl_ptr = ((dmix->slave_appl_ptr + dmix->slave_period_size - 1) / dmix->slave_period_size) * dmix->slave_period_size;