From patchwork Fri Sep 30 12:43:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Subhransu S. Prusty" X-Patchwork-Id: 9358487 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5AAA26075E for ; Fri, 30 Sep 2016 14:58:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4B5542A087 for ; Fri, 30 Sep 2016 14:58:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3FFD52A089; Fri, 30 Sep 2016 14:58:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7B20B2A088 for ; Fri, 30 Sep 2016 14:58:03 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id C84FB266838; Fri, 30 Sep 2016 16:58:02 +0200 (CEST) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 7C0652667EE; Fri, 30 Sep 2016 16:55:38 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id B1DA4261A1A; Fri, 30 Sep 2016 14:50:29 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by alsa0.perex.cz (Postfix) with ESMTP id 154DB2665C3 for ; Fri, 30 Sep 2016 14:50:23 +0200 (CEST) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP; 30 Sep 2016 05:50:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,272,1473145200"; d="scan'208";a="15394970" Received: from subhransu-desktop.iind.intel.com ([10.223.96.24]) by orsmga004.jf.intel.com with ESMTP; 30 Sep 2016 05:50:21 -0700 From: "Subhransu S. Prusty" To: alsa-devel@alsa-project.org Date: Fri, 30 Sep 2016 18:13:30 +0530 Message-Id: <1475239410-16548-8-git-send-email-subhransu.s.prusty@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1475239410-16548-1-git-send-email-subhransu.s.prusty@intel.com> References: <1475239410-16548-1-git-send-email-subhransu.s.prusty@intel.com> Cc: tiwai@suse.de, lgirdwood@gmail.com, Pierre-Louis Bossart , patches.audio@intel.com, broonie@kernel.org, "Subhransu S. Prusty" Subject: [alsa-devel] [PATCH 7/7] ALSA: usb: take startup delay into account X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Pierre-Louis Bossart For playback usages, the endpoints are started before the prepare step, and valid audio data will be rendered with a delay that cannot be recovered. Worst-case the initial delay due to buffering of empty URBS can be up to 12ms Tested with audio_time: Timestamps without delay taken into account: test$ ./audio_time -Dhw:1,0 -p playback: systime: 120093327 nsec, audio time 125000000 nsec, systime delta -4906673 playback: systime: 245090755 nsec, audio time 250000000 nsec, systime delta -4909245 playback: systime: 370034641 nsec, audio time 375000000 nsec, systime delta -4965359 playback: systime: 495089634 nsec, audio time 500000000 nsec, systime delta -4910366 Timestamps with delay taken into account (12ms delay shown) test$ ./audio_time -Dhw:1,0 -p -d playback: systime: 120095090 nsec, audio time 108000000 nsec, systime delta 12095090 playback: systime: 245090932 nsec, audio time 232000000 nsec, systime delta 13090932 playback: systime: 370091792 nsec, audio time 357000000 nsec, systime delta 13091792 playback: systime: 495092309 nsec, audio time 482000000 nsec, systime delta 13092309 Suggested-by: Rakesh Ughreja Signed-off-by: Pierre-Louis Bossart Signed-off-by: Subhransu S. Prusty --- sound/usb/card.h | 1 + sound/usb/pcm.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 71778ca..d128058 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -148,6 +148,7 @@ struct snd_usb_substream { int last_frame_number; /* stored frame number */ int last_delay; /* stored delay */ + int start_delay; /* initial delay due to empty frames */ struct { int marker; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 5bcc729..2bf7537 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -86,6 +86,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream hwptr_done = subs->hwptr_done; substream->runtime->delay = snd_usb_pcm_delay(subs, substream->runtime->rate); + substream->runtime->delay += subs->start_delay; spin_unlock(&subs->lock); return hwptr_done / (substream->runtime->frame_bits >> 3); } @@ -858,9 +859,34 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { ret = start_endpoints(subs, true); + /* + * Since we submit empty URBS, the constant initial delay will + * not be recovered and will be added to the dynamic delay + * measured with the frame counter. Worst-case the + * startup delay can be (MAX_URBS-1) * MAX_PACKS = 12ms + */ + if (ret == 0) { + struct snd_usb_endpoint *ep = subs->data_endpoint; + int total_packs = 0; + int i; + + for (i = 0; i < ep->nurbs - 1; i++) { + struct snd_urb_ctx *u = &ep->urb[i]; + + total_packs += u->packets; + } + subs->start_delay = DIV_ROUND_UP(total_packs * + subs->cur_rate, 1000); + if (subs->start_delay) + dev_dbg(&subs->dev->dev, + "Initial delay for EP @%p: %d frames\n", + ep, subs->start_delay); + } + } + unlock: snd_usb_unlock_shutdown(subs->stream->chip); return ret; @@ -1549,6 +1575,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, runtime->delay = subs->last_delay; runtime->delay += frames; subs->last_delay = runtime->delay; + runtime->delay += subs->start_delay; /* realign last_frame_number */ subs->last_frame_number = usb_get_current_frame_number(subs->dev); @@ -1597,8 +1624,7 @@ static void retire_playback_urb(struct snd_usb_substream *subs, subs->last_delay = 0; else subs->last_delay -= processed; - runtime->delay = subs->last_delay; - + runtime->delay = subs->last_delay + subs->start_delay; /* * Report when delay estimate is off by more than 2ms. * The error should be lower than 2ms since the estimate relies