From patchwork Mon Nov 23 08:53:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331471 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 DD083C56202 for ; Mon, 23 Nov 2020 08:57:35 +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 2001720731 for ; Mon, 23 Nov 2020 08:57:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="Lb3Jd7N3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2001720731 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 98CAB167B; Mon, 23 Nov 2020 09:56:43 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 98CAB167B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121853; bh=Ei9PJR33WmTGRPoT9agN5vomPEHjcazjnlMJl/TIQqY=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Lb3Jd7N3X7fDNTBuTTPcPLfMk6fm257dd6gbrBHSBjAW54sQ4ANCpZYbwqV8PDY6e 1Jr4Nnwufkf152dM2NbPjpXOCNSFebUpETysR3OHzFhpsD+KYi1GTwx5f1I8uHvR15 dUqDEgoOvQMRSpBvt3JZM2OVqu3h08vCT2VvQAmo= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id AE957F8051F; Mon, 23 Nov 2020 09:54:18 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id F2B3AF8051C; Mon, 23 Nov 2020 09:54:11 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9EE52F80113 for ; Mon, 23 Nov 2020 09:53:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9EE52F80113 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D7255AF72; Mon, 23 Nov 2020 08:53:56 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 01/41] ALSA: usb-audio: Handle discrete rates properly in hw constraints Date: Mon, 23 Nov 2020 09:53:07 +0100 Message-Id: <20201123085347.19667-2-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" In the current code, when the device provides the discrete sample rate tables with unusual sample rates, the driver tries to gather the whole values from the audioformat entries and create a hw-constraint rule to restrict with this single rate list. This is rather inefficient and may overlook the rates that are associated only with the certain audioformat entries. This patch improves the hw constraint setup by rewriting the existing hw_rule_rate(). The discrete sample rates (identified by rate_table and nr_rates of format entry) are checked in the existing hw_rule_rate() instead of extra rules; in the case of discrete rates, the function compares with each rate table entry and calculates the min/max values from there. For the contiguous rates, the behavior doesn't change. Along with it, snd_usb_pcm_check_knot() and snb_usb_substream rate_list field become superfluous, thus those are dropped. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 1 - sound/usb/pcm.c | 73 +++++++++++------------------------------------------- sound/usb/stream.c | 1 - 3 files changed, 15 insertions(+), 60 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 5351d7183b1b..3cc668f98f43 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -157,7 +157,6 @@ struct snd_usb_substream { u64 formats; /* format bitmasks (all or'ed) */ unsigned int num_formats; /* number of supported audio formats (list) */ struct list_head fmt_list; /* format list */ - struct snd_pcm_hw_constraint_list rate_list; /* limited rates */ spinlock_t lock; int last_frame_number; /* stored frame number */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index a860303cc522..3265155df1b5 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1039,27 +1039,31 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_usb_substream *subs = rule->private; struct audioformat *fp; struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - unsigned int rmin, rmax; + unsigned int rmin, rmax, r; int changed; + int i; hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max); - changed = 0; - rmin = rmax = 0; + rmin = UINT_MAX; + rmax = 0; list_for_each_entry(fp, &subs->fmt_list, list) { if (!hw_check_valid_format(subs, params, fp)) continue; - if (changed++) { - if (rmin > fp->rate_min) - rmin = fp->rate_min; - if (rmax < fp->rate_max) - rmax = fp->rate_max; + if (fp->rate_table && fp->nr_rates) { + for (i = 0; i < fp->nr_rates; i++) { + r = fp->rate_table[i]; + if (!snd_interval_test(it, r)) + continue; + rmin = min(rmin, r); + rmax = max(rmax, r); + } } else { - rmin = fp->rate_min; - rmax = fp->rate_max; + rmin = min(rmin, fp->rate_min); + rmax = max(rmax, fp->rate_max); } } - if (!changed) { + if (rmin > rmax) { hwc_debug(" --> get empty\n"); it->empty = 1; return -EINVAL; @@ -1205,50 +1209,6 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, return changed; } -/* - * If the device supports unusual bit rates, does the request meet these? - */ -static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, - struct snd_usb_substream *subs) -{ - struct audioformat *fp; - int *rate_list; - int count = 0, needs_knot = 0; - int err; - - kfree(subs->rate_list.list); - subs->rate_list.list = NULL; - - list_for_each_entry(fp, &subs->fmt_list, list) { - if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) - return 0; - count += fp->nr_rates; - if (fp->rates & SNDRV_PCM_RATE_KNOT) - needs_knot = 1; - } - if (!needs_knot) - return 0; - - subs->rate_list.list = rate_list = - kmalloc_array(count, sizeof(int), GFP_KERNEL); - if (!subs->rate_list.list) - return -ENOMEM; - subs->rate_list.count = count; - subs->rate_list.mask = 0; - count = 0; - list_for_each_entry(fp, &subs->fmt_list, list) { - int i; - for (i = 0; i < fp->nr_rates; i++) - rate_list[count++] = fp->rate_table[i]; - } - err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &subs->rate_list); - if (err < 0) - return err; - - return 0; -} - /* * set up the runtime hardware information. @@ -1338,9 +1298,6 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre if (err < 0) return err; } - err = snd_usb_pcm_check_knot(runtime, subs); - if (err < 0) - return err; return snd_usb_autoresume(subs->stream->chip); } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index ca76ba5b5c0b..f17913e0b5b4 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -47,7 +47,6 @@ static void free_substream(struct snd_usb_substream *subs) return; /* not initialized */ list_for_each_entry_safe(fp, n, &subs->fmt_list, list) audioformat_free(fp); - kfree(subs->rate_list.list); kfree(subs->str_pd); snd_media_stream_delete(subs); } From patchwork Mon Nov 23 08:53:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330717 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 643A7C2D0E4 for ; Mon, 23 Nov 2020 08:55:52 +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 3D87520731 for ; Mon, 23 Nov 2020 08:55:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="pcn0sogM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3D87520731 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 043AF1612; Mon, 23 Nov 2020 09:54:58 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 043AF1612 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121748; bh=D7ikUyhELWBvxE6AKWKy3Ch+BR8LWe97kkS8KBjtOyk=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=pcn0sogMmyfTBmheRJ1tutUdLjGuT+e7Z6b8udMnsiNgI4e8vKux5uuPH+fh9v3ce lveVjYEkQ2UVvnGhkxbWzMqAgjBj1IFlyURCocENEOVb1LLEbMRrREroLjh2S3tw2x 5BbMjOYVognz0bh2/5PE3gsUo3BoWbP5h94otzDI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 81E84F80507; Mon, 23 Nov 2020 09:54:07 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C4C49F804FF; Mon, 23 Nov 2020 09:54:04 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A684BF8015F for ; Mon, 23 Nov 2020 09:53:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A684BF8015F X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id E5C39AF82; Mon, 23 Nov 2020 08:53:56 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 02/41] ALSA: usb-audio: Don't call usb_set_interface() at trigger callback Date: Mon, 23 Nov 2020 09:53:08 +0100 Message-Id: <20201123085347.19667-3-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 trigger callback is atomic, hence we must not call a function like usb_set_interface() there. Calling it from there would lead to a kernel Oops. Fix it by moving the usb_set_interface() call to set_sync_endpoint(). Also, apply the snd_usb_set_interface_quirk() for consistency, too. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 3265155df1b5..380d7275d187 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -232,21 +232,6 @@ static int start_endpoints(struct snd_usb_substream *subs) !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->sync_endpoint; - if (subs->data_endpoint->iface != subs->sync_endpoint->iface || - subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) { - err = usb_set_interface(subs->dev, - subs->sync_endpoint->iface, - subs->sync_endpoint->altsetting); - if (err < 0) { - clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); - dev_err(&subs->dev->dev, - "%d:%d: cannot set interface (%d)\n", - subs->sync_endpoint->iface, - subs->sync_endpoint->altsetting, err); - return -EIO; - } - } - dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep); ep->sync_slave = subs->data_endpoint; @@ -530,6 +515,19 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, subs->data_endpoint->sync_master = subs->sync_endpoint; + if (subs->data_endpoint->iface != subs->sync_endpoint->iface || + subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) { + err = usb_set_interface(subs->dev, + subs->sync_endpoint->iface, + subs->sync_endpoint->altsetting); + if (err < 0) + return err; + dev_dbg(&dev->dev, "setting usb interface %d:%d\n", + subs->sync_endpoint->iface, + subs->sync_endpoint->altsetting); + snd_usb_set_interface_quirk(dev); + } + return 0; } From patchwork Mon Nov 23 08:53:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331472 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 80177C2D0E4 for ; Mon, 23 Nov 2020 08:56:48 +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 B23EC2078E for ; Mon, 23 Nov 2020 08:56:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="tImuiqr4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B23EC2078E 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 0923085D; Mon, 23 Nov 2020 09:55:56 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 0923085D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121806; bh=3G+gs1B9J3zSMze+zPyR6fDqiHVdOC9Snzva+H2kqYA=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=tImuiqr4bH7YafZkXFg13y2KfxGBKqMOKCHTfrBzIorz0MyGQwoS2b4097HgAym8y XOVnBhJezJV+6IW7R0rKofV+gltnPxqEm5sInLYJl9YxbryMg+9U8rYqm4nk4P3QtD CgknNEpYgcmtCorvOB+HASBidoRQScQqwjJ2PxkA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 973F5F80290; Mon, 23 Nov 2020 09:54:15 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 9DE30F80517; Mon, 23 Nov 2020 09:54:11 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A16ADF8015B for ; Mon, 23 Nov 2020 09:53:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A16ADF8015B X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 00DF5AF86; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 03/41] ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3 Date: Mon, 23 Nov 2020 09:53:09 +0100 Message-Id: <20201123085347.19667-4-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 current driver code assumes blindly that all found sample rates for the same endpoint from the UAC2 and UAC3 descriptors can be used no matter which altsetting, but actually this was wrong: some devices accept only limited sample rates in each altsetting. For determining which altsetting supports which rate, we need to verify each sample rate and check the validity via UAC2_AS_VAL_ALT_SETTINGS. This control reports back the available altsettings as a bitmap. This patch implements the missing piece above, the verification and reconstructs the sample rate tables based on the result. An open question is how to deal with the altsettings that ended up with no valid sample rates after verification. At least, there is a device that showed this problem although the sample rates did work in the later usage (see bug link). For now, we accept such an altset as is, assuming that it's a firmware bug. Reported-by: Dylan Robinson Tested-by: Keith Milner Tested-by: Dylan Robinson BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1178203 Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 106 ++++++++++++++++++++++++++++++----------------------- sound/usb/clock.h | 4 ++ sound/usb/format.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 45 deletions(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index f3ca59005d91..f174230d07d5 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -560,16 +560,60 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, return le32_to_cpu(data); } +/* + * Try to set the given sample rate: + * + * Return 0 if the clock source is read-only, the actual rate on success, + * or a negative error code. + * + * This function gets called from format.c to validate each sample rate, too. + * Hence no message is shown upon error + */ +int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, + const struct audioformat *fmt, + int clock, int rate) +{ + bool writeable; + u32 bmControls; + __le32 data; + int err; + + if (fmt->protocol == UAC_VERSION_3) { + struct uac3_clock_source_descriptor *cs_desc; + + cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock); + bmControls = le32_to_cpu(cs_desc->bmControls); + } else { + struct uac_clock_source_descriptor *cs_desc; + + cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock); + bmControls = cs_desc->bmControls; + } + + writeable = uac_v2v3_control_is_writeable(bmControls, + UAC2_CS_CONTROL_SAM_FREQ); + if (!writeable) + return 0; + + data = cpu_to_le32(rate); + err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + UAC2_CS_CONTROL_SAM_FREQ << 8, + snd_usb_ctrl_intf(chip) | (clock << 8), + &data, sizeof(data)); + if (err < 0) + return err; + + return get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock); +} + static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, - struct audioformat *fmt, int rate) + struct usb_host_interface *alts, + struct audioformat *fmt, int rate) { struct usb_device *dev = chip->dev; - __le32 data; - int err, cur_rate, prev_rate; + int cur_rate, prev_rate; int clock; - bool writeable; - u32 bmControls; /* First, try to find a valid clock. This may trigger * automatic clock selection if the current clock is not @@ -592,50 +636,22 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, if (prev_rate == rate) goto validation; - if (fmt->protocol == UAC_VERSION_3) { - struct uac3_clock_source_descriptor *cs_desc; - - cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock); - bmControls = le32_to_cpu(cs_desc->bmControls); - } else { - struct uac_clock_source_descriptor *cs_desc; - - cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock); - bmControls = cs_desc->bmControls; + cur_rate = snd_usb_set_sample_rate_v2v3(chip, fmt, clock, rate); + if (cur_rate < 0) { + usb_audio_err(chip, + "%d:%d: cannot set freq %d (v2/v3): err %d\n", + iface, fmt->altsetting, rate, cur_rate); + return cur_rate; } - writeable = uac_v2v3_control_is_writeable(bmControls, - UAC2_CS_CONTROL_SAM_FREQ); - if (writeable) { - data = cpu_to_le32(rate); - err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - &data, sizeof(data)); - if (err < 0) { - usb_audio_err(chip, - "%d:%d: cannot set freq %d (v2/v3): err %d\n", - iface, fmt->altsetting, rate, err); - return err; - } - - cur_rate = get_sample_rate_v2v3(chip, iface, - fmt->altsetting, clock); - } else { + if (!cur_rate) cur_rate = prev_rate; - } if (cur_rate != rate) { - if (!writeable) { - usb_audio_warn(chip, - "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n", - iface, fmt->altsetting, rate, cur_rate); - return -ENXIO; - } - usb_audio_dbg(chip, - "current rate %d is different from the runtime rate %d\n", - cur_rate, rate); + usb_audio_warn(chip, + "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n", + fmt->iface, fmt->altsetting, rate, cur_rate); + return -ENXIO; } /* Some devices doesn't respond to sample rate changes while the diff --git a/sound/usb/clock.h b/sound/usb/clock.h index 68df0fbe09d0..97597f5a3c18 100644 --- a/sound/usb/clock.h +++ b/sound/usb/clock.h @@ -9,4 +9,8 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, int snd_usb_clock_find_source(struct snd_usb_audio *chip, struct audioformat *fmt, bool validate); +int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, + const struct audioformat *fmt, + int clock, int rate); + #endif /* __USBAUDIO_CLOCK_H */ diff --git a/sound/usb/format.c b/sound/usb/format.c index 3bfead393aa3..3348032daa16 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -417,6 +417,97 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, return -ENODEV; } +/* check whether the given altsetting is supported for the already set rate */ +static bool check_valid_altsetting_v2v3(struct snd_usb_audio *chip, int iface, + int altsetting) +{ + struct usb_device *dev = chip->dev; + __le64 raw_data = 0; + u64 data; + int err; + + /* we assume 64bit is enough for any altsettings */ + if (snd_BUG_ON(altsetting >= 64 - 8)) + return false; + + err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + UAC2_AS_VAL_ALT_SETTINGS << 8, + iface, &raw_data, sizeof(raw_data)); + if (err < 0) + return false; + + data = le64_to_cpu(raw_data); + /* first byte contains the bitmap size */ + if ((data & 0xff) * 8 < altsetting) + return false; + if (data & (1ULL << (altsetting + 8))) + return true; + + return false; +} + +/* + * Validate each sample rate with the altsetting + * Rebuild the rate table if only partial values are valid + */ +static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, + struct audioformat *fp, + int clock) +{ + struct usb_device *dev = chip->dev; + unsigned int *table; + unsigned int nr_rates; + unsigned int rate_min = 0x7fffffff; + unsigned int rate_max = 0; + unsigned int rates = 0; + int i, err; + + table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + /* clear the interface altsetting at first */ + usb_set_interface(dev, fp->iface, 0); + + nr_rates = 0; + for (i = 0; i < fp->nr_rates; i++) { + err = snd_usb_set_sample_rate_v2v3(chip, fp, clock, + fp->rate_table[i]); + if (err < 0) + continue; + + if (check_valid_altsetting_v2v3(chip, fp->iface, fp->altsetting)) { + table[nr_rates++] = fp->rate_table[i]; + if (rate_min > fp->rate_table[i]) + rate_min = fp->rate_table[i]; + if (rate_max < fp->rate_table[i]) + rate_max = fp->rate_table[i]; + rates |= snd_pcm_rate_to_rate_bit(fp->rate_table[i]); + } + } + + if (!nr_rates) { + usb_audio_dbg(chip, + "No valid sample rate available for %d:%d, assuming a firmware bug\n", + fp->iface, fp->altsetting); + nr_rates = fp->nr_rates; /* continue as is */ + } + + if (fp->nr_rates == nr_rates) { + kfree(table); + return 0; + } + + kfree(fp->rate_table); + fp->rate_table = table; + fp->nr_rates = nr_rates; + fp->rate_min = rate_min; + fp->rate_max = rate_max; + fp->rates = rates; + return 0; +} + /* * parse the format descriptor and stores the possible sample rates * on the audioformat table (audio class v2 and v3). @@ -509,6 +600,8 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, * allocated, so the rates will be stored */ parse_uac2_sample_rate_range(chip, fp, nr_triplets, data); + ret = validate_sample_rate_table_v2v3(chip, fp, clock); + err_free: kfree(data); err: From patchwork Mon Nov 23 08:53:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330716 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 2B4FCC56202 for ; Mon, 23 Nov 2020 08:56:42 +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 5431520731 for ; Mon, 23 Nov 2020 08:56:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="mtmJbzo0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5431520731 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 B3C361688; Mon, 23 Nov 2020 09:55:49 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz B3C361688 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121799; bh=bM4jYkikz7Y+RT2LwD0nC/BvG51BN4zANxI85oTXYk4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=mtmJbzo0Apjloog7XpkfmNDV0nHC/J9oV9dnTdKWby9d+gROY6kEp0ckxk52fFLWR saJ/inKX3vbQjUdYarUdSlcR3uYAhrBUyuDpfZsGkxte5nZ0LxmgtwrwGNT8bciepF vtGsb8MOYsXFNOo+/0IbPzVToydhGxicdTWdyFj8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 498A5F80517; Mon, 23 Nov 2020 09:54:14 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 012D0F8050F; Mon, 23 Nov 2020 09:54:09 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C7A8FF80268 for ; Mon, 23 Nov 2020 09:53:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C7A8FF80268 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 1118AAF8D; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 04/41] ALSA: usb-audio: Check implicit feedback EP generically for UAC2 Date: Mon, 23 Nov 2020 09:53:10 +0100 Message-Id: <20201123085347.19667-5-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 seems that many UAC2 devices are with the implicit feedback, but they couldn't be probed properly because the assumption the driver takes currently isn't applied: they have the single endpoint for both data and implicit-fb streams, while we checked only the classical sync endpoints assigned to the next altsetting in the same interface. This patch extends the search to match with those typical cases where the implicit fb stream is found in the next interface number. While we're at it, slightly refactor the code, not returning 0/-ERROR but use the standard bool to success/failur, which is more intuitive in this particular case. Reported-by: Dylan Robinson Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 380d7275d187..2b11c2c837bf 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -272,33 +272,70 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) return 0; } -static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, - unsigned int altsetting, - struct usb_host_interface **alts, - unsigned int *ep) +/* Check whether the given iface:altsetting points to an implicit fb source */ +static bool search_generic_implicit_fb(struct usb_device *dev, int ifnum, + unsigned int altsetting, + struct usb_host_interface **altsp, + unsigned int *ep) { struct usb_interface *iface; + struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; + struct usb_endpoint_descriptor *epd; + + iface = usb_ifnum_to_if(dev, ifnum); + if (!iface) + return false; + alts = usb_altnum_to_altsetting(iface, altsetting); + if (!alts) + return false; + altsd = get_iface_desc(alts); + if (altsd->bInterfaceClass != USB_CLASS_AUDIO || + altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING || + altsd->bInterfaceProtocol != UAC_VERSION_2 || + altsd->bNumEndpoints < 1) + return false; + epd = get_endpoint(alts, 0); + if (!usb_endpoint_is_isoc_in(epd) || + (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != + USB_ENDPOINT_USAGE_IMPLICIT_FB) + return false; + *ep = epd->bEndpointAddress; + *altsp = alts; + return true; +} + +/* Like the function above, but specific to Roland with vendor class and hack */ +static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum, + unsigned int altsetting, + struct usb_host_interface **altsp, + unsigned int *ep) +{ + struct usb_interface *iface; + struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; struct usb_endpoint_descriptor *epd; iface = usb_ifnum_to_if(dev, ifnum); - if (!iface || iface->num_altsetting < altsetting + 1) - return -ENOENT; - *alts = &iface->altsetting[altsetting]; - altsd = get_iface_desc(*alts); - if (altsd->bAlternateSetting != altsetting || - altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC || + if (!iface) + return false; + alts = usb_altnum_to_altsetting(iface, altsetting); + if (!alts) + return false; + altsd = get_iface_desc(alts); + if (altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC || (altsd->bInterfaceSubClass != 2 && - altsd->bInterfaceProtocol != 2 ) || + altsd->bInterfaceProtocol != 2) || altsd->bNumEndpoints < 1) - return -ENOENT; - epd = get_endpoint(*alts, 0); + return false; + epd = get_endpoint(alts, 0); if (!usb_endpoint_is_isoc_in(epd) || (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != USB_ENDPOINT_USAGE_IMPLICIT_FB) - return -ENOENT; + return false; *ep = epd->bEndpointAddress; - return 0; + *altsp = alts; + return true; } /* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk @@ -375,6 +412,19 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, return 0; } + /* Generic UAC2 implicit feedback */ + if (attr == USB_ENDPOINT_SYNC_ASYNC && + altsd->bInterfaceClass == USB_CLASS_AUDIO && + altsd->bInterfaceProtocol == UAC_VERSION_2 && + altsd->bNumEndpoints == 1) { + ifnum = altsd->bInterfaceNumber + 1; + if (search_generic_implicit_fb(dev, ifnum, + altsd->bAlternateSetting, + &alts, &ep)) + goto add_sync_ep; + } + + /* Roland/BOSS implicit feedback with vendor spec class */ if (attr == USB_ENDPOINT_SYNC_ASYNC && altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && altsd->bInterfaceProtocol == 2 && @@ -382,9 +432,8 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ && search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1, altsd->bAlternateSetting, - &alts, &ep) >= 0) { + &alts, &ep)) goto add_sync_ep; - } /* No quirk */ return 0; From patchwork Mon Nov 23 08:53:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330715 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 75E2EC2D0E4 for ; Mon, 23 Nov 2020 08:57:29 +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 53F4220738 for ; Mon, 23 Nov 2020 08:57:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="sUAGIAdq" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 53F4220738 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 8D92E1616; Mon, 23 Nov 2020 09:56:36 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 8D92E1616 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121846; bh=/80Wxo3ZBHitJnvwBpweaPaqAkVaQ0AlbHTjkacSdjU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=sUAGIAdqjEZsRQceLPSrN4dZS5fvmeYU2bcocEMKd832P7f7hhxjLb+OL5xzl5s8D 3esf9AUjGs3sVv2cfW5KyF1y5hWHSOpUP+v11+SwJcumtt4z1BY/VrnPE1VY3z6WPD ZJklJHB7ehgXOXhVBrtClsocN3oNRDp/L9iJ+DnU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 7F4C9F80520; Mon, 23 Nov 2020 09:54:16 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 3030FF8051B; Mon, 23 Nov 2020 09:54:12 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 0819CF8027C for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 0819CF8027C X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 1F634AF90; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 05/41] ALSA: usb-audio: Add snd_usb_get_endpoint() helper Date: Mon, 23 Nov 2020 09:53:11 +0100 Message-Id: <20201123085347.19667-6-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Factor out the code to obtain snd_usb_endpoint object matching with the given endpoint. It'll be used in the later patch to add the implicit feedback hw-constraint. No functional change by this patch itself. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 36 +++++++++++++++++++++++++++--------- sound/usb/endpoint.h | 4 ++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e2f9ce2f5b8b..cf00871fd278 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -439,6 +439,26 @@ static void snd_complete_urb(struct urb *urb) clear_bit(ctx->index, &ep->active_mask); } +/* + * Get the existing endpoint object corresponding EP, iface and alt numbers + * Returns NULL if not present. + * Call inside chip->mutex locking for avoiding the race. + */ +struct snd_usb_endpoint * +snd_usb_get_endpoint(struct snd_usb_audio *chip, + int ep_num, int iface, int altsetting) +{ + struct snd_usb_endpoint *ep; + + list_for_each_entry(ep, &chip->ep_list, list) { + if (ep->ep_num == ep_num && + ep->iface == iface && + ep->altsetting == altsetting) + return ep; + } + return NULL; +} + /** * snd_usb_add_endpoint: Add an endpoint to an USB audio chip * @@ -470,15 +490,13 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, mutex_lock(&chip->mutex); - list_for_each_entry(ep, &chip->ep_list, list) { - if (ep->ep_num == ep_num && - ep->iface == alts->desc.bInterfaceNumber && - ep->altsetting == alts->desc.bAlternateSetting) { - usb_audio_dbg(ep->chip, - "Re-using EP %x in iface %d,%d @%p\n", - ep_num, ep->iface, ep->altsetting, ep); - goto __exit_unlock; - } + ep = snd_usb_get_endpoint(chip, ep_num, + alts->desc.bInterfaceNumber, + alts->desc.bAlternateSetting); + if (ep) { + usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d @%p\n", + ep_num, ep->iface, ep->altsetting, ep); + goto __exit_unlock; } usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n", diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index d23fa0a8c11b..61487095a766 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -5,6 +5,10 @@ #define SND_USB_ENDPOINT_TYPE_DATA 0 #define SND_USB_ENDPOINT_TYPE_SYNC 1 +struct snd_usb_endpoint *snd_usb_get_endpoint(struct snd_usb_audio *chip, + int ep_num, int iface, + int altsetting); + struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, struct usb_host_interface *alts, int ep_num, int direction, int type); From patchwork Mon Nov 23 08:53:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330711 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 9004EC56202 for ; Mon, 23 Nov 2020 09:00:37 +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 C62D520731 for ; Mon, 23 Nov 2020 09:00:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="Do+p6Pm3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C62D520731 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 38AF61680; Mon, 23 Nov 2020 09:59:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 38AF61680 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122035; bh=7potPxhnn3DNx+oSizO6giIzgsoUPAQbLn1YKSCSVcY=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Do+p6Pm3bEZEGz110kfmMSvmNYFSZgZB37OC2z4id91k4m+QW8rsy6xpQg/cYdfnJ P0347pgb4YvMgqnrQbSHtGdAXWDbiHDEoI7ulS9CSav4ApJj3HsVrXBX/wGaCNDFc7 zmRgSE3AHblKjN9CgmbDQN9e4pwbSXMRt3mYRV/8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 41552F8053C; Mon, 23 Nov 2020 09:54:41 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A5FDEF804C1; Mon, 23 Nov 2020 09:54:19 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3B76FF804BC for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3B76FF804BC X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 30329AF92; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 06/41] ALSA: usb-audio: Set and clear sync EP link properly Date: Mon, 23 Nov 2020 09:53:12 +0100 Message-Id: <20201123085347.19667-7-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 sync EP setup isn't cleared at stopping the stream but expected to be cleared at the next stream start. This may leave the sync link setup stale and can spoof wrongly when full duplex streams were running in the implicit fb sync. Let's initialize them properly at start and end of the stream. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 2b11c2c837bf..8800ec627a73 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -238,6 +238,7 @@ static int start_endpoints(struct snd_usb_substream *subs) err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); + ep->sync_slave = NULL; return err; } } @@ -253,8 +254,10 @@ static void sync_pending_stops(struct snd_usb_substream *subs) static void stop_endpoints(struct snd_usb_substream *subs) { - if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) + if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { snd_usb_endpoint_stop(subs->sync_endpoint); + subs->sync_endpoint->sync_slave = NULL; + } if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) snd_usb_endpoint_stop(subs->data_endpoint); @@ -471,26 +474,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, bool implicit_fb; int err; - /* we need a sync pipe in async OUT or adaptive IN mode */ - /* check the number of EP, since some devices have broken - * descriptors which fool us. if it has only one EP, - * assume it as adaptive-out or sync-in. - */ attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; - if ((is_playback && (attr != USB_ENDPOINT_SYNC_ASYNC)) || - (!is_playback && (attr != USB_ENDPOINT_SYNC_ADAPTIVE))) { - - /* - * In these modes the notion of sync_endpoint is irrelevant. - * Reset pointers to avoid using stale data from previously - * used settings, e.g. when configuration and endpoints were - * changed - */ - - subs->sync_endpoint = NULL; - subs->data_endpoint->sync_master = NULL; - } + subs->sync_endpoint = NULL; + subs->data_endpoint->sync_master = NULL; err = set_sync_ep_implicit_fb_quirk(subs, dev, altsd, attr); if (err < 0) @@ -939,6 +926,11 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) sync_pending_stops(subs); snd_usb_endpoint_deactivate(subs->sync_endpoint); snd_usb_endpoint_deactivate(subs->data_endpoint); + if (subs->data_endpoint) { + subs->data_endpoint->sync_master = NULL; + subs->data_endpoint = NULL; + } + subs->sync_endpoint = NULL; snd_usb_unlock_shutdown(subs->stream->chip); } From patchwork Mon Nov 23 08:53:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331473 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 41F0BC56202 for ; Mon, 23 Nov 2020 08:55:56 +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 D895720738 for ; Mon, 23 Nov 2020 08:55:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="XvEi6dq0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D895720738 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 16F0C15F2; Mon, 23 Nov 2020 09:55:03 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 16F0C15F2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121753; bh=bwOZ6calY1h3OmC7kbXEZV+Ml8cZIgyTHBYTr4fJn4Y=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=XvEi6dq0uzWG4eYkvZHeOs2gvQtJ3VdD4DwDOWrtMiPNMbuX/o+0TZqsnjJt98WP7 j9SdNx/76LcTgJTOexrMpH8fkiwvGTxvkJWEhm9WP1Fe555lsy00BWVn1qrokuNe13 MQd0/nsjuo0KPaU5lPD9Jr0FRGHaFmpBFqLDkDJg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 8F59BF80269; Mon, 23 Nov 2020 09:54:10 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A878AF80515; Mon, 23 Nov 2020 09:54:09 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 052E3F80269 for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 052E3F80269 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 3D306AF93; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 07/41] ALSA: usb-audio: Improve some debug prints Date: Mon, 23 Nov 2020 09:53:13 +0100 Message-Id: <20201123085347.19667-8-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 few rooms for improvements wrt the debug prints: - The EP debug print is shown only at starting, not at stopping - The EP debug print contains useless object addresses - Some helpers show the urb and the EP object addresses, too This patch addresses those shortcomings. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 8 ++++---- sound/usb/pcm.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index cf00871fd278..8205a64a734e 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -367,8 +367,8 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) err = usb_submit_urb(ctx->urb, GFP_ATOMIC); if (err < 0) usb_audio_err(ep->chip, - "Unable to submit urb #%d: %d (urb %p)\n", - ctx->index, err, ctx->urb); + "Unable to submit urb #%d: %d at %s\n", + ctx->index, err, __func__); else set_bit(ctx->index, &ep->active_mask); } @@ -494,8 +494,8 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, alts->desc.bInterfaceNumber, alts->desc.bAlternateSetting); if (ep) { - usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d @%p\n", - ep_num, ep->iface, ep->altsetting, ep); + usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d\n", + ep_num, ep->iface, ep->altsetting); goto __exit_unlock; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 8800ec627a73..8f4fe65d5c37 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -218,7 +218,7 @@ static int start_endpoints(struct snd_usb_substream *subs) if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->data_endpoint; - dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep); + dev_dbg(&subs->dev->dev, "Starting data EP 0x%x\n", ep->ep_num); ep->data_subs = subs; err = snd_usb_endpoint_start(ep); @@ -232,7 +232,7 @@ static int start_endpoints(struct snd_usb_substream *subs) !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->sync_endpoint; - dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep); + dev_dbg(&subs->dev->dev, "Starting sync EP 0x%x\n", ep->ep_num); ep->sync_slave = subs->data_endpoint; err = snd_usb_endpoint_start(ep); @@ -255,12 +255,17 @@ static void sync_pending_stops(struct snd_usb_substream *subs) static void stop_endpoints(struct snd_usb_substream *subs) { if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { + dev_dbg(&subs->dev->dev, "Stopping sync EP 0x%x\n", + subs->sync_endpoint->ep_num); snd_usb_endpoint_stop(subs->sync_endpoint); subs->sync_endpoint->sync_slave = NULL; } - if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) + if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { + dev_dbg(&subs->dev->dev, "Stopping data EP 0x%x\n", + subs->data_endpoint->ep_num); snd_usb_endpoint_stop(subs->data_endpoint); + } } /* PCM sync_stop callback */ From patchwork Mon Nov 23 08:53:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330712 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 6232AC2D0E4 for ; Mon, 23 Nov 2020 08:59:51 +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 94D8820731 for ; Mon, 23 Nov 2020 08:59:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="Ps7MMqCh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 94D8820731 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 11750168F; Mon, 23 Nov 2020 09:58:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 11750168F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121989; bh=Xmq5ZYug4yaLYVEV7AmoECxqIPIOoG3DlD5NkYoW9Fc=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Ps7MMqChs96bONGQjDQYpztQf9ZRih6A92G05t1FafDl1LeV8Iz4pR8j508jpAkLq 8gAy70RFNm3bkrMVcNrWiD3BXDppDhxMWEVvZA4pkx/x4Jk5dOsujeOWcDFf0PFDFG /MihfhJYB5JYBzoSGrLIyTP+5xPl3geVHmKI3CkU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 24807F80539; Mon, 23 Nov 2020 09:54:37 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 57A89F80525; Mon, 23 Nov 2020 09:54:17 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3692FF804B4 for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3692FF804B4 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 4E01BAF94; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 08/41] ALSA: usb-audio: Track implicit fb sync endpoint in audioformat list Date: Mon, 23 Nov 2020 09:53:14 +0100 Message-Id: <20201123085347.19667-9-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Instead of parsing and evaluating the sync endpoint and the implicit feedback mode at each time the audio stream is opened, let's parse it once at the probe time, as the all needed information can be obtained statically from the descriptor or from the quirk. This patch extends audioformat struct to record the sync endpoint, interface and altsetting as well as the implicit feedback flag, which are filled at parsing the streams. Then, set_sync_endpoint() is much simplified just to follow the already parsed data. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 4 ++ sound/usb/pcm.c | 149 +++++++++++++++++++++++++++++++++-------------------- sound/usb/pcm.h | 2 + sound/usb/stream.c | 2 + 4 files changed, 100 insertions(+), 57 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 3cc668f98f43..898a283576df 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -22,6 +22,10 @@ struct audioformat { unsigned char attributes; /* corresponding attributes of cs endpoint */ unsigned char endpoint; /* endpoint */ unsigned char ep_attr; /* endpoint attributes */ + bool implicit_fb; /* implicit feedback endpoint */ + unsigned char sync_ep; /* sync endpoint number */ + unsigned char sync_iface; /* sync EP interface */ + unsigned char sync_altsetting; /* sync EP alternate setting */ unsigned char datainterval; /* log_2 of data packet interval */ unsigned char protocol; /* UAC_VERSION_1/2/3 */ unsigned int maxpacksize; /* max. packet size */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 8f4fe65d5c37..fea2764163b4 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -349,21 +349,18 @@ static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum, /* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk * applies. Returns 1 if a quirk was found. */ -static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, - struct usb_device *dev, - struct usb_interface_descriptor *altsd, - unsigned int attr) +static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_interface *iface, + struct usb_host_interface *alts) { - struct usb_host_interface *alts; - struct usb_interface *iface; + struct usb_device *dev = chip->dev; + struct usb_interface_descriptor *altsd = get_iface_desc(alts); + unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; unsigned int ep; unsigned int ifnum; - /* Implicit feedback sync EPs consumers are always playback EPs */ - if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK) - return 0; - - switch (subs->stream->chip->usb_id) { + switch (chip->usb_id) { case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ case USB_ID(0x22f0, 0x0006): /* Allen&Heath Qu-16 */ @@ -437,11 +434,13 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && altsd->bInterfaceProtocol == 2 && altsd->bNumEndpoints == 1 && - USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ && - search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1, - altsd->bAlternateSetting, - &alts, &ep)) - goto add_sync_ep; + USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) { + ifnum = altsd->bInterfaceNumber + 1; + if (search_roland_implicit_fb(dev, ifnum, + altsd->bAlternateSetting, + &alts, &ep)) + goto add_sync_ep; + } /* No quirk */ return 0; @@ -450,56 +449,59 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, iface = usb_ifnum_to_if(dev, ifnum); if (!iface || iface->num_altsetting < 2) - return -EINVAL; + return 0; alts = &iface->altsetting[1]; add_sync_ep: - subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip, - alts, ep, !subs->direction, - SND_USB_ENDPOINT_TYPE_DATA); - if (!subs->sync_endpoint) - return -EINVAL; - - subs->sync_endpoint->is_implicit_feedback = 1; - - subs->data_endpoint->sync_master = subs->sync_endpoint; + fmt->sync_ep = ep; + fmt->sync_iface = ifnum; + fmt->sync_altsetting = alts->desc.bAlternateSetting; + fmt->implicit_fb = 1; + dev_dbg(&dev->dev, "%d:%d: found implicit_fb sync_ep=%x, iface=%d, alt=%d\n", + fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface, + fmt->sync_altsetting); return 1; } -static int set_sync_endpoint(struct snd_usb_substream *subs, - struct audioformat *fmt, - struct usb_device *dev, - struct usb_host_interface *alts, - struct usb_interface_descriptor *altsd) +int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, + struct audioformat *fmt) { - int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; - unsigned int ep, attr; - bool implicit_fb; + struct usb_device *dev = chip->dev; + struct usb_interface *iface; + struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; + unsigned int ep, attr, sync_attr; + bool is_playback; int err; - attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; - - subs->sync_endpoint = NULL; - subs->data_endpoint->sync_master = NULL; - - err = set_sync_ep_implicit_fb_quirk(subs, dev, altsd, attr); - if (err < 0) - return err; - - /* endpoint set by quirk */ - if (err > 0) + iface = usb_ifnum_to_if(dev, fmt->iface); + if (!iface) + return 0; + alts = usb_altnum_to_altsetting(iface, fmt->altsetting); + if (!alts) return 0; + altsd = get_iface_desc(alts); + + is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN); + if (is_playback) { + err = audioformat_implicit_fb_quirk(chip, fmt, iface, alts); + if (err > 0) + return 0; + } if (altsd->bNumEndpoints < 2) return 0; + attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; if ((is_playback && (attr == USB_ENDPOINT_SYNC_SYNC || attr == USB_ENDPOINT_SYNC_ADAPTIVE)) || (!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE)) return 0; + sync_attr = get_endpoint(alts, 1)->bmAttributes; + /* * In case of illegal SYNC_NONE for OUT endpoint, we keep going to see * if we don't find a sync endpoint, as on M-Audio Transit. In case of @@ -510,7 +512,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, /* ... and check descriptor size before accessing bSynchAddress because there is a version of the SB Audigy 2 NX firmware lacking the audio fields in the endpoint descriptors */ - if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC || + if ((sync_attr & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC || (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && get_endpoint(alts, 1)->bSynchAddress != 0)) { dev_err(&dev->dev, @@ -537,22 +539,57 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, return -EINVAL; } - implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK) - == USB_ENDPOINT_USAGE_IMPLICIT_FB; + fmt->sync_ep = ep; + fmt->sync_iface = altsd->bInterfaceNumber; + fmt->sync_altsetting = altsd->bAlternateSetting; + if ((sync_attr & USB_ENDPOINT_USAGE_MASK) == USB_ENDPOINT_USAGE_IMPLICIT_FB) + fmt->implicit_fb = 1; + + dev_dbg(&dev->dev, "%d:%d: found sync_ep=0x%x, iface=%d, alt=%d, implicit_fb=%d\n", + fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface, + fmt->sync_altsetting, fmt->implicit_fb); + + return 0; +} + +static int set_sync_endpoint(struct snd_usb_substream *subs, + struct audioformat *fmt) +{ + struct usb_device *dev = subs->dev; + struct usb_interface *iface; + struct usb_host_interface *alts; + int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; + unsigned int ep; + int err; + + subs->sync_endpoint = NULL; + subs->data_endpoint->sync_master = NULL; + + ep = fmt->sync_ep; + if (!ep) + return 0; + + iface = usb_ifnum_to_if(dev, fmt->sync_iface); + if (!iface) + return 0; + + alts = usb_altnum_to_altsetting(iface, fmt->altsetting); + if (!alts) + return 0; subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip, alts, ep, !subs->direction, - implicit_fb ? - SND_USB_ENDPOINT_TYPE_DATA : - SND_USB_ENDPOINT_TYPE_SYNC); - + fmt->implicit_fb ? + SND_USB_ENDPOINT_TYPE_DATA : + SND_USB_ENDPOINT_TYPE_SYNC); if (!subs->sync_endpoint) { - if (is_playback && attr == USB_ENDPOINT_SYNC_NONE) + if (is_playback && + (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE) return 0; return -EINVAL; } - subs->sync_endpoint->is_implicit_feedback = implicit_fb; + subs->sync_endpoint->is_implicit_feedback = fmt->implicit_fb; subs->data_endpoint->sync_master = subs->sync_endpoint; @@ -579,7 +616,6 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) { struct usb_device *dev = subs->dev; struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; struct usb_interface *iface; int err; @@ -589,7 +625,6 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) alts = usb_altnum_to_altsetting(iface, fmt->altsetting); if (WARN_ON(!alts)) return -EINVAL; - altsd = get_iface_desc(alts); if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt) return 0; @@ -639,7 +674,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) if (!subs->data_endpoint) return -EINVAL; - err = set_sync_endpoint(subs, fmt, dev, alts, altsd); + err = set_sync_endpoint(subs, fmt); if (err < 0) return err; diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index 9833627c1eca..362782c2df5c 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -14,5 +14,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, struct audioformat *fmt); void snd_usb_preallocate_buffer(struct snd_usb_substream *subs); +int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, + struct audioformat *fmt); #endif /* __USBAUDIO_PCM_H */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index f17913e0b5b4..7087ee2c8174 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1193,6 +1193,8 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, continue; } + snd_usb_audioformat_set_sync_ep(chip, fp); + dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); if (protocol == UAC_VERSION_3) err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); From patchwork Mon Nov 23 08:53:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330714 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 196EFC56202 for ; Mon, 23 Nov 2020 08:58:15 +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 48BCB20732 for ; Mon, 23 Nov 2020 08:58:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="UY3uI+2B" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 48BCB20732 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 A65A01684; Mon, 23 Nov 2020 09:57:22 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A65A01684 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121892; bh=uvYTtIT6vScUbITlnpwUkyTU/FGHxgp2uU0cbuJfcUU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=UY3uI+2BhKqXe3lclLqz8GxN45LTvY/QRGndZHkeG6IwdoE2n8JRYHDqcJiLiRqVR Z7N44RuzYU6BZmgcuoPAACSbdkkDykKJsi2RQtbKypLJIo3n6NfD8MbWInszH/l4L+ MKwWIsNZalCK1e6t8K0YJHUfNu5h+g+k1JrQA+N4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 8ADD4F80525; Mon, 23 Nov 2020 09:54:20 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 89E09F80517; Mon, 23 Nov 2020 09:54:12 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 08098F80273 for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 08098F80273 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 5D15EAF98; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 09/41] ALSA: usb-audio: Move snd_usb_autoresume() call out of setup_hw_info() Date: Mon, 23 Nov 2020 09:53:15 +0100 Message-Id: <20201123085347.19667-10-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" This is a preliminary work for the upcoming hw-constraint change for the implicit feedback mode. Currently snd_usb_autoresume() is called at the end of setup_hwinfo(). It's a bit confusing; because of this implicit refcount usage, the caller side needs to call snd_usb_autosuspend() later in the error path although it's not seen inside the function. Instead, it's clearer to call both snd_usb_autoresume() and suspend() in the very same function. It's only refactoring and no functional changes. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index fea2764163b4..78933b6571d0 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1378,7 +1378,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre return err; } - return snd_usb_autoresume(subs->stream->chip); + return 0; } static int snd_usb_pcm_open(struct snd_pcm_substream *substream) @@ -1402,11 +1402,14 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) subs->dsd_dop.marker = 1; ret = setup_hw_info(runtime, subs); - if (ret == 0) { - ret = snd_media_stream_init(subs, as->pcm, direction); - if (ret) - snd_usb_autosuspend(subs->stream->chip); - } + if (ret < 0) + return ret; + ret = snd_usb_autoresume(subs->stream->chip); + if (ret < 0) + return ret; + ret = snd_media_stream_init(subs, as->pcm, direction); + if (ret < 0) + snd_usb_autosuspend(subs->stream->chip); return ret; } From patchwork Mon Nov 23 08:53:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330713 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 94C6AC2D0E4 for ; Mon, 23 Nov 2020 08:59:06 +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 D1B3020731 for ; Mon, 23 Nov 2020 08:59:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="RXldRh81" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D1B3020731 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 515C2167F; Mon, 23 Nov 2020 09:58:14 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 515C2167F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121944; bh=BqdRASbTjZVs+hLCr/MCcIZHQF/lVvqHdcuIZFzjZuI=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=RXldRh81/zKs8RnMWXvxm0SO+lCkadOnKpmgn3KLl3jgBbxLv1mEMhiyrbi1nsHoR TcrNOmHTXhWnk4mVbF94tS1naZ5UNTAKfqVdJaO6R6m66KKNYYC+k5DMxHaZYW2N1Z sbdirSrqen/pMsZfBHLSZRU9Xuk5mJ7qSHxgCnsM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 54D46F80534; Mon, 23 Nov 2020 09:54:32 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 42B1CF8051B; Mon, 23 Nov 2020 09:54:15 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 09F85F80290 for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 09F85F80290 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 6E1ACAF99; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 10/41] ALSA: usb-audio: Add hw constraint for implicit fb sync Date: Mon, 23 Nov 2020 09:53:16 +0100 Message-Id: <20201123085347.19667-11-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" In the current code, there is no check at the stream open time whether the endpoint is being already used by others. In the normal operations, this shouldn't happen, but in the case of the implicit feedback mode, it's a common problem with the full duplex operation, because the capture stream is always opened by the playback stream as an implicit sync source. Although we recently introduced the check of such a conflict of parameters at the PCM hw_params time, it doesn't give any hint at the hw_params itself and just gives the error. This isn't quite comfortable, and it caused problems on many applications. This patch attempts to make the parameter handling easier by introducing the strict hw constraint matching with the counterpart stream that is being used. That said, when an implicit feedback playback stream is running before a capture stream is opened, the capture stream carries the PCM hw-constraint to allow only the same sample rate, format, periods and period frames as the running playback stream. If not opened or there is no conflict of endpoints, the behavior remains as same as before. Note that this kind of "weak link" should work for most cases, but this is no concrete solution; e.g. if an application changes the hw params multiple times while another stream is opened, this would lead to inconsistencies. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 9 ++++ sound/usb/endpoint.c | 72 ++++++++++++++++++------- sound/usb/pcm.c | 148 +++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 175 insertions(+), 54 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 898a283576df..1f61be98a31d 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -114,6 +114,14 @@ struct snd_usb_endpoint { in a stream */ bool is_implicit_feedback; /* This endpoint is used as implicit feedback */ + /* for hw constraints */ + unsigned int cur_rate; + snd_pcm_format_t cur_format; + unsigned int cur_channels; + unsigned int cur_period_frames; + unsigned int cur_period_bytes; + unsigned int cur_buffer_periods; + spinlock_t lock; struct list_head list; }; @@ -144,6 +152,7 @@ struct snd_usb_substream { unsigned int stream_offset_adj; /* Bytes to drop from beginning of stream (for non-compliant devices) */ unsigned int running: 1; /* running status */ + unsigned int fixed_hw:1; /* fixed hw constraints due to sync EP */ unsigned int hwptr_done; /* processed byte position in the buffer */ unsigned int transfer_done; /* processed frames since last period update */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 8205a64a734e..94490d706013 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -459,6 +459,9 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip, return NULL; } +#define ep_type_name(type) \ + (type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync") + /** * snd_usb_add_endpoint: Add an endpoint to an USB audio chip * @@ -500,9 +503,9 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, } usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n", - is_playback ? "playback" : "capture", - type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", - ep_num); + is_playback ? "playback" : "capture", + ep_type_name(type), + ep_num); ep = kzalloc(sizeof(*ep), GFP_KERNEL); if (!ep) @@ -644,13 +647,14 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) * Check data endpoint for format differences */ static bool check_ep_params(struct snd_usb_endpoint *ep, - snd_pcm_format_t pcm_format, - unsigned int channels, - unsigned int period_bytes, - unsigned int frames_per_period, - unsigned int periods_per_buffer, - struct audioformat *fmt, - struct snd_usb_endpoint *sync_ep) + snd_pcm_format_t pcm_format, + unsigned int channels, + unsigned int period_bytes, + unsigned int frames_per_period, + unsigned int periods_per_buffer, + unsigned int rate, + struct audioformat *fmt, + struct snd_usb_endpoint *sync_ep) { unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb; unsigned int max_packs_per_period, urbs_per_period, urb_packs; @@ -660,6 +664,14 @@ static bool check_ep_params(struct snd_usb_endpoint *ep, usb_pipeout(ep->pipe)); bool ret = 1; + /* matching with the saved parameters? */ + if (ep->cur_rate == rate && + ep->cur_format == pcm_format && + ep->cur_channels == channels && + ep->cur_period_frames == frames_per_period && + ep->cur_buffer_periods == periods_per_buffer) + return true; + if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) { /* * When operating in DSD DOP mode, the size of a sample frame @@ -917,7 +929,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, * as their corresponding capture endpoint. */ if (usb_pipein(ep->pipe) || - snd_usb_endpoint_implicit_feedback_sink(ep)) { + ep->is_implicit_feedback || + snd_usb_endpoint_implicit_feedback_sink(ep)) { urb_packs = packs_per_ms; /* @@ -1076,12 +1089,17 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, { int err; + usb_audio_dbg(ep->chip, + "Setting params for ep %x (type %s, count %d), rate=%d, format=%s, channels=%d, period_bytes=%d, periods=%d\n", + ep->ep_num, ep_type_name(ep->type), ep->use_count, + rate, snd_pcm_format_name(pcm_format), channels, + period_bytes, buffer_periods); + if (ep->use_count != 0) { bool check = ep->is_implicit_feedback && - check_ep_params(ep, pcm_format, - channels, period_bytes, - period_frames, buffer_periods, - fmt, sync_ep); + check_ep_params(ep, pcm_format, channels, period_bytes, + period_frames, buffer_periods, rate, + fmt, sync_ep); if (!check) { usb_audio_warn(ep->chip, @@ -1134,11 +1152,22 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, err = -EINVAL; } - usb_audio_dbg(ep->chip, - "Setting params for ep #%x (type %d, %d urbs), ret=%d\n", - ep->ep_num, ep->type, ep->nurbs, err); + usb_audio_dbg(ep->chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err); - return err; + if (err < 0) + return err; + + /* record the current set up in the endpoint (for implicit fb) */ + spin_lock_irq(&ep->lock); + ep->cur_rate = rate; + ep->cur_channels = channels; + ep->cur_format = pcm_format; + ep->cur_period_frames = period_frames; + ep->cur_period_bytes = period_bytes; + ep->cur_buffer_periods = buffer_periods; + spin_unlock_irq(&ep->lock); + + return 0; } /** @@ -1273,6 +1302,11 @@ void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) deactivate_urbs(ep, true); wait_clear_urbs(ep); + + /* clear the saved hw params */ + spin_lock_irq(&ep->lock); + ep->cur_rate = 0; + spin_unlock_irq(&ep->lock); } /** diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 78933b6571d0..6d1f5277cd90 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -81,30 +81,33 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream /* * find a matching audio format */ -static struct audioformat *find_format(struct snd_usb_substream *subs) +static struct audioformat *find_format(struct list_head *fmt_list_head, + snd_pcm_format_t format, + unsigned int rate, + unsigned int channels, + struct snd_usb_substream *subs) { struct audioformat *fp; struct audioformat *found = NULL; int cur_attr = 0, attr; - list_for_each_entry(fp, &subs->fmt_list, list) { - if (!(fp->formats & pcm_format_to_bits(subs->pcm_format))) + list_for_each_entry(fp, fmt_list_head, list) { + if (!(fp->formats & pcm_format_to_bits(format))) continue; - if (fp->channels != subs->channels) + if (fp->channels != channels) continue; - if (subs->cur_rate < fp->rate_min || - subs->cur_rate > fp->rate_max) + if (rate < fp->rate_min || rate > fp->rate_max) continue; - if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { + if (!(fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { unsigned int i; for (i = 0; i < fp->nr_rates; i++) - if (fp->rate_table[i] == subs->cur_rate) + if (fp->rate_table[i] == rate) break; if (i >= fp->nr_rates) continue; } attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE; - if (! found) { + if (!found) { found = fp; cur_attr = attr; continue; @@ -114,7 +117,7 @@ static struct audioformat *find_format(struct snd_usb_substream *subs) * this is a workaround for the case like * M-audio audiophile USB. */ - if (attr != cur_attr) { + if (subs && attr != cur_attr) { if ((attr == USB_ENDPOINT_SYNC_ASYNC && subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || (attr == USB_ENDPOINT_SYNC_ADAPTIVE && @@ -138,6 +141,12 @@ static struct audioformat *find_format(struct snd_usb_substream *subs) return found; } +static struct audioformat *find_substream_format(struct snd_usb_substream *subs) +{ + return find_format(&subs->fmt_list, subs->pcm_format, subs->cur_rate, + subs->channels, subs); +} + static int init_pitch_v1(struct snd_usb_audio *chip, int iface, struct usb_host_interface *alts, struct audioformat *fmt) @@ -744,7 +753,6 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs, */ static int configure_sync_endpoint(struct snd_usb_substream *subs) { - int ret; struct audioformat *fp; struct audioformat *sync_fp = NULL; int cur_score = 0; @@ -752,16 +760,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) struct snd_usb_substream *sync_subs = &subs->stream->substream[subs->direction ^ 1]; - if (subs->sync_endpoint->type != SND_USB_ENDPOINT_TYPE_DATA || - !subs->stream) - return snd_usb_endpoint_set_params(subs->sync_endpoint, - subs->pcm_format, - subs->channels, - subs->period_bytes, - 0, 0, - subs->cur_rate, - subs->cur_audiofmt, - NULL); + if (subs->fixed_hw || + !subs->sync_endpoint->is_implicit_feedback) { + sync_fp = subs->cur_audiofmt; + goto configure; + } + + sync_fp = find_format(&sync_subs->fmt_list, subs->pcm_format, + subs->cur_rate, subs->channels, NULL); + if (sync_fp) + goto configure; /* Try to find the best matching audioformat. */ list_for_each_entry(fp, &sync_subs->fmt_list, list) { @@ -794,16 +802,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) __func__, subs->period_bytes, sync_period_bytes); } - ret = snd_usb_endpoint_set_params(subs->sync_endpoint, - subs->pcm_format, - sync_fp->channels, - sync_period_bytes, - 0, 0, - subs->cur_rate, - sync_fp, - NULL); - - return ret; + configure: + return snd_usb_endpoint_set_params(subs->sync_endpoint, + subs->pcm_format, + sync_fp->channels, + sync_period_bytes, + subs->period_frames, + subs->buffer_periods, + subs->cur_rate, + sync_fp, + NULL); } /* @@ -912,7 +920,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->channels = params_channels(hw_params); subs->cur_rate = params_rate(hw_params); - fmt = find_format(subs); + fmt = find_substream_format(subs); if (!fmt) { dev_dbg(&subs->dev->dev, "cannot set format: format = %#x, rate = %d, channels = %d\n", @@ -956,12 +964,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, static int snd_usb_hw_free(struct snd_pcm_substream *substream) { struct snd_usb_substream *subs = substream->runtime->private_data; + struct snd_usb_audio *chip = subs->stream->chip; snd_media_stop_pipeline(subs); subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - if (!snd_usb_lock_shutdown(subs->stream->chip)) { + if (!snd_usb_lock_shutdown(chip)) { stop_endpoints(subs); sync_pending_stops(subs); snd_usb_endpoint_deactivate(subs->sync_endpoint); @@ -971,7 +980,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->data_endpoint = NULL; } subs->sync_endpoint = NULL; - snd_usb_unlock_shutdown(subs->stream->chip); + snd_usb_unlock_shutdown(chip); } return 0; @@ -1288,6 +1297,64 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, return changed; } +/* apply PCM hw constraints from the concurrent sync EP */ +static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, + struct snd_usb_substream *subs) +{ + struct snd_usb_audio *chip = subs->stream->chip; + struct snd_usb_endpoint *ep; + struct audioformat *fp; + int err; + + subs->fixed_hw = 0; + list_for_each_entry(fp, &subs->fmt_list, list) { + ep = snd_usb_get_endpoint(chip, fp->endpoint, fp->iface, + fp->altsetting); + if (ep && ep->cur_rate) + goto found; + if (!fp->implicit_fb) + continue; + /* for the implicit fb, check the sync ep as well */ + ep = snd_usb_get_endpoint(chip, fp->sync_ep, fp->sync_iface, + fp->sync_altsetting); + if (ep && ep->cur_rate) + goto found; + } + return 0; + + found: + if (!find_format(&subs->fmt_list, ep->cur_format, ep->cur_rate, + ep->cur_channels, NULL)) { + usb_audio_dbg(chip, "EP 0x%x being used, but not applicable\n", + ep->ep_num); + return 0; + } + + usb_audio_dbg(chip, "EP 0x%x being used, using fixed params:\n", + ep->ep_num); + usb_audio_dbg(chip, "rate=%d, format=%s, channels=%d, period_size=%d, periods=%d\n", + ep->cur_rate, snd_pcm_format_name(ep->cur_format), + ep->cur_channels, ep->cur_period_frames, + ep->cur_buffer_periods); + + runtime->hw.formats = pcm_format_to_bits(ep->cur_format); + runtime->hw.rate_min = runtime->hw.rate_max = ep->cur_rate; + runtime->hw.channels_min = runtime->hw.channels_max = + ep->cur_channels; + runtime->hw.rates = SNDRV_PCM_RATE_KNOT; + runtime->hw.periods_min = runtime->hw.periods_max = + ep->cur_buffer_periods; + subs->fixed_hw = 1; + + err = snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + ep->cur_period_frames, + ep->cur_period_frames); + if (err < 0) + return err; + + return 1; /* notify the finding */ +} /* * set up the runtime hardware information. @@ -1295,11 +1362,20 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) { + struct snd_usb_audio *chip = subs->stream->chip; struct audioformat *fp; unsigned int pt, ptmin; - int param_period_time_if_needed; + int param_period_time_if_needed = -1; int err; + mutex_lock(&chip->mutex); + err = apply_hw_constraint_from_sync(runtime, subs); + mutex_unlock(&chip->mutex); + if (err < 0) + return err; + if (err > 0) /* found the matching? */ + goto add_extra_rules; + runtime->hw.formats = subs->formats; runtime->hw.rate_min = 0x7fffffff; @@ -1350,6 +1426,8 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre -1); if (err < 0) return err; + +add_extra_rules: err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, subs, SNDRV_PCM_HW_PARAM_FORMAT, From patchwork Mon Nov 23 08:53:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331468 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 6CE8AC56202 for ; Mon, 23 Nov 2020 09:00:03 +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 876AB20732 for ; Mon, 23 Nov 2020 09:00:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="pxvJkOhd" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 876AB20732 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 0135985D; Mon, 23 Nov 2020 09:59:11 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 0135985D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122001; bh=SEw26tcJl3GDpzbhoqaskF332gJiDSdG+ONa4OVoWV8=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=pxvJkOhdAd2sZK7cZfRjXzGGMY1klwrMtFANGSm0KL7385YnGbGQJ8wHN62C88ki0 uM46js1j4pnseVPcLoDkzMdR3DLequcRU5EhDVHxqz+hQ8uOqMqUxW2A3hoItxPb3u BSJ1jiqrTJPFKUb5Jo318sghyBvaCezqP72fMwwk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BABECF8053D; Mon, 23 Nov 2020 09:54:39 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 9AB19F80528; Mon, 23 Nov 2020 09:54:19 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 49A15F804C1 for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 49A15F804C1 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 7CDB6AF9C; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 11/41] ALSA: usb-audio: Simplify hw_params rules Date: Mon, 23 Nov 2020 09:53:17 +0100 Message-Id: <20201123085347.19667-12-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Several hw_params functions narrows the interval via min/max rule in the very similar way, so factor out those into a helper function and use commonly. No functional changes, just minor code refactoring. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 110 ++++++++++++++++++++------------------------------------ 1 file changed, 38 insertions(+), 72 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 6d1f5277cd90..ecc6bf9b42f0 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1121,6 +1121,36 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 1; } +static int apply_hw_params_minmax(struct snd_interval *it, unsigned int rmin, + unsigned int rmax) +{ + int changed; + + if (rmin > rmax) { + hwc_debug(" --> get empty\n"); + it->empty = 1; + return -EINVAL; + } + + changed = 0; + if (it->min < rmin) { + it->min = rmin; + it->openmin = 0; + changed = 1; + } + if (it->max > rmax) { + it->max = rmax; + it->openmax = 0; + changed = 1; + } + if (snd_interval_checkempty(it)) { + it->empty = 1; + return -EINVAL; + } + hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); + return changed; +} + static int hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -1128,7 +1158,6 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, struct audioformat *fp; struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); unsigned int rmin, rmax, r; - int changed; int i; hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max); @@ -1151,29 +1180,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, } } - if (rmin > rmax) { - hwc_debug(" --> get empty\n"); - it->empty = 1; - return -EINVAL; - } - - changed = 0; - if (it->min < rmin) { - it->min = rmin; - it->openmin = 0; - changed = 1; - } - if (it->max > rmax) { - it->max = rmax; - it->openmax = 0; - changed = 1; - } - if (snd_interval_checkempty(it)) { - it->empty = 1; - return -EINVAL; - } - hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); - return changed; + return apply_hw_params_minmax(it, rmin, rmax); } @@ -1184,48 +1191,18 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params, struct audioformat *fp; struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); unsigned int rmin, rmax; - int changed; hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max); - changed = 0; - rmin = rmax = 0; + rmin = UINT_MAX; + rmax = 0; list_for_each_entry(fp, &subs->fmt_list, list) { if (!hw_check_valid_format(subs, params, fp)) continue; - if (changed++) { - if (rmin > fp->channels) - rmin = fp->channels; - if (rmax < fp->channels) - rmax = fp->channels; - } else { - rmin = fp->channels; - rmax = fp->channels; - } + rmin = min(rmin, fp->channels); + rmax = max(rmax, fp->channels); } - if (!changed) { - hwc_debug(" --> get empty\n"); - it->empty = 1; - return -EINVAL; - } - - changed = 0; - if (it->min < rmin) { - it->min = rmin; - it->openmin = 0; - changed = 1; - } - if (it->max > rmax) { - it->max = rmax; - it->openmax = 0; - changed = 1; - } - if (snd_interval_checkempty(it)) { - it->empty = 1; - return -EINVAL; - } - hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); - return changed; + return apply_hw_params_minmax(it, rmin, rmax); } static int hw_rule_format(struct snd_pcm_hw_params *params, @@ -1267,7 +1244,6 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, struct snd_interval *it; unsigned char min_datainterval; unsigned int pmin; - int changed; it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max); @@ -1283,18 +1259,8 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, return -EINVAL; } pmin = 125 * (1 << min_datainterval); - changed = 0; - if (it->min < pmin) { - it->min = pmin; - it->openmin = 0; - changed = 1; - } - if (snd_interval_checkempty(it)) { - it->empty = 1; - return -EINVAL; - } - hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed); - return changed; + + return apply_hw_params_minmax(it, pmin, UINT_MAX); } /* apply PCM hw constraints from the concurrent sync EP */ From patchwork Mon Nov 23 08:53:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331470 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 F1D68C56202 for ; Mon, 23 Nov 2020 08:58:32 +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 240D020731 for ; Mon, 23 Nov 2020 08:58:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="NVXYH4lS" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 240D020731 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 91C9410E; Mon, 23 Nov 2020 09:57:40 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 91C9410E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121910; bh=+U1jgdADtbJmR8IfYmHI7auIxeItOEsWtTRnY/lZAY8=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=NVXYH4lSOwrvT97takSxLJEw1jjcdYeVUBi8+Yz9UdBL7pWlh9WKoKnhGMz/9Pbjq w63HBzJGkrhTAinTQvmMA9nAbIf9r07vZ8ISJug/yVVPqk3h4RzDQRULT/mYzET8L5 m+UgWQV8DzTEBapMiUvoTGo44CGh/wIjcPcizJQE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 178D5F80529; Mon, 23 Nov 2020 09:54:30 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 20963F8051E; Mon, 23 Nov 2020 09:54:15 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 31153F8026A for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 31153F8026A X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 8BD60AFAA; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 12/41] ALSA: usb-audio: Drop debug.h Date: Mon, 23 Nov 2020 09:53:18 +0100 Message-Id: <20201123085347.19667-13-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 file debug.h contains a simple macro for debug prints, and it's used only in two places, the format parser and the hw_params rules. The former actually should print a more informative message instead, so the only users are the hw_parmas rules. This patch moves the contents of debug.h into the hw_params rules local code and remove the unneeded includes. Also, the debug print in the format parser is replaced with the information print with more useful information, and the raw printk() call is replaced with pr_debug(). Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.c | 1 - sound/usb/debug.h | 16 ---------------- sound/usb/format.c | 5 +++-- sound/usb/pcm.c | 11 ++++++++++- 4 files changed, 13 insertions(+), 20 deletions(-) delete mode 100644 sound/usb/debug.h diff --git a/sound/usb/card.c b/sound/usb/card.c index 4457214a3ae6..096dd8e3c64b 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -49,7 +49,6 @@ #include "quirks.h" #include "endpoint.h" #include "helper.h" -#include "debug.h" #include "pcm.h" #include "format.h" #include "power.h" diff --git a/sound/usb/debug.h b/sound/usb/debug.h deleted file mode 100644 index 7dd983c35001..000000000000 --- a/sound/usb/debug.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __USBAUDIO_DEBUG_H -#define __USBAUDIO_DEBUG_H - -/* - * h/w constraints - */ - -#ifdef HW_CONST_DEBUG -#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) -#else -#define hwc_debug(fmt, args...) do { } while(0) -#endif - -#endif /* __USBAUDIO_DEBUG_H */ - diff --git a/sound/usb/format.c b/sound/usb/format.c index 3348032daa16..7641716f0c6c 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -16,7 +16,6 @@ #include "card.h" #include "quirks.h" #include "helper.h" -#include "debug.h" #include "clock.h" #include "format.h" @@ -227,7 +226,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof fp->nr_rates++; } if (!fp->nr_rates) { - hwc_debug("All rates were zero. Skipping format!\n"); + usb_audio_info(chip, + "%u:%d: All rates were zero\n", + fp->iface, fp->altsetting); return -EINVAL; } } else { diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index ecc6bf9b42f0..d83a6a6ac023 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -17,7 +17,6 @@ #include "usbaudio.h" #include "card.h" #include "quirks.h" -#include "debug.h" #include "endpoint.h" #include "helper.h" #include "pcm.h" @@ -1061,6 +1060,16 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return ret; } +/* + * h/w constraints + */ + +#ifdef HW_CONST_DEBUG +#define hwc_debug(fmt, args...) pr_debug(fmt, ##args) +#else +#define hwc_debug(fmt, args...) do { } while(0) +#endif + static const struct snd_pcm_hardware snd_usb_hardware = { .info = SNDRV_PCM_INFO_MMAP | From patchwork Mon Nov 23 08:53:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331469 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 EB2A4C2D0E4 for ; Mon, 23 Nov 2020 08:59:16 +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 3281020731 for ; Mon, 23 Nov 2020 08:59:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="d/Nf+0mh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3281020731 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 942FA1693; Mon, 23 Nov 2020 09:58:24 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 942FA1693 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606121954; bh=xsB/jsjf7Aon/wFPbUsmCnEu5AxktczKTY+btqmVrbs=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=d/Nf+0mhCMK/MA1Yx8BKpOIDF9K67VBsfom7agY2/jvx5gYlH4BZSSzcJ4pG2nybp l4VRuREbbF0HHXBJ1qrd/vlQaLzUnjT4APv49eiQSEDqHspMf3bqYrBvzyBQ4+6rIs 3lLolYJK46PStFcNB1EAVfFf9OlO59vC2kA/qYbk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D677AF80537; Mon, 23 Nov 2020 09:54:33 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C1127F80525; Mon, 23 Nov 2020 09:54:16 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 4483DF804BD for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4483DF804BD X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 9B5ECAFAB; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 13/41] ALSA: usb-audio: Avoid doubly initialization for implicit fb Date: Mon, 23 Nov 2020 09:53:19 +0100 Message-Id: <20201123085347.19667-14-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 implicit feedback mode initializes both the main data stream and the sync data stream. When a sync stream was already opened, this would result in the doubly initialization and might screw up things. Add the check of already opened sync streams and skip the unnecessary initialization. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index d83a6a6ac023..8ae7d2fdba0d 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -601,8 +601,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, subs->data_endpoint->sync_master = subs->sync_endpoint; - if (subs->data_endpoint->iface != subs->sync_endpoint->iface || - subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) { + if (!subs->sync_endpoint->use_count && + (subs->data_endpoint->iface != subs->sync_endpoint->iface || + subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) { err = usb_set_interface(subs->dev, subs->sync_endpoint->iface, subs->sync_endpoint->altsetting); @@ -625,6 +626,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) struct usb_device *dev = subs->dev; struct usb_host_interface *alts; struct usb_interface *iface; + struct snd_usb_endpoint *ep; int err; iface = usb_ifnum_to_if(dev, fmt->iface); @@ -637,6 +639,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt) return 0; + /* shared EP with implicit fb */ + if (fmt->implicit_fb && !subs->need_setup_fmt) { + ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint, + fmt->iface, fmt->altsetting); + if (ep && ep->use_count > 0) + goto add_data_ep; + } + /* close the old interface */ if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) { if (!subs->stream->chip->keep_iface) { @@ -673,6 +683,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) snd_usb_set_interface_quirk(dev); } + subs->need_setup_ep = true; + + add_data_ep: subs->interface = fmt->iface; subs->altset_idx = fmt->altset_idx; subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, @@ -686,9 +699,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) if (err < 0) return err; - err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt); - if (err < 0) - return err; + if (subs->need_setup_ep) { + err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt); + if (err < 0) + return err; + } subs->cur_audiofmt = fmt; @@ -940,10 +955,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, if (ret < 0) goto unlock; - subs->interface = fmt->iface; - subs->altset_idx = fmt->altset_idx; - subs->need_setup_ep = true; - unlock: snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) From patchwork Mon Nov 23 08:53:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331467 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 9B3EFC56202 for ; Mon, 23 Nov 2020 09:00:51 +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 8145F20732 for ; Mon, 23 Nov 2020 09:00:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="owxSNHwD" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8145F20732 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 D5B2A16A5; Mon, 23 Nov 2020 09:59:58 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D5B2A16A5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122048; bh=giLoMiQoKE7RLRpeTShX/jlScOkN+OwZI0IF217eZA4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=owxSNHwDjg1VU+tX2BzBnOtmo98rzVDFM9wgX7LnvRT5fO/LtN7b2r05Jv6USwQnq xeeIKMdpFulv1FBRftJC48tIr76qoFad9KxBYH2np2uKPa1wmSvWeSr/9Lme++m6dc HHBLLqb/BWd4jdChFI1/uQyoaBOSG1csI9BmF6C8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 85278F804ED; Mon, 23 Nov 2020 09:54:42 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id CB965F804C3; Mon, 23 Nov 2020 09:54:19 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 5F6B4F804C3 for ; Mon, 23 Nov 2020 09:53:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 5F6B4F804C3 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id A05A5AFAC; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase Date: Mon, 23 Nov 2020 09:53:20 +0100 Message-Id: <20201123085347.19667-15-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Currently snd_usb_endpoint objects are created at first when the substream is opened and tries to assign the endpoints corresponding to the matching audioformat. But since basically the all endpoints have been already parsed and the information have been obtained, we may create the endpoint objects statically at the init phase. It's easier to manage for the implicit fb case, for example. This patch changes the endpoint object management and lets the parser to create the all endpoint objects. This change shouldn't bring any functional changes. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 87 ++++++++++++++++++++-------------------------------- sound/usb/endpoint.h | 10 +++--- sound/usb/pcm.c | 27 ++++++++-------- sound/usb/stream.c | 16 ++++++++++ 4 files changed, 67 insertions(+), 73 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 94490d706013..eb459db511f8 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -440,22 +440,19 @@ static void snd_complete_urb(struct urb *urb) } /* - * Get the existing endpoint object corresponding EP, iface and alt numbers + * Get the existing endpoint object corresponding EP * Returns NULL if not present. - * Call inside chip->mutex locking for avoiding the race. */ struct snd_usb_endpoint * -snd_usb_get_endpoint(struct snd_usb_audio *chip, - int ep_num, int iface, int altsetting) +snd_usb_get_endpoint(struct snd_usb_audio *chip, int ep_num) { struct snd_usb_endpoint *ep; list_for_each_entry(ep, &chip->ep_list, list) { - if (ep->ep_num == ep_num && - ep->iface == iface && - ep->altsetting == altsetting) + if (ep->ep_num == ep_num) return ep; } + return NULL; } @@ -466,14 +463,13 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip, * snd_usb_add_endpoint: Add an endpoint to an USB audio chip * * @chip: The chip - * @alts: The USB host interface * @ep_num: The number of the endpoint to use - * @direction: SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE * @type: SND_USB_ENDPOINT_TYPE_DATA or SND_USB_ENDPOINT_TYPE_SYNC * * If the requested endpoint has not been added to the given chip before, - * a new instance is created. Otherwise, a pointer to the previoulsy - * created instance is returned. In case of any error, NULL is returned. + * a new instance is created. + * + * Returns zero on success or a negative error code. * * New endpoints will be added to chip->ep_list and must be freed by * calling snd_usb_endpoint_free(). @@ -481,74 +477,59 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip, * For SND_USB_ENDPOINT_TYPE_SYNC, the caller needs to guarantee that * bNumEndpoints > 1 beforehand. */ -struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, - struct usb_host_interface *alts, - int ep_num, int direction, int type) +int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type) { struct snd_usb_endpoint *ep; - int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; - - if (WARN_ON(!alts)) - return NULL; + bool is_playback; - mutex_lock(&chip->mutex); - - ep = snd_usb_get_endpoint(chip, ep_num, - alts->desc.bInterfaceNumber, - alts->desc.bAlternateSetting); - if (ep) { - usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d\n", - ep_num, ep->iface, ep->altsetting); - goto __exit_unlock; - } + ep = snd_usb_get_endpoint(chip, ep_num); + if (ep) + return 0; - usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n", - is_playback ? "playback" : "capture", + usb_audio_dbg(chip, "Creating new %s endpoint #%x\n", ep_type_name(type), ep_num); - ep = kzalloc(sizeof(*ep), GFP_KERNEL); if (!ep) - goto __exit_unlock; + return -ENOMEM; ep->chip = chip; spin_lock_init(&ep->lock); ep->type = type; ep->ep_num = ep_num; - ep->iface = alts->desc.bInterfaceNumber; - ep->altsetting = alts->desc.bAlternateSetting; INIT_LIST_HEAD(&ep->ready_playback_urbs); - ep_num &= USB_ENDPOINT_NUMBER_MASK; + is_playback = ((ep_num & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); + ep_num &= USB_ENDPOINT_NUMBER_MASK; if (is_playback) ep->pipe = usb_sndisocpipe(chip->dev, ep_num); else ep->pipe = usb_rcvisocpipe(chip->dev, ep_num); - if (type == SND_USB_ENDPOINT_TYPE_SYNC) { - if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && - get_endpoint(alts, 1)->bRefresh >= 1 && - get_endpoint(alts, 1)->bRefresh <= 9) - ep->syncinterval = get_endpoint(alts, 1)->bRefresh; + list_add_tail(&ep->list, &chip->ep_list); + return 0; +} + +/* Set up syncinterval and maxsyncsize for a sync EP */ +void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep, + struct usb_host_interface *alts) +{ + struct usb_endpoint_descriptor *desc = get_endpoint(alts, 1); + + if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) { + if (desc->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && + desc->bRefresh >= 1 && desc->bRefresh <= 9) + ep->syncinterval = desc->bRefresh; else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL) ep->syncinterval = 1; - else if (get_endpoint(alts, 1)->bInterval >= 1 && - get_endpoint(alts, 1)->bInterval <= 16) - ep->syncinterval = get_endpoint(alts, 1)->bInterval - 1; + else if (desc->bInterval >= 1 && desc->bInterval <= 16) + ep->syncinterval = desc->bInterval - 1; else ep->syncinterval = 3; - ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize); + ep->syncmaxsize = le16_to_cpu(desc->wMaxPacketSize); } - - list_add_tail(&ep->list, &chip->ep_list); - - ep->is_implicit_feedback = 0; - -__exit_unlock: - mutex_unlock(&chip->mutex); - - return ep; } /* diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 61487095a766..76b6de7de991 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -6,12 +6,9 @@ #define SND_USB_ENDPOINT_TYPE_SYNC 1 struct snd_usb_endpoint *snd_usb_get_endpoint(struct snd_usb_audio *chip, - int ep_num, int iface, - int altsetting); + int ep_num); -struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, - struct usb_host_interface *alts, - int ep_num, int direction, int type); +int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type); int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, snd_pcm_format_t pcm_format, @@ -34,6 +31,9 @@ void snd_usb_endpoint_free(struct snd_usb_endpoint *ep); int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep); int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); +void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep, + struct usb_host_interface *alts); void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, struct snd_usb_endpoint *sender, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 8ae7d2fdba0d..03b1a02bcff4 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -585,11 +585,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, if (!alts) return 0; - subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip, - alts, ep, !subs->direction, - fmt->implicit_fb ? - SND_USB_ENDPOINT_TYPE_DATA : - SND_USB_ENDPOINT_TYPE_SYNC); + subs->sync_endpoint = snd_usb_get_endpoint(subs->stream->chip, ep); if (!subs->sync_endpoint) { if (is_playback && (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE) @@ -597,10 +593,14 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, return -EINVAL; } + subs->sync_endpoint->iface = fmt->sync_iface; + subs->sync_endpoint->altsetting = fmt->sync_altsetting; subs->sync_endpoint->is_implicit_feedback = fmt->implicit_fb; subs->data_endpoint->sync_master = subs->sync_endpoint; + snd_usb_endpoint_set_syncinterval(subs->stream->chip, subs->sync_endpoint, alts); + if (!subs->sync_endpoint->use_count && (subs->data_endpoint->iface != subs->sync_endpoint->iface || subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) { @@ -641,8 +641,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) /* shared EP with implicit fb */ if (fmt->implicit_fb && !subs->need_setup_fmt) { - ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint, - fmt->iface, fmt->altsetting); + ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint); if (ep && ep->use_count > 0) goto add_data_ep; } @@ -688,12 +687,12 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) add_data_ep: subs->interface = fmt->iface; subs->altset_idx = fmt->altset_idx; - subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, - alts, fmt->endpoint, subs->direction, - SND_USB_ENDPOINT_TYPE_DATA); - + subs->data_endpoint = snd_usb_get_endpoint(subs->stream->chip, + fmt->endpoint); if (!subs->data_endpoint) return -EINVAL; + subs->data_endpoint->iface = fmt->iface; + subs->data_endpoint->altsetting = fmt->altsetting; err = set_sync_endpoint(subs, fmt); if (err < 0) @@ -1294,15 +1293,13 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, subs->fixed_hw = 0; list_for_each_entry(fp, &subs->fmt_list, list) { - ep = snd_usb_get_endpoint(chip, fp->endpoint, fp->iface, - fp->altsetting); + ep = snd_usb_get_endpoint(chip, fp->endpoint); if (ep && ep->cur_rate) goto found; if (!fp->implicit_fb) continue; /* for the implicit fb, check the sync ep as well */ - ep = snd_usb_get_endpoint(chip, fp->sync_ep, fp->sync_iface, - fp->sync_altsetting); + ep = snd_usb_get_endpoint(chip, fp->sync_ep); if (ep && ep->cur_rate) goto found; } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 7087ee2c8174..816fd3e5aada 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1206,6 +1206,22 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, kfree(pd); return err; } + + /* add endpoints */ + err = snd_usb_add_endpoint(chip, fp->endpoint, + SND_USB_ENDPOINT_TYPE_DATA); + if (err < 0) + return err; + + if (fp->sync_ep) { + err = snd_usb_add_endpoint(chip, fp->sync_ep, + fp->implicit_fb ? + SND_USB_ENDPOINT_TYPE_DATA : + SND_USB_ENDPOINT_TYPE_SYNC); + if (err < 0) + return err; + } + /* try to set the interface... */ usb_set_interface(chip->dev, iface_no, altno); snd_usb_init_pitch(chip, iface_no, alts, fp); From patchwork Mon Nov 23 08:53:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330710 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 46FA9C56202 for ; Mon, 23 Nov 2020 09:01:17 +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 6E0FF20732 for ; Mon, 23 Nov 2020 09:01:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="S5eXuN1c" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6E0FF20732 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 D76B1166C; Mon, 23 Nov 2020 10:00:24 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D76B1166C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122074; bh=AYkLz8/u5opVFSLg2jqoGIWkV7gM7GFqTHIOJYbEyLA=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=S5eXuN1cOQuKUsvQAbw0hAMBV+pytIo7OjaKpJUBAKoQzaTsOIKM9Afp7HfWsZWGy PoPWKalA+DlJO8hZBaLYKwvkQsA4oRVh7nVU1d649+XBwHvsGPCcUOIKcDudmAD/cI zFLWK8NNG5svu+BjlO3rkW1/pVHJNND37lFkOfdg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B2729F80553; Mon, 23 Nov 2020 09:54:43 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id B3E53F80528; Mon, 23 Nov 2020 09:54:20 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 4E7DCF804CB for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4E7DCF804CB X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id AF8D2AFB4; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 15/41] ALSA: usb-audio: Drop keep_interface flag again Date: Mon, 23 Nov 2020 09:53:21 +0100 Message-Id: <20201123085347.19667-16-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" This behavior turned out to be invalid from the USB spec POV and shouldn't be applied. As it's an optional flag that is set only via an card control element that must be hardly used, let's drop it again. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 46 ---------------------------------------------- sound/usb/pcm.c | 17 +++++++---------- sound/usb/usbaudio.h | 3 --- 3 files changed, 7 insertions(+), 59 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 81e987eaf063..12b15ed59eaa 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -3454,48 +3454,6 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) return 0; } -static int keep_iface_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = mixer->chip->keep_iface; - return 0; -} - -static int keep_iface_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); - bool keep_iface = !!ucontrol->value.integer.value[0]; - - if (mixer->chip->keep_iface == keep_iface) - return 0; - mixer->chip->keep_iface = keep_iface; - return 1; -} - -static const struct snd_kcontrol_new keep_iface_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "Keep Interface", - .info = snd_ctl_boolean_mono_info, - .get = keep_iface_ctl_get, - .put = keep_iface_ctl_put, -}; - -static int create_keep_iface_ctl(struct usb_mixer_interface *mixer) -{ - struct snd_kcontrol *kctl = snd_ctl_new1(&keep_iface_ctl, mixer); - - /* need only one control per card */ - if (snd_ctl_find_id(mixer->chip->card, &kctl->id)) { - snd_ctl_free_one(kctl); - return 0; - } - - return snd_ctl_add(mixer->chip->card, kctl); -} - int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, int ignore_error) { @@ -3548,10 +3506,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, if (err < 0) goto _error; - err = create_keep_iface_ctl(mixer); - if (err < 0) - goto _error; - err = snd_usb_mixer_apply_create_quirk(mixer); if (err < 0) goto _error; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 03b1a02bcff4..392aa1cba61c 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -648,14 +648,12 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) /* close the old interface */ if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) { - if (!subs->stream->chip->keep_iface) { - err = usb_set_interface(subs->dev, subs->interface, 0); - if (err < 0) { - dev_err(&dev->dev, - "%d:%d: return to setting 0 failed (%d)\n", - fmt->iface, fmt->altsetting, err); - return -EIO; - } + err = usb_set_interface(subs->dev, subs->interface, 0); + if (err < 0) { + dev_err(&dev->dev, + "%d:%d: return to setting 0 failed (%d)\n", + fmt->iface, fmt->altsetting, err); + return -EIO; } subs->interface = -1; subs->altset_idx = 0; @@ -1483,8 +1481,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) snd_media_stop_pipeline(subs); - if (!as->chip->keep_iface && - subs->interface >= 0 && + if (subs->interface >= 0 && !snd_usb_lock_shutdown(subs->stream->chip)) { usb_set_interface(subs->dev, subs->interface, 0); subs->interface = -1; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 0805b7f21272..aa017a93f7bd 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -53,9 +53,6 @@ struct snd_usb_audio { int setup; /* from the 'device_setup' module param */ bool autoclock; /* from the 'autoclock' module param */ - bool keep_iface; /* keep interface/altset after closing - * or parameter change - */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ struct media_device *media_dev; From patchwork Mon Nov 23 08:53:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330707 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 B891AC56202 for ; Mon, 23 Nov 2020 09:03:24 +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 EC86220731 for ; Mon, 23 Nov 2020 09:03:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="SCqPlfa/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EC86220731 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 66EFB16CC; Mon, 23 Nov 2020 10:02:32 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 66EFB16CC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122202; bh=LTlV4Qsp2M3OvDAp8Xrts5qsqecMpex9CSrpDOQ0woM=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=SCqPlfa/CSke/xC0ov4/Aj51SpPe0d4RopRYfNBwAVVW+JnQs2+04XxvPJ+E+olzo OSz/OCdbMlTafj7ZjuvcOSR522eceVC499L6I5ETaFI+fR7FUpY74qP9ssyG19yNDJ PsmCcWjJ4H9p1D6AN4dEWjA5csIOEDg0I+SSjxv4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 98FF2F804FE; Mon, 23 Nov 2020 09:54:58 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 02664F804D6; Mon, 23 Nov 2020 09:54:27 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7BDB5F804CA for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7BDB5F804CA X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id BECEBAFB5; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 16/41] ALSA: usb-audio: Add snd_usb_get_host_interface() helper Date: Mon, 23 Nov 2020 09:53:22 +0100 Message-Id: <20201123085347.19667-17-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Add a helper function to retrieve the usb_host_interface object from the given interface and altsetting number pair, which is a commonly used procedure in the driver code. No functional changes, just minor code refactoring. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/helper.c | 10 ++++++++++ sound/usb/helper.h | 3 +++ sound/usb/pcm.c | 38 +++++++++++--------------------------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/sound/usb/helper.c b/sound/usb/helper.c index cf92d7110773..a4410267bf70 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -121,3 +121,13 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, return 0; } +struct usb_host_interface * +snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting) +{ + struct usb_interface *iface; + + iface = usb_ifnum_to_if(chip->dev, ifnum); + if (!iface) + return NULL; + return usb_altnum_to_altsetting(iface, altsetting); +} diff --git a/sound/usb/helper.h b/sound/usb/helper.h index f5b4c6647e4d..e2b51ec96ec6 100644 --- a/sound/usb/helper.h +++ b/sound/usb/helper.h @@ -14,6 +14,9 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, struct usb_host_interface *alts); +struct usb_host_interface * +snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting); + /* * retrieve usb_interface descriptor from the host interface * (conditional for compatibility with the older API) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 392aa1cba61c..b0961ebd71f4 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -289,20 +289,16 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) } /* Check whether the given iface:altsetting points to an implicit fb source */ -static bool search_generic_implicit_fb(struct usb_device *dev, int ifnum, +static bool search_generic_implicit_fb(struct snd_usb_audio *chip, int ifnum, unsigned int altsetting, struct usb_host_interface **altsp, unsigned int *ep) { - struct usb_interface *iface; struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; struct usb_endpoint_descriptor *epd; - iface = usb_ifnum_to_if(dev, ifnum); - if (!iface) - return false; - alts = usb_altnum_to_altsetting(iface, altsetting); + alts = snd_usb_get_host_interface(chip, ifnum, altsetting); if (!alts) return false; altsd = get_iface_desc(alts); @@ -322,20 +318,16 @@ static bool search_generic_implicit_fb(struct usb_device *dev, int ifnum, } /* Like the function above, but specific to Roland with vendor class and hack */ -static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum, +static bool search_roland_implicit_fb(struct snd_usb_audio *chip, int ifnum, unsigned int altsetting, struct usb_host_interface **altsp, unsigned int *ep) { - struct usb_interface *iface; struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; struct usb_endpoint_descriptor *epd; - iface = usb_ifnum_to_if(dev, ifnum); - if (!iface) - return false; - alts = usb_altnum_to_altsetting(iface, altsetting); + alts = snd_usb_get_host_interface(chip, ifnum, altsetting); if (!alts) return false; altsd = get_iface_desc(alts); @@ -359,11 +351,11 @@ static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum, */ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, struct audioformat *fmt, - struct usb_interface *iface, struct usb_host_interface *alts) { struct usb_device *dev = chip->dev; struct usb_interface_descriptor *altsd = get_iface_desc(alts); + struct usb_interface *iface; unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; unsigned int ep; unsigned int ifnum; @@ -431,7 +423,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, altsd->bInterfaceProtocol == UAC_VERSION_2 && altsd->bNumEndpoints == 1) { ifnum = altsd->bInterfaceNumber + 1; - if (search_generic_implicit_fb(dev, ifnum, + if (search_generic_implicit_fb(chip, ifnum, altsd->bAlternateSetting, &alts, &ep)) goto add_sync_ep; @@ -444,7 +436,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, altsd->bNumEndpoints == 1 && USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) { ifnum = altsd->bInterfaceNumber + 1; - if (search_roland_implicit_fb(dev, ifnum, + if (search_roland_implicit_fb(chip, ifnum, altsd->bAlternateSetting, &alts, &ep)) goto add_sync_ep; @@ -477,24 +469,20 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, struct audioformat *fmt) { struct usb_device *dev = chip->dev; - struct usb_interface *iface; struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; unsigned int ep, attr, sync_attr; bool is_playback; int err; - iface = usb_ifnum_to_if(dev, fmt->iface); - if (!iface) - return 0; - alts = usb_altnum_to_altsetting(iface, fmt->altsetting); + alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting); if (!alts) return 0; altsd = get_iface_desc(alts); is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN); if (is_playback) { - err = audioformat_implicit_fb_quirk(chip, fmt, iface, alts); + err = audioformat_implicit_fb_quirk(chip, fmt, alts); if (err > 0) return 0; } @@ -564,7 +552,6 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, struct audioformat *fmt) { struct usb_device *dev = subs->dev; - struct usb_interface *iface; struct usb_host_interface *alts; int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; unsigned int ep; @@ -577,11 +564,8 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, if (!ep) return 0; - iface = usb_ifnum_to_if(dev, fmt->sync_iface); - if (!iface) - return 0; - - alts = usb_altnum_to_altsetting(iface, fmt->altsetting); + alts = snd_usb_get_host_interface(subs->stream->chip, fmt->sync_iface, + fmt->altsetting); if (!alts) return 0; From patchwork Mon Nov 23 08:53:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331458 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 6EFA4C2D0E4 for ; Mon, 23 Nov 2020 09:08:03 +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 965E020756 for ; Mon, 23 Nov 2020 09:08:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="Y/JZTw2Z" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 965E020756 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 1482D16E2; Mon, 23 Nov 2020 10:07:11 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 1482D16E2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122481; bh=junKauIDueGgswt/O4uPn/+OwTHe6zkc9xhDLd32BNE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Y/JZTw2Z65wwcdsDazWVOb9Np8GeucVRKMV/nOxRCUJqERVEF0JaeiKu6lUBnz6fl iln6UDA7w4gt4gH46G+WYLogLstpdBAe87R1dQ5gVKTs2iZtkuyhk2gC8DMyW4hVn0 OCOw2mG/OsZ1Zc0yBcAx2gba2cUAiyQ5Ywn5xUY8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D3787F805EE; Mon, 23 Nov 2020 09:55:12 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 15625F8055C; Mon, 23 Nov 2020 09:54:48 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A549EF804E7 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A549EF804E7 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id CEF9BAFBE; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 17/41] ALSA: usb-audio: Don't set altsetting before initializing sample rate Date: Mon, 23 Nov 2020 09:53:23 +0100 Message-Id: <20201123085347.19667-18-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Setting the active altsetting at changing sample rate seems unrecommended. The host should deselect the altsetting at first before that, then select it again. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/stream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 816fd3e5aada..4501e042a944 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1223,9 +1223,10 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, } /* try to set the interface... */ - usb_set_interface(chip->dev, iface_no, altno); + usb_set_interface(chip->dev, iface_no, 0); snd_usb_init_pitch(chip, iface_no, alts, fp); snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); + usb_set_interface(chip->dev, iface_no, altno); } return 0; } From patchwork Mon Nov 23 08:53:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331463 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 3A32FC2D0E4 for ; Mon, 23 Nov 2020 09:04:18 +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 6847020732 for ; Mon, 23 Nov 2020 09:04:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="azbGCV9v" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6847020732 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 D910216C0; Mon, 23 Nov 2020 10:03:25 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D910216C0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122255; bh=iIflz33mnJKdkJ8vKIm6Rhk5ymd17CPrwWDh91AaeIc=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=azbGCV9vhZP/xVgmUFZkr8hJzjgWRR0EGXK6tmFX3qr9/G/+2TyHYG0LBtX9oFoZR Di6zvtKdsY+qdV77Vq5pcmxWE3jr2If37OjGJ5lyVGk0218MIXgUectn6upG1FkkwE UArNpaJlIRQ1vkQo5tBClVSVIFUlIbq5B7tQHJvA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 1B2D1F805AA; Mon, 23 Nov 2020 09:55:02 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 774FEF804DF; Mon, 23 Nov 2020 09:54:31 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 8DF68F804E3 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 8DF68F804E3 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id DCEEAAFBF; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 18/41] ALSA: usb-audio: Pass snd_usb_audio object to quirk functions Date: Mon, 23 Nov 2020 09:53:24 +0100 Message-Id: <20201123085347.19667-19-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" A preliminary patch for the later big change. Just a minor code refactoring. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 4 ++-- sound/usb/pcm.c | 17 +++++++++-------- sound/usb/quirks.c | 10 ++++------ sound/usb/quirks.h | 4 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index f174230d07d5..3298a654ce96 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -658,9 +658,9 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, * interface is active. */ if (rate != prev_rate) { usb_set_interface(dev, iface, 0); - snd_usb_set_interface_quirk(dev); + snd_usb_set_interface_quirk(chip); usb_set_interface(dev, iface, fmt->altsetting); - snd_usb_set_interface_quirk(dev); + snd_usb_set_interface_quirk(chip); } validation: diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b0961ebd71f4..2518d4c82ad5 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -553,6 +553,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, { struct usb_device *dev = subs->dev; struct usb_host_interface *alts; + struct snd_usb_audio *chip = subs->stream->chip; int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; unsigned int ep; int err; @@ -569,7 +570,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, if (!alts) return 0; - subs->sync_endpoint = snd_usb_get_endpoint(subs->stream->chip, ep); + subs->sync_endpoint = snd_usb_get_endpoint(chip, ep); if (!subs->sync_endpoint) { if (is_playback && (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE) @@ -596,7 +597,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, dev_dbg(&dev->dev, "setting usb interface %d:%d\n", subs->sync_endpoint->iface, subs->sync_endpoint->altsetting); - snd_usb_set_interface_quirk(dev); + snd_usb_set_interface_quirk(chip); } return 0; @@ -608,6 +609,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) { struct usb_device *dev = subs->dev; + struct snd_usb_audio *chip = subs->stream->chip; struct usb_host_interface *alts; struct usb_interface *iface; struct snd_usb_endpoint *ep; @@ -625,7 +627,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) /* shared EP with implicit fb */ if (fmt->implicit_fb && !subs->need_setup_fmt) { - ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint); + ep = snd_usb_get_endpoint(chip, fmt->endpoint); if (ep && ep->use_count > 0) goto add_data_ep; } @@ -648,7 +650,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) /* set interface */ if (iface->cur_altsetting != alts) { - err = snd_usb_select_mode_quirk(subs, fmt); + err = snd_usb_select_mode_quirk(chip, fmt); if (err < 0) return -EIO; @@ -661,7 +663,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) } dev_dbg(&dev->dev, "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting); - snd_usb_set_interface_quirk(dev); + snd_usb_set_interface_quirk(chip); } subs->need_setup_ep = true; @@ -669,8 +671,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) add_data_ep: subs->interface = fmt->iface; subs->altset_idx = fmt->altset_idx; - subs->data_endpoint = snd_usb_get_endpoint(subs->stream->chip, - fmt->endpoint); + subs->data_endpoint = snd_usb_get_endpoint(chip, fmt->endpoint); if (!subs->data_endpoint) return -EINVAL; subs->data_endpoint->iface = fmt->iface; @@ -681,7 +682,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) return err; if (subs->need_setup_ep) { - err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt); + err = snd_usb_init_pitch(chip, fmt->iface, alts, fmt); if (err < 0) return err; } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index c50be2f75f70..bb4c1ae0a4a7 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1553,13 +1553,13 @@ static bool is_itf_usb_dsd_dac(unsigned int id) return false; } -int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, +int snd_usb_select_mode_quirk(struct snd_usb_audio *chip, struct audioformat *fmt) { - struct usb_device *dev = subs->dev; + struct usb_device *dev = chip->dev; int err; - if (is_itf_usb_dsd_dac(subs->stream->chip->usb_id)) { + if (is_itf_usb_dsd_dac(chip->usb_id)) { /* First switch to alt set 0, otherwise the mode switch cmd * will not be accepted by the DAC */ @@ -1622,10 +1622,8 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ep->tenor_fb_quirk = 1; } -void snd_usb_set_interface_quirk(struct usb_device *dev) +void snd_usb_set_interface_quirk(struct snd_usb_audio *chip) { - struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev); - if (!chip) return; /* diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index c76cf24a640a..011f22cf2bf6 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -35,12 +35,12 @@ int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep); -void snd_usb_set_interface_quirk(struct usb_device *dev); +void snd_usb_set_interface_quirk(struct snd_usb_audio *chip); void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size); -int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, +int snd_usb_select_mode_quirk(struct snd_usb_audio *chip, struct audioformat *fmt); u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, From patchwork Mon Nov 23 08:53:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330697 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 E5E64C2D0E4 for ; Mon, 23 Nov 2020 09:11:46 +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 2199D20888 for ; Mon, 23 Nov 2020 09:11:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="e/L5f03h" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2199D20888 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 456A416F9; Mon, 23 Nov 2020 10:10:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 456A416F9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122704; bh=j9IqJjtlzMiYFmsfZ7oI1ZHXp33QYIcI/+25HgCjO00=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=e/L5f03hRgYQYEg09V3+4VblQftkjjLIk+9XHBLVyci91jjNfscwXQ+JtPRCrtN59 u0Tt1z+8pEmPMi6Mfd3JlfEhPkjTq9E2tkKnSszDwHPW+SXEGlPH3hJcBVt86Sm7/t 9ra7T3uyVoQpuB9JO+nkd0osvXPMmqIjzTqKjcxQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 26753F80632; Mon, 23 Nov 2020 09:55:20 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 8A105F8015F; Mon, 23 Nov 2020 09:54:58 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9DD3FF804FE for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9DD3FF804FE X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id ECD6EAFC1; Mon, 23 Nov 2020 08:53:57 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 19/41] ALSA: usb-audio: Simplify snd_usb_init_sample_rate() arguments Date: Mon, 23 Nov 2020 09:53:25 +0100 Message-Id: <20201123085347.19667-20-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" A preliminary change for the later big changes. This is a minor code refactoring to drop the unnecessary arguments that can be retrieved in a different way. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 29 +++++++++++++++-------------- sound/usb/clock.h | 3 +-- sound/usb/pcm.c | 2 -- sound/usb/quirks.c | 2 +- sound/usb/stream.c | 2 +- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 3298a654ce96..f25da11fce3a 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -481,15 +481,18 @@ int snd_usb_clock_find_source(struct snd_usb_audio *chip, } } -static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +static int set_sample_rate_v1(struct snd_usb_audio *chip, struct audioformat *fmt, int rate) { struct usb_device *dev = chip->dev; + struct usb_host_interface *alts; unsigned int ep; unsigned char data[3]; int err, crate; + alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting); + if (!alts) + return -EINVAL; if (get_iface_desc(alts)->bNumEndpoints < 1) return -EINVAL; ep = get_endpoint(alts, 0)->bEndpointAddress; @@ -507,7 +510,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, data, sizeof(data)); if (err < 0) { dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n", - iface, fmt->altsetting, rate, ep); + fmt->iface, fmt->altsetting, rate, ep); return err; } @@ -525,7 +528,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, data, sizeof(data)); if (err < 0) { dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n", - iface, fmt->altsetting, ep); + fmt->iface, fmt->altsetting, ep); chip->sample_rate_read_error++; return 0; /* some devices don't support reading */ } @@ -607,8 +610,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, return get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock); } -static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +static int set_sample_rate_v2v3(struct snd_usb_audio *chip, struct audioformat *fmt, int rate) { struct usb_device *dev = chip->dev; @@ -632,7 +634,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, return clock; } - prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock); + prev_rate = get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock); if (prev_rate == rate) goto validation; @@ -640,7 +642,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, if (cur_rate < 0) { usb_audio_err(chip, "%d:%d: cannot set freq %d (v2/v3): err %d\n", - iface, fmt->altsetting, rate, cur_rate); + fmt->iface, fmt->altsetting, rate, cur_rate); return cur_rate; } @@ -657,9 +659,9 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, /* Some devices doesn't respond to sample rate changes while the * interface is active. */ if (rate != prev_rate) { - usb_set_interface(dev, iface, 0); + usb_set_interface(dev, fmt->iface, 0); snd_usb_set_interface_quirk(chip); - usb_set_interface(dev, iface, fmt->altsetting); + usb_set_interface(dev, fmt->iface, fmt->altsetting); snd_usb_set_interface_quirk(chip); } @@ -670,14 +672,13 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, return 0; } -int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +int snd_usb_init_sample_rate(struct snd_usb_audio *chip, struct audioformat *fmt, int rate) { switch (fmt->protocol) { case UAC_VERSION_1: default: - return set_sample_rate_v1(chip, iface, alts, fmt, rate); + return set_sample_rate_v1(chip, fmt, rate); case UAC_VERSION_3: if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { @@ -688,7 +689,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, } fallthrough; case UAC_VERSION_2: - return set_sample_rate_v2v3(chip, iface, alts, fmt, rate); + return set_sample_rate_v2v3(chip, fmt, rate); } } diff --git a/sound/usb/clock.h b/sound/usb/clock.h index 97597f5a3c18..8d406ed294d6 100644 --- a/sound/usb/clock.h +++ b/sound/usb/clock.h @@ -2,8 +2,7 @@ #ifndef __USBAUDIO_CLOCK_H #define __USBAUDIO_CLOCK_H -int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +int snd_usb_init_sample_rate(struct snd_usb_audio *chip, struct audioformat *fmt, int rate); int snd_usb_clock_find_source(struct snd_usb_audio *chip, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 2518d4c82ad5..38b461bdca86 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1017,8 +1017,6 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; ret = snd_usb_init_sample_rate(subs->stream->chip, - subs->cur_audiofmt->iface, - alts, subs->cur_audiofmt, subs->cur_rate); if (ret < 0) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index bb4c1ae0a4a7..018c6f241ffb 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -178,7 +178,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); usb_set_interface(chip->dev, fp->iface, 0); snd_usb_init_pitch(chip, fp->iface, alts, fp); - snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max); + snd_usb_init_sample_rate(chip, fp, fp->rate_max); return 0; error: diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 4501e042a944..23e881985123 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1225,7 +1225,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, /* try to set the interface... */ usb_set_interface(chip->dev, iface_no, 0); snd_usb_init_pitch(chip, iface_no, alts, fp); - snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); + snd_usb_init_sample_rate(chip, fp, fp->rate_max); usb_set_interface(chip->dev, iface_no, altno); } return 0; From patchwork Mon Nov 23 08:53:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330709 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 240ECC63777 for ; Mon, 23 Nov 2020 09:01:55 +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 1033120732 for ; Mon, 23 Nov 2020 09:01:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="OdWCvrad" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1033120732 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 846AA16AE; Mon, 23 Nov 2020 10:01:02 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 846AA16AE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122112; bh=2JnhS3A0gWQW42YqMTutkjvnnfot3fbv0pGV2IFFLW4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=OdWCvradE8mWo6dIuI9jVZTqLkA8VdG+ilMFKnYtsHp0kpDYF57N9bhsH0a+B4saY +8+ngQm5LrF/SQ1yE6dETtuOZjmtpupmAQ96VSMaI3NYnPN7rNWd0I11stZ9ZRbRIn ic/8AhkW9YU4fZFNM5ZXgZlJZzqshv9aJv8zEtcQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 247D7F8055B; Mon, 23 Nov 2020 09:54:50 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 06579F80534; Mon, 23 Nov 2020 09:54:26 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 4F369F804CC for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4F369F804CC X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 07826AFC6; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 20/41] ALSA: usb-audio: Simplify snd_usb_init_pitch() arguments Date: Mon, 23 Nov 2020 09:53:26 +0100 Message-Id: <20201123085347.19667-21-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" A preliminary change for the later big changes. This is a minor code refactoring to drop the unnecessary arguments that can be retrieved in a different way. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 23 +++++++++-------------- sound/usb/pcm.h | 3 +-- sound/usb/quirks.c | 2 +- sound/usb/stream.c | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 38b461bdca86..0998be109af3 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -146,8 +146,7 @@ static struct audioformat *find_substream_format(struct snd_usb_substream *subs) subs->channels, subs); } -static int init_pitch_v1(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +static int init_pitch_v1(struct snd_usb_audio *chip, struct audioformat *fmt) { struct usb_device *dev = chip->dev; @@ -155,9 +154,7 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface, unsigned char data[1]; int err; - if (get_iface_desc(alts)->bNumEndpoints < 1) - return -EINVAL; - ep = get_endpoint(alts, 0)->bEndpointAddress; + ep = fmt->endpoint; data[0] = 1; err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, @@ -166,15 +163,14 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface, data, sizeof(data)); if (err < 0) { usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n", - iface, ep); + fmt->iface, ep); return err; } return 0; } -static int init_pitch_v2(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +static int init_pitch_v2(struct snd_usb_audio *chip, struct audioformat *fmt) { struct usb_device *dev = chip->dev; @@ -188,7 +184,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface, data, sizeof(data)); if (err < 0) { usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n", - iface, fmt->altsetting); + fmt->iface, fmt->altsetting); return err; } @@ -198,8 +194,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface, /* * initialize the pitch control and sample rate */ -int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +int snd_usb_init_pitch(struct snd_usb_audio *chip, struct audioformat *fmt) { /* if endpoint doesn't have pitch control, bail out */ @@ -209,10 +204,10 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, switch (fmt->protocol) { case UAC_VERSION_1: default: - return init_pitch_v1(chip, iface, alts, fmt); + return init_pitch_v1(chip, fmt); case UAC_VERSION_2: - return init_pitch_v2(chip, iface, alts, fmt); + return init_pitch_v2(chip, fmt); } } @@ -682,7 +677,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) return err; if (subs->need_setup_ep) { - err = snd_usb_init_pitch(chip, fmt->iface, alts, fmt); + err = snd_usb_init_pitch(chip, fmt); if (err < 0) return err; } diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index 362782c2df5c..a4f784225abc 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -9,8 +9,7 @@ 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); -int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, - struct usb_host_interface *alts, +int snd_usb_init_pitch(struct snd_usb_audio *chip, struct audioformat *fmt); void snd_usb_preallocate_buffer(struct snd_usb_substream *subs); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 018c6f241ffb..013ab93fb640 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -177,7 +177,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, if (fp->maxpacksize == 0) fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); usb_set_interface(chip->dev, fp->iface, 0); - snd_usb_init_pitch(chip, fp->iface, alts, fp); + snd_usb_init_pitch(chip, fp); snd_usb_init_sample_rate(chip, fp, fp->rate_max); return 0; diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 23e881985123..7f58c7625cd4 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1224,7 +1224,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, /* try to set the interface... */ usb_set_interface(chip->dev, iface_no, 0); - snd_usb_init_pitch(chip, iface_no, alts, fp); + snd_usb_init_pitch(chip, fp); snd_usb_init_sample_rate(chip, fp, fp->rate_max); usb_set_interface(chip->dev, iface_no, altno); } From patchwork Mon Nov 23 08:53:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331466 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 207D7C56202 for ; Mon, 23 Nov 2020 09:01:38 +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 4D8EF20732 for ; Mon, 23 Nov 2020 09:01:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="QsudsO3j" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4D8EF20732 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 B9F7F16A9; Mon, 23 Nov 2020 10:00:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz B9F7F16A9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122095; bh=pgyAev7qeTgsJ3w4rbRF0vZN/m5SslFBpvms0e0nvao=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=QsudsO3juEYPmyv+vyOr8NfjaYHzQ36MM8vyT5YxfIH8Ni1TXS3QhujpnBGsIz32K HRwTtI2vY3FmJfGoWj2ZURzR3Q0NGx5VapeX2MGQCtsgDTQYaH4xtaC7kXxEwQE+Aw TSRnJZpAvASHtiLfPtlqbYVExgyLFGBTrHzqax5E= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 73120F8055A; Mon, 23 Nov 2020 09:54:46 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C7A03F80529; Mon, 23 Nov 2020 09:54:21 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 4DB44F804C2 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4DB44F804C2 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 16DFBAFC8; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 21/41] ALSA: usb-audio: Stop both endpoints properly at error Date: Mon, 23 Nov 2020 09:53:27 +0100 Message-Id: <20201123085347.19667-22-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" start_endpoints() may leave the data endpoint running if an error happens at starting the sync endpoint. We should stop both streams properly, instead. While we're at it, move the debug prints into the endpoint.c that is a more suitable place. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 6 ++++++ sound/usb/pcm.c | 39 +++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index eb459db511f8..0cc7e9c01263 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1172,6 +1172,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (atomic_read(&ep->chip->shutdown)) return -EBADFD; + usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (count %d)\n", + ep_type_name(ep->type), ep->ep_num, ep->use_count); + /* already running? */ if (++ep->use_count != 1) return 0; @@ -1254,6 +1257,9 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) if (!ep) return; + usb_audio_dbg(ep->chip, "Stopping %s EP 0x%x (count %d)\n", + ep_type_name(ep->type), ep->ep_num, ep->use_count); + if (snd_BUG_ON(ep->use_count == 0)) return; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0998be109af3..c4e39aa92a84 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -211,6 +211,17 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, } } +static void stop_endpoints(struct snd_usb_substream *subs) +{ + if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { + snd_usb_endpoint_stop(subs->sync_endpoint); + subs->sync_endpoint->sync_slave = NULL; + } + + if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) + snd_usb_endpoint_stop(subs->data_endpoint); +} + static int start_endpoints(struct snd_usb_substream *subs) { int err; @@ -221,13 +232,11 @@ static int start_endpoints(struct snd_usb_substream *subs) if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->data_endpoint; - dev_dbg(&subs->dev->dev, "Starting data EP 0x%x\n", ep->ep_num); - ep->data_subs = subs; err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); - return err; + goto error; } } @@ -235,18 +244,20 @@ static int start_endpoints(struct snd_usb_substream *subs) !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->sync_endpoint; - dev_dbg(&subs->dev->dev, "Starting sync EP 0x%x\n", ep->ep_num); - ep->sync_slave = subs->data_endpoint; err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); ep->sync_slave = NULL; - return err; + goto error; } } return 0; + + error: + stop_endpoints(subs); + return err; } static void sync_pending_stops(struct snd_usb_substream *subs) @@ -255,22 +266,6 @@ static void sync_pending_stops(struct snd_usb_substream *subs) snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); } -static void stop_endpoints(struct snd_usb_substream *subs) -{ - if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { - dev_dbg(&subs->dev->dev, "Stopping sync EP 0x%x\n", - subs->sync_endpoint->ep_num); - snd_usb_endpoint_stop(subs->sync_endpoint); - subs->sync_endpoint->sync_slave = NULL; - } - - if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { - dev_dbg(&subs->dev->dev, "Stopping data EP 0x%x\n", - subs->data_endpoint->ep_num); - snd_usb_endpoint_stop(subs->data_endpoint); - } -} - /* PCM sync_stop callback */ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) { From patchwork Mon Nov 23 08:53:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331460 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 B33D5C2D0E4 for ; Mon, 23 Nov 2020 09:06: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 CA7EE20731 for ; Mon, 23 Nov 2020 09:06:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="KFkZ+w8P" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CA7EE20731 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 3E7D9168E; Mon, 23 Nov 2020 10:05:41 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 3E7D9168E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122391; bh=8V6FC/5DRb0UCefESLlSf8eHWCxqNU0NBT44qqbPXHI=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=KFkZ+w8P65IvgyY7SnUSNvDpkSs8ufxuLiSJNN2x2Rv8XItmSS/XXtg/cnyB8BLVU LhicsvmaXGK1iMR34eQlPSswY1KQCGOuQ3RAKOFeG/pASk22zEcB325LjONlxzqa5+ DdUUWXWGBB9ia2aNwtxOVjad+1bWeTXLWMWngEnM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 14CCFF805DA; Mon, 23 Nov 2020 09:55:10 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id EC6F5F8053C; Mon, 23 Nov 2020 09:54:39 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9CFC8F804E6 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9CFC8F804E6 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 28CDDAFC9; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 22/41] ALSA: usb-audio: Set callbacks via snd_usb_endpoint_set_callback() Date: Mon, 23 Nov 2020 09:53:28 +0100 Message-Id: <20201123085347.19667-23-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 prepare_data_urb and retire_data_urb fields of the endpoint object are set dynamically at PCM trigger start/stop. Those are evaluated in the endpoint handler, but there can be a race, especially if two different PCM substreams are handling the same endpoint for the implicit feedback case. Also, the data_subs field of the endpoint is set and accessed dynamically, too, which has the same risk. As a slight improvement for the concurrency, this patch introduces the function to set the callbacks and the data in a shot with the memory barrier. In the reader side, it's also fetched with the memory barrier. There is still a room of race if prepare and retire callbacks are set during executing the URB completion. But such an inconsistency may happen only for the implicit fb source, i.e. it's only about the capture stream. And luckily, the capture stream never sets the prepare callback, hence the problem doesn't happen practically. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 60 +++++++++++++++++++++++++++++++++++----------------- sound/usb/endpoint.h | 7 ++++++ sound/usb/pcm.c | 33 ++++++++++++++++------------- 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 0cc7e9c01263..7012fdafc3d8 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -169,11 +169,20 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) return ret; } +static void call_retire_callback(struct snd_usb_endpoint *ep, + struct urb *urb) +{ + struct snd_usb_substream *data_subs; + + data_subs = READ_ONCE(ep->data_subs); + if (data_subs && ep->retire_data_urb) + ep->retire_data_urb(data_subs, urb); +} + static void retire_outbound_urb(struct snd_usb_endpoint *ep, struct snd_urb_ctx *urb_ctx) { - if (ep->retire_data_urb) - ep->retire_data_urb(ep->data_subs, urb_ctx->urb); + call_retire_callback(ep, urb_ctx->urb); } static void retire_inbound_urb(struct snd_usb_endpoint *ep, @@ -189,8 +198,7 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, if (ep->sync_slave) snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); - if (ep->retire_data_urb) - ep->retire_data_urb(ep->data_subs, urb); + call_retire_callback(ep, urb); } static void prepare_silent_urb(struct snd_usb_endpoint *ep, @@ -244,17 +252,17 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, { struct urb *urb = ctx->urb; unsigned char *cp = urb->transfer_buffer; + struct snd_usb_substream *data_subs; urb->dev = ep->chip->dev; /* we need to set this at each time */ switch (ep->type) { case SND_USB_ENDPOINT_TYPE_DATA: - if (ep->prepare_data_urb) { - ep->prepare_data_urb(ep->data_subs, urb); - } else { - /* no data provider, so send silence */ + data_subs = READ_ONCE(ep->data_subs); + if (data_subs && ep->prepare_data_urb) + ep->prepare_data_urb(data_subs, urb); + else /* no data provider, so send silence */ prepare_silent_urb(ep, ctx); - } break; case SND_USB_ENDPOINT_TYPE_SYNC: @@ -381,7 +389,7 @@ static void snd_complete_urb(struct urb *urb) { struct snd_urb_ctx *ctx = urb->context; struct snd_usb_endpoint *ep = ctx->ep; - struct snd_pcm_substream *substream; + struct snd_usb_substream *data_subs; unsigned long flags; int err; @@ -430,10 +438,9 @@ static void snd_complete_urb(struct urb *urb) return; usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); - if (ep->data_subs && ep->data_subs->pcm_substream) { - substream = ep->data_subs->pcm_substream; - snd_pcm_stop_xrun(substream); - } + data_subs = READ_ONCE(ep->data_subs); + if (data_subs && data_subs->pcm_substream) + snd_pcm_stop_xrun(data_subs->pcm_substream); exit_clear: clear_bit(ctx->index, &ep->active_mask); @@ -532,6 +539,24 @@ void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip, } } +/* + * Set data endpoint callbacks and the assigned data stream + * + * Called at PCM trigger and cleanups. + * Pass NULL to deactivate each callback. + */ +void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, + void (*prepare)(struct snd_usb_substream *subs, + struct urb *urb), + void (*retire)(struct snd_usb_substream *subs, + struct urb *urb), + struct snd_usb_substream *data_subs) +{ + ep->prepare_data_urb = prepare; + ep->retire_data_urb = retire; + WRITE_ONCE(ep->data_subs, data_subs); +} + /* * wait until all urbs are processed. */ @@ -554,10 +579,8 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) alive, ep->ep_num); clear_bit(EP_FLAG_STOPPING, &ep->flags); - ep->data_subs = NULL; ep->sync_slave = NULL; - ep->retire_data_urb = NULL; - ep->prepare_data_urb = NULL; + snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); return 0; } @@ -607,8 +630,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) int i; /* route incoming urbs to nirvana */ - ep->retire_data_urb = NULL; - ep->prepare_data_urb = NULL; + snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); /* stop urbs */ deactivate_urbs(ep, force); diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 76b6de7de991..e2fddb3dcf7a 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -20,6 +20,13 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, struct audioformat *fmt, struct snd_usb_endpoint *sync_ep); +void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, + void (*prepare)(struct snd_usb_substream *subs, + struct urb *urb), + void (*retire)(struct snd_usb_substream *subs, + struct urb *urb), + struct snd_usb_substream *data_subs); + int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index c4e39aa92a84..32237623de96 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -232,7 +232,6 @@ static int start_endpoints(struct snd_usb_substream *subs) if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { struct snd_usb_endpoint *ep = subs->data_endpoint; - ep->data_subs = subs; err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); @@ -1830,18 +1829,24 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea subs->trigger_tstamp_pending_update = true; fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - subs->data_endpoint->prepare_data_urb = prepare_playback_urb; - subs->data_endpoint->retire_data_urb = retire_playback_urb; + snd_usb_endpoint_set_callback(subs->data_endpoint, + prepare_playback_urb, + retire_playback_urb, + subs); subs->running = 1; return 0; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, NULL, NULL); subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - subs->data_endpoint->prepare_data_urb = NULL; /* keep retire_data_urb for delay calculation */ - subs->data_endpoint->retire_data_urb = retire_playback_urb; + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, + retire_playback_urb, + subs); subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_SUSPEND: @@ -1867,23 +1872,21 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream err = start_endpoints(subs); if (err < 0) return err; - - subs->data_endpoint->retire_data_urb = retire_capture_urb; + fallthrough; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, retire_capture_urb, + subs); subs->running = 1; return 0; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); - subs->data_endpoint->retire_data_urb = NULL; - subs->running = 0; - return 0; + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - subs->data_endpoint->retire_data_urb = NULL; + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, NULL, NULL); subs->running = 0; return 0; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - subs->data_endpoint->retire_data_urb = retire_capture_urb; - subs->running = 1; - return 0; case SNDRV_PCM_TRIGGER_SUSPEND: if (subs->stream->chip->setup_fmt_after_resume_quirk) { stop_endpoints(subs); From patchwork Mon Nov 23 08:53:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331464 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 2D8C5C2D0E4 for ; Mon, 23 Nov 2020 09:03:11 +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 61EF620724 for ; Mon, 23 Nov 2020 09:03:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="jYa22Dlq" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 61EF620724 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 C921E16C3; Mon, 23 Nov 2020 10:02:18 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C921E16C3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122188; bh=sFQK55Xo29stmXsXL7ZK2tWIrc7BQvtcGBaNAawLku4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=jYa22DlqpNP0qZu4rHXGtQjUN8t3CnbWHpvjfiKqE2DZZewG5nqBkkan787zinjg7 J5qojIk90AlKp2Q4LvELkxeSB+cah6ZeCL98nCXNPsuCGzMOeQAR7iEC5RtAHoVxNC OiecOC87krwhNDbRrqXGTZF1Utk1v7q0Tu3Mp3RI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 1AEB5F804FA; Mon, 23 Nov 2020 09:54:55 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7A116F804DF; Mon, 23 Nov 2020 09:54:27 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7286EF804D6 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7286EF804D6 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 37019AFCB; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 23/41] ALSA: usb-audio: Always set up the parameters after resume Date: Mon, 23 Nov 2020 09:53:29 +0100 Message-Id: <20201123085347.19667-24-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 commit 92adc96f8eec ("ALSA: usb-audio: set the interface format after resume on Dell WD19") introduced the workaround for the broken setup after the resume specifically on a Dell dock model. However, the full setup should have been performed after the resume on all devices, as we can't guarantee the same state. So this patch removes the conditional check and applies the workaround always. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 20 ++++++-------------- sound/usb/quirks-table.h | 8 -------- sound/usb/quirks.c | 11 ----------- sound/usb/usbaudio.h | 1 - 4 files changed, 6 insertions(+), 34 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 32237623de96..ac6385a4eb70 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1835,6 +1835,9 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea subs); subs->running = 1; return 0; + case SNDRV_PCM_TRIGGER_SUSPEND: + subs->need_setup_fmt = true; + fallthrough; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); snd_usb_endpoint_set_callback(subs->data_endpoint, @@ -1849,13 +1852,6 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea subs); subs->running = 0; return 0; - case SNDRV_PCM_TRIGGER_SUSPEND: - if (subs->stream->chip->setup_fmt_after_resume_quirk) { - stop_endpoints(subs); - subs->need_setup_fmt = true; - return 0; - } - break; } return -EINVAL; @@ -1879,6 +1875,9 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream subs); subs->running = 1; return 0; + case SNDRV_PCM_TRIGGER_SUSPEND: + subs->need_setup_fmt = true; + fallthrough; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); fallthrough; @@ -1887,13 +1886,6 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream NULL, NULL, NULL); subs->running = 0; return 0; - case SNDRV_PCM_TRIGGER_SUSPEND: - if (subs->stream->chip->setup_fmt_after_resume_quirk) { - stop_endpoints(subs); - subs->need_setup_fmt = true; - return 0; - } - break; } return -EINVAL; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 3c1697f6b60c..85b99c6d3c61 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3256,14 +3256,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, -/* Dell WD19 Dock */ -{ - USB_DEVICE(0x0bda, 0x402e), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_SETUP_FMT_AFTER_RESUME - } -}, /* MOTU Microbook II */ { USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 013ab93fb640..7e7f258011ff 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -508,16 +508,6 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip, return snd_usb_create_mixer(chip, quirk->ifnum, 0); } - -static int setup_fmt_after_resume_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - chip->setup_fmt_after_resume_quirk = 1; - return 1; /* Continue with creating streams and mixer */ -} - static int setup_disable_autosuspend(struct snd_usb_audio *chip, struct usb_interface *iface, struct usb_driver *driver, @@ -565,7 +555,6 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk, [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, - [QUIRK_SETUP_FMT_AFTER_RESUME] = setup_fmt_after_resume_quirk, [QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend, }; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index aa017a93f7bd..cc338e8e2597 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -35,7 +35,6 @@ struct snd_usb_audio { wait_queue_head_t shutdown_wait; unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ unsigned int tx_length_quirk:1; /* Put length specifier in transfers */ - unsigned int setup_fmt_after_resume_quirk:1; /* setup the format to interface after resume */ unsigned int need_delayed_register:1; /* warn for delayed registration */ int num_interfaces; int num_suspended_intf; From patchwork Mon Nov 23 08:53:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330708 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 C5B7FC63777 for ; Mon, 23 Nov 2020 09:02:38 +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 0C0142078E for ; Mon, 23 Nov 2020 09:02:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="hw12C5sk" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0C0142078E 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 75DDA16BF; Mon, 23 Nov 2020 10:01:46 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 75DDA16BF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122156; bh=ujR70FJzM8byzUAFZnnbiGs+hY9QYMa1+Uyf8UjlN/E=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=hw12C5skV9hyAsMasqQTEdvWk47sub73lL0gaMLmknjSQakYNMtE58NGTLeqy9TVJ H9BeZq0k7wkcWe1791OuqyNfr34Sx6o4i5K+WesT7/+Y7bnXy5tjZ0Ksz9Y7WcWQzQ 6OSCDu1UYE3Ey7RjvVqvNcnUM7t7uZSx3u9VRmHQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 5D6F3F80567; Mon, 23 Nov 2020 09:54:53 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 65ABEF80529; Mon, 23 Nov 2020 09:54:26 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 725FFF804D2 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 725FFF804D2 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 46117AE30; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 24/41] ALSA: usb-audio: Fix EP matching for continuous rates Date: Mon, 23 Nov 2020 09:53:30 +0100 Message-Id: <20201123085347.19667-25-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 function to evaluate the match of the parameters with an EP assumes only the discrete rate tables and doesn't handle the continuous rates properly. This patch fixes match_endpoint_audioformats() to handle the continuous rates. Also the almost useless debug prints there are dropped. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index ac6385a4eb70..45a692512d27 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -695,41 +695,30 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs, struct audioformat *match, int rate, snd_pcm_format_t pcm_format) { - int i; - int score = 0; + int i, score; - if (fp->channels < 1) { - dev_dbg(&subs->dev->dev, - "%s: (fmt @%p) no channels\n", __func__, fp); + if (fp->channels < 1) return 0; - } - if (!(fp->formats & pcm_format_to_bits(pcm_format))) { - dev_dbg(&subs->dev->dev, - "%s: (fmt @%p) no match for format %d\n", __func__, - fp, pcm_format); + if (!(fp->formats & pcm_format_to_bits(pcm_format))) return 0; - } - for (i = 0; i < fp->nr_rates; i++) { - if (fp->rate_table[i] == rate) { - score++; - break; + if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) { + if (rate < fp->rate_min || rate > fp->rate_max) + return 0; + } else { + for (i = 0; i < fp->nr_rates; i++) { + if (fp->rate_table[i] == rate) + break; } - } - if (!score) { - dev_dbg(&subs->dev->dev, - "%s: (fmt @%p) no match for rate %d\n", __func__, - fp, rate); - return 0; + if (i >= fp->nr_rates) + return 0; } + score = 1; if (fp->channels == match->channels) score++; - dev_dbg(&subs->dev->dev, - "%s: (fmt @%p) score %d\n", __func__, fp, score); - return score; } From patchwork Mon Nov 23 08:53:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330702 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 DEA75C2D0E4 for ; Mon, 23 Nov 2020 09:07:37 +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 E3D6220738 for ; Mon, 23 Nov 2020 09:07:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="TnJsbEOa" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E3D6220738 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 29BA216F1; Mon, 23 Nov 2020 10:06:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 29BA216F1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122455; bh=fUONp+XAk1lg8+paeAerxut1gzW6bhIRMPRptRRSqk8=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=TnJsbEOac+r86t7n8sRL56lYhNx7ontR8aRxR9vigDuJtd4eVRxcagp0ZqNIQpu/3 CFrWJgwImIHIQX2lemDIKIA5GdVVIyL508wffj1wxX9fbozCRjF1aM8EGF1+ldvA55 xPOLNlY78u4eL5qjcxQYQFCWRdhDxhUvjPhlX8EI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 1E3ADF805EA; Mon, 23 Nov 2020 09:55:12 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C50D6F8055C; Mon, 23 Nov 2020 09:54:46 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 8B0C2F804E0 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 8B0C2F804E0 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 5371AAFB0; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 25/41] ALSA: usb-audio: Refactor endpoint management Date: Mon, 23 Nov 2020 09:53:31 +0100 Message-Id: <20201123085347.19667-26-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" This is an intensive surgery for the endpoint and stream management for achieving more robust and clean code. The goals of this patch are: - More clear endpoint resource changes - The interface altsetting control in a single place Below are brief description of the whole changes. First off, most of the endpoint operations are moved into endpoint.c, so that the snd_usb_endpoint object is only referred in other places. The endpoint object is acquired and released via the new functions snd_usb_endpoint_open() and snd_usb_endpoint_close() that are called at PCM hw_params and hw_free callbacks, respectively. Those are ref-counted and EPs can manage the multiple opens. The open callback receives the audioformat and hw_params arguments, and those are used for initializing the EP parameters; especially the endpoint, interface and altset numbers are read from there, as well as the PCM parameters like the format, rate and channels. Those are stored in snd_usb_endpoint object. If it's the secondary open, the function checks whether the given parameters are compatible with the already opened EP setup, too. The coupling with a sync EP (including an implicit feedback sync) is done by the sole snd_usb_endpoint_set_sync() call. The configuration of each endpoint is done in a single shot via snd_usb_endpoint_configure() call. This is the place where most of PCM configurations are done. A few flags and special handling in the snd_usb_substream are dropped along with this change. A significant difference wrt the configuration from the previous code is the order of USB host interface setups. Now the interface is always disabled at beginning and (re-)enabled at the last step of snd_usb_endpoint_configure(), in order to be compliant with the standard UAC2/3. For UAC1, the interface is set before the parameter setups since there seem devices that require it (e.g. Yamaha THR10), just like how it was done in the previous driver code. The start/stop are almost same as before, also single-shots. The URB callbacks need to be set via snd_usb_endpoint_set_callback() like the previous code at the trigger phase, too. Finally, the flag for the re-setup is set at the device suspend through the full EP list, instead of PCM trigger. This catches the overlooked cases where the PCM hasn't been running yet but the device needs the full setup after resume. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.c | 8 +- sound/usb/card.h | 11 +- sound/usb/clock.c | 13 +- sound/usb/endpoint.c | 662 ++++++++++++++++++++++++++------------------------- sound/usb/endpoint.h | 40 ++-- sound/usb/pcm.c | 616 +++++++++++++++++++---------------------------- 6 files changed, 616 insertions(+), 734 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 096dd8e3c64b..58958afcec93 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -980,6 +980,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) { struct snd_usb_audio *chip = usb_get_intfdata(intf); struct snd_usb_stream *as; + struct snd_usb_endpoint *ep; struct usb_mixer_interface *mixer; struct list_head *p; @@ -987,11 +988,10 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) return 0; if (!chip->num_suspended_intf++) { - list_for_each_entry(as, &chip->pcm_list, list) { + list_for_each_entry(as, &chip->pcm_list, list) snd_usb_pcm_suspend(as); - as->substream[0].need_setup_ep = - as->substream[1].need_setup_ep = true; - } + list_for_each_entry(ep, &chip->ep_list, list) + snd_usb_endpoint_suspend(ep); list_for_each(p, &chip->midi_list) snd_usbmidi_suspend(p); list_for_each_entry(mixer, &chip->mixer_list, list) diff --git a/sound/usb/card.h b/sound/usb/card.h index 1f61be98a31d..66a249ae138f 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -26,6 +26,7 @@ struct audioformat { unsigned char sync_ep; /* sync endpoint number */ unsigned char sync_iface; /* sync EP interface */ unsigned char sync_altsetting; /* sync EP alternate setting */ + unsigned char sync_ep_idx; /* sync EP array index */ unsigned char datainterval; /* log_2 of data packet interval */ unsigned char protocol; /* UAC_VERSION_1/2/3 */ unsigned int maxpacksize; /* max. packet size */ @@ -58,6 +59,7 @@ struct snd_urb_ctx { struct snd_usb_endpoint { struct snd_usb_audio *chip; + int opened; /* open refcount; protect with chip->mutex */ int use_count; int ep_num; /* the referenced endpoint number */ int type; /* SND_USB_ENDPOINT_TYPE_* */ @@ -110,14 +112,18 @@ struct snd_usb_endpoint { unsigned char silence_value; unsigned int stride; int iface, altsetting; + unsigned char ep_idx; /* endpoint array index */ int skip_packets; /* quirks for devices to ignore the first n packets in a stream */ - bool is_implicit_feedback; /* This endpoint is used as implicit feedback */ + bool implicit_fb_sync; /* syncs with implicit feedback */ + bool need_setup; /* (re-)need for configure? */ /* for hw constraints */ + struct audioformat *cur_audiofmt; unsigned int cur_rate; snd_pcm_format_t cur_format; unsigned int cur_channels; + unsigned int cur_frame_bytes; unsigned int cur_period_frames; unsigned int cur_period_bytes; unsigned int cur_buffer_periods; @@ -152,7 +158,6 @@ struct snd_usb_substream { unsigned int stream_offset_adj; /* Bytes to drop from beginning of stream (for non-compliant devices) */ unsigned int running: 1; /* running status */ - unsigned int fixed_hw:1; /* fixed hw constraints due to sync EP */ unsigned int hwptr_done; /* processed byte position in the buffer */ unsigned int transfer_done; /* processed frames since last period update */ @@ -163,8 +168,6 @@ struct snd_usb_substream { struct snd_usb_endpoint *data_endpoint; struct snd_usb_endpoint *sync_endpoint; unsigned long flags; - bool need_setup_ep; /* (re)configure EP at prepare? */ - bool need_setup_fmt; /* (re)configure fmt after resume? */ unsigned int speed; /* USB_SPEED_XXX */ u64 formats; /* format bitmasks (all or'ed) */ diff --git a/sound/usb/clock.c b/sound/usb/clock.c index f25da11fce3a..b869a711afbf 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -613,7 +613,6 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, static int set_sample_rate_v2v3(struct snd_usb_audio *chip, struct audioformat *fmt, int rate) { - struct usb_device *dev = chip->dev; int cur_rate, prev_rate; int clock; @@ -656,15 +655,6 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, return -ENXIO; } - /* Some devices doesn't respond to sample rate changes while the - * interface is active. */ - if (rate != prev_rate) { - usb_set_interface(dev, fmt->iface, 0); - snd_usb_set_interface_quirk(chip); - usb_set_interface(dev, fmt->iface, fmt->altsetting); - snd_usb_set_interface_quirk(chip); - } - validation: /* validate clock after rate change */ if (!uac_clock_source_is_valid(chip, fmt, clock)) @@ -675,6 +665,9 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int snd_usb_init_sample_rate(struct snd_usb_audio *chip, struct audioformat *fmt, int rate) { + usb_audio_dbg(chip, "%d:%d Set sample rate %d, clock %d\n", + fmt->iface, fmt->altsetting, rate, fmt->clock); + switch (fmt->protocol) { case UAC_VERSION_1: default: diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7012fdafc3d8..eee74313603e 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -18,6 +18,7 @@ #include "card.h" #include "endpoint.h" #include "pcm.h" +#include "clock.h" #include "quirks.h" #define EP_FLAG_RUNNING 1 @@ -116,10 +117,7 @@ static const char *usb_error_string(int err) */ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep) { - return ep->sync_master && - ep->sync_master->type == SND_USB_ENDPOINT_TYPE_DATA && - ep->type == SND_USB_ENDPOINT_TYPE_DATA && - usb_pipeout(ep->pipe); + return ep->implicit_fb_sync && usb_pipeout(ep->pipe); } /* @@ -185,18 +183,24 @@ static void retire_outbound_urb(struct snd_usb_endpoint *ep, call_retire_callback(ep, urb_ctx->urb); } +static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, + struct snd_usb_endpoint *sender, + const struct urb *urb); + static void retire_inbound_urb(struct snd_usb_endpoint *ep, struct snd_urb_ctx *urb_ctx) { struct urb *urb = urb_ctx->urb; + struct snd_usb_endpoint *sync_slave; if (unlikely(ep->skip_packets > 0)) { ep->skip_packets--; return; } - if (ep->sync_slave) - snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); + sync_slave = READ_ONCE(ep->sync_slave); + if (sync_slave) + snd_usb_handle_sync_urb(sync_slave, ep, urb); call_retire_callback(ep, urb); } @@ -518,25 +522,155 @@ int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type) } /* Set up syncinterval and maxsyncsize for a sync EP */ -void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep, - struct usb_host_interface *alts) +static void endpoint_set_syncinterval(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) { - struct usb_endpoint_descriptor *desc = get_endpoint(alts, 1); - - if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) { - if (desc->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && - desc->bRefresh >= 1 && desc->bRefresh <= 9) - ep->syncinterval = desc->bRefresh; - else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL) - ep->syncinterval = 1; - else if (desc->bInterval >= 1 && desc->bInterval <= 16) - ep->syncinterval = desc->bInterval - 1; - else - ep->syncinterval = 3; + struct usb_host_interface *alts; + struct usb_endpoint_descriptor *desc; + + alts = snd_usb_get_host_interface(chip, ep->iface, ep->altsetting); + if (!alts) + return; + + desc = get_endpoint(alts, ep->ep_idx); + if (desc->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && + desc->bRefresh >= 1 && desc->bRefresh <= 9) + ep->syncinterval = desc->bRefresh; + else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL) + ep->syncinterval = 1; + else if (desc->bInterval >= 1 && desc->bInterval <= 16) + ep->syncinterval = desc->bInterval - 1; + else + ep->syncinterval = 3; + + ep->syncmaxsize = le16_to_cpu(desc->wMaxPacketSize); +} + +static bool endpoint_compatible(struct snd_usb_endpoint *ep, + const struct audioformat *fp, + const struct snd_pcm_hw_params *params) +{ + if (!ep->opened) + return false; + if (ep->cur_audiofmt != fp) + return false; + if (ep->cur_rate != params_rate(params) || + ep->cur_format != params_format(params) || + ep->cur_period_frames != params_period_size(params) || + ep->cur_buffer_periods != params_periods(params)) + return false; + return true; +} + +/* + * Check whether the given fp and hw params are compatbile with the current + * setup of the target EP for implicit feedback sync + */ +bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep, + const struct audioformat *fp, + const struct snd_pcm_hw_params *params) +{ + bool ret; + + mutex_lock(&chip->mutex); + ret = endpoint_compatible(ep, fp, params); + mutex_unlock(&chip->mutex); + return ret; +} + +/* + * snd_usb_endpoint_open: Open the endpoint + * + * Called from hw_params to assign the endpoint to the substream. + * It's reference-counted, and only the first opener is allowed to set up + * arbitrary parameters. The later opener must be compatible with the + * former opened parameters. + * The endpoint needs to be closed via snd_usb_endpoint_close() later. + * + * Note that this function doesn't configure the endpoint. The substream + * needs to set it up later via snd_usb_endpoint_configure(). + */ +struct snd_usb_endpoint * +snd_usb_endpoint_open(struct snd_usb_audio *chip, + struct audioformat *fp, + const struct snd_pcm_hw_params *params, + bool is_sync_ep) +{ + struct snd_usb_endpoint *ep; + int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint; - ep->syncmaxsize = le16_to_cpu(desc->wMaxPacketSize); + mutex_lock(&chip->mutex); + ep = snd_usb_get_endpoint(chip, ep_num); + if (!ep) { + usb_audio_err(chip, "Cannot find EP 0x%x to open\n", ep_num); + goto unlock; } + + if (!ep->opened) { + if (is_sync_ep) { + ep->iface = fp->sync_iface; + ep->altsetting = fp->sync_altsetting; + ep->ep_idx = fp->sync_ep_idx; + } else { + ep->iface = fp->iface; + ep->altsetting = fp->altsetting; + ep->ep_idx = 0; + } + usb_audio_dbg(chip, "Open EP 0x%x, iface=%d:%d, idx=%d\n", + ep_num, ep->iface, ep->altsetting, ep->ep_idx); + + ep->cur_audiofmt = fp; + ep->cur_channels = fp->channels; + ep->cur_rate = params_rate(params); + ep->cur_format = params_format(params); + ep->cur_frame_bytes = snd_pcm_format_physical_width(ep->cur_format) * + ep->cur_channels / 8; + ep->cur_period_frames = params_period_size(params); + ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes; + ep->cur_buffer_periods = params_periods(params); + + if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) + endpoint_set_syncinterval(chip, ep); + + ep->implicit_fb_sync = fp->implicit_fb; + ep->need_setup = true; + + usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n", + ep->cur_channels, ep->cur_rate, + snd_pcm_format_name(ep->cur_format), + ep->cur_period_bytes, ep->cur_buffer_periods, + ep->implicit_fb_sync); + + } else { + if (!endpoint_compatible(ep, fp, params)) { + usb_audio_err(chip, "Incompatible EP setup for 0x%x\n", + ep_num); + ep = NULL; + goto unlock; + } + + usb_audio_dbg(chip, "Reopened EP 0x%x (count %d)\n", + ep_num, ep->opened); + } + + ep->opened++; + + unlock: + mutex_unlock(&chip->mutex); + return ep; +} + +/* + * snd_usb_endpoint_set_sync: Link data and sync endpoints + * + * Pass NULL to sync_ep to unlink again + */ +void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, + struct snd_usb_endpoint *data_ep, + struct snd_usb_endpoint *sync_ep) +{ + data_ep->sync_master = sync_ep; } /* @@ -557,6 +691,54 @@ void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, WRITE_ONCE(ep->data_subs, data_subs); } +static int endpoint_set_interface(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep, + bool set) +{ + int altset = set ? ep->altsetting : 0; + int err; + + usb_audio_dbg(chip, "Setting usb interface %d:%d for EP 0x%x\n", + ep->iface, altset, ep->ep_num); + err = usb_set_interface(chip->dev, ep->iface, altset); + if (err < 0) { + usb_audio_err(chip, "%d:%d: usb_set_interface failed (%d)\n", + ep->iface, altset, err); + return err; + } + + snd_usb_set_interface_quirk(chip); + return 0; +} + +/* + * snd_usb_endpoint_close: Close the endpoint + * + * Unreference the already opened endpoint via snd_usb_endpoint_open(). + */ +void snd_usb_endpoint_close(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) +{ + mutex_lock(&chip->mutex); + usb_audio_dbg(chip, "Closing EP 0x%x (count %d)\n", + ep->ep_num, ep->opened); + if (!--ep->opened) { + endpoint_set_interface(chip, ep, false); + ep->iface = -1; + ep->altsetting = 0; + ep->cur_audiofmt = NULL; + ep->cur_rate = 0; + usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num); + } + mutex_unlock(&chip->mutex); +} + +/* Prepare for suspening EP, called from the main suspend handler */ +void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep) +{ + ep->need_setup = true; +} + /* * wait until all urbs are processed. */ @@ -646,219 +828,36 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) ep->nurbs = 0; } -/* - * Check data endpoint for format differences - */ -static bool check_ep_params(struct snd_usb_endpoint *ep, - snd_pcm_format_t pcm_format, - unsigned int channels, - unsigned int period_bytes, - unsigned int frames_per_period, - unsigned int periods_per_buffer, - unsigned int rate, - struct audioformat *fmt, - struct snd_usb_endpoint *sync_ep) -{ - unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb; - unsigned int max_packs_per_period, urbs_per_period, urb_packs; - unsigned int max_urbs; - int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; - int tx_length_quirk = (ep->chip->tx_length_quirk && - usb_pipeout(ep->pipe)); - bool ret = 1; - - /* matching with the saved parameters? */ - if (ep->cur_rate == rate && - ep->cur_format == pcm_format && - ep->cur_channels == channels && - ep->cur_period_frames == frames_per_period && - ep->cur_buffer_periods == periods_per_buffer) - return true; - - if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) { - /* - * When operating in DSD DOP mode, the size of a sample frame - * in hardware differs from the actual physical format width - * because we need to make room for the DOP markers. - */ - frame_bits += channels << 3; - } - - ret = ret && (ep->datainterval == fmt->datainterval); - ret = ret && (ep->stride == frame_bits >> 3); - - switch (pcm_format) { - case SNDRV_PCM_FORMAT_U8: - ret = ret && (ep->silence_value == 0x80); - break; - case SNDRV_PCM_FORMAT_DSD_U8: - case SNDRV_PCM_FORMAT_DSD_U16_LE: - case SNDRV_PCM_FORMAT_DSD_U32_LE: - case SNDRV_PCM_FORMAT_DSD_U16_BE: - case SNDRV_PCM_FORMAT_DSD_U32_BE: - ret = ret && (ep->silence_value == 0x69); - break; - default: - ret = ret && (ep->silence_value == 0); - } - - /* assume max. frequency is 50% higher than nominal */ - ret = ret && (ep->freqmax == ep->freqn + (ep->freqn >> 1)); - /* Round up freqmax to nearest integer in order to calculate maximum - * packet size, which must represent a whole number of frames. - * This is accomplished by adding 0x0.ffff before converting the - * Q16.16 format into integer. - * In order to accurately calculate the maximum packet size when - * the data interval is more than 1 (i.e. ep->datainterval > 0), - * multiply by the data interval prior to rounding. For instance, - * a freqmax of 41 kHz will result in a max packet size of 6 (5.125) - * frames with a data interval of 1, but 11 (10.25) frames with a - * data interval of 2. - * (ep->freqmax << ep->datainterval overflows at 8.192 MHz for the - * maximum datainterval value of 3, at USB full speed, higher for - * USB high speed, noting that ep->freqmax is in units of - * frames per packet in Q16.16 format.) - */ - maxsize = (((ep->freqmax << ep->datainterval) + 0xffff) >> 16) * - (frame_bits >> 3); - if (tx_length_quirk) - maxsize += sizeof(__le32); /* Space for length descriptor */ - /* but wMaxPacketSize might reduce this */ - if (ep->maxpacksize && ep->maxpacksize < maxsize) { - /* whatever fits into a max. size packet */ - unsigned int data_maxsize = maxsize = ep->maxpacksize; - - if (tx_length_quirk) - /* Need to remove the length descriptor to calc freq */ - data_maxsize -= sizeof(__le32); - ret = ret && (ep->freqmax == (data_maxsize / (frame_bits >> 3)) - << (16 - ep->datainterval)); - } - - if (ep->fill_max) - ret = ret && (ep->curpacksize == ep->maxpacksize); - else - ret = ret && (ep->curpacksize == maxsize); - - if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) { - packs_per_ms = 8 >> ep->datainterval; - max_packs_per_urb = MAX_PACKS_HS; - } else { - packs_per_ms = 1; - max_packs_per_urb = MAX_PACKS; - } - if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep)) - max_packs_per_urb = min(max_packs_per_urb, - 1U << sync_ep->syncinterval); - max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval); - - /* - * Capture endpoints need to use small URBs because there's no way - * to tell in advance where the next period will end, and we don't - * want the next URB to complete much after the period ends. - * - * Playback endpoints with implicit sync much use the same parameters - * as their corresponding capture endpoint. - */ - if (usb_pipein(ep->pipe) || - snd_usb_endpoint_implicit_feedback_sink(ep)) { - - urb_packs = packs_per_ms; - /* - * Wireless devices can poll at a max rate of once per 4ms. - * For dataintervals less than 5, increase the packet count to - * allow the host controller to use bursting to fill in the - * gaps. - */ - if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) { - int interval = ep->datainterval; - - while (interval < 5) { - urb_packs <<= 1; - ++interval; - } - } - /* make capture URBs <= 1 ms and smaller than a period */ - urb_packs = min(max_packs_per_urb, urb_packs); - while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) - urb_packs >>= 1; - ret = ret && (ep->nurbs == MAX_URBS); - - /* - * Playback endpoints without implicit sync are adjusted so that - * a period fits as evenly as possible in the smallest number of - * URBs. The total number of URBs is adjusted to the size of the - * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits. - */ - } else { - /* determine how small a packet can be */ - minsize = (ep->freqn >> (16 - ep->datainterval)) * - (frame_bits >> 3); - /* with sync from device, assume it can be 12% lower */ - if (sync_ep) - minsize -= minsize >> 3; - minsize = max(minsize, 1u); - - /* how many packets will contain an entire ALSA period? */ - max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize); - - /* how many URBs will contain a period? */ - urbs_per_period = DIV_ROUND_UP(max_packs_per_period, - max_packs_per_urb); - /* how many packets are needed in each URB? */ - urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period); - - /* limit the number of frames in a single URB */ - ret = ret && (ep->max_urb_frames == - DIV_ROUND_UP(frames_per_period, urbs_per_period)); - - /* try to use enough URBs to contain an entire ALSA buffer */ - max_urbs = min((unsigned) MAX_URBS, - MAX_QUEUE * packs_per_ms / urb_packs); - ret = ret && (ep->nurbs == min(max_urbs, - urbs_per_period * periods_per_buffer)); - } - - ret = ret && (ep->datainterval == fmt->datainterval); - ret = ret && (ep->maxpacksize == fmt->maxpacksize); - ret = ret && - (ep->fill_max == !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)); - - return ret; -} - /* * configure a data endpoint */ -static int data_ep_set_params(struct snd_usb_endpoint *ep, - snd_pcm_format_t pcm_format, - unsigned int channels, - unsigned int period_bytes, - unsigned int frames_per_period, - unsigned int periods_per_buffer, - struct audioformat *fmt, - struct snd_usb_endpoint *sync_ep) +static int data_ep_set_params(struct snd_usb_endpoint *ep) { + struct snd_usb_audio *chip = ep->chip; unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb; unsigned int max_packs_per_period, urbs_per_period, urb_packs; unsigned int max_urbs, i; - int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; - int tx_length_quirk = (ep->chip->tx_length_quirk && + const struct audioformat *fmt = ep->cur_audiofmt; + int frame_bits = ep->cur_frame_bytes * 8; + int tx_length_quirk = (chip->tx_length_quirk && usb_pipeout(ep->pipe)); - if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) { + usb_audio_dbg(chip, "Setting params for data EP 0x%x, pipe 0x%x\n", + ep->ep_num, ep->pipe); + + if (ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) { /* * When operating in DSD DOP mode, the size of a sample frame * in hardware differs from the actual physical format width * because we need to make room for the DOP markers. */ - frame_bits += channels << 3; + frame_bits += ep->cur_channels << 3; } ep->datainterval = fmt->datainterval; ep->stride = frame_bits >> 3; - switch (pcm_format) { + switch (ep->cur_format) { case SNDRV_PCM_FORMAT_U8: ep->silence_value = 0x80; break; @@ -911,16 +910,16 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, else ep->curpacksize = maxsize; - if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) { + if (snd_usb_get_speed(chip->dev) != USB_SPEED_FULL) { packs_per_ms = 8 >> ep->datainterval; max_packs_per_urb = MAX_PACKS_HS; } else { packs_per_ms = 1; max_packs_per_urb = MAX_PACKS; } - if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep)) + if (ep->sync_master && !ep->implicit_fb_sync) max_packs_per_urb = min(max_packs_per_urb, - 1U << sync_ep->syncinterval); + 1U << ep->sync_master->syncinterval); max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval); /* @@ -931,9 +930,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, * Playback endpoints with implicit sync much use the same parameters * as their corresponding capture endpoint. */ - if (usb_pipein(ep->pipe) || - ep->is_implicit_feedback || - snd_usb_endpoint_implicit_feedback_sink(ep)) { + if (usb_pipein(ep->pipe) || ep->implicit_fb_sync) { urb_packs = packs_per_ms; /* @@ -942,7 +939,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, * allow the host controller to use bursting to fill in the * gaps. */ - if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) { + if (snd_usb_get_speed(chip->dev) == USB_SPEED_WIRELESS) { int interval = ep->datainterval; while (interval < 5) { urb_packs <<= 1; @@ -951,7 +948,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, } /* make capture URBs <= 1 ms and smaller than a period */ urb_packs = min(max_packs_per_urb, urb_packs); - while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) + while (urb_packs > 1 && urb_packs * maxsize >= ep->cur_period_bytes) urb_packs >>= 1; ep->nurbs = MAX_URBS; @@ -966,12 +963,12 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, minsize = (ep->freqn >> (16 - ep->datainterval)) * (frame_bits >> 3); /* with sync from device, assume it can be 12% lower */ - if (sync_ep) + if (ep->sync_master) minsize -= minsize >> 3; minsize = max(minsize, 1u); /* how many packets will contain an entire ALSA period? */ - max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize); + max_packs_per_period = DIV_ROUND_UP(ep->cur_period_bytes, minsize); /* how many URBs will contain a period? */ urbs_per_period = DIV_ROUND_UP(max_packs_per_period, @@ -980,13 +977,13 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period); /* limit the number of frames in a single URB */ - ep->max_urb_frames = DIV_ROUND_UP(frames_per_period, - urbs_per_period); + ep->max_urb_frames = DIV_ROUND_UP(ep->cur_period_frames, + urbs_per_period); /* try to use enough URBs to contain an entire ALSA buffer */ max_urbs = min((unsigned) MAX_URBS, MAX_QUEUE * packs_per_ms / urb_packs); - ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer); + ep->nurbs = min(max_urbs, urbs_per_period * ep->cur_buffer_periods); } /* allocate and initialize data urbs */ @@ -1004,7 +1001,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, goto out_of_memory; u->urb->transfer_buffer = - usb_alloc_coherent(ep->chip->dev, u->buffer_size, + usb_alloc_coherent(chip->dev, u->buffer_size, GFP_KERNEL, &u->urb->transfer_dma); if (!u->urb->transfer_buffer) goto out_of_memory; @@ -1028,9 +1025,13 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, */ static int sync_ep_set_params(struct snd_usb_endpoint *ep) { + struct snd_usb_audio *chip = ep->chip; int i; - ep->syncbuf = usb_alloc_coherent(ep->chip->dev, SYNC_URBS * 4, + usb_audio_dbg(chip, "Setting params for sync EP 0x%x, pipe 0x%x\n", + ep->ep_num, ep->pipe); + + ep->syncbuf = usb_alloc_coherent(chip->dev, SYNC_URBS * 4, GFP_KERNEL, &ep->sync_dma); if (!ep->syncbuf) return -ENOMEM; @@ -1063,60 +1064,19 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) return -ENOMEM; } -/** +/* * snd_usb_endpoint_set_params: configure an snd_usb_endpoint * - * @ep: the snd_usb_endpoint to configure - * @pcm_format: the audio fomat. - * @channels: the number of audio channels. - * @period_bytes: the number of bytes in one alsa period. - * @period_frames: the number of frames in one alsa period. - * @buffer_periods: the number of periods in one alsa buffer. - * @rate: the frame rate. - * @fmt: the USB audio format information - * @sync_ep: the sync endpoint to use, if any - * * Determine the number of URBs to be used on this endpoint. * An endpoint must be configured before it can be started. * An endpoint that is already running can not be reconfigured. */ -int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - snd_pcm_format_t pcm_format, - unsigned int channels, - unsigned int period_bytes, - unsigned int period_frames, - unsigned int buffer_periods, - unsigned int rate, - struct audioformat *fmt, - struct snd_usb_endpoint *sync_ep) +static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) { + const struct audioformat *fmt = ep->cur_audiofmt; int err; - usb_audio_dbg(ep->chip, - "Setting params for ep %x (type %s, count %d), rate=%d, format=%s, channels=%d, period_bytes=%d, periods=%d\n", - ep->ep_num, ep_type_name(ep->type), ep->use_count, - rate, snd_pcm_format_name(pcm_format), channels, - period_bytes, buffer_periods); - - if (ep->use_count != 0) { - bool check = ep->is_implicit_feedback && - check_ep_params(ep, pcm_format, channels, period_bytes, - period_frames, buffer_periods, rate, - fmt, sync_ep); - - if (!check) { - usb_audio_warn(ep->chip, - "Unable to change format on ep #%x: already in use\n", - ep->ep_num); - return -EBUSY; - } - - usb_audio_dbg(ep->chip, - "Ep #%x already in use as implicit feedback but format not changed\n", - ep->ep_num); - return 0; - } - /* release old buffers, if any */ release_urbs(ep, 0); @@ -1124,17 +1084,17 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, ep->maxpacksize = fmt->maxpacksize; ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX); - if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) { - ep->freqn = get_usb_full_speed_rate(rate); + if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL) { + ep->freqn = get_usb_full_speed_rate(ep->cur_rate); ep->pps = 1000 >> ep->datainterval; } else { - ep->freqn = get_usb_high_speed_rate(rate); + ep->freqn = get_usb_high_speed_rate(ep->cur_rate); ep->pps = 8000 >> ep->datainterval; } - ep->sample_rem = rate % ep->pps; - ep->packsize[0] = rate / ep->pps; - ep->packsize[1] = (rate + (ep->pps - 1)) / ep->pps; + ep->sample_rem = ep->cur_rate % ep->pps; + ep->packsize[0] = ep->cur_rate / ep->pps; + ep->packsize[1] = (ep->cur_rate + (ep->pps - 1)) / ep->pps; /* calculate the frequency in 16.16 format */ ep->freqm = ep->freqn; @@ -1144,9 +1104,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, switch (ep->type) { case SND_USB_ENDPOINT_TYPE_DATA: - err = data_ep_set_params(ep, pcm_format, channels, - period_bytes, period_frames, - buffer_periods, fmt, sync_ep); + err = data_ep_set_params(ep); break; case SND_USB_ENDPOINT_TYPE_SYNC: err = sync_ep_set_params(ep); @@ -1155,24 +1113,92 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, err = -EINVAL; } - usb_audio_dbg(ep->chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err); + usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err); if (err < 0) return err; - /* record the current set up in the endpoint (for implicit fb) */ - spin_lock_irq(&ep->lock); - ep->cur_rate = rate; - ep->cur_channels = channels; - ep->cur_format = pcm_format; - ep->cur_period_frames = period_frames; - ep->cur_period_bytes = period_bytes; - ep->cur_buffer_periods = buffer_periods; - spin_unlock_irq(&ep->lock); + /* some unit conversions in runtime */ + ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes; + ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; return 0; } +/* + * snd_usb_endpoint_configure: Configure the endpoint + * + * This function sets up the EP to be fully usable state. + * It's called either from hw_params or prepare callback. + * The function checks need_setup flag, and perfoms nothing unless needed, + * so it's safe to call this multiple times. + * + * This returns zero if unchanged, 1 if the configuration has changed, + * or a negative error code. + */ +int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) +{ + bool iface_first; + int err = 0; + + mutex_lock(&chip->mutex); + if (!ep->need_setup) + goto unlock; + + /* No need to (re-)configure the sync EP belonging to the same altset */ + if (ep->ep_idx) { + err = snd_usb_endpoint_set_params(chip, ep); + if (err < 0) + goto unlock; + goto done; + } + + /* Need to deselect altsetting at first */ + endpoint_set_interface(chip, ep, false); + + /* Some UAC1 devices (e.g. Yamaha THR10) need the host interface + * to be set up before parameter setups + */ + iface_first = ep->cur_audiofmt->protocol == UAC_VERSION_1; + if (iface_first) { + err = endpoint_set_interface(chip, ep, true); + if (err < 0) + goto unlock; + } + + err = snd_usb_init_pitch(chip, ep->cur_audiofmt); + if (err < 0) + goto unlock; + + err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate); + if (err < 0) + goto unlock; + + err = snd_usb_endpoint_set_params(chip, ep); + if (err < 0) + goto unlock; + + err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt); + if (err < 0) + goto unlock; + + /* for UAC2/3, enable the interface altset here at last */ + if (!iface_first) { + err = endpoint_set_interface(chip, ep, true); + if (err < 0) + goto unlock; + } + + done: + ep->need_setup = false; + err = 1; + +unlock: + mutex_unlock(&chip->mutex); + return err; +} + /** * snd_usb_endpoint_start: start an snd_usb_endpoint * @@ -1194,6 +1220,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (atomic_read(&ep->chip->shutdown)) return -EBADFD; + if (ep->sync_master) + WRITE_ONCE(ep->sync_master->sync_slave, ep); + usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (count %d)\n", ep_type_name(ep->type), ep->ep_num, ep->use_count); @@ -1226,6 +1255,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); } + usb_audio_dbg(ep->chip, "No URB submission due to implicit fb sync\n"); return 0; } @@ -1251,9 +1281,13 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) set_bit(i, &ep->active_mask); } + usb_audio_dbg(ep->chip, "%d URBs submitted for EP 0x%x\n", + ep->nurbs, ep->ep_num); return 0; __error: + if (ep->sync_master) + WRITE_ONCE(ep->sync_master->sync_slave, NULL); clear_bit(EP_FLAG_RUNNING, &ep->flags); ep->use_count--; deactivate_urbs(ep, false); @@ -1285,39 +1319,15 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) if (snd_BUG_ON(ep->use_count == 0)) return; + if (ep->sync_master) + WRITE_ONCE(ep->sync_master->sync_slave, NULL); + if (--ep->use_count == 0) { deactivate_urbs(ep, false); set_bit(EP_FLAG_STOPPING, &ep->flags); } } -/** - * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint - * - * @ep: the endpoint to deactivate - * - * If the endpoint is not currently in use, this functions will - * deactivate its associated URBs. - * - * In case of any active users, this functions does nothing. - */ -void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) -{ - if (!ep) - return; - - if (ep->use_count != 0) - return; - - deactivate_urbs(ep, true); - wait_clear_urbs(ep); - - /* clear the saved hw params */ - spin_lock_irq(&ep->lock); - ep->cur_rate = 0; - spin_unlock_irq(&ep->lock); -} - /** * snd_usb_endpoint_release: Tear down an snd_usb_endpoint * @@ -1343,7 +1353,7 @@ void snd_usb_endpoint_free(struct snd_usb_endpoint *ep) kfree(ep); } -/** +/* * snd_usb_handle_sync_urb: parse an USB sync packet * * @ep: the endpoint to handle the packet @@ -1353,9 +1363,9 @@ void snd_usb_endpoint_free(struct snd_usb_endpoint *ep) * This function is called from the context of an endpoint that received * the packet and is used to let another endpoint object handle the payload. */ -void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, - struct snd_usb_endpoint *sender, - const struct urb *urb) +static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, + struct snd_usb_endpoint *sender, + const struct urb *urb) { int shift; unsigned int f; diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index e2fddb3dcf7a..2bfa6d3e029c 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -10,16 +10,25 @@ struct snd_usb_endpoint *snd_usb_get_endpoint(struct snd_usb_audio *chip, int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type); -int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - snd_pcm_format_t pcm_format, - unsigned int channels, - unsigned int period_bytes, - unsigned int period_frames, - unsigned int buffer_periods, - unsigned int rate, - struct audioformat *fmt, - struct snd_usb_endpoint *sync_ep); - +struct snd_usb_endpoint * +snd_usb_endpoint_open(struct snd_usb_audio *chip, + struct audioformat *fp, + const struct snd_pcm_hw_params *params, + bool is_sync_ep); +void snd_usb_endpoint_close(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); +int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); +void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep); + +bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep, + const struct audioformat *fp, + const struct snd_pcm_hw_params *params); + +void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, + struct snd_usb_endpoint *data_ep, + struct snd_usb_endpoint *sync_ep); void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, void (*prepare)(struct snd_usb_substream *subs, struct urb *urb), @@ -27,23 +36,16 @@ void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, struct urb *urb), struct snd_usb_substream *data_subs); -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); +void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep); int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); -void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); void snd_usb_endpoint_release(struct snd_usb_endpoint *ep); void snd_usb_endpoint_free(struct snd_usb_endpoint *ep); int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep); int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); -void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep, - struct usb_host_interface *alts); - -void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, - struct snd_usb_endpoint *sender, - const struct urb *urb); #endif /* __USBAUDIO_ENDPOINT_H */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 45a692512d27..e80e8cf1e863 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -80,21 +80,22 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream /* * find a matching audio format */ -static struct audioformat *find_format(struct list_head *fmt_list_head, - snd_pcm_format_t format, - unsigned int rate, - unsigned int channels, - struct snd_usb_substream *subs) +static struct audioformat * +find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, + unsigned int rate, unsigned int channels, bool strict_match, + struct snd_usb_substream *subs) { struct audioformat *fp; struct audioformat *found = NULL; int cur_attr = 0, attr; list_for_each_entry(fp, fmt_list_head, list) { - if (!(fp->formats & pcm_format_to_bits(format))) - continue; - if (fp->channels != channels) - continue; + if (strict_match) { + if (!(fp->formats & pcm_format_to_bits(format))) + continue; + if (fp->channels != channels) + continue; + } if (rate < fp->rate_min || rate > fp->rate_max) continue; if (!(fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { @@ -140,38 +141,30 @@ static struct audioformat *find_format(struct list_head *fmt_list_head, return found; } -static struct audioformat *find_substream_format(struct snd_usb_substream *subs) +static struct audioformat * +find_substream_format(struct snd_usb_substream *subs, + const struct snd_pcm_hw_params *params) { - return find_format(&subs->fmt_list, subs->pcm_format, subs->cur_rate, - subs->channels, subs); + return find_format(&subs->fmt_list, params_format(params), + params_rate(params), params_channels(params), + true, subs); } -static int init_pitch_v1(struct snd_usb_audio *chip, - struct audioformat *fmt) +static int init_pitch_v1(struct snd_usb_audio *chip, int ep) { struct usb_device *dev = chip->dev; - unsigned int ep; unsigned char data[1]; int err; - ep = fmt->endpoint; - data[0] = 1; err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, data, sizeof(data)); - if (err < 0) { - usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n", - fmt->iface, ep); - return err; - } - - return 0; + return err; } -static int init_pitch_v2(struct snd_usb_audio *chip, - struct audioformat *fmt) +static int init_pitch_v2(struct snd_usb_audio *chip, int ep) { struct usb_device *dev = chip->dev; unsigned char data[1]; @@ -182,13 +175,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, UAC2_EP_CS_PITCH << 8, 0, data, sizeof(data)); - if (err < 0) { - usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n", - fmt->iface, fmt->altsetting); - return err; - } - - return 0; + return err; } /* @@ -197,29 +184,47 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int snd_usb_init_pitch(struct snd_usb_audio *chip, struct audioformat *fmt) { + int err; + /* if endpoint doesn't have pitch control, bail out */ if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) return 0; + usb_audio_dbg(chip, "enable PITCH for EP 0x%x\n", fmt->endpoint); + switch (fmt->protocol) { case UAC_VERSION_1: + err = init_pitch_v1(chip, fmt->endpoint); + break; + case UAC_VERSION_2: + err = init_pitch_v2(chip, fmt->endpoint); + break; default: - return init_pitch_v1(chip, fmt); + return 0; + } - case UAC_VERSION_2: - return init_pitch_v2(chip, fmt); + if (err < 0) { + usb_audio_err(chip, "failed to enable PITCH for EP 0x%x\n", + fmt->endpoint); + return err; } + + return 0; } -static void stop_endpoints(struct snd_usb_substream *subs) +static bool stop_endpoints(struct snd_usb_substream *subs) { + bool stopped = 0; + if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { snd_usb_endpoint_stop(subs->sync_endpoint); - subs->sync_endpoint->sync_slave = NULL; + stopped = true; } - - if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) + if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { snd_usb_endpoint_stop(subs->data_endpoint); + stopped = true; + } + return stopped; } static int start_endpoints(struct snd_usb_substream *subs) @@ -230,9 +235,7 @@ static int start_endpoints(struct snd_usb_substream *subs) return -EINVAL; if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { - struct snd_usb_endpoint *ep = subs->data_endpoint; - - err = snd_usb_endpoint_start(ep); + err = snd_usb_endpoint_start(subs->data_endpoint); if (err < 0) { clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); goto error; @@ -241,13 +244,9 @@ static int start_endpoints(struct snd_usb_substream *subs) if (subs->sync_endpoint && !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { - struct snd_usb_endpoint *ep = subs->sync_endpoint; - - ep->sync_slave = subs->data_endpoint; - err = snd_usb_endpoint_start(ep); + err = snd_usb_endpoint_start(subs->sync_endpoint); if (err < 0) { clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); - ep->sync_slave = NULL; goto error; } } @@ -446,6 +445,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, fmt->sync_ep = ep; fmt->sync_iface = ifnum; fmt->sync_altsetting = alts->desc.bAlternateSetting; + fmt->sync_ep_idx = 0; fmt->implicit_fb = 1; dev_dbg(&dev->dev, "%d:%d: found implicit_fb sync_ep=%x, iface=%d, alt=%d\n", fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface, @@ -527,6 +527,7 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, fmt->sync_ep = ep; fmt->sync_iface = altsd->bInterfaceNumber; fmt->sync_altsetting = altsd->bAlternateSetting; + fmt->sync_ep_idx = 1; if ((sync_attr & USB_ENDPOINT_USAGE_MASK) == USB_ENDPOINT_USAGE_IMPLICIT_FB) fmt->implicit_fb = 1; @@ -537,152 +538,6 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, return 0; } -static int set_sync_endpoint(struct snd_usb_substream *subs, - struct audioformat *fmt) -{ - struct usb_device *dev = subs->dev; - struct usb_host_interface *alts; - struct snd_usb_audio *chip = subs->stream->chip; - int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; - unsigned int ep; - int err; - - subs->sync_endpoint = NULL; - subs->data_endpoint->sync_master = NULL; - - ep = fmt->sync_ep; - if (!ep) - return 0; - - alts = snd_usb_get_host_interface(subs->stream->chip, fmt->sync_iface, - fmt->altsetting); - if (!alts) - return 0; - - subs->sync_endpoint = snd_usb_get_endpoint(chip, ep); - if (!subs->sync_endpoint) { - if (is_playback && - (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE) - return 0; - return -EINVAL; - } - - subs->sync_endpoint->iface = fmt->sync_iface; - subs->sync_endpoint->altsetting = fmt->sync_altsetting; - subs->sync_endpoint->is_implicit_feedback = fmt->implicit_fb; - - subs->data_endpoint->sync_master = subs->sync_endpoint; - - snd_usb_endpoint_set_syncinterval(subs->stream->chip, subs->sync_endpoint, alts); - - if (!subs->sync_endpoint->use_count && - (subs->data_endpoint->iface != subs->sync_endpoint->iface || - subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) { - err = usb_set_interface(subs->dev, - subs->sync_endpoint->iface, - subs->sync_endpoint->altsetting); - if (err < 0) - return err; - dev_dbg(&dev->dev, "setting usb interface %d:%d\n", - subs->sync_endpoint->iface, - subs->sync_endpoint->altsetting); - snd_usb_set_interface_quirk(chip); - } - - return 0; -} - -/* - * find a matching format and set up the interface - */ -static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) -{ - struct usb_device *dev = subs->dev; - struct snd_usb_audio *chip = subs->stream->chip; - struct usb_host_interface *alts; - struct usb_interface *iface; - struct snd_usb_endpoint *ep; - int err; - - iface = usb_ifnum_to_if(dev, fmt->iface); - if (WARN_ON(!iface)) - return -EINVAL; - alts = usb_altnum_to_altsetting(iface, fmt->altsetting); - if (WARN_ON(!alts)) - return -EINVAL; - - if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt) - return 0; - - /* shared EP with implicit fb */ - if (fmt->implicit_fb && !subs->need_setup_fmt) { - ep = snd_usb_get_endpoint(chip, fmt->endpoint); - if (ep && ep->use_count > 0) - goto add_data_ep; - } - - /* close the old interface */ - if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) { - err = usb_set_interface(subs->dev, subs->interface, 0); - if (err < 0) { - dev_err(&dev->dev, - "%d:%d: return to setting 0 failed (%d)\n", - fmt->iface, fmt->altsetting, err); - return -EIO; - } - subs->interface = -1; - subs->altset_idx = 0; - } - - if (subs->need_setup_fmt) - subs->need_setup_fmt = false; - - /* set interface */ - if (iface->cur_altsetting != alts) { - err = snd_usb_select_mode_quirk(chip, fmt); - if (err < 0) - return -EIO; - - err = usb_set_interface(dev, fmt->iface, fmt->altsetting); - if (err < 0) { - dev_err(&dev->dev, - "%d:%d: usb_set_interface failed (%d)\n", - fmt->iface, fmt->altsetting, err); - return -EIO; - } - dev_dbg(&dev->dev, "setting usb interface %d:%d\n", - fmt->iface, fmt->altsetting); - snd_usb_set_interface_quirk(chip); - } - - subs->need_setup_ep = true; - - add_data_ep: - subs->interface = fmt->iface; - subs->altset_idx = fmt->altset_idx; - subs->data_endpoint = snd_usb_get_endpoint(chip, fmt->endpoint); - if (!subs->data_endpoint) - return -EINVAL; - subs->data_endpoint->iface = fmt->iface; - subs->data_endpoint->altsetting = fmt->altsetting; - - err = set_sync_endpoint(subs, fmt); - if (err < 0) - return err; - - if (subs->need_setup_ep) { - err = snd_usb_init_pitch(chip, fmt); - if (err < 0) - return err; - } - - subs->cur_audiofmt = fmt; - - snd_usb_set_format_quirk(subs, fmt); - - return 0; -} - /* * Return the score of matching two audioformats. * Veto the audioformat if: @@ -691,8 +546,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) * - Requested sample rate is not supported. */ static int match_endpoint_audioformats(struct snd_usb_substream *subs, - struct audioformat *fp, - struct audioformat *match, int rate, + const struct audioformat *fp, + int rate, int channels, snd_pcm_format_t pcm_format) { int i, score; @@ -716,108 +571,12 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs, } score = 1; - if (fp->channels == match->channels) + if (fp->channels == channels) score++; return score; } -/* - * Configure the sync ep using the rate and pcm format of the data ep. - */ -static int configure_sync_endpoint(struct snd_usb_substream *subs) -{ - struct audioformat *fp; - struct audioformat *sync_fp = NULL; - int cur_score = 0; - int sync_period_bytes = subs->period_bytes; - struct snd_usb_substream *sync_subs = - &subs->stream->substream[subs->direction ^ 1]; - - if (subs->fixed_hw || - !subs->sync_endpoint->is_implicit_feedback) { - sync_fp = subs->cur_audiofmt; - goto configure; - } - - sync_fp = find_format(&sync_subs->fmt_list, subs->pcm_format, - subs->cur_rate, subs->channels, NULL); - if (sync_fp) - goto configure; - - /* Try to find the best matching audioformat. */ - list_for_each_entry(fp, &sync_subs->fmt_list, list) { - int score = match_endpoint_audioformats(subs, - fp, subs->cur_audiofmt, - subs->cur_rate, subs->pcm_format); - - if (score > cur_score) { - sync_fp = fp; - cur_score = score; - } - } - - if (unlikely(sync_fp == NULL)) { - dev_err(&subs->dev->dev, - "%s: no valid audioformat for sync ep %x found\n", - __func__, sync_subs->ep_num); - return -EINVAL; - } - - /* - * Recalculate the period bytes if channel number differ between - * data and sync ep audioformat. - */ - if (sync_fp->channels != subs->channels) { - sync_period_bytes = (subs->period_bytes / subs->channels) * - sync_fp->channels; - dev_dbg(&subs->dev->dev, - "%s: adjusted sync ep period bytes (%d -> %d)\n", - __func__, subs->period_bytes, sync_period_bytes); - } - - configure: - return snd_usb_endpoint_set_params(subs->sync_endpoint, - subs->pcm_format, - sync_fp->channels, - sync_period_bytes, - subs->period_frames, - subs->buffer_periods, - subs->cur_rate, - sync_fp, - NULL); -} - -/* - * configure endpoint params - * - * called during initial setup and upon resume - */ -static int configure_endpoint(struct snd_usb_substream *subs) -{ - int ret; - - /* format changed */ - stop_endpoints(subs); - sync_pending_stops(subs); - ret = snd_usb_endpoint_set_params(subs->data_endpoint, - subs->pcm_format, - subs->channels, - subs->period_bytes, - subs->period_frames, - subs->buffer_periods, - subs->cur_rate, - subs->cur_audiofmt, - subs->sync_endpoint); - if (ret < 0) - return ret; - - if (subs->sync_endpoint) - ret = configure_sync_endpoint(subs); - - return ret; -} - static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state) { int ret; @@ -866,6 +625,92 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as) return 0; } +static struct snd_usb_substream * +find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num, + int fmt_type) +{ + struct snd_usb_stream *as; + struct snd_usb_substream *subs; + + list_for_each_entry(as, &chip->pcm_list, list) { + subs = &as->substream[stream]; + if (as->fmt_type == fmt_type && subs->ep_num == ep_num) + return subs; + } + + return NULL; +} + +static struct audioformat * +find_implicit_fb_sync_format(struct snd_usb_audio *chip, + const struct audioformat *target, + const struct snd_pcm_hw_params *params, + int stream) +{ + struct snd_usb_substream *subs; + struct audioformat *fp, *sync_fmt; + int score, high_score; + + subs = find_matching_substream(chip, stream, target->sync_ep, + target->fmt_type); + if (!subs) + return NULL; + + sync_fmt = NULL; + high_score = 0; + list_for_each_entry(fp, &subs->fmt_list, list) { + score = match_endpoint_audioformats(subs, fp, + params_rate(params), + params_channels(params), + params_format(params)); + if (score > high_score) { + sync_fmt = fp; + high_score = score; + } + } + + return sync_fmt; +} + +static void close_endpoints(struct snd_usb_audio *chip, + struct snd_usb_substream *subs) +{ + if (subs->data_endpoint) { + snd_usb_endpoint_set_sync(chip, subs->data_endpoint, NULL); + snd_usb_endpoint_close(chip, subs->data_endpoint); + subs->data_endpoint = NULL; + } + + if (subs->sync_endpoint) { + snd_usb_endpoint_close(chip, subs->sync_endpoint); + subs->sync_endpoint = NULL; + } +} + +static int configure_endpoints(struct snd_usb_audio *chip, + struct snd_usb_substream *subs) +{ + int err; + + if (subs->data_endpoint->need_setup) { + /* stop any running stream beforehand */ + if (stop_endpoints(subs)) + sync_pending_stops(subs); + err = snd_usb_endpoint_configure(chip, subs->data_endpoint); + if (err < 0) + return err; + snd_usb_set_format_quirk(subs, subs->cur_audiofmt); + } + + if (subs->sync_endpoint) { + err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); + if (err < 0) + return err; + } + + return 0; +} + /* * hw_params callback * @@ -880,30 +725,45 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_usb_substream *subs = substream->runtime->private_data; + struct snd_usb_audio *chip = subs->stream->chip; struct audioformat *fmt; + struct audioformat *sync_fmt; int ret; ret = snd_media_start_pipeline(subs); if (ret) return ret; - subs->pcm_format = params_format(hw_params); - subs->period_bytes = params_period_bytes(hw_params); - subs->period_frames = params_period_size(hw_params); - subs->buffer_periods = params_periods(hw_params); - subs->channels = params_channels(hw_params); - subs->cur_rate = params_rate(hw_params); - - fmt = find_substream_format(subs); + fmt = find_substream_format(subs, hw_params); if (!fmt) { - dev_dbg(&subs->dev->dev, - "cannot set format: format = %#x, rate = %d, channels = %d\n", - subs->pcm_format, subs->cur_rate, subs->channels); + usb_audio_dbg(chip, + "cannot find format: format=%s, rate=%d, channels=%d\n", + snd_pcm_format_name(params_format(hw_params)), + params_rate(hw_params), params_channels(hw_params)); ret = -EINVAL; goto stop_pipeline; } - ret = snd_usb_lock_shutdown(subs->stream->chip); + if (fmt->implicit_fb && + (fmt->iface != fmt->sync_iface || + fmt->altsetting != fmt->sync_altsetting)) { + sync_fmt = find_implicit_fb_sync_format(chip, fmt, hw_params, + !substream->stream); + if (!sync_fmt) { + usb_audio_dbg(chip, + "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n", + fmt->sync_ep, fmt->sync_iface, + fmt->sync_altsetting, + snd_pcm_format_name(params_format(hw_params)), + params_rate(hw_params), params_channels(hw_params)); + ret = -EINVAL; + goto stop_pipeline; + } + } else { + sync_fmt = fmt; + } + + ret = snd_usb_lock_shutdown(chip); if (ret < 0) goto stop_pipeline; @@ -911,18 +771,56 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, if (ret < 0) goto unlock; - ret = set_format(subs, fmt); + if (subs->data_endpoint) { + if (snd_usb_endpoint_compatible(chip, subs->data_endpoint, + fmt, hw_params)) + goto unlock; + close_endpoints(chip, subs); + } + + subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false); + if (!subs->data_endpoint) { + ret = -EINVAL; + goto unlock; + } + + if (fmt->sync_ep) { + subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt, + hw_params, + fmt == sync_fmt); + if (!subs->sync_endpoint) { + ret = -EINVAL; + goto unlock; + } + + snd_usb_endpoint_set_sync(chip, subs->data_endpoint, + subs->sync_endpoint); + } + + subs->interface = fmt->iface; + subs->altset_idx = fmt->altset_idx; + subs->cur_audiofmt = fmt; + + ret = configure_endpoints(chip, subs); if (ret < 0) goto unlock; + subs->pcm_format = params_format(hw_params); + subs->period_bytes = params_period_bytes(hw_params); + subs->period_frames = params_period_size(hw_params); + subs->buffer_periods = params_periods(hw_params); + subs->channels = params_channels(hw_params); + subs->cur_rate = params_rate(hw_params); + unlock: - snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) - goto stop_pipeline; - return ret; + close_endpoints(chip, subs); + snd_usb_unlock_shutdown(chip); stop_pipeline: - snd_media_stop_pipeline(subs); + if (ret < 0) + snd_media_stop_pipeline(subs); + return ret; } @@ -941,15 +839,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_rate = 0; subs->period_bytes = 0; if (!snd_usb_lock_shutdown(chip)) { - stop_endpoints(subs); - sync_pending_stops(subs); - snd_usb_endpoint_deactivate(subs->sync_endpoint); - snd_usb_endpoint_deactivate(subs->data_endpoint); - if (subs->data_endpoint) { - subs->data_endpoint->sync_master = NULL; - subs->data_endpoint = NULL; - } - subs->sync_endpoint = NULL; + if (stop_endpoints(subs)) + sync_pending_stops(subs); + close_endpoints(chip, subs); snd_usb_unlock_shutdown(chip); } @@ -965,16 +857,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = runtime->private_data; - struct usb_host_interface *alts; - struct usb_interface *iface; + struct snd_usb_audio *chip = subs->stream->chip; int ret; - if (! subs->cur_audiofmt) { - dev_err(&subs->dev->dev, "no format is specified!\n"); - return -ENXIO; - } - - ret = snd_usb_lock_shutdown(subs->stream->chip); + ret = snd_usb_lock_shutdown(chip); if (ret < 0) return ret; if (snd_BUG_ON(!subs->data_endpoint)) { @@ -982,36 +868,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } - ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); - if (ret < 0) - goto unlock; - - ret = set_format(subs, subs->cur_audiofmt); + ret = configure_endpoints(chip, subs); if (ret < 0) goto unlock; - if (subs->need_setup_ep) { - - iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); - alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; - ret = snd_usb_init_sample_rate(subs->stream->chip, - subs->cur_audiofmt, - subs->cur_rate); - if (ret < 0) - goto unlock; - - ret = configure_endpoint(subs); - if (ret < 0) - goto unlock; - subs->need_setup_ep = false; - } - - /* some unit conversions in runtime */ - subs->data_endpoint->maxframesize = - bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); - subs->data_endpoint->curframesize = - bytes_to_frames(runtime, subs->data_endpoint->curpacksize); - /* reset the pointer */ subs->hwptr_done = 0; subs->transfer_done = 0; @@ -1025,7 +885,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) ret = start_endpoints(subs); unlock: - snd_usb_unlock_shutdown(subs->stream->chip); + snd_usb_unlock_shutdown(chip); return ret; } @@ -1047,6 +907,8 @@ static const struct snd_pcm_hardware snd_usb_hardware = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE, + .channels_min = 1, + .channels_max = 256, .buffer_bytes_max = 1024 * 1024, .period_bytes_min = 64, .period_bytes_max = 512 * 1024, @@ -1250,7 +1112,6 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, struct audioformat *fp; int err; - subs->fixed_hw = 0; list_for_each_entry(fp, &subs->fmt_list, list) { ep = snd_usb_get_endpoint(chip, fp->endpoint); if (ep && ep->cur_rate) @@ -1266,7 +1127,7 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, found: if (!find_format(&subs->fmt_list, ep->cur_format, ep->cur_rate, - ep->cur_channels, NULL)) { + ep->cur_channels, false, NULL)) { usb_audio_dbg(chip, "EP 0x%x being used, but not applicable\n", ep->ep_num); return 0; @@ -1274,19 +1135,23 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, usb_audio_dbg(chip, "EP 0x%x being used, using fixed params:\n", ep->ep_num); - usb_audio_dbg(chip, "rate=%d, format=%s, channels=%d, period_size=%d, periods=%d\n", - ep->cur_rate, snd_pcm_format_name(ep->cur_format), - ep->cur_channels, ep->cur_period_frames, + usb_audio_dbg(chip, "rate=%d, period_size=%d, periods=%d\n", + ep->cur_rate, ep->cur_period_frames, ep->cur_buffer_periods); - runtime->hw.formats = pcm_format_to_bits(ep->cur_format); + runtime->hw.formats = subs->formats; runtime->hw.rate_min = runtime->hw.rate_max = ep->cur_rate; - runtime->hw.channels_min = runtime->hw.channels_max = - ep->cur_channels; runtime->hw.rates = SNDRV_PCM_RATE_KNOT; runtime->hw.periods_min = runtime->hw.periods_max = ep->cur_buffer_periods; - subs->fixed_hw = 1; + + err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_channels, subs, + SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_HW_PARAM_RATE, + -1); + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, @@ -1442,9 +1307,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) snd_media_stop_pipeline(subs); - if (subs->interface >= 0 && - !snd_usb_lock_shutdown(subs->stream->chip)) { - usb_set_interface(subs->dev, subs->interface, 0); + if (!snd_usb_lock_shutdown(subs->stream->chip)) { subs->interface = -1; ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1); snd_usb_unlock_shutdown(subs->stream->chip); @@ -1823,15 +1686,19 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea retire_playback_urb, subs); subs->running = 1; + dev_dbg(&subs->dev->dev, "%d:%d Start Playback PCM\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altsetting); return 0; case SNDRV_PCM_TRIGGER_SUSPEND: - subs->need_setup_fmt = true; - fallthrough; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); snd_usb_endpoint_set_callback(subs->data_endpoint, NULL, NULL, NULL); subs->running = 0; + dev_dbg(&subs->dev->dev, "%d:%d Stop Playback PCM\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altsetting); return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* keep retire_data_urb for delay calculation */ @@ -1840,6 +1707,9 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea retire_playback_urb, subs); subs->running = 0; + dev_dbg(&subs->dev->dev, "%d:%d Pause Playback PCM\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altsetting); return 0; } @@ -1863,10 +1733,11 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream NULL, retire_capture_urb, subs); subs->running = 1; + dev_dbg(&subs->dev->dev, "%d:%d Start Capture PCM\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altsetting); return 0; case SNDRV_PCM_TRIGGER_SUSPEND: - subs->need_setup_fmt = true; - fallthrough; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); fallthrough; @@ -1874,6 +1745,9 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream snd_usb_endpoint_set_callback(subs->data_endpoint, NULL, NULL, NULL); subs->running = 0; + dev_dbg(&subs->dev->dev, "%d:%d Stop Capture PCM\n", + subs->cur_audiofmt->iface, + subs->cur_audiofmt->altsetting); return 0; } From patchwork Mon Nov 23 08:53:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330706 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 8FC14C2D0E4 for ; Mon, 23 Nov 2020 09:04:40 +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 BADD220731 for ; Mon, 23 Nov 2020 09:04:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="hJtPFwRP" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BADD220731 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 376B516B6; Mon, 23 Nov 2020 10:03:48 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 376B516B6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122278; bh=SEyU/9rnwgTy+4MCciZNOZTc+ii7uPyjHz8uWWcCpK4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=hJtPFwRP2/eAsvokGivfHOc0Qq+6/8nhPtxC7gMlErpdJTLAvLWdHrk8bExONEISZ UraYKrU0vNXwIfeZTTxxMYaXCbqqkO3J1z8Lw6Zz+4Blh0jF2x7wqg7epS4qDKJD8r 7uXx4B01vifc1xg8/ABwV4OzbvUVNIbnkAHMQgEA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 4132CF805B1; Mon, 23 Nov 2020 09:55:05 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 70126F804D8; Mon, 23 Nov 2020 09:54:31 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 86CB9F804D8 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 86CB9F804D8 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 61B2AAFCD; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 26/41] ALSA: usb-audio: Fix possible stall of implicit fb packet ring-buffer Date: Mon, 23 Nov 2020 09:53:32 +0100 Message-Id: <20201123085347.19667-27-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 implicit feedback mode uses a ring buffer for storing the received packet sizes from the feedback source, and the code has a slight flaw; when a playback stream stalls by some reason and the URBs aren't processed, the next_packet FIFO might become empty, but the driver can't distinguish whether it's empty or full because it's managed with read_poss and write_pos. This patch addresses those by changing the next_packet array management. Instead of keeping read and write positions, now the head position and the queued amount are kept. It's easier to understand about the emptiness. Also, the URB active flag is now cleared before calling queue_pending_output_urbs() for avoiding (theoretically) possible inconsistency. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 5 ++-- sound/usb/endpoint.c | 83 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 66a249ae138f..cde492e9581a 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -80,8 +80,9 @@ struct snd_usb_endpoint { uint32_t packet_size[MAX_PACKS_HS]; int packets; } next_packet[MAX_URBS]; - int next_packet_read_pos, next_packet_write_pos; - struct list_head ready_playback_urbs; + unsigned int next_packet_head; /* ring buffer offset to read */ + unsigned int next_packet_queued; /* queued items in the ring buffer */ + struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */ unsigned int nurbs; /* # urbs */ unsigned long active_mask; /* bitmask of active urbs */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index eee74313603e..b8f06a75fc2a 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -328,6 +328,39 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep, } } +/* notify an error as XRUN to the assigned PCM data substream */ +static void notify_xrun(struct snd_usb_endpoint *ep) +{ + struct snd_usb_substream *data_subs; + + data_subs = READ_ONCE(ep->data_subs); + if (data_subs && data_subs->pcm_substream) + snd_pcm_stop_xrun(data_subs->pcm_substream); +} + +static struct snd_usb_packet_info * +next_packet_fifo_enqueue(struct snd_usb_endpoint *ep) +{ + struct snd_usb_packet_info *p; + + p = ep->next_packet + (ep->next_packet_head + ep->next_packet_queued) % + ARRAY_SIZE(ep->next_packet); + ep->next_packet_queued++; + return p; +} + +static struct snd_usb_packet_info * +next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) +{ + struct snd_usb_packet_info *p; + + p = ep->next_packet + ep->next_packet_head; + ep->next_packet_head++; + ep->next_packet_head %= ARRAY_SIZE(ep->next_packet); + ep->next_packet_queued--; + return p; +} + /* * Send output urbs that have been prepared previously. URBs are dequeued * from ep->ready_playback_urbs and in case there aren't any available @@ -352,17 +385,14 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) int err, i; spin_lock_irqsave(&ep->lock, flags); - if (ep->next_packet_read_pos != ep->next_packet_write_pos) { - packet = ep->next_packet + ep->next_packet_read_pos; - ep->next_packet_read_pos++; - ep->next_packet_read_pos %= MAX_URBS; - + if (ep->next_packet_queued > 0 && + !list_empty(&ep->ready_playback_urbs)) { /* take URB out of FIFO */ - if (!list_empty(&ep->ready_playback_urbs)) { - ctx = list_first_entry(&ep->ready_playback_urbs, + ctx = list_first_entry(&ep->ready_playback_urbs, struct snd_urb_ctx, ready_list); - list_del_init(&ctx->ready_list); - } + list_del_init(&ctx->ready_list); + + packet = next_packet_fifo_dequeue(ep); } spin_unlock_irqrestore(&ep->lock, flags); @@ -377,12 +407,15 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) prepare_outbound_urb(ep, ctx); err = usb_submit_urb(ctx->urb, GFP_ATOMIC); - if (err < 0) + if (err < 0) { usb_audio_err(ep->chip, "Unable to submit urb #%d: %d at %s\n", ctx->index, err, __func__); - else - set_bit(ctx->index, &ep->active_mask); + notify_xrun(ep); + return; + } + + set_bit(ctx->index, &ep->active_mask); } } @@ -393,7 +426,6 @@ static void snd_complete_urb(struct urb *urb) { struct snd_urb_ctx *ctx = urb->context; struct snd_usb_endpoint *ep = ctx->ep; - struct snd_usb_substream *data_subs; unsigned long flags; int err; @@ -418,10 +450,10 @@ static void snd_complete_urb(struct urb *urb) if (snd_usb_endpoint_implicit_feedback_sink(ep)) { spin_lock_irqsave(&ep->lock, flags); list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); + clear_bit(ctx->index, &ep->active_mask); spin_unlock_irqrestore(&ep->lock, flags); queue_pending_output_urbs(ep); - - goto exit_clear; + return; } prepare_outbound_urb(ep, ctx); @@ -442,9 +474,7 @@ static void snd_complete_urb(struct urb *urb) return; usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); - data_subs = READ_ONCE(ep->data_subs); - if (data_subs && data_subs->pcm_substream) - snd_pcm_stop_xrun(data_subs->pcm_substream); + notify_xrun(ep); exit_clear: clear_bit(ctx->index, &ep->active_mask); @@ -789,8 +819,8 @@ static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force) clear_bit(EP_FLAG_RUNNING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); - ep->next_packet_read_pos = 0; - ep->next_packet_write_pos = 0; + ep->next_packet_head = 0; + ep->next_packet_queued = 0; for (i = 0; i < ep->nurbs; i++) { if (test_bit(i, &ep->active_mask)) { @@ -1402,7 +1432,16 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, return; spin_lock_irqsave(&ep->lock, flags); - out_packet = ep->next_packet + ep->next_packet_write_pos; + if (ep->next_packet_queued >= ARRAY_SIZE(ep->next_packet)) { + spin_unlock_irqrestore(&ep->lock, flags); + usb_audio_err(ep->chip, + "next package FIFO overflow EP 0x%x\n", + ep->ep_num); + notify_xrun(ep); + return; + } + + out_packet = next_packet_fifo_enqueue(ep); /* * Iterate through the inbound packet and prepare the lengths @@ -1423,8 +1462,6 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, out_packet->packet_size[i] = 0; } - ep->next_packet_write_pos++; - ep->next_packet_write_pos %= MAX_URBS; spin_unlock_irqrestore(&ep->lock, flags); queue_pending_output_urbs(ep); From patchwork Mon Nov 23 08:53:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331465 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 E5398C56202 for ; Mon, 23 Nov 2020 09:02:24 +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 116AA20732 for ; Mon, 23 Nov 2020 09:02:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="CcoyBH5n" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 116AA20732 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 45AEC16B5; Mon, 23 Nov 2020 10:01:32 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 45AEC16B5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122142; bh=1Ai5AFhp2hzBie3IWe/urEZ6u9o+eqG1bVGZ9cwqm8s=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=CcoyBH5nFTETcIxYvBXKV83JVC97BX/8HiyCkjO/yRGZgOZTF/Jclrlfh6xpU0mC2 Wy3m021KpQFYvN58LE5oCto5FI66ZoDmsoXg+oRaZJul33zAJcaIDaWjmqT4SIpGq1 JshAfZ2pEV/nZmTjNyX/TxumnlzTDekY3wX3YVK0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 29377F804E7; Mon, 23 Nov 2020 09:54:52 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 497FAF80533; Mon, 23 Nov 2020 09:54:26 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7DA08F804DF for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7DA08F804DF X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 73BE5AFCE; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 27/41] ALSA: usb-audio: Constify audioformat pointer references Date: Mon, 23 Nov 2020 09:53:33 +0100 Message-Id: <20201123085347.19667-28-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 audioformat is referred in many places but most of usages are read-only. Let's add const prefix in the possible places. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 4 ++-- sound/usb/clock.c | 16 ++++++++-------- sound/usb/clock.h | 4 ++-- sound/usb/endpoint.c | 2 +- sound/usb/endpoint.h | 2 +- sound/usb/pcm.c | 32 ++++++++++++++++---------------- sound/usb/pcm.h | 2 +- sound/usb/quirks.c | 9 +++++---- sound/usb/quirks.h | 6 +++--- 9 files changed, 39 insertions(+), 38 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index cde492e9581a..53f0ce61f858 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -120,7 +120,7 @@ struct snd_usb_endpoint { bool need_setup; /* (re-)need for configure? */ /* for hw constraints */ - struct audioformat *cur_audiofmt; + const struct audioformat *cur_audiofmt; unsigned int cur_rate; snd_pcm_format_t cur_format; unsigned int cur_channels; @@ -142,7 +142,7 @@ struct snd_usb_substream { int direction; /* playback or capture */ int interface; /* current interface */ int endpoint; /* assigned endpoint */ - struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ + const struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ struct snd_usb_power_domain *str_pd; /* UAC3 Power Domain for streaming path */ snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */ unsigned int channels; /* current number of channels (for hw_params callback) */ diff --git a/sound/usb/clock.c b/sound/usb/clock.c index b869a711afbf..e940dcee792b 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -152,7 +152,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i } static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, - struct audioformat *fmt, + const struct audioformat *fmt, int source_id) { bool ret = false; @@ -215,7 +215,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, } static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, - struct audioformat *fmt, + const struct audioformat *fmt, int source_id) { int err; @@ -264,7 +264,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, } static int __uac_clock_find_source(struct snd_usb_audio *chip, - struct audioformat *fmt, int entity_id, + const struct audioformat *fmt, int entity_id, unsigned long *visited, bool validate) { struct uac_clock_source_descriptor *source; @@ -358,7 +358,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, } static int __uac3_clock_find_source(struct snd_usb_audio *chip, - struct audioformat *fmt, int entity_id, + const struct audioformat *fmt, int entity_id, unsigned long *visited, bool validate) { struct uac3_clock_source_descriptor *source; @@ -464,7 +464,7 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, * Returns the clock source UnitID (>=0) on success, or an error. */ int snd_usb_clock_find_source(struct snd_usb_audio *chip, - struct audioformat *fmt, bool validate) + const struct audioformat *fmt, bool validate) { DECLARE_BITMAP(visited, 256); memset(visited, 0, sizeof(visited)); @@ -482,7 +482,7 @@ int snd_usb_clock_find_source(struct snd_usb_audio *chip, } static int set_sample_rate_v1(struct snd_usb_audio *chip, - struct audioformat *fmt, int rate) + const struct audioformat *fmt, int rate) { struct usb_device *dev = chip->dev; struct usb_host_interface *alts; @@ -611,7 +611,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, } static int set_sample_rate_v2v3(struct snd_usb_audio *chip, - struct audioformat *fmt, int rate) + const struct audioformat *fmt, int rate) { int cur_rate, prev_rate; int clock; @@ -663,7 +663,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, } int snd_usb_init_sample_rate(struct snd_usb_audio *chip, - struct audioformat *fmt, int rate) + const struct audioformat *fmt, int rate) { usb_audio_dbg(chip, "%d:%d Set sample rate %d, clock %d\n", fmt->iface, fmt->altsetting, rate, fmt->clock); diff --git a/sound/usb/clock.h b/sound/usb/clock.h index 8d406ed294d6..ed9fc2dc0510 100644 --- a/sound/usb/clock.h +++ b/sound/usb/clock.h @@ -3,10 +3,10 @@ #define __USBAUDIO_CLOCK_H int snd_usb_init_sample_rate(struct snd_usb_audio *chip, - struct audioformat *fmt, int rate); + const struct audioformat *fmt, int rate); int snd_usb_clock_find_source(struct snd_usb_audio *chip, - struct audioformat *fmt, bool validate); + const struct audioformat *fmt, bool validate); int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, const struct audioformat *fmt, diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index b8f06a75fc2a..49fb934ee432 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -623,7 +623,7 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, */ struct snd_usb_endpoint * snd_usb_endpoint_open(struct snd_usb_audio *chip, - struct audioformat *fp, + const struct audioformat *fp, const struct snd_pcm_hw_params *params, bool is_sync_ep) { diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 2bfa6d3e029c..201011d89659 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -12,7 +12,7 @@ int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type); struct snd_usb_endpoint * snd_usb_endpoint_open(struct snd_usb_audio *chip, - struct audioformat *fp, + const struct audioformat *fp, const struct snd_pcm_hw_params *params, bool is_sync_ep); void snd_usb_endpoint_close(struct snd_usb_audio *chip, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e80e8cf1e863..fc028492dd1a 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -80,13 +80,13 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream /* * find a matching audio format */ -static struct audioformat * +static const struct audioformat * find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, unsigned int rate, unsigned int channels, bool strict_match, struct snd_usb_substream *subs) { - struct audioformat *fp; - struct audioformat *found = NULL; + const struct audioformat *fp; + const struct audioformat *found = NULL; int cur_attr = 0, attr; list_for_each_entry(fp, fmt_list_head, list) { @@ -141,7 +141,7 @@ find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, return found; } -static struct audioformat * +static const struct audioformat * find_substream_format(struct snd_usb_substream *subs, const struct snd_pcm_hw_params *params) { @@ -182,7 +182,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int ep) * initialize the pitch control and sample rate */ int snd_usb_init_pitch(struct snd_usb_audio *chip, - struct audioformat *fmt) + const struct audioformat *fmt) { int err; @@ -641,14 +641,14 @@ find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num, return NULL; } -static struct audioformat * +static const struct audioformat * find_implicit_fb_sync_format(struct snd_usb_audio *chip, const struct audioformat *target, const struct snd_pcm_hw_params *params, int stream) { struct snd_usb_substream *subs; - struct audioformat *fp, *sync_fmt; + const struct audioformat *fp, *sync_fmt; int score, high_score; subs = find_matching_substream(chip, stream, target->sync_ep, @@ -726,8 +726,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, { struct snd_usb_substream *subs = substream->runtime->private_data; struct snd_usb_audio *chip = subs->stream->chip; - struct audioformat *fmt; - struct audioformat *sync_fmt; + const struct audioformat *fmt; + const struct audioformat *sync_fmt; int ret; ret = snd_media_start_pipeline(subs); @@ -918,7 +918,7 @@ static const struct snd_pcm_hardware snd_usb_hardware = static int hw_check_valid_format(struct snd_usb_substream *subs, struct snd_pcm_hw_params *params, - struct audioformat *fp) + const struct audioformat *fp) { struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); @@ -995,7 +995,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_usb_substream *subs = rule->private; - struct audioformat *fp; + const struct audioformat *fp; struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); unsigned int rmin, rmax, r; int i; @@ -1028,7 +1028,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_usb_substream *subs = rule->private; - struct audioformat *fp; + const struct audioformat *fp; struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); unsigned int rmin, rmax; @@ -1049,7 +1049,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_usb_substream *subs = rule->private; - struct audioformat *fp; + const struct audioformat *fp; struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); u64 fbits; u32 oldbits[2]; @@ -1080,7 +1080,7 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_usb_substream *subs = rule->private; - struct audioformat *fp; + const struct audioformat *fp; struct snd_interval *it; unsigned char min_datainterval; unsigned int pmin; @@ -1109,7 +1109,7 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, { struct snd_usb_audio *chip = subs->stream->chip; struct snd_usb_endpoint *ep; - struct audioformat *fp; + const struct audioformat *fp; int err; list_for_each_entry(fp, &subs->fmt_list, list) { @@ -1170,7 +1170,7 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime, static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) { struct snd_usb_audio *chip = subs->stream->chip; - struct audioformat *fp; + const struct audioformat *fp; unsigned int pt, ptmin; int param_period_time_if_needed = -1; int err; diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index a4f784225abc..06c586467d3f 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -10,7 +10,7 @@ int snd_usb_pcm_suspend(struct snd_usb_stream *as); int snd_usb_pcm_resume(struct snd_usb_stream *as); int snd_usb_init_pitch(struct snd_usb_audio *chip, - struct audioformat *fmt); + const struct audioformat *fmt); void snd_usb_preallocate_buffer(struct snd_usb_substream *subs); int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 7e7f258011ff..5510c8a98447 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1375,7 +1375,8 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev, /* * check if the device uses big-endian samples */ -int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp) +int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, + const struct audioformat *fp) { /* it depends on altsetting whether the device is big-endian or not */ switch (chip->usb_id) { @@ -1414,7 +1415,7 @@ enum { }; static void set_format_emu_quirk(struct snd_usb_substream *subs, - struct audioformat *fmt) + const struct audioformat *fmt) { unsigned char emu_samplerate_id = 0; @@ -1476,7 +1477,7 @@ static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs) } void snd_usb_set_format_quirk(struct snd_usb_substream *subs, - struct audioformat *fmt) + const struct audioformat *fmt) { switch (subs->stream->chip->usb_id) { case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */ @@ -1543,7 +1544,7 @@ static bool is_itf_usb_dsd_dac(unsigned int id) } int snd_usb_select_mode_quirk(struct snd_usb_audio *chip, - struct audioformat *fmt) + const struct audioformat *fmt) { struct usb_device *dev = chip->dev; int err; diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 011f22cf2bf6..67a02303c820 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -26,12 +26,12 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev, unsigned int usb_id); void snd_usb_set_format_quirk(struct snd_usb_substream *subs, - struct audioformat *fmt); + const struct audioformat *fmt); bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip); int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, - struct audioformat *fp); + const struct audioformat *fp); void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep); @@ -41,7 +41,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, __u16 index, void *data, __u16 size); int snd_usb_select_mode_quirk(struct snd_usb_audio *chip, - struct audioformat *fmt); + const struct audioformat *fmt); u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, struct audioformat *fp, From patchwork Mon Nov 23 08:53:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330704 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 0826EC56202 for ; Mon, 23 Nov 2020 09:06:05 +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 1D4CC20738 for ; Mon, 23 Nov 2020 09:06:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="VU17yvHT" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1D4CC20738 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 7E58116DD; Mon, 23 Nov 2020 10:05:12 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 7E58116DD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122362; bh=6EbO6fe3QhnZMlw1/OCWHRhmoxzMAPYIgftOrYO+ETk=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=VU17yvHT4oPVhHs1iRt8O9oYXOh5MDDsX93P9fs90T6NlXhrXz2u5ZUMEHipwmlE4 vpoJ+iHNU4jmxkyKWryuse8Po98BK43k4Z5fMzmhEOkFwvwhCKV+YovCJCbKP7exRI w16AF/MTaYt1p7Uxhzeo9MRNdtd1HrDI7eO8hx0A= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 2F202F805D6; Mon, 23 Nov 2020 09:55:09 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id D2AB3F80542; Mon, 23 Nov 2020 09:54:39 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9CECCF804E1 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9CECCF804E1 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 82626AFCF; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 28/41] ALSA: usb-audio: Use atomic_t for endpoint use_count Date: Mon, 23 Nov 2020 09:53:34 +0100 Message-Id: <20201123085347.19667-29-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 endpoint objects may be started/stopped concurrently by different substreams in the case of implicit feedback mode, while the current code handles the reference counter without any protection. This patch changes the refcount to atomic_t for avoiding the inconsistency. We need no reference_t here as the refcount goes only up to 2. Also the name "use_count" is renamed to "running" since this is about actually the running status, not the open refcount. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 2 +- sound/usb/endpoint.c | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 53f0ce61f858..f58c3769b058 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -60,7 +60,7 @@ struct snd_usb_endpoint { struct snd_usb_audio *chip; int opened; /* open refcount; protect with chip->mutex */ - int use_count; + atomic_t running; /* running status */ int ep_num; /* the referenced endpoint number */ int type; /* SND_USB_ENDPOINT_TYPE_* */ unsigned long flags; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 49fb934ee432..4d733b2d8287 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1234,7 +1234,7 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip, * * @ep: the endpoint to start * - * A call to this function will increment the use count of the endpoint. + * A call to this function will increment the running count of the endpoint. * In case it is not already running, the URBs for this endpoint will be * submitted. Otherwise, this function does nothing. * @@ -1253,11 +1253,12 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (ep->sync_master) WRITE_ONCE(ep->sync_master->sync_slave, ep); - usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (count %d)\n", - ep_type_name(ep->type), ep->ep_num, ep->use_count); + usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (running %d)\n", + ep_type_name(ep->type), ep->ep_num, + atomic_read(&ep->running)); /* already running? */ - if (++ep->use_count != 1) + if (atomic_inc_return(&ep->running) != 1) return 0; /* just to be sure */ @@ -1319,7 +1320,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (ep->sync_master) WRITE_ONCE(ep->sync_master->sync_slave, NULL); clear_bit(EP_FLAG_RUNNING, &ep->flags); - ep->use_count--; + atomic_dec(&ep->running); deactivate_urbs(ep, false); return -EPIPE; } @@ -1329,7 +1330,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) * * @ep: the endpoint to stop (may be NULL) * - * A call to this function will decrement the use count of the endpoint. + * A call to this function will decrement the running count of the endpoint. * In case the last user has requested the endpoint stop, the URBs will * actually be deactivated. * @@ -1343,16 +1344,17 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) if (!ep) return; - usb_audio_dbg(ep->chip, "Stopping %s EP 0x%x (count %d)\n", - ep_type_name(ep->type), ep->ep_num, ep->use_count); + usb_audio_dbg(ep->chip, "Stopping %s EP 0x%x (running %d)\n", + ep_type_name(ep->type), ep->ep_num, + atomic_read(&ep->running)); - if (snd_BUG_ON(ep->use_count == 0)) + if (snd_BUG_ON(!atomic_read(&ep->running))) return; if (ep->sync_master) WRITE_ONCE(ep->sync_master->sync_slave, NULL); - if (--ep->use_count == 0) { + if (!atomic_dec_return(&ep->running)) { deactivate_urbs(ep, false); set_bit(EP_FLAG_STOPPING, &ep->flags); } @@ -1363,7 +1365,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) * * @ep: the endpoint to release * - * This function does not care for the endpoint's use count but will tear + * This function does not care for the endpoint's running count but will tear * down all the streaming URBs immediately. */ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep) @@ -1410,7 +1412,7 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, * will take care of them later. */ if (snd_usb_endpoint_implicit_feedback_sink(ep) && - ep->use_count != 0) { + atomic_read(&ep->running)) { /* implicit feedback case */ int i, bytes = 0; From patchwork Mon Nov 23 08:53:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331462 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 1ED65C56202 for ; Mon, 23 Nov 2020 09:05: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 5B1E320732 for ; Mon, 23 Nov 2020 09:05:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="TfWKqbD0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5B1E320732 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 C2DC216D6; Mon, 23 Nov 2020 10:04:11 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C2DC216D6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122301; bh=nSoMKQBFld5V+k44IkbXCKNvvN7jYjohSvt/DLU0D7I=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=TfWKqbD02t6XombMT1MMfPquF8YkMxj4wU41R+v1A2S7qw0ubCf/O55Dp5iHfPX4J r7N3GYgFkh5Dn7XBEn0aanZVtOAkUqnrGpCm08DC2PYeHGRLRT2rCiEWczBkEAzQA4 yw1PwobLJPsYN0Gg56iOUekUOM7ISqvpRhDSqpCM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 0DE3BF805C2; Mon, 23 Nov 2020 09:55:07 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5927FF80536; Mon, 23 Nov 2020 09:54:32 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 8D7F8F804E2 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 8D7F8F804E2 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 87F32AFD0; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 29/41] ALSA: usb-audio: Refactoring endpoint URB deactivation Date: Mon, 23 Nov 2020 09:53:35 +0100 Message-Id: <20201123085347.19667-30-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Minor code refactoring to consolidate the URB deactivation code in endpoint.c. A slight behavior change is that the error handling in snd_usb_endpoint_start() leaves EP_FLAG_STOPPING now. This should be synced with the later PCM sync_stop callback. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 4d733b2d8287..35c84c2264e1 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -777,6 +777,9 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) unsigned long end_time = jiffies + msecs_to_jiffies(1000); int alive; + if (!test_bit(EP_FLAG_STOPPING, &ep->flags)) + return 0; + do { alive = bitmap_weight(&ep->active_mask, ep->nurbs); if (!alive) @@ -802,22 +805,31 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) */ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) { - if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) + if (ep) wait_clear_urbs(ep); } /* - * unlink active urbs. + * Stop and unlink active urbs. + * + * This function checks and clears EP_FLAG_RUNNING state. + * When @wait_sync is set, it waits until all pending URBs are killed. */ -static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force) +static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force, + bool wait_sync) { unsigned int i; if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */ return -EBADFD; - clear_bit(EP_FLAG_RUNNING, &ep->flags); + if (atomic_read(&ep->running)) + return -EBUSY; + + if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags)) + goto out; + set_bit(EP_FLAG_STOPPING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); ep->next_packet_head = 0; ep->next_packet_queued = 0; @@ -831,6 +843,9 @@ static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force) } } + out: + if (wait_sync) + return wait_clear_urbs(ep); return 0; } @@ -845,8 +860,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); /* stop urbs */ - deactivate_urbs(ep, force); - wait_clear_urbs(ep); + stop_and_unlink_urbs(ep, force, true); for (i = 0; i < ep->nurbs; i++) release_urb_ctx(&ep->urb[i]); @@ -1261,9 +1275,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (atomic_inc_return(&ep->running) != 1) return 0; - /* just to be sure */ - deactivate_urbs(ep, false); - ep->active_mask = 0; ep->unlink_mask = 0; ep->phase = 0; @@ -1317,11 +1328,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) return 0; __error: - if (ep->sync_master) - WRITE_ONCE(ep->sync_master->sync_slave, NULL); - clear_bit(EP_FLAG_RUNNING, &ep->flags); - atomic_dec(&ep->running); - deactivate_urbs(ep, false); + snd_usb_endpoint_stop(ep); return -EPIPE; } @@ -1354,10 +1361,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) if (ep->sync_master) WRITE_ONCE(ep->sync_master->sync_slave, NULL); - if (!atomic_dec_return(&ep->running)) { - deactivate_urbs(ep, false); - set_bit(EP_FLAG_STOPPING, &ep->flags); - } + if (!atomic_dec_return(&ep->running)) + stop_and_unlink_urbs(ep, false, false); } /** From patchwork Mon Nov 23 08:53:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330705 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 8964DC2D0E4 for ; Mon, 23 Nov 2020 09:05:20 +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 BC45F20732 for ; Mon, 23 Nov 2020 09:05:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="EGbrMaNH" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BC45F20732 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 1E5EF16E5; Mon, 23 Nov 2020 10:04:28 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 1E5EF16E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122318; bh=SuNA1N6kMPHoIf0CdWmXZFYcqNl5D6u44uq9nEXdNhs=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=EGbrMaNHt62eLELC6g73e6yCu7yLDarnmGgoBOFwPdhMEhSzChAwCurr4/e4mr93R Gr9oKREoc9qbtbgM8aUskF1GCCfyq7zoyx175tWYqdDhMNhS1ly9loPldiQTE9m7nF HvEfL1wmPubzyREm+oYn81yjQcQsxW9aPEM/eG4g= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BA443F805C4; Mon, 23 Nov 2020 09:55:07 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C594EF8053A; Mon, 23 Nov 2020 09:54:34 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 98EB6F804E4 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 98EB6F804E4 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 980B8AFD7; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 30/41] ALSA: usb-audio: Drop unneeded snd_usb_substream fields Date: Mon, 23 Nov 2020 09:53:36 +0100 Message-Id: <20201123085347.19667-31-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Some fields like interface and alt_idx in snd_usb_substream are mostly useless now as they can be referred via either cur_audiofmt or data_endpoint assigned to the substream. Drop those, and also assure the concurrency about the access of cur_audiofmt field. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.c | 1 - sound/usb/card.h | 8 -------- sound/usb/pcm.c | 24 ++++++------------------ sound/usb/proc.c | 19 +++++++++++++------ sound/usb/quirks.c | 10 +++++----- 5 files changed, 24 insertions(+), 38 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 58958afcec93..7940b3bff5bc 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -124,7 +124,6 @@ static void snd_usb_stream_disconnect(struct snd_usb_stream *as) subs = &as->substream[idx]; if (!subs->num_formats) continue; - subs->interface = -1; subs->data_endpoint = NULL; subs->sync_endpoint = NULL; } diff --git a/sound/usb/card.h b/sound/usb/card.h index f58c3769b058..1dd7a514d1d5 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -140,18 +140,10 @@ struct snd_usb_substream { struct usb_device *dev; struct snd_pcm_substream *pcm_substream; int direction; /* playback or capture */ - int interface; /* current interface */ int endpoint; /* assigned endpoint */ const struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ struct snd_usb_power_domain *str_pd; /* UAC3 Power Domain for streaming path */ - snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */ - unsigned int channels; /* current number of channels (for hw_params callback) */ unsigned int channels_max; /* max channels in the all audiofmts */ - unsigned int cur_rate; /* current rate (for hw_params callback) */ - unsigned int period_bytes; /* current period bytes (for hw_params callback) */ - unsigned int period_frames; /* current frames per period */ - unsigned int buffer_periods; /* current periods per buffer */ - unsigned int altset_idx; /* USB data format: index of alternate setting */ unsigned int txfr_quirk:1; /* allow sub-frame alignment */ unsigned int tx_length_quirk:1; /* add length specifier to transfers */ unsigned int fmt_type; /* USB audio format type (1-3) */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index fc028492dd1a..95a6a854dc55 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -797,20 +797,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->sync_endpoint); } - subs->interface = fmt->iface; - subs->altset_idx = fmt->altset_idx; + mutex_lock(&chip->mutex); subs->cur_audiofmt = fmt; + mutex_unlock(&chip->mutex); ret = configure_endpoints(chip, subs); - if (ret < 0) - goto unlock; - - subs->pcm_format = params_format(hw_params); - subs->period_bytes = params_period_bytes(hw_params); - subs->period_frames = params_period_size(hw_params); - subs->buffer_periods = params_periods(hw_params); - subs->channels = params_channels(hw_params); - subs->cur_rate = params_rate(hw_params); unlock: if (ret < 0) @@ -835,9 +826,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) struct snd_usb_audio *chip = subs->stream->chip; snd_media_stop_pipeline(subs); + mutex_lock(&chip->mutex); subs->cur_audiofmt = NULL; - subs->cur_rate = 0; - subs->period_bytes = 0; + mutex_unlock(&chip->mutex); if (!snd_usb_lock_shutdown(chip)) { if (stop_endpoints(subs)) sync_pending_stops(subs); @@ -1274,8 +1265,6 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) struct snd_usb_substream *subs = &as->substream[direction]; int ret; - subs->interface = -1; - subs->altset_idx = 0; runtime->hw = snd_usb_hardware; runtime->private_data = subs; subs->pcm_substream = substream; @@ -1308,7 +1297,6 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) snd_media_stop_pipeline(subs); if (!snd_usb_lock_shutdown(subs->stream->chip)) { - subs->interface = -1; ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1); snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) @@ -1570,10 +1558,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, } bytes = frames * ep->stride; - if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && + if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && subs->cur_audiofmt->dsd_dop)) { fill_playback_urb_dsd_dop(subs, urb, bytes); - } else if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U8 && + } 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; diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 889c550c9f29..447ba32e281c 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -175,32 +175,39 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, } } -static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer) +static void proc_dump_substream_status(struct snd_usb_audio *chip, + struct snd_usb_substream *subs, + struct snd_info_buffer *buffer) { + mutex_lock(&chip->mutex); if (subs->running) { snd_iprintf(buffer, " Status: Running\n"); - snd_iprintf(buffer, " Interface = %d\n", subs->interface); - snd_iprintf(buffer, " Altset = %d\n", subs->altset_idx); + if (subs->cur_audiofmt) { + snd_iprintf(buffer, " Interface = %d\n", subs->cur_audiofmt->iface); + snd_iprintf(buffer, " Altset = %d\n", subs->cur_audiofmt->altsetting); + } proc_dump_ep_status(subs, subs->data_endpoint, subs->sync_endpoint, buffer); } else { snd_iprintf(buffer, " Status: Stop\n"); } + mutex_unlock(&chip->mutex); } static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_usb_stream *stream = entry->private_data; + struct snd_usb_audio *chip = stream->chip; - snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name); + snd_iprintf(buffer, "%s : %s\n", chip->card->longname, stream->pcm->name); if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) { snd_iprintf(buffer, "\nPlayback:\n"); - proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer); + proc_dump_substream_status(chip, &stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer); proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer); } if (stream->substream[SNDRV_PCM_STREAM_CAPTURE].num_formats) { snd_iprintf(buffer, "\nCapture:\n"); - proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer); + proc_dump_substream_status(chip, &stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer); proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer); } } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 5510c8a98447..02f3f6ed9390 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1424,7 +1424,7 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs, * by playback substream */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { - if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1) + if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].cur_audiofmt) return; } @@ -1459,13 +1459,13 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs, */ static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs) { - + unsigned int cur_rate = subs->data_endpoint->cur_rate; /* Convert sample rate value to little endian */ u8 sr[3]; - sr[0] = subs->cur_rate & 0xff; - sr[1] = (subs->cur_rate >> 8) & 0xff; - sr[2] = (subs->cur_rate >> 16) & 0xff; + sr[0] = cur_rate & 0xff; + sr[1] = (cur_rate >> 8) & 0xff; + sr[2] = (cur_rate >> 16) & 0xff; /* Configure device */ usb_set_interface(subs->dev, 0, 1); From patchwork Mon Nov 23 08:53:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331461 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 1ADD1C2D0E4 for ; Mon, 23 Nov 2020 09:05:49 +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 4340220732 for ; Mon, 23 Nov 2020 09:05:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="llnaNfDS" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4340220732 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 BBD3C16EC; Mon, 23 Nov 2020 10:04:56 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz BBD3C16EC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122346; bh=ow11qwAEDOvF+My8FsPAkgX2Uc4U9EBQiqLgHiKrygU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=llnaNfDS5bZsClhlEdSiyWSPb61kL2mxoDJTYPYYomSxleU3m6oBa5SRkvUo7eiyp OXoBKBIagjA1y2dENPrt5kMvIE6uHWMKIZfs75w2rhngaPriKbXf6hNPkGKr18DCx/ gv5Eoi+XNKtHeWOcrkkZRGxqj92hJcMhOKQuQZwA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 837B5F805CA; Mon, 23 Nov 2020 09:55:08 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7B144F8053A; Mon, 23 Nov 2020 09:54:36 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9E9D3F804E5 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9E9D3F804E5 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id A6D06AFD8; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 31/41] ALSA: usb-audio: Unify the code for the next packet size calculation Date: Mon, 23 Nov 2020 09:53:37 +0100 Message-Id: <20201123085347.19667-32-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 two places calculating the next packet size for the playback stream in the exactly same way. Provide the single helper for this purpose and use it from both places gracefully. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 40 ++++++++++++++++++++++++---------------- sound/usb/endpoint.h | 4 ++-- sound/usb/pcm.c | 8 +------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 35c84c2264e1..5d618724bd75 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -121,13 +121,13 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep) } /* - * For streaming based on information derived from sync endpoints, - * prepare_outbound_urb_sizes() will call slave_next_packet_size() to - * determine the number of samples to be sent in the next packet. + * Return the number of samples to be sent in the next packet + * for streaming based on information derived from sync endpoints * - * For implicit feedback, slave_next_packet_size() is unused. + * This won't be used for implicit feedback which takes the packet size + * returned from the sync source */ -int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep) +static int slave_next_packet_size(struct snd_usb_endpoint *ep) { unsigned long flags; int ret; @@ -145,11 +145,10 @@ int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep) } /* - * For adaptive and synchronous endpoints, prepare_outbound_urb_sizes() - * will call next_packet_size() to determine the number of samples to be - * sent in the next packet. + * Return the number of samples to be sent in the next packet + * for adaptive and synchronous endpoints */ -int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) +static int next_packet_size(struct snd_usb_endpoint *ep) { int ret; @@ -167,6 +166,21 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) return ret; } +/* + * snd_usb_endpoint_next_packet_size: Return the number of samples to be sent + * in the next packet + */ +int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, + struct snd_urb_ctx *ctx, int idx) +{ + if (ctx->packet_size[idx]) + return ctx->packet_size[idx]; + else if (ep->sync_master) + return slave_next_packet_size(ep); + else + return next_packet_size(ep); +} + static void call_retire_callback(struct snd_usb_endpoint *ep, struct urb *urb) { @@ -223,13 +237,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, unsigned int length; int counts; - if (ctx->packet_size[i]) - counts = ctx->packet_size[i]; - else if (ep->sync_master) - counts = snd_usb_endpoint_slave_next_packet_size(ep); - else - counts = snd_usb_endpoint_next_packet_size(ep); - + counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); length = counts * ep->stride; /* number of silent bytes */ offset = offs * ep->stride + extra * i; urb->iso_frame_desc[i].offset = offset; diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 201011d89659..11e3bb839fd7 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -45,7 +45,7 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep); void snd_usb_endpoint_free(struct snd_usb_endpoint *ep); int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); -int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep); -int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep); +int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, + struct snd_urb_ctx *ctx, int idx); #endif /* __USBAUDIO_ENDPOINT_H */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 95a6a854dc55..5953e22a72c5 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1512,13 +1512,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, spin_lock_irqsave(&subs->lock, flags); subs->frame_limit += ep->max_urb_frames; for (i = 0; i < ctx->packets; i++) { - if (ctx->packet_size[i]) - counts = ctx->packet_size[i]; - else if (ep->sync_master) - counts = snd_usb_endpoint_slave_next_packet_size(ep); - else - counts = snd_usb_endpoint_next_packet_size(ep); - + 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; From patchwork Mon Nov 23 08:53:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330701 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 9B626C2D0E4 for ; Mon, 23 Nov 2020 09:08:50 +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 C9D8E20756 for ; Mon, 23 Nov 2020 09:08:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="lMnOVcta" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C9D8E20756 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 293DB170B; Mon, 23 Nov 2020 10:07:58 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 293DB170B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122528; bh=8sCfA94mkjOS7BBakfGh/h1rueuRz+DxkxwxuCt1iBE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=lMnOVctag2N6rBpOBEaq4lGWIq60X6uCK1bgmIkWVmeSJKK5s2qDe9hieN2J6yuEk Y7t+bEb1NoxIlQMwT66NVLwiT1hAEt8ZTiVB6sVLvWmdJAV8R4IDSlxprFG9Ym/NQ9 Rfseyef6Cpxk7OgYlcyFUXQ2U7PcQBvnya52nyeg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A66ADF80604; Mon, 23 Nov 2020 09:55:15 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 357D8F8055C; Mon, 23 Nov 2020 09:54:49 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B8FE6F804F1 for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B8FE6F804F1 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id B6B79AFDB; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 32/41] ALSA: usb-audio: Simplify rate_min/max and rates set up Date: Mon, 23 Nov 2020 09:53:38 +0100 Message-Id: <20201123085347.19667-33-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 multiple places in format.c performing the similar code for setting the rate_min, rate_max and rates fields. This patch unifies those in a helper function and calls it at the end of the parser phase so that all rate_table entries have been already determined. No functional changes, just a minor code refactoring. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/format.c | 53 ++++++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/sound/usb/format.c b/sound/usb/format.c index 7641716f0c6c..93459ba228d3 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -164,6 +164,23 @@ static int set_fixed_rate(struct audioformat *fp, int rate, int rate_bits) return 0; } +/* set up rate_min, rate_max and rates from the rate table */ +static void set_rate_table_min_max(struct audioformat *fp) +{ + unsigned int rate; + int i; + + fp->rate_min = INT_MAX; + fp->rate_max = 0; + fp->rates = 0; + for (i = 0; i < fp->nr_rates; i++) { + rate = fp->rate_table[i]; + fp->rate_min = min(fp->rate_min, rate); + fp->rate_max = max(fp->rate_max, rate); + fp->rates |= snd_pcm_rate_to_rate_bit(rate); + } +} + /* * parse the format descriptor and stores the possible sample rates * on the audioformat table (audio class v1). @@ -198,7 +215,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof return -ENOMEM; fp->nr_rates = 0; - fp->rate_min = fp->rate_max = 0; for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { unsigned int rate = combine_triple(&fmt[idx]); if (!rate) @@ -217,13 +233,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof chip->usb_id == USB_ID(0x041e, 0x4068))) rate = 8000; - fp->rate_table[fp->nr_rates] = rate; - if (!fp->rate_min || rate < fp->rate_min) - fp->rate_min = rate; - if (!fp->rate_max || rate > fp->rate_max) - fp->rate_max = rate; - fp->rates |= snd_pcm_rate_to_rate_bit(rate); - fp->nr_rates++; + fp->rate_table[fp->nr_rates++] = rate; } if (!fp->nr_rates) { usb_audio_info(chip, @@ -231,6 +241,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof fp->iface, fp->altsetting); return -EINVAL; } + set_rate_table_min_max(fp); } else { /* continuous rates */ fp->rates = SNDRV_PCM_RATE_CONTINUOUS; @@ -336,8 +347,6 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, { int i, nr_rates = 0; - fp->rates = fp->rate_min = fp->rate_max = 0; - for (i = 0; i < nr_triplets; i++) { int min = combine_quad(&data[2 + 12 * i]); int max = combine_quad(&data[6 + 12 * i]); @@ -373,12 +382,6 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, if (fp->rate_table) fp->rate_table[nr_rates] = rate; - if (!fp->rate_min || rate < fp->rate_min) - fp->rate_min = rate; - if (!fp->rate_max || rate > fp->rate_max) - fp->rate_max = rate; - fp->rates |= snd_pcm_rate_to_rate_bit(rate); - nr_rates++; if (nr_rates >= MAX_NR_RATES) { usb_audio_err(chip, "invalid uac2 rates\n"); @@ -459,9 +462,6 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, struct usb_device *dev = chip->dev; unsigned int *table; unsigned int nr_rates; - unsigned int rate_min = 0x7fffffff; - unsigned int rate_max = 0; - unsigned int rates = 0; int i, err; table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL); @@ -478,14 +478,8 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, if (err < 0) continue; - if (check_valid_altsetting_v2v3(chip, fp->iface, fp->altsetting)) { + if (check_valid_altsetting_v2v3(chip, fp->iface, fp->altsetting)) table[nr_rates++] = fp->rate_table[i]; - if (rate_min > fp->rate_table[i]) - rate_min = fp->rate_table[i]; - if (rate_max < fp->rate_table[i]) - rate_max = fp->rate_table[i]; - rates |= snd_pcm_rate_to_rate_bit(fp->rate_table[i]); - } } if (!nr_rates) { @@ -503,9 +497,6 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, kfree(fp->rate_table); fp->rate_table = table; fp->nr_rates = nr_rates; - fp->rate_min = rate_min; - fp->rate_max = rate_max; - fp->rates = rates; return 0; } @@ -602,6 +593,10 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, parse_uac2_sample_rate_range(chip, fp, nr_triplets, data); ret = validate_sample_rate_table_v2v3(chip, fp, clock); + if (ret < 0) + goto err_free; + + set_rate_table_min_max(fp); err_free: kfree(data); From patchwork Mon Nov 23 08:53:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330703 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=-13.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED, 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 C50FDC56202 for ; Mon, 23 Nov 2020 09:06:51 +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 CC21820732 for ; Mon, 23 Nov 2020 09:06:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="gDA9bFba" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CC21820732 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 2A3BE16DF; Mon, 23 Nov 2020 10:05:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2A3BE16DF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122409; bh=40nJEb7yfS9f8sthbYJwLF76MLrc+stn+FYt5bQSexw=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=gDA9bFbaPEF2Jfu2yyjBsIbtVT1K6/ENqeVXJLZAnVksK6MqYJJlg5ljd1g3lFosb 65FG1ERgvbqRpDXIqhjPdD6pvefqjs9yXTRreHC91/u2HC2Qg6rbkWqy+2OktWUvN5 2HAcmBsQLAYyDbOS6zl2HLNJNiwL3IxbTcAN2/5A= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BF2C3F805E2; Mon, 23 Nov 2020 09:55:10 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 2C888F80543; Mon, 23 Nov 2020 09:54:41 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A6DDAF804EC for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A6DDAF804EC X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id C5B32AD75; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 33/41] ALSA: usb-audio: Replace slave/master terms Date: Mon, 23 Nov 2020 09:53:39 +0100 Message-Id: <20201123085347.19667-34-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Follow the inclusive terminology, just replace sync_master/sync_slave with sync_source/sync_sink. It's also a bit clearer from its meaning, too. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 4 ++-- sound/usb/endpoint.c | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 1dd7a514d1d5..3e16b9288693 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -71,8 +71,8 @@ struct snd_usb_endpoint { struct urb *urb); struct snd_usb_substream *data_subs; - struct snd_usb_endpoint *sync_master; - struct snd_usb_endpoint *sync_slave; + struct snd_usb_endpoint *sync_source; + struct snd_usb_endpoint *sync_sink; struct snd_urb_ctx urb[MAX_URBS]; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 5d618724bd75..5f1d5f1ed8db 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -175,7 +175,7 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, { if (ctx->packet_size[idx]) return ctx->packet_size[idx]; - else if (ep->sync_master) + else if (ep->sync_source) return slave_next_packet_size(ep); else return next_packet_size(ep); @@ -205,16 +205,16 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, struct snd_urb_ctx *urb_ctx) { struct urb *urb = urb_ctx->urb; - struct snd_usb_endpoint *sync_slave; + struct snd_usb_endpoint *sync_sink; if (unlikely(ep->skip_packets > 0)) { ep->skip_packets--; return; } - sync_slave = READ_ONCE(ep->sync_slave); - if (sync_slave) - snd_usb_handle_sync_urb(sync_slave, ep, urb); + sync_sink = READ_ONCE(ep->sync_sink); + if (sync_sink) + snd_usb_handle_sync_urb(sync_sink, ep, urb); call_retire_callback(ep, urb); } @@ -708,7 +708,7 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, struct snd_usb_endpoint *data_ep, struct snd_usb_endpoint *sync_ep) { - data_ep->sync_master = sync_ep; + data_ep->sync_source = sync_ep; } /* @@ -802,7 +802,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) alive, ep->ep_num); clear_bit(EP_FLAG_STOPPING, &ep->flags); - ep->sync_slave = NULL; + ep->sync_sink = NULL; snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); return 0; @@ -969,9 +969,9 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep) packs_per_ms = 1; max_packs_per_urb = MAX_PACKS; } - if (ep->sync_master && !ep->implicit_fb_sync) + if (ep->sync_source && !ep->implicit_fb_sync) max_packs_per_urb = min(max_packs_per_urb, - 1U << ep->sync_master->syncinterval); + 1U << ep->sync_source->syncinterval); max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval); /* @@ -1015,7 +1015,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep) minsize = (ep->freqn >> (16 - ep->datainterval)) * (frame_bits >> 3); /* with sync from device, assume it can be 12% lower */ - if (ep->sync_master) + if (ep->sync_source) minsize -= minsize >> 3; minsize = max(minsize, 1u); @@ -1272,8 +1272,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (atomic_read(&ep->chip->shutdown)) return -EBADFD; - if (ep->sync_master) - WRITE_ONCE(ep->sync_master->sync_slave, ep); + if (ep->sync_source) + WRITE_ONCE(ep->sync_source->sync_sink, ep); usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (running %d)\n", ep_type_name(ep->type), ep->ep_num, @@ -1366,8 +1366,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) if (snd_BUG_ON(!atomic_read(&ep->running))) return; - if (ep->sync_master) - WRITE_ONCE(ep->sync_master->sync_slave, NULL); + if (ep->sync_source) + WRITE_ONCE(ep->sync_source->sync_sink, NULL); if (!atomic_dec_return(&ep->running)) stop_and_unlink_urbs(ep, false, false); From patchwork Mon Nov 23 08:53:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331459 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 D9AD7C2D0E4 for ; Mon, 23 Nov 2020 09:07:18 +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 0702520731 for ; Mon, 23 Nov 2020 09:07:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="UvtRT6Ug" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0702520731 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 75BDF16E5; Mon, 23 Nov 2020 10:06:26 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 75BDF16E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122436; bh=lUUCe0ACQaH37hevcW/hdZ/i/+Z4F5wor05fTpy+1RM=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=UvtRT6UglNQD9KtHipbGrW03mPYCbNKli6YawfeXNCpG49Hf4K5m3Vzp81mNALcFJ MSg8qJm5MGQN1HmdDzEaXLnTAmd8NScqEJ0uinuU2cEwVVDOl6AL52Nlps2Wf3BEZm WzPSMjj7YQfMS8P+DXwO8kdJ1/3eg7BGypctRGEU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6C7D0F805E4; Mon, 23 Nov 2020 09:55:11 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 775D9F80551; Mon, 23 Nov 2020 09:54:42 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B6398F804ED for ; Mon, 23 Nov 2020 09:54:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B6398F804ED X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D3EDDACBD; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 34/41] ALSA: usb-audio: Use unsigned char for iface and altsettings fields Date: Mon, 23 Nov 2020 09:53:40 +0100 Message-Id: <20201123085347.19667-35-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 for consistency, use unsigned char for iface and altsetting in allover places. Also rearrange the field positions of snd_usb_endpiont and tidy up with some comments. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/card.h | 11 +++++++---- sound/usb/endpoint.c | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 3e16b9288693..6a027c349194 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -16,7 +16,7 @@ struct audioformat { unsigned int fmt_type; /* USB audio format type (1-3) */ unsigned int fmt_bits; /* number of significant bits */ unsigned int frame_size; /* samples per frame for non-audio */ - int iface; /* interface number */ + unsigned char iface; /* interface number */ unsigned char altsetting; /* corresponding alternate setting */ unsigned char altset_idx; /* array index of altenate setting */ unsigned char attributes; /* corresponding attributes of cs endpoint */ @@ -63,7 +63,12 @@ struct snd_usb_endpoint { atomic_t running; /* running status */ int ep_num; /* the referenced endpoint number */ int type; /* SND_USB_ENDPOINT_TYPE_* */ - unsigned long flags; + + unsigned char iface; /* interface number */ + unsigned char altsetting; /* corresponding alternate setting */ + unsigned char ep_idx; /* endpoint array index */ + + unsigned long flags; /* running bit flags */ void (*prepare_data_urb) (struct snd_usb_substream *subs, struct urb *urb); @@ -112,8 +117,6 @@ struct snd_usb_endpoint { unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ unsigned char silence_value; unsigned int stride; - int iface, altsetting; - unsigned char ep_idx; /* endpoint array index */ int skip_packets; /* quirks for devices to ignore the first n packets in a stream */ bool implicit_fb_sync; /* syncs with implicit feedback */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 5f1d5f1ed8db..162da7a50046 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -762,7 +762,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, ep->ep_num, ep->opened); if (!--ep->opened) { endpoint_set_interface(chip, ep, false); - ep->iface = -1; + ep->iface = 0; ep->altsetting = 0; ep->cur_audiofmt = NULL; ep->cur_rate = 0; From patchwork Mon Nov 23 08:53:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331455 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 32237C2D0E4 for ; Mon, 23 Nov 2020 09:10:41 +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 1EC1420756 for ; Mon, 23 Nov 2020 09:10:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="F8eHaKIK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1EC1420756 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 7C999172B; Mon, 23 Nov 2020 10:09:48 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 7C999172B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122638; bh=8c67hbcqSjedQsnC1Rm3n97xs+jO13/52jHobUqK4og=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=F8eHaKIK829+HmGwDKJ3BDNe/Ky5S4L642bB1FkyE/mWCk+YiHMRw9QBBoB7Ti/oU PHvftXA1F/dA8kr7Qgiaarb9ZsRoeBOOdYig15C/d2lphSY0DwFSJ0/Q/45U6hXkEA 9RhHoZX4I7hcANJP5NTbvE2Vz1FXOWBv0iEpE75k= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 7A5D7F8061E; Mon, 23 Nov 2020 09:55:18 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 8B488F804FA; Mon, 23 Nov 2020 09:54:54 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B6A81F804F2 for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B6A81F804F2 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D772CAF72; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 35/41] ALSA: usb-audio: Show sync endpoint information in proc outputs Date: Mon, 23 Nov 2020 09:53:41 +0100 Message-Id: <20201123085347.19667-36-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" Now the sync endpoints have been parsed at the beginning and won't be changed dynamically, let's show them in the proc outputs for helping debugging. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/proc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 447ba32e281c..e9bbaea7b2fa 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -108,7 +108,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_pcm_format_name(fmt)); snd_iprintf(buffer, "\n"); snd_iprintf(buffer, " Channels: %d\n", fp->channels); - snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", + snd_iprintf(buffer, " Endpoint: 0x%02x (%d %s) (%s)\n", + fp->endpoint, fp->endpoint & USB_ENDPOINT_NUMBER_MASK, fp->endpoint & USB_DIR_IN ? "IN" : "OUT", sync_types[(fp->ep_attr & USB_ENDPOINT_SYNCTYPE) >> 2]); @@ -150,6 +151,19 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, "\n"); } + if (fp->sync_ep) { + snd_iprintf(buffer, " Sync Endpoint: 0x%02x (%d %s)\n", + fp->sync_ep, + fp->sync_ep & USB_ENDPOINT_NUMBER_MASK, + fp->sync_ep & USB_DIR_IN ? "IN" : "OUT"); + snd_iprintf(buffer, " Sync EP Interface: %d\n", + fp->sync_iface); + snd_iprintf(buffer, " Sync EP Altset: %d\n", + fp->sync_altsetting); + snd_iprintf(buffer, " Implicit Feedback Mode: %s\n", + fp->implicit_fb ? "Yes" : "No"); + } + // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); } From patchwork Mon Nov 23 08:53:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330700 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 9086AC2D0E4 for ; Mon, 23 Nov 2020 09:09:35 +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 CCAAF20756 for ; Mon, 23 Nov 2020 09:09:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="fq9be/j8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CCAAF20756 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 3A19E16FE; Mon, 23 Nov 2020 10:08:43 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 3A19E16FE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122573; bh=qYIwPJbAZ7pdo/HRQSB8WMU5/Gap9p3jhRZH3q/G3jQ=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=fq9be/j8+/VcZgl8GwgzGOjaEGXYEURFBU/1hfKmhWSXkHDAsC+KNuqqyBslcKYt4 dX2PlslENsitKYC6PHsQw6SnaaeHbjHecEAQX0BjdheDjEH8WoY/FeVTf6bsMOL4zG 9g8wgD5NnHkWaVOWZvXnddjyuuOXIKOFSL7Bd3Uk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id C6321F80612; Mon, 23 Nov 2020 09:55:16 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 69D7EF8055C; Mon, 23 Nov 2020 09:54:51 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id AAD0DF804F3 for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz AAD0DF804F3 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id E75F3AF82; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 36/41] ALSA: usb-audio: Quirk for BOSS GT-001 Date: Mon, 23 Nov 2020 09:53:42 +0100 Message-Id: <20201123085347.19667-37-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 capture stream of BOSS GT-001 seems always requiring to be tied with the playback stream. OTOH, the playback stream of this device doesn't seem working in the implicit fb mode, per se, since the playback must be running before the capture stream. This patch tries to address the points above: - Avoid the implicit fb mode for the playback - Set up a fake sync EP for the capture stream with the hard-coded playback stream using the implicit fb mode Reported-by: Keith Milner Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 5953e22a72c5..676acc20595b 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -403,6 +403,9 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ /* BOSS Katana amplifiers do not need quirks */ return 0; + case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */ + /* BOSS GT-001 needs no implicit fb for playback */ + return 0; } /* Generic UAC2 implicit feedback */ @@ -454,6 +457,30 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, return 1; } +static int audioformat_capture_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_host_interface *alts) +{ + struct usb_device *dev = chip->dev; + + switch (chip->usb_id) { + case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */ + if (!snd_usb_get_host_interface(chip, 0x01, 0x01)) + return 0; + fmt->sync_ep = 0x0d; + fmt->sync_iface = 0x01; + fmt->sync_altsetting = 0x01; + fmt->sync_ep_idx = 0; + fmt->implicit_fb = 1; + dev_dbg(&dev->dev, "%d:%d: added fake capture sync sync_ep=%x, iface=%d, alt=%d\n", + fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface, + fmt->sync_altsetting); + return 1; + } + return 0; + +} + int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, struct audioformat *fmt) { @@ -474,6 +501,10 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, err = audioformat_implicit_fb_quirk(chip, fmt, alts); if (err > 0) return 0; + } else { + err = audioformat_capture_quirk(chip, fmt, alts); + if (err > 0) + return 0; } if (altsd->bNumEndpoints < 2) From patchwork Mon Nov 23 08:53:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331454 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 9E062C2D0E4 for ; Mon, 23 Nov 2020 09:11:26 +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 DCDA420731 for ; Mon, 23 Nov 2020 09:11:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="hFmy1HDI" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DCDA420731 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 51F9216C0; Mon, 23 Nov 2020 10:10:34 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 51F9216C0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122684; bh=LpqKpdsHjjiG5K9+k/J4+GfKCTpKB3ebPtuEdCs71B4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=hFmy1HDIHetkk6rcnfEV2pDBeStmR3gpHNFqWzjW0UavvQJa7+VfoLttQBZQ8xq9S d7b5xH4j6JHNyiV4uQ076Bm0X6RltKqHXQC1wiSgZjF7DYR+K7PLmDPHzjlAsidSVL ApNrPaTQBsjqbBB+YstqQ2J04f2Ne1bdLutBnfWA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 91F7DF8062E; Mon, 23 Nov 2020 09:55:19 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 07121F80571; Mon, 23 Nov 2020 09:54:58 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E956BF804FB for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E956BF804FB X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id F2ECDAF86; Mon, 23 Nov 2020 08:53:58 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 37/41] ALSA: usb-audio: Factor out the implicit feedback quirk code Date: Mon, 23 Nov 2020 09:53:43 +0100 Message-Id: <20201123085347.19667-38-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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 code dealing with the implicit feedback mode grew recently, and it's becoming messy. As we receive more and more devices that need the similar handling, it's better to be processed through a table instead of the open code. This patch moves the code that is relevant with parsing the implicit feedback mode and some helpers into another file, implicit.c. The detection and the setup of the implicit feedback sync EPs are rewritten to use the ID/class matching table instead. There should be no functional changes. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/Makefile | 1 + sound/usb/implicit.c | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/implicit.h | 14 +++ sound/usb/pcm.c | 320 +++-------------------------------------------- 4 files changed, 376 insertions(+), 306 deletions(-) create mode 100644 sound/usb/implicit.c create mode 100644 sound/usb/implicit.h diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 56031026b113..9ccb21a4ff8a 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -8,6 +8,7 @@ snd-usb-audio-objs := card.o \ endpoint.o \ format.o \ helper.o \ + implicit.o \ mixer.o \ mixer_quirks.o \ mixer_scarlett.o \ diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c new file mode 100644 index 000000000000..bc7edecff946 --- /dev/null +++ b/sound/usb/implicit.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Special handling for implicit feedback mode +// + +#include +#include +#include +#include + +#include +#include +#include + +#include "usbaudio.h" +#include "card.h" +#include "helper.h" +#include "implicit.h" + +enum { + IMPLICIT_FB_NONE, + IMPLICIT_FB_FIXED, +}; + +struct snd_usb_implicit_fb_match { + unsigned int id; + unsigned int iface_class; + unsigned int ep_num; + unsigned int iface; + int type; +}; + +#define IMPLICIT_FB_FIXED_DEV(vend, prod, ep, ifnum) \ + { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_FIXED, .ep_num = (ep),\ + .iface = (ifnum) } +#define IMPLICIT_FB_SKIP_DEV(vend, prod) \ + { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_NONE } + +/* Implicit feedback quirk table for playback */ +static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { + /* Fixed EP */ + IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */ + IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */ + IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */ + IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */ + IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */ + IMPLICIT_FB_FIXED_DEV(0x07fd, 0x0008, 0x81, 2), /* MOTU M Series */ + IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */ + IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */ + IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */ + IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */ + IMPLICIT_FB_FIXED_DEV(0x0763, 0x2030, 0x81, 3), /* M-Audio Fast Track C400 */ + IMPLICIT_FB_FIXED_DEV(0x0763, 0x2031, 0x81, 3), /* M-Audio Fast Track C600 */ + IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */ + IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */ + IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */ + IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */ + IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */ + IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */ + + /* Special matching */ + { .id = USB_ID(0x07fd, 0x0004), .iface_class = USB_CLASS_AUDIO, + .type = IMPLICIT_FB_NONE }, /* MicroBook IIc */ + /* ep = 0x84, ifnum = 0 */ + { .id = USB_ID(0x07fd, 0x0004), .iface_class = USB_CLASS_VENDOR_SPEC, + .type = IMPLICIT_FB_FIXED, + .ep_num = 0x84, .iface = 0 }, /* MOTU MicroBook II */ + + /* No quirk */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8), /* BOSS Katana */ + + /* No quirk for playback but with capture quirk (see below) */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x01e5), /* BOSS GT-001 */ + + {} /* terminator */ +}; + +/* Implicit feedback quirk table for capture */ +static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { + IMPLICIT_FB_FIXED_DEV(0x0582, 0x01e5, 0x0d, 0x01), /* BOSS GT-001 */ + + {} /* terminator */ +}; + +/* set up sync EP information on the audioformat */ +static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip, + struct audioformat *fmt, + int ep, int ifnum, + const struct usb_host_interface *alts) +{ + struct usb_interface *iface; + + if (!alts) { + iface = usb_ifnum_to_if(chip->dev, ifnum); + if (!iface || iface->num_altsetting < 2) + return 0; + alts = &iface->altsetting[1]; + } + + fmt->sync_ep = ep; + fmt->sync_iface = ifnum; + fmt->sync_altsetting = alts->desc.bAlternateSetting; + fmt->sync_ep_idx = 0; + fmt->implicit_fb = 1; + usb_audio_dbg(chip, + "%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n", + fmt->iface, fmt->altsetting, + (ep & USB_DIR_IN) ? "playback" : "capture", + fmt->sync_ep, fmt->sync_iface, fmt->sync_altsetting); + return 1; +} + +/* Check whether the given UAC2 iface:altset points to an implicit fb source */ +static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip, + struct audioformat *fmt, + unsigned int ifnum, + unsigned int altsetting) +{ + struct usb_host_interface *alts; + struct usb_endpoint_descriptor *epd; + + alts = snd_usb_get_host_interface(chip, ifnum, altsetting); + if (!alts) + return 0; + if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || + alts->desc.bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING || + alts->desc.bInterfaceProtocol != UAC_VERSION_2 || + alts->desc.bNumEndpoints < 1) + return 0; + epd = get_endpoint(alts, 0); + if (!usb_endpoint_is_isoc_in(epd) || + (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != + USB_ENDPOINT_USAGE_IMPLICIT_FB) + return 0; + return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, + ifnum, alts); +} + +/* Like the function above, but specific to Roland with vendor class and hack */ +static int add_roland_implicit_fb(struct snd_usb_audio *chip, + struct audioformat *fmt, + unsigned int ifnum, + unsigned int altsetting) +{ + struct usb_host_interface *alts; + struct usb_endpoint_descriptor *epd; + + alts = snd_usb_get_host_interface(chip, ifnum, altsetting); + if (!alts) + return 0; + if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC || + (alts->desc.bInterfaceSubClass != 2 && + alts->desc.bInterfaceProtocol != 2) || + alts->desc.bNumEndpoints < 1) + return 0; + epd = get_endpoint(alts, 0); + if (!usb_endpoint_is_isoc_in(epd) || + (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != + USB_ENDPOINT_USAGE_IMPLICIT_FB) + return 0; + return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, + ifnum, alts); +} + +static const struct snd_usb_implicit_fb_match * +find_implicit_fb_entry(struct snd_usb_audio *chip, + const struct snd_usb_implicit_fb_match *match, + const struct usb_host_interface *alts) +{ + for (; match->id; match++) + if (match->id == chip->usb_id && + (!match->iface_class || + (alts->desc.bInterfaceClass == match->iface_class))) + return match; + + return NULL; +} + +/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk + * applies. Returns 1 if a quirk was found. + */ +static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_host_interface *alts) +{ + const struct snd_usb_implicit_fb_match *p; + unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; + + p = find_implicit_fb_entry(chip, playback_implicit_fb_quirks, alts); + if (p) { + switch (p->type) { + case IMPLICIT_FB_NONE: + return 0; /* No quirk */ + case IMPLICIT_FB_FIXED: + return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, + p->iface, NULL); + } + } + + /* Generic UAC2 implicit feedback */ + if (attr == USB_ENDPOINT_SYNC_ASYNC && + alts->desc.bInterfaceClass == USB_CLASS_AUDIO && + alts->desc.bInterfaceProtocol == UAC_VERSION_2 && + alts->desc.bNumEndpoints == 1) { + if (add_generic_uac2_implicit_fb(chip, fmt, + alts->desc.bInterfaceNumber + 1, + alts->desc.bAlternateSetting)) + return 1; + } + + /* Roland/BOSS implicit feedback with vendor spec class */ + if (attr == USB_ENDPOINT_SYNC_ASYNC && + alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC && + alts->desc.bInterfaceProtocol == 2 && + alts->desc.bNumEndpoints == 1 && + USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) { + if (add_roland_implicit_fb(chip, fmt, + alts->desc.bInterfaceNumber + 1, + alts->desc.bAlternateSetting)) + return 1; + } + + /* No quirk */ + return 0; +} + +/* same for capture, but only handling FIXED entry */ +static int audioformat_capture_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_host_interface *alts) +{ + const struct snd_usb_implicit_fb_match *p; + + p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts); + if (p && p->type == IMPLICIT_FB_FIXED) + return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, p->iface, + NULL); + return 0; +} + +/* + * Parse altset and set up implicit feedback endpoint on the audioformat + */ +int snd_usb_parse_implicit_fb_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_host_interface *alts) +{ + if (fmt->endpoint & USB_DIR_IN) + return audioformat_capture_quirk(chip, fmt, alts); + else + return audioformat_implicit_fb_quirk(chip, fmt, alts); +} + +/* + * Return the score of matching two audioformats. + * Veto the audioformat if: + * - It has no channels for some reason. + * - Requested PCM format is not supported. + * - Requested sample rate is not supported. + */ +static int match_endpoint_audioformats(struct snd_usb_substream *subs, + const struct audioformat *fp, + int rate, int channels, + snd_pcm_format_t pcm_format) +{ + int i, score; + + if (fp->channels < 1) + return 0; + + if (!(fp->formats & pcm_format_to_bits(pcm_format))) + return 0; + + if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) { + if (rate < fp->rate_min || rate > fp->rate_max) + return 0; + } else { + for (i = 0; i < fp->nr_rates; i++) { + if (fp->rate_table[i] == rate) + break; + } + if (i >= fp->nr_rates) + return 0; + } + + score = 1; + if (fp->channels == channels) + score++; + + return score; +} + +static struct snd_usb_substream * +find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num, + int fmt_type) +{ + struct snd_usb_stream *as; + struct snd_usb_substream *subs; + + list_for_each_entry(as, &chip->pcm_list, list) { + subs = &as->substream[stream]; + if (as->fmt_type == fmt_type && subs->ep_num == ep_num) + return subs; + } + + return NULL; +} + +/* + * Return the audioformat that is suitable for the implicit fb + */ +const struct audioformat * +snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, + const struct audioformat *target, + const struct snd_pcm_hw_params *params, + int stream) +{ + struct snd_usb_substream *subs; + const struct audioformat *fp, *sync_fmt; + int score, high_score; + + /* When sharing the same altset, use the original audioformat */ + if (target->iface == target->sync_iface && + target->altsetting == target->sync_altsetting) + return target; + + subs = find_matching_substream(chip, stream, target->sync_ep, + target->fmt_type); + if (!subs) + return NULL; + + sync_fmt = NULL; + high_score = 0; + list_for_each_entry(fp, &subs->fmt_list, list) { + score = match_endpoint_audioformats(subs, fp, + params_rate(params), + params_channels(params), + params_format(params)); + if (score > high_score) { + sync_fmt = fp; + high_score = score; + } + } + + return sync_fmt; +} + diff --git a/sound/usb/implicit.h b/sound/usb/implicit.h new file mode 100644 index 000000000000..ccb415a0ea86 --- /dev/null +++ b/sound/usb/implicit.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef __USBAUDIO_IMPLICIT_H +#define __USBAUDIO_IMPLICIT_H + +int snd_usb_parse_implicit_fb_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_host_interface *alts); +const struct audioformat * +snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, + const struct audioformat *target, + const struct snd_pcm_hw_params *params, + int stream); + +#endif /* __USBAUDIO_IMPLICIT_H */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 676acc20595b..56079901769f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -23,6 +23,7 @@ #include "clock.h" #include "power.h" #include "media.h" +#include "implicit.h" #define SUBSTREAM_FLAG_DATA_EP_STARTED 0 #define SUBSTREAM_FLAG_SYNC_EP_STARTED 1 @@ -276,211 +277,7 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) return 0; } -/* Check whether the given iface:altsetting points to an implicit fb source */ -static bool search_generic_implicit_fb(struct snd_usb_audio *chip, int ifnum, - unsigned int altsetting, - struct usb_host_interface **altsp, - unsigned int *ep) -{ - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct usb_endpoint_descriptor *epd; - - alts = snd_usb_get_host_interface(chip, ifnum, altsetting); - if (!alts) - return false; - altsd = get_iface_desc(alts); - if (altsd->bInterfaceClass != USB_CLASS_AUDIO || - altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING || - altsd->bInterfaceProtocol != UAC_VERSION_2 || - altsd->bNumEndpoints < 1) - return false; - epd = get_endpoint(alts, 0); - if (!usb_endpoint_is_isoc_in(epd) || - (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != - USB_ENDPOINT_USAGE_IMPLICIT_FB) - return false; - *ep = epd->bEndpointAddress; - *altsp = alts; - return true; -} - -/* Like the function above, but specific to Roland with vendor class and hack */ -static bool search_roland_implicit_fb(struct snd_usb_audio *chip, int ifnum, - unsigned int altsetting, - struct usb_host_interface **altsp, - unsigned int *ep) -{ - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct usb_endpoint_descriptor *epd; - - alts = snd_usb_get_host_interface(chip, ifnum, altsetting); - if (!alts) - return false; - altsd = get_iface_desc(alts); - if (altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC || - (altsd->bInterfaceSubClass != 2 && - altsd->bInterfaceProtocol != 2) || - altsd->bNumEndpoints < 1) - return false; - epd = get_endpoint(alts, 0); - if (!usb_endpoint_is_isoc_in(epd) || - (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != - USB_ENDPOINT_USAGE_IMPLICIT_FB) - return false; - *ep = epd->bEndpointAddress; - *altsp = alts; - return true; -} - -/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk - * applies. Returns 1 if a quirk was found. - */ -static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, - struct audioformat *fmt, - struct usb_host_interface *alts) -{ - struct usb_device *dev = chip->dev; - struct usb_interface_descriptor *altsd = get_iface_desc(alts); - struct usb_interface *iface; - unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; - unsigned int ep; - unsigned int ifnum; - - switch (chip->usb_id) { - case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ - case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ - case USB_ID(0x22f0, 0x0006): /* Allen&Heath Qu-16 */ - ep = 0x81; - ifnum = 3; - goto add_sync_ep_from_ifnum; - case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */ - case USB_ID(0x0763, 0x2081): - ep = 0x81; - ifnum = 2; - goto add_sync_ep_from_ifnum; - case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */ - case USB_ID(0x0499, 0x172a): /* Yamaha MODX */ - ep = 0x86; - ifnum = 2; - goto add_sync_ep_from_ifnum; - case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx III */ - ep = 0x81; - ifnum = 2; - goto add_sync_ep_from_ifnum; - case USB_ID(0x1686, 0xf029): /* Zoom UAC-2 */ - ep = 0x82; - ifnum = 2; - goto add_sync_ep_from_ifnum; - case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */ - case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */ - ep = 0x81; - ifnum = 1; - goto add_sync_ep_from_ifnum; - case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */ - /* MicroBook IIc */ - if (altsd->bInterfaceClass == USB_CLASS_AUDIO) - return 0; - - /* MicroBook II */ - ep = 0x84; - ifnum = 0; - goto add_sync_ep_from_ifnum; - case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ - case USB_ID(0x31e9, 0x0001): /* Solid State Logic SSL2 */ - case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */ - case USB_ID(0x0499, 0x172f): /* Steinberg UR22C */ - case USB_ID(0x0d9a, 0x00df): /* RTX6001 */ - ep = 0x81; - ifnum = 2; - goto add_sync_ep_from_ifnum; - case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ - case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */ - ep = 0x82; - ifnum = 0; - goto add_sync_ep_from_ifnum; - case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ - /* BOSS Katana amplifiers do not need quirks */ - return 0; - case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */ - /* BOSS GT-001 needs no implicit fb for playback */ - return 0; - } - - /* Generic UAC2 implicit feedback */ - if (attr == USB_ENDPOINT_SYNC_ASYNC && - altsd->bInterfaceClass == USB_CLASS_AUDIO && - altsd->bInterfaceProtocol == UAC_VERSION_2 && - altsd->bNumEndpoints == 1) { - ifnum = altsd->bInterfaceNumber + 1; - if (search_generic_implicit_fb(chip, ifnum, - altsd->bAlternateSetting, - &alts, &ep)) - goto add_sync_ep; - } - - /* Roland/BOSS implicit feedback with vendor spec class */ - if (attr == USB_ENDPOINT_SYNC_ASYNC && - altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && - altsd->bInterfaceProtocol == 2 && - altsd->bNumEndpoints == 1 && - USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) { - ifnum = altsd->bInterfaceNumber + 1; - if (search_roland_implicit_fb(chip, ifnum, - altsd->bAlternateSetting, - &alts, &ep)) - goto add_sync_ep; - } - - /* No quirk */ - return 0; - -add_sync_ep_from_ifnum: - iface = usb_ifnum_to_if(dev, ifnum); - - if (!iface || iface->num_altsetting < 2) - return 0; - - alts = &iface->altsetting[1]; - -add_sync_ep: - fmt->sync_ep = ep; - fmt->sync_iface = ifnum; - fmt->sync_altsetting = alts->desc.bAlternateSetting; - fmt->sync_ep_idx = 0; - fmt->implicit_fb = 1; - dev_dbg(&dev->dev, "%d:%d: found implicit_fb sync_ep=%x, iface=%d, alt=%d\n", - fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface, - fmt->sync_altsetting); - - return 1; -} - -static int audioformat_capture_quirk(struct snd_usb_audio *chip, - struct audioformat *fmt, - struct usb_host_interface *alts) -{ - struct usb_device *dev = chip->dev; - - switch (chip->usb_id) { - case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */ - if (!snd_usb_get_host_interface(chip, 0x01, 0x01)) - return 0; - fmt->sync_ep = 0x0d; - fmt->sync_iface = 0x01; - fmt->sync_altsetting = 0x01; - fmt->sync_ep_idx = 0; - fmt->implicit_fb = 1; - dev_dbg(&dev->dev, "%d:%d: added fake capture sync sync_ep=%x, iface=%d, alt=%d\n", - fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface, - fmt->sync_altsetting); - return 1; - } - return 0; - -} - +/* Set up sync endpoint */ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, struct audioformat *fmt) { @@ -496,20 +293,18 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, return 0; altsd = get_iface_desc(alts); - is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN); - if (is_playback) { - err = audioformat_implicit_fb_quirk(chip, fmt, alts); - if (err > 0) - return 0; - } else { - err = audioformat_capture_quirk(chip, fmt, alts); - if (err > 0) - return 0; - } + err = snd_usb_parse_implicit_fb_quirk(chip, fmt, alts); + if (err > 0) + return 0; /* matched */ + + /* + * Generic sync EP handling + */ if (altsd->bNumEndpoints < 2) return 0; + is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN); attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; if ((is_playback && (attr == USB_ENDPOINT_SYNC_SYNC || attr == USB_ENDPOINT_SYNC_ADAPTIVE)) || @@ -569,45 +364,6 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, return 0; } -/* - * Return the score of matching two audioformats. - * Veto the audioformat if: - * - It has no channels for some reason. - * - Requested PCM format is not supported. - * - Requested sample rate is not supported. - */ -static int match_endpoint_audioformats(struct snd_usb_substream *subs, - const struct audioformat *fp, - int rate, int channels, - snd_pcm_format_t pcm_format) -{ - int i, score; - - if (fp->channels < 1) - return 0; - - if (!(fp->formats & pcm_format_to_bits(pcm_format))) - return 0; - - if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) { - if (rate < fp->rate_min || rate > fp->rate_max) - return 0; - } else { - for (i = 0; i < fp->nr_rates; i++) { - if (fp->rate_table[i] == rate) - break; - } - if (i >= fp->nr_rates) - return 0; - } - - score = 1; - if (fp->channels == channels) - score++; - - return score; -} - static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state) { int ret; @@ -656,53 +412,6 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as) return 0; } -static struct snd_usb_substream * -find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num, - int fmt_type) -{ - struct snd_usb_stream *as; - struct snd_usb_substream *subs; - - list_for_each_entry(as, &chip->pcm_list, list) { - subs = &as->substream[stream]; - if (as->fmt_type == fmt_type && subs->ep_num == ep_num) - return subs; - } - - return NULL; -} - -static const struct audioformat * -find_implicit_fb_sync_format(struct snd_usb_audio *chip, - const struct audioformat *target, - const struct snd_pcm_hw_params *params, - int stream) -{ - struct snd_usb_substream *subs; - const struct audioformat *fp, *sync_fmt; - int score, high_score; - - subs = find_matching_substream(chip, stream, target->sync_ep, - target->fmt_type); - if (!subs) - return NULL; - - sync_fmt = NULL; - high_score = 0; - list_for_each_entry(fp, &subs->fmt_list, list) { - score = match_endpoint_audioformats(subs, fp, - params_rate(params), - params_channels(params), - params_format(params)); - if (score > high_score) { - sync_fmt = fp; - high_score = score; - } - } - - return sync_fmt; -} - static void close_endpoints(struct snd_usb_audio *chip, struct snd_usb_substream *subs) { @@ -775,11 +484,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, goto stop_pipeline; } - if (fmt->implicit_fb && - (fmt->iface != fmt->sync_iface || - fmt->altsetting != fmt->sync_altsetting)) { - sync_fmt = find_implicit_fb_sync_format(chip, fmt, hw_params, - !substream->stream); + if (fmt->implicit_fb) { + sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt, + hw_params, + !substream->stream); if (!sync_fmt) { usb_audio_dbg(chip, "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n", From patchwork Mon Nov 23 08:53:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331457 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 36682C56202 for ; Mon, 23 Nov 2020 09:09:11 +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 6A19920731 for ; Mon, 23 Nov 2020 09:09:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="sSBHyBUG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6A19920731 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 D80631714; Mon, 23 Nov 2020 10:08:18 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D80631714 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122548; bh=D7ijhhHSOVoVhU9VWeACkUO8RbzrByXwrB2+Kb/V0hQ=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=sSBHyBUGle8Hd1aUWRaWm2l1teqjVtIg2gq88Zp88s4JOPd1FOOlZt17XMWteEcrf rGwaNx6CPCEEoi5TdkkzXKSjCmHgrwEcFf2r8rYx4RxYO98N0OibuGlGmW2dTDmoRJ YFNgsQ5fUb0jPlQAVfkANwRF1eOUolzlzQmb+iao= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3E830F8060E; Mon, 23 Nov 2020 09:55:16 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id DA560F80563; Mon, 23 Nov 2020 09:54:50 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id A502AF804EB for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz A502AF804EB X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 00C9AAF8D; Mon, 23 Nov 2020 08:53:59 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 38/41] ALSA: usb-audio: Add generic implicit fb parsing Date: Mon, 23 Nov 2020 09:53:44 +0100 Message-Id: <20201123085347.19667-39-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" This patch extends the implicit feedback mode parser code to check the description more generically, so that the quirk entries can be added without the explicit EP and interface numbers. The search is done for the next and the previous interface of the given altset, and if both entries are ASYNC mode and the direction matches, it just takes as the sync endpoint. The generic parser is applicable only for the playback stream. As of now, only a few M-Audio devices have been converted to use this mode. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/implicit.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index bc7edecff946..16b1fb55b7b9 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -19,6 +19,7 @@ enum { IMPLICIT_FB_NONE, + IMPLICIT_FB_GENERIC, IMPLICIT_FB_FIXED, }; @@ -30,6 +31,8 @@ struct snd_usb_implicit_fb_match { int type; }; +#define IMPLICIT_FB_GENERIC_DEV(vend, prod) \ + { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_GENERIC } #define IMPLICIT_FB_FIXED_DEV(vend, prod, ep, ifnum) \ { .id = USB_ID(vend, prod), .type = IMPLICIT_FB_FIXED, .ep_num = (ep),\ .iface = (ifnum) } @@ -38,19 +41,22 @@ struct snd_usb_implicit_fb_match { /* Implicit feedback quirk table for playback */ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { + /* Generic matching */ + IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2080), /* M-Audio FastTrack Ultra */ + IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2081), /* M-Audio FastTrack Ultra */ + IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2030), /* M-Audio Fast Track C400 */ + IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2031), /* M-Audio Fast Track C600 */ + /* Fixed EP */ + /* FIXME: check the availability of generic matching */ IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */ IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */ - IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */ - IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */ IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */ IMPLICIT_FB_FIXED_DEV(0x07fd, 0x0008, 0x81, 2), /* MOTU M Series */ IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */ IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */ IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */ IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */ - IMPLICIT_FB_FIXED_DEV(0x0763, 0x2030, 0x81, 3), /* M-Audio Fast Track C400 */ - IMPLICIT_FB_FIXED_DEV(0x0763, 0x2031, 0x81, 3), /* M-Audio Fast Track C600 */ IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */ IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */ IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */ @@ -75,7 +81,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { {} /* terminator */ }; -/* Implicit feedback quirk table for capture */ +/* Implicit feedback quirk table for capture: only FIXED type */ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { IMPLICIT_FB_FIXED_DEV(0x0582, 0x01e5, 0x0d, 0x01), /* BOSS GT-001 */ @@ -162,6 +168,47 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip, ifnum, alts); } + +static int __add_generic_implicit_fb(struct snd_usb_audio *chip, + struct audioformat *fmt, + int iface, int altset) +{ + struct usb_host_interface *alts; + struct usb_endpoint_descriptor *epd; + + alts = snd_usb_get_host_interface(chip, iface, altset); + if (!alts) + return 0; + + if ((alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC && + alts->desc.bInterfaceClass != USB_CLASS_AUDIO) || + alts->desc.bNumEndpoints < 1) + return 0; + epd = get_endpoint(alts, 0); + if (!usb_endpoint_is_isoc_in(epd) || + (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC) + return 0; + return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, + iface, alts); +} + +/* More generic quirk: look for the sync EP next to the data EP */ +static int add_generic_implicit_fb(struct snd_usb_audio *chip, + struct audioformat *fmt, + struct usb_host_interface *alts) +{ + if ((fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC) + return 0; + + if (__add_generic_implicit_fb(chip, fmt, + alts->desc.bInterfaceNumber + 1, + alts->desc.bAlternateSetting)) + return 1; + return __add_generic_implicit_fb(chip, fmt, + alts->desc.bInterfaceNumber - 1, + alts->desc.bAlternateSetting); +} + static const struct snd_usb_implicit_fb_match * find_implicit_fb_entry(struct snd_usb_audio *chip, const struct snd_usb_implicit_fb_match *match, @@ -189,6 +236,8 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, p = find_implicit_fb_entry(chip, playback_implicit_fb_quirks, alts); if (p) { switch (p->type) { + case IMPLICIT_FB_GENERIC: + return add_generic_implicit_fb(chip, fmt, alts); case IMPLICIT_FB_NONE: return 0; /* No quirk */ case IMPLICIT_FB_FIXED: From patchwork Mon Nov 23 08:53:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330699 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 62878C2D0E4 for ; Mon, 23 Nov 2020 09:10:20 +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 4203520756 for ; Mon, 23 Nov 2020 09:10:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="qeLJpaBW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4203520756 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 4E5C41701; Mon, 23 Nov 2020 10:09:27 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 4E5C41701 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122617; bh=+iqd6rd8BTNeHP2BrxZHD0W+6KlHsYBVbXjQJve4pWU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=qeLJpaBWBm/PHpyGny0m0t2qnFwUZ7hCGaO2oPWGLz4iZ4yFN4ZEerk2pDQLFXWaT Ci7q7dO8vT3hQ6y3GslGompfONJwg7309tpb9KtVf4Yi6cYff2tTzozDXkBygycw2b wLT9MlJ9hKE46KCQKzMMgRc6pEwS4NBEodAQ1+zY= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id E1761F8061A; Mon, 23 Nov 2020 09:55:17 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id ECC33F80570; Mon, 23 Nov 2020 09:54:53 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C8CDCF804FA for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C8CDCF804FA X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 050FEAFDC; Mon, 23 Nov 2020 08:53:59 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option Date: Mon, 23 Nov 2020 09:53:45 +0100 Message-Id: <20201123085347.19667-40-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" A new module option, implicit_fb, is added to specify the driver looking for the implicit feedback sync. This can be useful for a device that could be working better in the implicit feed back mode and user wants to test it quickly. When this works, we can add the quirk entry easily. Tested-by: Keith Milner Tested-by: Dylan Robinson Signed-off-by: Takashi Iwai --- Documentation/sound/alsa-configuration.rst | 5 +++++ sound/usb/card.c | 4 ++++ sound/usb/implicit.c | 4 ++++ sound/usb/usbaudio.h | 1 + 4 files changed, 14 insertions(+) diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst index c755b1c5e16f..fe52c314b763 100644 --- a/Documentation/sound/alsa-configuration.rst +++ b/Documentation/sound/alsa-configuration.rst @@ -2227,6 +2227,11 @@ quirk_alias Quirk alias list, pass strings like ``0123abcd:5678beef``, which applies the existing quirk for the device 5678:beef to a new device 0123:abcd. +implicit_fb + Apply the generic implicit feedback sync mode. When this is set + and the playback stream sync mode is ASYNC, the driver tries to + tie an adjacent ASYNC capture stream as the implicit feedback + source. use_vmalloc Use vmalloc() for allocations of the PCM buffers (default: yes). For architectures with non-coherent memory like ARM or MIPS, the diff --git a/sound/usb/card.c b/sound/usb/card.c index 7940b3bff5bc..cb0b6582dfee 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -72,6 +72,7 @@ static bool ignore_ctl_error; static bool autoclock = true; static char *quirk_alias[SNDRV_CARDS]; static char *delayed_register[SNDRV_CARDS]; +static bool implicit_fb[SNDRV_CARDS]; bool snd_usb_use_vmalloc = true; bool snd_usb_skip_validation; @@ -97,6 +98,8 @@ module_param_array(quirk_alias, charp, NULL, 0444); MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef."); module_param_array(delayed_register, charp, NULL, 0444); MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4."); +module_param_array(implicit_fb, bool, NULL, 0444); +MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode."); module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444); MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes)."); module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444); @@ -596,6 +599,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, chip->dev = dev; chip->card = card; chip->setup = device_setup[idx]; + chip->generic_implicit_fb = implicit_fb[idx]; chip->autoclock = autoclock; atomic_set(&chip->active, 1); /* avoid autopm during probing */ atomic_set(&chip->usage_count, 0); diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index 16b1fb55b7b9..1d87fcdae95b 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -269,6 +269,10 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, return 1; } + /* Try the generic implicit fb if available */ + if (chip->generic_implicit_fb) + return add_generic_implicit_fb(chip, fmt, alts); + /* No quirk */ return 0; } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index cc338e8e2597..980287aadd36 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -51,6 +51,7 @@ struct snd_usb_audio { struct list_head mixer_list; /* list of mixer interfaces */ int setup; /* from the 'device_setup' module param */ + bool generic_implicit_fb; /* from the 'implicit_fb' module param */ bool autoclock; /* from the 'autoclock' module param */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ From patchwork Mon Nov 23 08:53:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 331456 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 4946DC2D0E4 for ; Mon, 23 Nov 2020 09:09:57 +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 212EC20756 for ; Mon, 23 Nov 2020 09:09:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="GPEozcoD" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 212EC20756 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 855D5171E; Mon, 23 Nov 2020 10:09:04 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 855D5171E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122594; bh=79y/nSWMPEKnNr4pLKSEQrH2GYR6ymyiC9cQnhf+rFg=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=GPEozcoDcPMoDLizCPZe8OrFI2LxzQbkfHP/68uXgPYzBh93nhzebBrYJq9nKezkb smKFlxI0eDBwiU/8jUPxzB9l3jOzUeBF08kdZ1WN6Va3JMg+jatiIGRkAxoIMbFIms nTNJG8o+lXBwcJIonKY9ku3+52rDrsMEOJhVMeFw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 590EFF80616; Mon, 23 Nov 2020 09:55:17 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 05961F80568; Mon, 23 Nov 2020 09:54:53 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id DD12AF804FC for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz DD12AF804FC X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 0A40CAFE1; Mon, 23 Nov 2020 08:53:59 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 40/41] ALSA: usb-audio: Fix quirks for other BOSS devices Date: Mon, 23 Nov 2020 09:53:46 +0100 Message-Id: <20201123085347.19667-41-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" A few other BOSS devices (BR-80, GT-100v2, Katana) seem requiring the same quirk as BOSS GT-001, i.e. no implicit feedback for playback but tying with capture. Add and correct the corresponding quirk table entries for them. Reported-and-tested-by: Keith Milner Signed-off-by: Takashi Iwai --- sound/usb/implicit.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index 1d87fcdae95b..1f7fb036c5b6 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -72,10 +72,10 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { .type = IMPLICIT_FB_FIXED, .ep_num = 0x84, .iface = 0 }, /* MOTU MicroBook II */ - /* No quirk */ - IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8), /* BOSS Katana */ - /* No quirk for playback but with capture quirk (see below) */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x0130), /* BOSS BR-80 */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x0189), /* BOSS GT-100v2 */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8), /* BOSS Katana */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x01e5), /* BOSS GT-001 */ {} /* terminator */ @@ -83,6 +83,9 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { /* Implicit feedback quirk table for capture: only FIXED type */ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { + IMPLICIT_FB_FIXED_DEV(0x0582, 0x0130, 0x0d, 0x01), /* BOSS BR-80 */ + IMPLICIT_FB_FIXED_DEV(0x0582, 0x0189, 0x0d, 0x01), /* BOSS GT-100v2 */ + IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d8, 0x0d, 0x01), /* BOSS Katana */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x01e5, 0x0d, 0x01), /* BOSS GT-001 */ {} /* terminator */ From patchwork Mon Nov 23 08:53:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 330698 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=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 6EFD5C56202 for ; Mon, 23 Nov 2020 09:11:02 +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 8CDD120756 for ; Mon, 23 Nov 2020 09:11:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="ZkecK7mP" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8CDD120756 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 997F1172F; Mon, 23 Nov 2020 10:10:09 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 997F1172F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1606122659; bh=b+M1+mpnYUdn4TzcRPK6iwU9rtb8Dp/Z08q046TBAT8=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=ZkecK7mP84Wd/YQ+vvQ5nzupdRlePM8XgNu6qbd++9Wuut2mcnRQxmk0BRCIXDXgB RkcExl3airURyX4/gdFJoqvqgLA9LrF/sm2VfrDBKfI1PU6BUJ1yFSduoBlthaZQTZ ++8Ew2KWM/ZVLgyTf5ovjzfG9KUTBBxqdW7J92i8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 0F454F80622; Mon, 23 Nov 2020 09:55:19 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 4A7AFF80571; Mon, 23 Nov 2020 09:54:55 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id E07D1F804FD for ; Mon, 23 Nov 2020 09:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E07D1F804FD X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 18BC7AE2E; Mon, 23 Nov 2020 08:53:59 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Subject: [PATCH 41/41] ALSA: usb-audio: Fix MOTU M-Series quirks Date: Mon, 23 Nov 2020 09:53:47 +0100 Message-Id: <20201123085347.19667-42-tiwai@suse.de> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20201123085347.19667-1-tiwai@suse.de> References: <20201123085347.19667-1-tiwai@suse.de> Cc: Matwey Kornilov , Dylan Robinson , Keith Milner 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" From: Dylan Robinson Now that the usb audio driver correctly finds implicit feedback endpoints, the implicit feedback quirk for the MOTU M-Series is no longer required. This also removes some unnecessary vendor specific messages from the MOTU M-Series boot quirk. The removed vendor specific messages turned on vendor specific interrupts to the host every 32 samples. The only thing the boot quirk needs to do is wait for 2 seconds. Tested-by: Dylan Robinson Signed-off-by: Dylan Robinson Signed-off-by: Takashi Iwai --- sound/usb/implicit.c | 1 - sound/usb/quirks.c | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index 1f7fb036c5b6..386198b36b87 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -52,7 +52,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */ IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */ IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */ - IMPLICIT_FB_FIXED_DEV(0x07fd, 0x0008, 0x81, 2), /* MOTU M Series */ IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */ IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */ IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */ diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 02f3f6ed9390..63cdf3c8c2bc 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1110,24 +1110,8 @@ static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev) static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev) { - int ret; - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 1, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, 0, NULL, 0, 1000); - - if (ret < 0) - return ret; - msleep(2000); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 1, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x20, 0, NULL, 0, 1000); - - if (ret < 0) - return ret; - return 0; }