From 7c878cc62f3a657a0c8ec534dbc2afe4f01b7577 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 23 Oct 2018 16:23:32 +0800 Subject: [PATCH] ALSA: aloop: using raw cycles and jiffies The system tick may be modified by NTP when we connect with network, then jiffies have an offset compared to the local clock, it will cause the irq_pos / delta_play / delta_capt also be inaccurate. Therefore, we need a way to get raw jiffies which follows local raw clocks. Change-Id: I9be1790dfd98e430982dad6f03b04532889279a6 Signed-off-by: Xing Zheng --- sound/drivers/aloop.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 2c5f7e905ab8..51821334fcee 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -37,6 +37,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); #define MAX_PCM_SUBSTREAMS 8 +static bool use_raw_jiffies; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; @@ -44,6 +45,8 @@ static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; static int pcm_notify[SNDRV_CARDS]; static char *timer_source[SNDRV_CARDS]; +module_param(use_raw_jiffies, bool, 0444); +MODULE_PARM_DESC(use_raw_jiffies, "Use raw jiffies follows local clocks."); module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for loopback soundcard."); module_param_array(id, charp, NULL, 0444); @@ -163,6 +166,22 @@ struct loopback_pcm { static struct platform_device *devices[SNDRV_CARDS]; +static inline unsigned long get_raw_jiffies(void) +{ + struct timespec64 ts64; + + ktime_get_raw_ts64(&ts64); + return timespec64_to_jiffies(&ts64); +} + +static inline unsigned long cycles_to_jiffies(void) +{ + if (likely(use_raw_jiffies)) + return get_raw_jiffies(); + + return jiffies; +} + static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x) { if (dpcm->pcm_rate_shift == NO_PITCH) { @@ -387,7 +406,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) err = loopback_check_format(cable, substream->stream); if (err < 0) return err; - dpcm->last_jiffies = jiffies; + dpcm->last_jiffies = cycles_to_jiffies(); dpcm->pcm_rate_shift = 0; dpcm->last_drift = 0; spin_lock(&cable->lock); @@ -419,7 +438,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: spin_lock(&cable->lock); - dpcm->last_jiffies = jiffies; + dpcm->last_jiffies = cycles_to_jiffies(); cable->pause &= ~stream; err = cable->ops->start(dpcm); spin_unlock(&cable->lock); @@ -608,15 +627,16 @@ static unsigned int loopback_jiffies_timer_pos_update cable->streams[SNDRV_PCM_STREAM_CAPTURE]; unsigned long delta_play = 0, delta_capt = 0; unsigned int running, count1, count2; + unsigned long cur_jiffies = cycles_to_jiffies(); running = cable->running ^ cable->pause; if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { - delta_play = jiffies - dpcm_play->last_jiffies; + delta_play = cur_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; + delta_capt = cur_jiffies - dpcm_capt->last_jiffies; dpcm_capt->last_jiffies += delta_capt; } @@ -842,7 +862,7 @@ static void loopback_jiffies_timer_dpcm_info(struct loopback_pcm *dpcm, snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos); snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac); snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n", - dpcm->last_jiffies, jiffies); + dpcm->last_jiffies, cycles_to_jiffies()); snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires); }