mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user