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 <zhengxing@rock-chips.com>
This commit is contained in:
Xing Zheng
2018-10-23 16:23:32 +08:00
committed by Tao Huang
parent 7aac3b4eef
commit 7c878cc62f

View File

@@ -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);
}