Skip to content

Commit 9027c46

Browse files
committed
ALSA: pcm: Call ack() whenever appl_ptr is updated
Although the ack callback is supposed to be called at each appl_ptr or hw_ptr update, we missed a few opportunities: namely, forward, rewind and sync_ptr. Formerly calling ack at rewind may have leaded to unexpected results due to the forgotten negative appl_ptr update in indirect-PCM helper, which is the major user of the PCM ack callback. But now we fixed this oversights, thus we can call ack callback safely even at rewind callback -- of course with the proper handling of the error from the callback. This patch adds the calls of ack callback in the places mentioned in the above. Signed-off-by: Takashi Iwai <[email protected]>
1 parent 9ce7b9c commit 9027c46

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

sound/core/pcm_native.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,13 +2449,35 @@ static int do_pcm_hwsync(struct snd_pcm_substream *substream)
24492449
}
24502450
}
24512451

2452-
/* increase the appl_ptr; returns the processed frames */
2452+
/* update to the given appl_ptr and call ack callback if needed;
2453+
* when an error is returned, take back to the original value
2454+
*/
2455+
static int apply_appl_ptr(struct snd_pcm_substream *substream,
2456+
snd_pcm_uframes_t appl_ptr)
2457+
{
2458+
struct snd_pcm_runtime *runtime = substream->runtime;
2459+
snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
2460+
int ret;
2461+
2462+
runtime->control->appl_ptr = appl_ptr;
2463+
if (substream->ops->ack) {
2464+
ret = substream->ops->ack(substream);
2465+
if (ret < 0) {
2466+
runtime->control->appl_ptr = old_appl_ptr;
2467+
return ret;
2468+
}
2469+
}
2470+
return 0;
2471+
}
2472+
2473+
/* increase the appl_ptr; returns the processed frames or a negative error */
24532474
static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
24542475
snd_pcm_uframes_t frames,
24552476
snd_pcm_sframes_t avail)
24562477
{
24572478
struct snd_pcm_runtime *runtime = substream->runtime;
24582479
snd_pcm_sframes_t appl_ptr;
2480+
int ret;
24592481

24602482
if (avail <= 0)
24612483
return 0;
@@ -2464,17 +2486,18 @@ static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
24642486
appl_ptr = runtime->control->appl_ptr + frames;
24652487
if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
24662488
appl_ptr -= runtime->boundary;
2467-
runtime->control->appl_ptr = appl_ptr;
2468-
return frames;
2489+
ret = apply_appl_ptr(substream, appl_ptr);
2490+
return ret < 0 ? ret : frames;
24692491
}
24702492

2471-
/* decrease the appl_ptr; returns the processed frames */
2493+
/* decrease the appl_ptr; returns the processed frames or a negative error */
24722494
static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
24732495
snd_pcm_uframes_t frames,
24742496
snd_pcm_sframes_t avail)
24752497
{
24762498
struct snd_pcm_runtime *runtime = substream->runtime;
24772499
snd_pcm_sframes_t appl_ptr;
2500+
int ret;
24782501

24792502
if (avail <= 0)
24802503
return 0;
@@ -2483,8 +2506,8 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
24832506
appl_ptr = runtime->control->appl_ptr - frames;
24842507
if (appl_ptr < 0)
24852508
appl_ptr += runtime->boundary;
2486-
runtime->control->appl_ptr = appl_ptr;
2487-
return frames;
2509+
ret = apply_appl_ptr(substream, appl_ptr);
2510+
return ret < 0 ? ret : frames;
24882511
}
24892512

24902513
static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
@@ -2610,10 +2633,15 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
26102633
return err;
26112634
}
26122635
snd_pcm_stream_lock_irq(substream);
2613-
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
2614-
control->appl_ptr = sync_ptr.c.control.appl_ptr;
2615-
else
2636+
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
2637+
err = apply_appl_ptr(substream, sync_ptr.c.control.appl_ptr);
2638+
if (err < 0) {
2639+
snd_pcm_stream_unlock_irq(substream);
2640+
return err;
2641+
}
2642+
} else {
26162643
sync_ptr.c.control.appl_ptr = control->appl_ptr;
2644+
}
26172645
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
26182646
control->avail_min = sync_ptr.c.control.avail_min;
26192647
else

0 commit comments

Comments
 (0)