At Tue, 07 Oct 2008 17:32:05 +0200, I wrote:
Hi,
the patch below (to the latest sound git tree) adds the extra delay count for USB-audio driver. This change will appear as the return value of snd_pcm_delay().
Could you check whether it's appropriate behavior you've wanted?
Ping.
Takashi
thanks,
Takashi
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 40c5a6f..dcbdc60 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -269,6 +269,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t avail_max; snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
/* -- HW params -- */ snd_pcm_access_t access; /* access mode */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e61e125..df7c3fa 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -597,14 +597,15 @@ int snd_pcm_status(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { status->avail = snd_pcm_playback_avail(runtime); if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
runtime->status->state == SNDRV_PCM_STATE_DRAINING)
runtime->status->state == SNDRV_PCM_STATE_DRAINING) { status->delay = runtime->buffer_size - status->avail;
else
status->delay += runtime->delay;
} else { status->avail = snd_pcm_capture_avail(runtime); if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)} else status->delay = 0;
status->delay = status->avail;
else status->delay = 0; }status->delay = status->avail + runtime->delay;
@@ -2423,6 +2424,7 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream, n = snd_pcm_playback_hw_avail(runtime); else n = snd_pcm_capture_avail(runtime);
break; case SNDRV_PCM_STATE_XRUN: err = -EPIPE;n += runtime->delay;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 6e70ba4..7d5a103 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -629,6 +629,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, subs->hwptr_done += offs; if (subs->hwptr_done >= runtime->buffer_size) subs->hwptr_done -= runtime->buffer_size;
- runtime->delay += offs; spin_unlock_irqrestore(&subs->lock, flags); urb->transfer_buffer_length = offs * stride; if (period_elapsed)
@@ -638,12 +639,20 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
/*
- process after playback data complete
- nothing to do
*/
- decrease the delay count again
static int retire_playback_urb(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *urb) {
- unsigned long flags;
- int stride = runtime->frame_bits >> 3;
- int processed = urb->transfer_buffer_length / stride;
- spin_lock_irqsave(&subs->lock, flags);
- if (processed > runtime->delay)
runtime->delay -= processed;
- spin_unlock_irqrestore(&subs->lock, flags); return 0;
}
@@ -1542,6 +1551,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->hwptr_done = 0; subs->transfer_done = 0; subs->phase = 0;
runtime->delay = 0;
/* clear urbs (to be sure) */ deactivate_urbs(subs, 0, 1);