static unsigned int loopback_pos_update(struct loopback_cable *cable) { struct loopback_pcm *dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; struct loopback_pcm *dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; unsigned long delta_play = 0, delta_capt = 0; unsigned int running; spin_lock(&cable->lock); running = cable->running; if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { delta_play = jiffies - dpcm_play->last_jiffies; dpcm_play->last_jiffies += delta_play; } if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { delta_capt = jiffies - dpcm_capt->last_jiffies; dpcm_capt->last_jiffies += delta_capt; } if (delta_play == 0 && delta_capt == 0) { spin_unlock(&cable->lock); return running; } if (delta_play > delta_capt) { loopback_bytepos_update(dpcm_play, delta_play - delta_capt, BYTEPOS_UPDATE_POSONLY); delta_play = delta_capt; } else if (delta_play < delta_capt) { loopback_bytepos_update(dpcm_capt, delta_capt - delta_play, BYTEPOS_UPDATE_CLEAR); delta_capt = delta_play; } if (delta_play == 0 && delta_capt == 0) { spin_unlock(&cable->lock); return running; } /* note delta_capt == delta_play at this moment */ loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); spin_unlock(&cable->lock); return running; }
static unsigned int loopback_pos_update(struct loopback_cable *cable) { struct loopback_pcm *dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; struct loopback_pcm *dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; unsigned long delta_play = 0, delta_capt = 0; unsigned int running; unsigned long flags; spin_lock_irqsave(&cable->lock, flags); running = cable->running ^ cable->pause; if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { delta_play = jiffies - dpcm_play->last_jiffies; dpcm_play->last_jiffies += delta_play; } if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { delta_capt = jiffies - dpcm_capt->last_jiffies; dpcm_capt->last_jiffies += delta_capt; } if (delta_play == 0 && delta_capt == 0) goto unlock; if (delta_play > delta_capt) { loopback_bytepos_update(dpcm_play, delta_play - delta_capt, BYTEPOS_UPDATE_POSONLY); delta_play = delta_capt; } else if (delta_play < delta_capt) { loopback_bytepos_update(dpcm_capt, delta_capt - delta_play, BYTEPOS_UPDATE_CLEAR); delta_capt = delta_play; } if (delta_play == 0 && delta_capt == 0) goto unlock; loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); unlock: spin_unlock_irqrestore(&cable->lock, flags); return running; }