From patchwork Tue Jun 1 16:24:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 451447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2AD1C47080 for ; Tue, 1 Jun 2021 16:28:19 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 78EF461375 for ; Tue, 1 Jun 2021 16:28:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 78EF461375 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id C64FC16E0; Tue, 1 Jun 2021 18:27:27 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C64FC16E0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1622564897; bh=H7O8ZrpSIMZCHAO7xg+mjTrB/WExa5vGbRhdS1i7do4=; h=From:To:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=TWQu3I64oR9CQoabrGHyv2k5epUqF2caFPTZZ9H8vfsKh7Q3pzAO3H24u57K92t31 aGEpIQRKSG3pGJDK+qKrV0vIwhJegho5C6PuMs9DnWZb59x+cWArcDA7B9LFOMijCZ GM3S7hnFcZ285sdD01wiPd7iwODnxfrNcIOZArOo= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6A3BFF804CC; Tue, 1 Jun 2021 18:25:17 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id D2228F804C3; Tue, 1 Jun 2021 18:25:14 +0200 (CEST) Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id D904CF80253 for ; Tue, 1 Jun 2021 18:24:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz D904CF80253 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="pdNlqkSP"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="mr02ufPg" Received: from relay2.suse.de (unknown [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id 9A76121961 for ; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pvViDmprfGU02rol3x9WrN2xdF73SjXD0su7HbsJeks=; b=pdNlqkSPm5EaB+hwy+TyNPdW7473zPQhWzxsaR1rajnPBH0wsONULQVUhlpAuqKZp/VK5Z 4qlRrNJCmO8jh63KlLnKRVhMsMqmxs5+RgPBC2zNLKtMd6gRvet/yr7Ji8sSK31XkybBeA fZyTHJHnkgvmvt8RwWFAczpOnTUuFrc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pvViDmprfGU02rol3x9WrN2xdF73SjXD0su7HbsJeks=; b=mr02ufPg4PYJehBXTM0f7OVF2mkOf1yCnkRNG2nSTTTWeNFGaInQlO1eEuPG1uysvGVOEE bzRjO/jXfwgBMaCw== Received: from alsa1.nue.suse.com (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id 8B273A3B87; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 1/5] ALSA: usb-audio: Make snd_usb_pcm_delay() static Date: Tue, 1 Jun 2021 18:24:53 +0200 Message-Id: <20210601162457.4877-2-tiwai@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210601162457.4877-1-tiwai@suse.de> References: <20210601162457.4877-1-tiwai@suse.de> MIME-Version: 1.0 X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" It's a local function, let's make it static. Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 4 ++-- sound/usb/pcm.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e5311b6bb3f6..359c759a7023 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -29,8 +29,8 @@ #define SUBSTREAM_FLAG_SYNC_EP_STARTED 1 /* return the estimated delay based on USB frame counters */ -snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate) +static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, + unsigned int rate) { int current_frame_number; int frame_diff; diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index 06c586467d3f..493a4e34d78d 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -2,9 +2,6 @@ #ifndef __USBAUDIO_PCM_H #define __USBAUDIO_PCM_H -snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate); - void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); int snd_usb_pcm_suspend(struct snd_usb_stream *as); int snd_usb_pcm_resume(struct snd_usb_stream *as); From patchwork Tue Jun 1 16:24:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 452562 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3AEE2C4708F for ; Tue, 1 Jun 2021 16:26:04 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5CE76613AD for ; Tue, 1 Jun 2021 16:26:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5CE76613AD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 12EDC16BC; Tue, 1 Jun 2021 18:25:10 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 12EDC16BC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1622564760; bh=VrseM5FpkCAFR4lkbDaSP+JIGI0Ijvnf++JHBEdvkxs=; h=From:To:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=TfkP2E07HoddLN2RuG1q+l8mLnKkX6HQP47hvEPus5+dQV2yDc3yFuWEORQwzziJz MpfebEGYGPtzU4/UwilDnHHH/bGB+/v+JU0PCEzuq49Irfsiopx5eQhCULXNAk+u9K CQmOtpyJqitQ7U/RczB6SpHES2vtyj/ILwLT+mTU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 4B062F800B2; Tue, 1 Jun 2021 18:25:09 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 402E1F804B0; Tue, 1 Jun 2021 18:25:07 +0200 (CEST) Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id D40F1F800B2 for ; Tue, 1 Jun 2021 18:24:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz D40F1F800B2 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="dOPIUvbJ"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="8RDhxjbC" Received: from relay2.suse.de (unknown [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id AADF721962 for ; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/0YFotyzjNX0LaaqZyHwENV/YIVPfrs9t3MrkdeGork=; b=dOPIUvbJqYxn6z6eISze4DlQIWDgkMdgK/yZTLmAcGaN5O6zKi85vOAduth38/qUxw3Uo4 xgdZrBgvviNb9B4ct1MICqpKPunUWolHUjVvN+fXbVSvwEPC13UdR4mnA11vilcZOPa98P I4njE7UUThOrnSLKXbrTtcfeQiZM/Rk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/0YFotyzjNX0LaaqZyHwENV/YIVPfrs9t3MrkdeGork=; b=8RDhxjbCM9UJz0HhDaQ4mNfZeWC9Lf+1rDVk9G+/APTxuzgRwy3ehHHjgwXc1fLU3YxvOC O0zdQ0M91iHl3rDA== Received: from alsa1.nue.suse.com (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id 99177A3B84; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 2/5] ALSA: usb-audio: Pre-calculate buffer byte size Date: Tue, 1 Jun 2021 18:24:54 +0200 Message-Id: <20210601162457.4877-3-tiwai@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210601162457.4877-1-tiwai@suse.de> References: <20210601162457.4877-1-tiwai@suse.de> MIME-Version: 1.0 X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" There are a bunch of lines calculating the buffer size in bytes at each time. Keep the value in subs->buffer_bytes and use it consistently for the code simplicity. Signed-off-by: Takashi Iwai --- sound/usb/card.h | 1 + sound/usb/pcm.c | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index a741e7da83a2..b346653d4b76 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -158,6 +158,7 @@ struct snd_usb_substream { unsigned int running: 1; /* running status */ + unsigned int buffer_bytes; /* buffer size in bytes */ unsigned int hwptr_done; /* processed byte position in the buffer */ unsigned int transfer_done; /* processed frames since last period update */ unsigned int frame_limit; /* limits number of packets in URB */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 359c759a7023..e8121af8e1d5 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -600,6 +600,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; /* reset the pointer */ + subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); subs->hwptr_done = 0; subs->transfer_done = 0; subs->last_delay = 0; @@ -1147,8 +1148,8 @@ static void retire_capture_urb(struct snd_usb_substream *subs, spin_lock_irqsave(&subs->lock, flags); oldptr = subs->hwptr_done; subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; frames = (bytes + (oldptr % stride)) / stride; subs->transfer_done += frames; if (subs->transfer_done >= runtime->period_size) { @@ -1166,9 +1167,9 @@ static void retire_capture_urb(struct snd_usb_substream *subs, spin_unlock_irqrestore(&subs->lock, flags); /* copy a data chunk */ - if (oldptr + bytes > runtime->buffer_size * stride) { - unsigned int bytes1 = - runtime->buffer_size * stride - oldptr; + if (oldptr + bytes > subs->buffer_bytes) { + unsigned int bytes1 = subs->buffer_bytes - oldptr; + memcpy(runtime->dma_area + oldptr, cp, bytes1); memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1); } else { @@ -1184,10 +1185,9 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, struct urb *urb, unsigned int bytes) { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - unsigned int stride = runtime->frame_bits >> 3; unsigned int dst_idx = 0; unsigned int src_idx = subs->hwptr_done; - unsigned int wrap = runtime->buffer_size * stride; + unsigned int wrap = subs->buffer_bytes; u8 *dst = urb->transfer_buffer; u8 *src = runtime->dma_area; u8 marker[] = { 0x05, 0xfa }; @@ -1233,8 +1233,8 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, subs->hwptr_done++; } } - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; } static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, @@ -1242,10 +1242,10 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { + if (subs->hwptr_done + bytes > subs->buffer_bytes) { /* err, the transferred area goes over buffer boundary. */ - unsigned int bytes1 = - runtime->buffer_size * stride - subs->hwptr_done; + unsigned int bytes1 = subs->buffer_bytes - subs->hwptr_done; + memcpy(urb->transfer_buffer + offset, runtime->dma_area + subs->hwptr_done, bytes1); memcpy(urb->transfer_buffer + offset + bytes1, @@ -1255,8 +1255,8 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, runtime->dma_area + subs->hwptr_done, bytes); } subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; } static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs, @@ -1295,7 +1295,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, int i, stride, period_elapsed = 0; unsigned long flags; - stride = runtime->frame_bits >> 3; + stride = ep->stride; frames = 0; urb->number_of_packets = 0; @@ -1304,8 +1304,8 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, for (i = 0; i < ctx->packets; i++) { counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); /* set up descriptor */ - urb->iso_frame_desc[i].offset = frames * ep->stride; - urb->iso_frame_desc[i].length = counts * ep->stride; + urb->iso_frame_desc[i].offset = frames * stride; + urb->iso_frame_desc[i].length = counts * stride; frames += counts; urb->number_of_packets++; subs->transfer_done += counts; @@ -1320,14 +1320,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, frames -= subs->transfer_done; counts -= subs->transfer_done; urb->iso_frame_desc[i].length = - counts * ep->stride; + counts * stride; subs->transfer_done = 0; } i++; if (i < ctx->packets) { /* add a transfer delimiter */ urb->iso_frame_desc[i].offset = - frames * ep->stride; + frames * stride; urb->iso_frame_desc[i].length = 0; urb->number_of_packets++; } @@ -1340,7 +1340,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, !snd_usb_endpoint_implicit_feedback_sink(ep)) break; } - bytes = frames * ep->stride; + bytes = frames * stride; if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && subs->cur_audiofmt->dsd_dop)) { @@ -1350,14 +1350,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, /* bit-reverse the bytes */ u8 *buf = urb->transfer_buffer; for (i = 0; i < bytes; i++) { - int idx = (subs->hwptr_done + i) - % (runtime->buffer_size * stride); + int idx = (subs->hwptr_done + i) % subs->buffer_bytes; + buf[i] = bitrev8(runtime->dma_area[idx]); } subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; } else { /* usual PCM */ if (!subs->tx_length_quirk) From patchwork Tue Jun 1 16:24:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 451448 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ACCC9C47080 for ; Tue, 1 Jun 2021 16:27:33 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CE6F3613C1 for ; Tue, 1 Jun 2021 16:27:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CE6F3613C1 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 20EE716E8; Tue, 1 Jun 2021 18:26:41 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 20EE716E8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1622564851; bh=oZYJOMquk0FhzBFezaO6SDfgrOwKPcpM3mHfF5ELKEE=; h=From:To:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=GWoVDCoHi51d1FXqTqj3YDY37KVN8726G6jPE3tCHXLPXx+gKCYt31hNDCIfwg/CH GN2xuQHkgw0TzI6X63LMFqJwYYEP6tcHPMYZ+eb6WrkxHpilm4h3Xa6gQeFDvAZvWy xLzqluNJcB+Yamokjwffuasr0aj2Z9f+BnOPgCe0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 2DC9BF802E7; Tue, 1 Jun 2021 18:25:16 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 8D76EF804CB; Tue, 1 Jun 2021 18:25:14 +0200 (CEST) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E3409F8025B for ; Tue, 1 Jun 2021 18:24:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E3409F8025B Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="BA1xBJTF"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="1abwnFIq" Received: from relay2.suse.de (unknown [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id AF2201FD4C for ; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MtAvfreVllcyN6I1H6OT4sDGvfDXFw/DB9rRHUWamlI=; b=BA1xBJTFTWZ0+a4AedTzTBAJa+w0Pcre47MvoPGDD48gsj6O7hl3PSl4zO9s3kXIRCJGJs nPWleBlsXQwo7+TdmjCrMtILlCfVoqNUt3yLzmEwnB0GjvN1geSfHtn3vMco0WOfElgXKh iNXZBte594hbuISi8wjNiZLcwYgOEg8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MtAvfreVllcyN6I1H6OT4sDGvfDXFw/DB9rRHUWamlI=; b=1abwnFIq2iu670XLbMxnYvhx0uKL50H9dhQ1aLxJzJESb41HhzWAKAFnE1BF2DlhNjOwb4 CMbZB8c9M1GKNwAQ== Received: from alsa1.nue.suse.com (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id A83BCA3B87; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 3/5] ALSA: usb-audio: Refactoring delay account code Date: Tue, 1 Jun 2021 18:24:55 +0200 Message-Id: <20210601162457.4877-4-tiwai@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210601162457.4877-1-tiwai@suse.de> References: <20210601162457.4877-1-tiwai@suse.de> MIME-Version: 1.0 X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The PCM delay accounting in USB-audio driver is a bit complex to follow, and this is an attempt to improve the readability and provide some potential fix. Basically, the PCM position delay is calculated from two factors: the in-flight data on URBs and the USB frame counter. For the playback stream, we advance the hwptr already at submitting URBs. Those "in-flight" data amount is now tracked, and this is used as the base value for the PCM delay correction. The in-flight data is decreased again at URB completion in return. For the capture stream, OTOH, there is no in-flight data, hence the delay base is zero. The USB frame counter is used in addition for correcting the current position. The reference frame counter is updated at each submission and receiving time, and the difference from the current counter value is taken into account. In this patch, each in-flight data bytes is recorded in the new snd_usb_ctx.queued field, and the total in-flight amount is tracked in snd_usb_substream.inflight_bytes field, as the replacement of last_delay field. Note that updating the hwptr after URB completion doesn't work for PulseAudio who tries to scratch the buffer on the fly; USB-audio is basically a double-buffer implementation, hence the scratching the buffer can't work for the already submitted data. So we always update hwptr beforehand. It's not ideal, but the delay account should give enough correctness. Signed-off-by: Takashi Iwai --- sound/usb/card.h | 7 ++- sound/usb/endpoint.c | 1 + sound/usb/pcm.c | 128 +++++++++++++++++-------------------------- 3 files changed, 56 insertions(+), 80 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index b346653d4b76..5577a776561b 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -54,6 +54,7 @@ struct snd_urb_ctx { struct snd_usb_endpoint *ep; int index; /* index for urb array */ int packets; /* number of packets per urb */ + int queued; /* queued data bytes by this urb */ int packet_size[MAX_PACKS_HS]; /* size of packets for next submission */ struct list_head ready_list; }; @@ -159,8 +160,9 @@ struct snd_usb_substream { unsigned int running: 1; /* running status */ unsigned int buffer_bytes; /* buffer size in bytes */ + unsigned int inflight_bytes; /* in-flight data bytes on buffer (for playback) */ unsigned int hwptr_done; /* processed byte position in the buffer */ - unsigned int transfer_done; /* processed frames since last period update */ + unsigned int transfer_done; /* processed frames since last period update */ unsigned int frame_limit; /* limits number of packets in URB */ /* data and sync endpoints for this stream */ @@ -175,8 +177,7 @@ struct snd_usb_substream { struct list_head fmt_list; /* format list */ spinlock_t lock; - int last_frame_number; /* stored frame number */ - int last_delay; /* stored delay */ + unsigned int last_frame_number; /* stored frame number */ struct { int marker; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 014c43862826..da649211bff3 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -275,6 +275,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, urb->number_of_packets = ctx->packets; urb->transfer_buffer_length = offs * ep->stride + ctx->packets * extra; + ctx->queued = 0; } /* diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e8121af8e1d5..8ee45f2e8dce 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -30,14 +30,20 @@ /* return the estimated delay based on USB frame counters */ static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate) + struct snd_pcm_runtime *runtime) { - int current_frame_number; - int frame_diff; + unsigned int current_frame_number; + unsigned int frame_diff; int est_delay; + int queued; - if (!subs->last_delay) - return 0; /* short path */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { + queued = bytes_to_frames(runtime, subs->inflight_bytes); + if (!queued) + return 0; + } else if (!subs->running) { + return 0; + } current_frame_number = usb_get_current_frame_number(subs->dev); /* @@ -49,14 +55,14 @@ static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, /* Approximation based on number of samples per USB frame (ms), some truncation for 44.1 but the estimate is good enough */ - est_delay = frame_diff * rate / 1000; - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - est_delay = subs->last_delay - est_delay; - else - est_delay = subs->last_delay + est_delay; + est_delay = frame_diff * runtime->rate / 1000; + + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { + est_delay = queued - est_delay; + if (est_delay < 0) + est_delay = 0; + } - if (est_delay < 0) - est_delay = 0; return est_delay; } @@ -65,17 +71,17 @@ static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, */ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_usb_substream *subs = substream->runtime->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_usb_substream *subs = runtime->private_data; unsigned int hwptr_done; if (atomic_read(&subs->stream->chip->shutdown)) return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; - substream->runtime->delay = snd_usb_pcm_delay(subs, - substream->runtime->rate); + runtime->delay = snd_usb_pcm_delay(subs, runtime); spin_unlock(&subs->lock); - return hwptr_done / (substream->runtime->frame_bits >> 3); + return bytes_to_frames(runtime, hwptr_done); } /* @@ -601,9 +607,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* reset the pointer */ subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); + subs->inflight_bytes = 0; subs->hwptr_done = 0; subs->transfer_done = 0; - subs->last_delay = 0; subs->last_frame_number = 0; runtime->delay = 0; @@ -1156,14 +1162,9 @@ static void retire_capture_urb(struct snd_usb_substream *subs, subs->transfer_done -= runtime->period_size; period_elapsed = 1; } - /* capture delay is by construction limited to one URB, - * reset delays here - */ - runtime->delay = subs->last_delay = 0; /* realign last_frame_number */ subs->last_frame_number = current_frame_number; - subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ spin_unlock_irqrestore(&subs->lock, flags); /* copy a data chunk */ @@ -1181,6 +1182,18 @@ static void retire_capture_urb(struct snd_usb_substream *subs, snd_pcm_period_elapsed(subs->pcm_substream); } +static void urb_ctx_queue_advance(struct snd_usb_substream *subs, + struct urb *urb, unsigned int bytes) +{ + struct snd_urb_ctx *ctx = urb->context; + + ctx->queued += bytes; + subs->inflight_bytes += bytes; + subs->hwptr_done += bytes; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; +} + static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, struct urb *urb, unsigned int bytes) { @@ -1191,6 +1204,7 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, u8 *dst = urb->transfer_buffer; u8 *src = runtime->dma_area; u8 marker[] = { 0x05, 0xfa }; + unsigned int queued = 0; /* * The DSP DOP format defines a way to transport DSD samples over @@ -1229,12 +1243,11 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, dst[dst_idx++] = bitrev8(src[idx]); else dst[dst_idx++] = src[idx]; - - subs->hwptr_done++; + queued++; } } - if (subs->hwptr_done >= subs->buffer_bytes) - subs->hwptr_done -= subs->buffer_bytes; + + urb_ctx_queue_advance(subs, urb, queued); } static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, @@ -1254,9 +1267,8 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, memcpy(urb->transfer_buffer + offset, runtime->dma_area + subs->hwptr_done, bytes); } - subs->hwptr_done += bytes; - if (subs->hwptr_done >= subs->buffer_bytes) - subs->hwptr_done -= subs->buffer_bytes; + + urb_ctx_queue_advance(subs, urb, bytes); } static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs, @@ -1298,6 +1310,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, stride = ep->stride; frames = 0; + ctx->queued = 0; urb->number_of_packets = 0; spin_lock_irqsave(&subs->lock, flags); subs->frame_limit += ep->max_urb_frames; @@ -1355,9 +1368,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, buf[i] = bitrev8(runtime->dma_area[idx]); } - subs->hwptr_done += bytes; - if (subs->hwptr_done >= subs->buffer_bytes) - subs->hwptr_done -= subs->buffer_bytes; + urb_ctx_queue_advance(subs, urb, bytes); } else { /* usual PCM */ if (!subs->tx_length_quirk) @@ -1367,14 +1378,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, /* bytes is now amount of outgoing data */ } - /* update delay with exact number of samples queued */ - runtime->delay = subs->last_delay; - runtime->delay += frames; - subs->last_delay = runtime->delay; - - /* realign last_frame_number */ subs->last_frame_number = usb_get_current_frame_number(subs->dev); - subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ if (subs->trigger_tstamp_pending_update) { /* this is the first actual URB submitted, @@ -1398,48 +1402,17 @@ static void retire_playback_urb(struct snd_usb_substream *subs, struct urb *urb) { unsigned long flags; - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - struct snd_usb_endpoint *ep = subs->data_endpoint; - int processed = urb->transfer_buffer_length / ep->stride; - int est_delay; - - /* ignore the delay accounting when processed=0 is given, i.e. - * silent payloads are processed before handling the actual data - */ - if (!processed) - return; + struct snd_urb_ctx *ctx = urb->context; spin_lock_irqsave(&subs->lock, flags); - if (!subs->last_delay) - goto out; /* short path */ - - est_delay = snd_usb_pcm_delay(subs, runtime->rate); - /* update delay with exact number of samples played */ - if (processed > subs->last_delay) - subs->last_delay = 0; - else - subs->last_delay -= processed; - runtime->delay = subs->last_delay; - - /* - * Report when delay estimate is off by more than 2ms. - * The error should be lower than 2ms since the estimate relies - * on two reads of a counter updated every ms. - */ - if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) - dev_dbg_ratelimited(&subs->dev->dev, - "delay: estimated %d, actual %d\n", - est_delay, subs->last_delay); - - if (!subs->running) { - /* update last_frame_number for delay counting here since - * prepare_playback_urb won't be called during pause - */ - subs->last_frame_number = - usb_get_current_frame_number(subs->dev) & 0xff; + if (ctx->queued) { + if (subs->inflight_bytes >= ctx->queued) + subs->inflight_bytes -= ctx->queued; + else + subs->inflight_bytes = 0; } - out: + subs->last_frame_number = usb_get_current_frame_number(subs->dev); spin_unlock_irqrestore(&subs->lock, flags); } @@ -1504,6 +1477,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream snd_usb_endpoint_set_callback(subs->data_endpoint, NULL, retire_capture_urb, subs); + subs->last_frame_number = usb_get_current_frame_number(subs->dev); subs->running = 1; dev_dbg(&subs->dev->dev, "%d:%d Start Capture PCM\n", subs->cur_audiofmt->iface, From patchwork Tue Jun 1 16:24:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 452560 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52B7EC4708F for ; Tue, 1 Jun 2021 16:27:45 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C0615613C8 for ; Tue, 1 Jun 2021 16:27:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C0615613C8 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 5D47B16E5; Tue, 1 Jun 2021 18:26:53 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 5D47B16E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1622564863; bh=wYBBhNXpK4iiSD2Ep5PdIX+jSL5eyKHUsOIup0Qr7rA=; h=From:To:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=TDK0Qb6OeCyTNMTWzv2g0o17nSY6g3Z2wmUhqBCwR6uWYO+ktHn8vuY346emxtMGW ffpVG460D31KZLrdNFBNMZKuwuSWg1VRVGiEc3SfZa2EufzjxFLJmlffDilzBjhO9N /aiAAmvl2DAaUp0RQX82rJvDLuek1Wc6oACdipE8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id DC77EF804CB; Tue, 1 Jun 2021 18:25:16 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 99ED5F8025B; Tue, 1 Jun 2021 18:25:14 +0200 (CEST) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E89D0F802E7 for ; Tue, 1 Jun 2021 18:24:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E89D0F802E7 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="QuUYmSRz"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="sOmtYLYk" Received: from relay2.suse.de (unknown [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id BD5891FD58 for ; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sZD8j97SubT2o6prBLaEK8syMxFxCRQzWFe7mWPOoNE=; b=QuUYmSRzbiIKx8g+TTnxfCQ4GQMYaMuVAWwpVWruFmEGEV1BX9y+i/5Ty4iT/VRCOdmUcJ ed73x7penNedXEOfc10BwAt3Gu8WAY8fE2OKPYYcTUW5rTQC3NFPY8sQxEkQpz4aqHQGSc fjK2rNI/BGfpwe3U13emqTuADGK25N4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sZD8j97SubT2o6prBLaEK8syMxFxCRQzWFe7mWPOoNE=; b=sOmtYLYkY4BO/e4JtlsJi91RQiwQyZdKbP0afkrA0PcEJwdqpaV9O5vDgY3y44JRUizQp/ +9JWk/7ivLC9zdCg== Received: from alsa1.nue.suse.com (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id AED57A3B88; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 4/5] ALSA: usb-audio: Factor out DSD bitrev copy function Date: Tue, 1 Jun 2021 18:24:56 +0200 Message-Id: <20210601162457.4877-5-tiwai@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210601162457.4877-1-tiwai@suse.de> References: <20210601162457.4877-1-tiwai@suse.de> MIME-Version: 1.0 X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Just minor code refactoring. Like DOP DSD code, it can be better in a separate function for code readability. Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 8ee45f2e8dce..e26d37365f02 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1250,6 +1250,24 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, urb_ctx_queue_advance(subs, urb, queued); } +/* copy bit-reversed bytes onto transfer buffer */ +static void fill_playback_urb_dsd_bitrev(struct snd_usb_substream *subs, + struct urb *urb, unsigned int bytes) +{ + struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; + const u8 *src = runtime->dma_area; + u8 *buf = urb->transfer_buffer; + int i, ofs = subs->hwptr_done; + + for (i = 0; i < bytes; i++) { + *buf++ = bitrev8(src[ofs]); + if (++ofs >= subs->buffer_bytes) + ofs = 0; + } + + urb_ctx_queue_advance(subs, urb, bytes); +} + static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, int offset, int stride, unsigned int bytes) { @@ -1360,15 +1378,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, fill_playback_urb_dsd_dop(subs, urb, bytes); } else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 && subs->cur_audiofmt->dsd_bitrev)) { - /* bit-reverse the bytes */ - u8 *buf = urb->transfer_buffer; - for (i = 0; i < bytes; i++) { - int idx = (subs->hwptr_done + i) % subs->buffer_bytes; - - buf[i] = bitrev8(runtime->dma_area[idx]); - } - - urb_ctx_queue_advance(subs, urb, bytes); + fill_playback_urb_dsd_bitrev(subs, urb, bytes); } else { /* usual PCM */ if (!subs->tx_length_quirk) From patchwork Tue Jun 1 16:24:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 451449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43267C4708F for ; Tue, 1 Jun 2021 16:26:54 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 15896613AD for ; Tue, 1 Jun 2021 16:26:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 15896613AD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 2B32A16D8; Tue, 1 Jun 2021 18:26:01 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2B32A16D8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1622564811; bh=5ySjhuuk4SkenMYPGm0I2Nz0DZ4p68O8FD07sAdYH4A=; h=From:To:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=XpM7jJMJyQ1fkY9k1oA40poCM369xjCkisTREeQfJ64p/9GCTbV7FIX+2LBpsjUVH FpxA7BQImxKV71XT1XoXH60xmai48OAPt8Tc+1fxLAumcqlr1u+P11SRO8r9DlFEKB 5ArTF+Hq8fhe9OOyz1Ew0loX530KDG6A7YOAy3tw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BBB5EF804BB; Tue, 1 Jun 2021 18:25:10 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A232EF804AF; Tue, 1 Jun 2021 18:25:07 +0200 (CEST) Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id DCCEAF80254 for ; Tue, 1 Jun 2021 18:24:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz DCCEAF80254 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="NDWheX7r"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="91ZPWIEN" Received: from relay2.suse.de (unknown [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id CC57821963 for ; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WYCquLZWAUtwsKRsm1Vk986BlBN+cqLHdeQkKaeSawE=; b=NDWheX7rytan3cGq6omD9EYFE7dfgzB959upl6RUgaBT7K6cSqIVLmc5OcPgydfrzviBLp jEafTGwjP3n8K+uL1CvXz/fD+/2Nlv6atLN2SAZ2960F9DpKMw2teygsFOXdTI8erfcF/1 gA39FUvAQUyIryMXvyALfRYebJWY3k8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1622564698; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WYCquLZWAUtwsKRsm1Vk986BlBN+cqLHdeQkKaeSawE=; b=91ZPWIENg2Oeu3Og0VbJy+01CIAYm7YJfoB7JNqYh9VGtczeavswoIEild0wipatVP/56G 74Yug7BpSmqiGDBQ== Received: from alsa1.nue.suse.com (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id BCE21A3B87; Tue, 1 Jun 2021 16:24:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 5/5] ALSA: usb-audio: Reduce latency at playback start Date: Tue, 1 Jun 2021 18:24:57 +0200 Message-Id: <20210601162457.4877-6-tiwai@suse.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210601162457.4877-1-tiwai@suse.de> References: <20210601162457.4877-1-tiwai@suse.de> MIME-Version: 1.0 X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" USB-audio driver behaves a bit strangely for the playback stream -- namely, it starts sending silent packets at PCM prepare state while the actual data is submitted at first when the trigger START is kicked off. This is a workaround for the behavior where URBs are processed too quickly at the beginning. That is, if we start submitting URBs at trigger START, the first few URBs will be immediately completed, and this would result in the immediate period-elapsed calls right after the start, which may confuse applications. OTOH, submitting the data after silent URBs would, of course, result in a certain delay of the actual data processing, and this is rather more serious problem on modern systems, in practice. This patch tries to revert the workaround and lets the URB submission starting at PCM trigger for the playback again. As far as I've tested with various backends (native ALSA, PA, JACK, PW), I haven't seen any problems (famous last words :) Note that the capture stream handling needs no such workaround, since the capture is driven per received URB. Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e26d37365f02..c66831ee15f9 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -613,11 +613,6 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->last_frame_number = 0; runtime->delay = 0; - /* 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) - ret = start_endpoints(subs); - unlock: snd_usb_unlock_shutdown(chip); return ret; @@ -1430,6 +1425,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea int cmd) { struct snd_usb_substream *subs = substream->runtime->private_data; + int err; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -1440,6 +1436,14 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea prepare_playback_urb, retire_playback_urb, subs); + if (cmd == SNDRV_PCM_TRIGGER_START) { + err = start_endpoints(subs); + if (err < 0) { + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, NULL, NULL); + return err; + } + } subs->running = 1; dev_dbg(&subs->dev->dev, "%d:%d Start Playback PCM\n", subs->cur_audiofmt->iface,