From patchwork Mon Mar 25 16:00:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10869581 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 914B318A6 for ; Mon, 25 Mar 2019 16:21:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7A12A28EB5 for ; Mon, 25 Mar 2019 16:21:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E64929184; Mon, 25 Mar 2019 16:21:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2A52D28F42 for ; Mon, 25 Mar 2019 16:21:20 +0000 (UTC) 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 78AB088A; Mon, 25 Mar 2019 17:02:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 78AB088A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553529829; bh=0Re+UeEP+/MvRtCfMZRjhzPDKg3UsV6rGqg5BzYCA1g=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Z2o0AJc6l8D1x0IJhh9iuWSpficNyzlD/N7OLSRdseYvl1ilK5eVyF/+IewKQlOBj TmrhKh3zX/CrtufYl+c3iGHf0aAA1wcn1i4bjui2L6iPmQIh/jhz0ON39e04cZzi51 NpXTKw/2k++KTd2Lh+wjFtsG5SQ4Um/z56gop5j8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 53BF8F808F6; Mon, 25 Mar 2019 17:01:27 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id C794CF89713; Mon, 25 Mar 2019 17:01:22 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B9BCBF80C16; Mon, 25 Mar 2019 17:01:16 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B9BCBF80C16 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id 84C563C0149; Mon, 25 Mar 2019 17:01:15 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CWS3vUPDxEol; Mon, 25 Mar 2019 17:01:04 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 677573C00C4; Mon, 25 Mar 2019 17:01:04 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Mon, 25 Mar 2019 17:01:03 +0100 From: To: , , , Date: Mon, 25 Mar 2019 17:00:35 +0100 Message-ID: <1553529644-5654-2-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 01/10] ALSA: aloop: Describe units of variables 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer Describe the unit of the variables used to calculate the hw pointer depending on jiffies ticks. Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 8c3fbe1..70145e6 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -116,8 +116,10 @@ struct loopback_pcm { /* flags */ unsigned int period_update_pending :1; /* timer stuff */ - unsigned int irq_pos; /* fractional IRQ position */ - unsigned int period_size_frac; + unsigned int irq_pos; /* fractional IRQ position in jiffies + * ticks + */ + unsigned int period_size_frac; /* period size in jiffies ticks */ unsigned int last_drift; unsigned long last_jiffies; struct timer_list timer; From patchwork Mon Mar 25 16:00:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10869579 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4D635925 for ; Mon, 25 Mar 2019 16:21:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 30F8D28EB5 for ; Mon, 25 Mar 2019 16:21:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 24006291BE; Mon, 25 Mar 2019 16:21:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2802228EB5 for ; Mon, 25 Mar 2019 16:21:20 +0000 (UTC) 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 1C318843; Mon, 25 Mar 2019 17:02:16 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 1C318843 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553529786; bh=BgfC2t7AkUxx9hJQ+MlK5fuI+eD5Madk9awBH86Fl+E=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=L5+VtL0tmq/I7Uwd/hW8+56qkFUEjDadqU/AOlISdiwkc4hjfjNtiHZwDIicPP6IJ GohGwuttc8R70Dnj1wxyWrQ32RDL7gfp3PUaZrG4eBOQ0sY+dxuIPVJLQAliBQEed4 ifWXK1HKiWrAMjsQ/CDFhS0Wbi9QPSBl645P6p1U= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id EA60EF89713; Mon, 25 Mar 2019 17:01:25 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7FCE8F89714; Mon, 25 Mar 2019 17:01:22 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 6F68BF808F6; Mon, 25 Mar 2019 17:01:16 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 6F68BF808F6 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id B4AF23C00C4; Mon, 25 Mar 2019 17:01:15 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zbsQ41msZljZ; Mon, 25 Mar 2019 17:01:04 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 9FFFC3C00DD; Mon, 25 Mar 2019 17:01:04 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Mon, 25 Mar 2019 17:01:04 +0100 From: To: , , , Date: Mon, 25 Mar 2019 17:00:36 +0100 Message-ID: <1553529644-5654-3-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 02/10] ALSA: aloop: loopback_timer_start: Support return of error code 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer This is required for additional timer implementations which could detect errors and want to throw them. Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 70145e6..f0c7b5b 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -169,7 +169,7 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm) } /* call in cable->lock */ -static void loopback_timer_start(struct loopback_pcm *dpcm) +static int loopback_timer_start(struct loopback_pcm *dpcm) { unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); @@ -185,6 +185,8 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) tick = dpcm->period_size_frac - dpcm->irq_pos; tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; mod_timer(&dpcm->timer, jiffies + tick); + + return 0; } /* call in cable->lock */ @@ -265,7 +267,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_pcm_runtime *runtime = substream->runtime; struct loopback_pcm *dpcm = runtime->private_data; struct loopback_cable *cable = dpcm->cable; - int err, stream = 1 << substream->stream; + int err = 0, stream = 1 << substream->stream; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -278,7 +280,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); cable->running |= stream; cable->pause &= ~stream; - loopback_timer_start(dpcm); + err = loopback_timer_start(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -306,7 +308,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); dpcm->last_jiffies = jiffies; cable->pause &= ~stream; - loopback_timer_start(dpcm); + err = loopback_timer_start(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -314,7 +316,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) default: return -EINVAL; } - return 0; + return err; } static void params_change(struct snd_pcm_substream *substream) From patchwork Mon Mar 25 16:00:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10869639 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DD691186D for ; Mon, 25 Mar 2019 16:41:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C454628E12 for ; Mon, 25 Mar 2019 16:41:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B86AF294AF; Mon, 25 Mar 2019 16:41:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8D2ED28E12 for ; Mon, 25 Mar 2019 16:41:17 +0000 (UTC) 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 92DE1872; Mon, 25 Mar 2019 17:04:24 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 92DE1872 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553529914; bh=+0DX02YKGw/nzOrhWmi76oE2SZHtadpo2J+On5hwlOs=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=YfYZJw9qwErn4YAyrPve9caocdVKwmY4T75HqJBk+Tj7TxxLqa4QxzzkXMrGDDnTj e0cAJ6Vll84Rp4uasA0kH1zCAmqXl2nKYDMXKObT/v3Gb6s3wxh4pj/CVsKHmY97ly k0Imtu+mEvYpE/vSB+vHEsNANP9xLHH399zvXsjA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 45740F8972C; Mon, 25 Mar 2019 17:01:37 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 51110F89718; Mon, 25 Mar 2019 17:01:27 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 87C20F808F6; Mon, 25 Mar 2019 17:01:22 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 87C20F808F6 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id 402A63C00C4; Mon, 25 Mar 2019 17:01:22 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id V3w0utbygsbS; Mon, 25 Mar 2019 17:01:15 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 1A4923C013A; Mon, 25 Mar 2019 17:01:05 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Mon, 25 Mar 2019 17:01:04 +0100 From: To: , , , Date: Mon, 25 Mar 2019 17:00:37 +0100 Message-ID: <1553529644-5654-4-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 03/10] ALSA: aloop: loopback_timer_stop: Support return of error code 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer This is required for additional timer implementations which could detect errors and want to throw them. Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index f0c7b5b..11e8ed6 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -190,15 +190,19 @@ static int loopback_timer_start(struct loopback_pcm *dpcm) } /* call in cable->lock */ -static inline void loopback_timer_stop(struct loopback_pcm *dpcm) +static inline int loopback_timer_stop(struct loopback_pcm *dpcm) { del_timer(&dpcm->timer); dpcm->timer.expires = 0; + + return 0; } -static inline void loopback_timer_stop_sync(struct loopback_pcm *dpcm) +static inline int loopback_timer_stop_sync(struct loopback_pcm *dpcm) { del_timer_sync(&dpcm->timer); + + return 0; } #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -289,7 +293,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); cable->running &= ~stream; cable->pause &= ~stream; - loopback_timer_stop(dpcm); + err = loopback_timer_stop(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -298,7 +302,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: spin_lock(&cable->lock); cable->pause |= stream; - loopback_timer_stop(dpcm); + err = loopback_timer_stop(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -337,9 +341,11 @@ static int loopback_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct loopback_pcm *dpcm = runtime->private_data; struct loopback_cable *cable = dpcm->cable; - int bps, salign; + int err, bps, salign; - loopback_timer_stop_sync(dpcm); + err = loopback_timer_stop_sync(dpcm); + if (err < 0) + return err; salign = (snd_pcm_format_width(runtime->format) * runtime->channels) / 8; From patchwork Tue Mar 26 07:49:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10870579 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8F1701390 for ; Tue, 26 Mar 2019 07:51:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7566B28D18 for ; Tue, 26 Mar 2019 07:51:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6668629087; Tue, 26 Mar 2019 07:51:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6C8CC28D18 for ; Tue, 26 Mar 2019 07:51:04 +0000 (UTC) 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 40B94851; Tue, 26 Mar 2019 08:50:12 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 40B94851 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553586662; bh=AbYTjdgxsVlSkGFQgD52tlivxAVNhN3+Tr1bNumUtHM=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=fIG6eXh8eX6UxRiyYpAZz7G5jh/+rIcKux85dejmV8gkyd5NwY32iNlDqjlIUJ31L Go1Gvn5Dnx2pckv3H0Zz7ssue/bM/tSqZ4wTJNtubHUPEzRRoPkrLyTCd3DP+dVtNm L/wS9JhYfn11+qShHo6eYecvHqgtxaEPVo9J3vVU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A02BEF89622; Tue, 26 Mar 2019 08:50:11 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 94AA4F8963B; Tue, 26 Mar 2019 08:50:10 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 66B02F801D9; Tue, 26 Mar 2019 08:50:03 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 66B02F801D9 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id CD2E23C00C4; Tue, 26 Mar 2019 08:50:00 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id x6C92qGOclwe; Tue, 26 Mar 2019 08:49:54 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 7AF683C013A; Tue, 26 Mar 2019 08:49:54 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Tue, 26 Mar 2019 08:49:54 +0100 From: To: , , , Date: Tue, 26 Mar 2019 08:49:29 +0100 Message-ID: <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 05/10] ALSA: aloop: Use callback functions for timer specific implementations 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer This commit only refectors the implementation. It does not change the behaviour. It is required to support other timers (e.g sound timer). Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 113 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 19 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index c6217c4..422d130 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -69,8 +69,39 @@ MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels change #define NO_PITCH 100000 +struct loopback_cable; struct loopback_pcm; +struct loopback_ops { + /* optional + * call in loopback->cable_lock + */ + int (*open)(struct loopback_pcm *dpcm); + /* required + * call in cable->lock + */ + int (*start)(struct loopback_pcm *dpcm); + /* required + * call in cable->lock + */ + int (*stop)(struct loopback_pcm *dpcm); + /* optional */ + int (*stop_sync)(struct loopback_pcm *dpcm); + /* optional */ + int (*close_substream)(struct loopback_pcm *dpcm); + /* optional + * call in loopback->cable_lock + */ + int (*close_cable)(struct loopback_pcm *dpcm); + /* optional + * call in cable->lock + */ + unsigned int (*pos_update)(struct loopback_cable *cable); + /* optional */ + void (*dpcm_info)(struct loopback_pcm *dpcm, + struct snd_info_buffer *buffer); +}; + struct loopback_cable { spinlock_t lock; struct loopback_pcm *streams[2]; @@ -79,6 +110,8 @@ struct loopback_cable { unsigned int valid; unsigned int running; unsigned int pause; + /* timer specific */ + struct loopback_ops *ops; }; struct loopback_setup { @@ -285,7 +318,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock_irqsave(&cable->lock, flags); cable->running |= stream; cable->pause &= ~stream; - err = loopback_timer_start(dpcm); + err = cable->ops->start(dpcm); spin_unlock_irqrestore(&cable->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -294,7 +327,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock_irqsave(&cable->lock, flags); cable->running &= ~stream; cable->pause &= ~stream; - err = loopback_timer_stop(dpcm); + err = cable->ops->stop(dpcm); spin_unlock_irqrestore(&cable->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -303,7 +336,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: spin_lock_irqsave(&cable->lock, flags); cable->pause |= stream; - err = loopback_timer_stop(dpcm); + err = cable->ops->stop(dpcm); spin_unlock_irqrestore(&cable->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -313,7 +346,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock_irqsave(&cable->lock, flags); dpcm->last_jiffies = jiffies; cable->pause &= ~stream; - err = loopback_timer_start(dpcm); + err = cable->ops->start(dpcm); spin_unlock_irqrestore(&cable->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -344,9 +377,11 @@ static int loopback_prepare(struct snd_pcm_substream *substream) struct loopback_cable *cable = dpcm->cable; int err, bps, salign; - err = loopback_timer_stop_sync(dpcm); - if (err < 0) - return err; + if (cable->ops->stop_sync) { + err = cable->ops->stop_sync(dpcm); + if (err < 0) + return err; + } salign = (snd_pcm_format_width(runtime->format) * runtime->channels) / 8; @@ -554,6 +589,18 @@ static void loopback_timer_function(struct timer_list *t) spin_unlock_irqrestore(&dpcm->cable->lock, flags); } +static void loopback_jiffies_timer_dpcm_info(struct loopback_pcm *dpcm, + struct snd_info_buffer *buffer) +{ + snd_iprintf(buffer, " update_pending:\t%u\n", + dpcm->period_update_pending); + snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos); + snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac); + snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n", + dpcm->last_jiffies, jiffies); + snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires); +} + static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -562,7 +609,8 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) snd_pcm_uframes_t pos; spin_lock_irqsave(&dpcm->cable->lock, flags); - loopback_pos_update(dpcm->cable); + if (dpcm->cable->ops->pos_update) + dpcm->cable->ops->pos_update(dpcm->cable); pos = dpcm->buf_pos; spin_unlock_irqrestore(&dpcm->cable->lock, flags); return bytes_to_frames(runtime, pos); @@ -688,12 +736,33 @@ static void free_cable(struct snd_pcm_substream *substream) cable->streams[substream->stream] = NULL; spin_unlock_irqrestore(&cable->lock, flags); } else { + struct loopback_pcm *dpcm = substream->runtime->private_data; + + if (cable->ops && cable->ops->close_cable && dpcm) + cable->ops->close_cable(dpcm); /* free the cable */ loopback->cables[substream->number][dev] = NULL; kfree(cable); } } +static int loopback_jiffies_timer_open(struct loopback_pcm *dpcm) +{ + timer_setup(&dpcm->timer, loopback_timer_function, 0); + + return 0; +} + +static struct loopback_ops loopback_jiffies_timer_ops = { + .open = loopback_jiffies_timer_open, + .start = loopback_timer_start, + .stop = loopback_timer_stop, + .stop_sync = loopback_timer_stop_sync, + .close_substream = loopback_timer_stop_sync, + .pos_update = loopback_pos_update, + .dpcm_info = loopback_jiffies_timer_dpcm_info, +}; + static int loopback_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -712,7 +781,6 @@ static int loopback_open(struct snd_pcm_substream *substream) } dpcm->loopback = loopback; dpcm->substream = substream; - timer_setup(&dpcm->timer, loopback_timer_function, 0); cable = loopback->cables[substream->number][dev]; if (!cable) { @@ -723,9 +791,17 @@ static int loopback_open(struct snd_pcm_substream *substream) } spin_lock_init(&cable->lock); cable->hw = loopback_pcm_hardware; + cable->ops = &loopback_jiffies_timer_ops; loopback->cables[substream->number][dev] = cable; } dpcm->cable = cable; + runtime->private_data = dpcm; + + if (cable->ops->open) { + err = cable->ops->open(dpcm); + if (err < 0) + goto unlock; + } snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); @@ -751,7 +827,9 @@ static int loopback_open(struct snd_pcm_substream *substream) if (err < 0) goto unlock; - runtime->private_data = dpcm; + /* loopback_runtime_free() has not to be called if kfree(dpcm) was + * already called here. Otherwise it will end up with a double free. + */ runtime->private_free = loopback_runtime_free; if (get_notify(dpcm)) runtime->hw = loopback_pcm_hardware; @@ -775,12 +853,14 @@ static int loopback_close(struct snd_pcm_substream *substream) { struct loopback *loopback = substream->private_data; struct loopback_pcm *dpcm = substream->runtime->private_data; + int err = 0; - loopback_timer_stop_sync(dpcm); + if (dpcm->cable->ops->close_substream) + err = dpcm->cable->ops->close_substream(dpcm); mutex_lock(&loopback->cable_lock); free_cable(substream); mutex_unlock(&loopback->cable_lock); - return 0; + return err; } static const struct snd_pcm_ops loopback_pcm_ops = { @@ -1103,13 +1183,8 @@ static void print_dpcm_info(struct snd_info_buffer *buffer, snd_iprintf(buffer, " bytes_per_sec:\t%u\n", dpcm->pcm_bps); snd_iprintf(buffer, " sample_align:\t%u\n", dpcm->pcm_salign); snd_iprintf(buffer, " rate_shift:\t\t%u\n", dpcm->pcm_rate_shift); - snd_iprintf(buffer, " update_pending:\t%u\n", - dpcm->period_update_pending); - snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos); - snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac); - snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n", - dpcm->last_jiffies, jiffies); - snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires); + if (dpcm->cable->ops->dpcm_info) + dpcm->cable->ops->dpcm_info(dpcm, buffer); } static void print_substream_info(struct snd_info_buffer *buffer, From patchwork Tue Mar 26 07:49:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10870581 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C4A1A1708 for ; Tue, 26 Mar 2019 07:52:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AEA6D28DB9 for ; Tue, 26 Mar 2019 07:52:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A26C229089; Tue, 26 Mar 2019 07:52:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3053628DB9 for ; Tue, 26 Mar 2019 07:52:02 +0000 (UTC) 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 3F249843; Tue, 26 Mar 2019 08:51:10 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 3F249843 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553586720; bh=1A1q6u+6keu/KbJO8ECcxNHuldIdSEPfTjjayeKeXQs=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=W5O+lQkAemjQJZK6q0+Xr49q1biy9o4wEJYH9DKmwg3zdgrrjAGJp/oy/QuQPwjTO xA4bxKSCq2eGrdsICME3ypDFuZ2gQ2mFEycBWAenrPE9iKOBtQeAHQfkO2Nm1uE6td Z+rmaeG8owzaM0n9/Monlw6XKUGzgMZImioVfdZg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 5387BF8963B; Tue, 26 Mar 2019 08:51:05 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id C8ECCF89708; Tue, 26 Mar 2019 08:51:03 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C883CF801D9; Tue, 26 Mar 2019 08:50:59 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C883CF801D9 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id 7D8F23C00C4; Tue, 26 Mar 2019 08:50:59 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7s8cfOfHsxAw; Tue, 26 Mar 2019 08:50:53 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id E479E3C0149; Tue, 26 Mar 2019 08:50:21 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Tue, 26 Mar 2019 08:50:21 +0100 From: To: , , , Date: Tue, 26 Mar 2019 08:49:30 +0100 Message-ID: <1553586574-18608-2-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 06/10] ALSA: aloop: Rename all jiffies timer specific functions 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer This commit does not change the behaviour. It only seperates the jiffies timer specific implementation from the generic part. Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 422d130..3105757 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -202,7 +202,7 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm) } /* call in cable->lock */ -static int loopback_timer_start(struct loopback_pcm *dpcm) +static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm) { unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); @@ -223,7 +223,7 @@ static int loopback_timer_start(struct loopback_pcm *dpcm) } /* call in cable->lock */ -static inline int loopback_timer_stop(struct loopback_pcm *dpcm) +static inline int loopback_jiffies_timer_stop(struct loopback_pcm *dpcm) { del_timer(&dpcm->timer); dpcm->timer.expires = 0; @@ -231,7 +231,7 @@ static inline int loopback_timer_stop(struct loopback_pcm *dpcm) return 0; } -static inline int loopback_timer_stop_sync(struct loopback_pcm *dpcm) +static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) { del_timer_sync(&dpcm->timer); @@ -517,7 +517,8 @@ static inline void bytepos_finish(struct loopback_pcm *dpcm, } /* call in cable->lock */ -static unsigned int loopback_pos_update(struct loopback_cable *cable) +static unsigned int loopback_jiffies_timer_pos_update + (struct loopback_cable *cable) { struct loopback_pcm *dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; @@ -570,14 +571,15 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) return running; } -static void loopback_timer_function(struct timer_list *t) +static void loopback_jiffies_timer_function(struct timer_list *t) { struct loopback_pcm *dpcm = from_timer(dpcm, t, timer); unsigned long flags; spin_lock_irqsave(&dpcm->cable->lock, flags); - if (loopback_pos_update(dpcm->cable) & (1 << dpcm->substream->stream)) { - loopback_timer_start(dpcm); + if (loopback_jiffies_timer_pos_update(dpcm->cable) & + (1 << dpcm->substream->stream)) { + loopback_jiffies_timer_start(dpcm); if (dpcm->period_update_pending) { dpcm->period_update_pending = 0; spin_unlock_irqrestore(&dpcm->cable->lock, flags); @@ -748,18 +750,18 @@ static void free_cable(struct snd_pcm_substream *substream) static int loopback_jiffies_timer_open(struct loopback_pcm *dpcm) { - timer_setup(&dpcm->timer, loopback_timer_function, 0); + timer_setup(&dpcm->timer, loopback_jiffies_timer_function, 0); return 0; } static struct loopback_ops loopback_jiffies_timer_ops = { .open = loopback_jiffies_timer_open, - .start = loopback_timer_start, - .stop = loopback_timer_stop, - .stop_sync = loopback_timer_stop_sync, - .close_substream = loopback_timer_stop_sync, - .pos_update = loopback_pos_update, + .start = loopback_jiffies_timer_start, + .stop = loopback_jiffies_timer_stop, + .stop_sync = loopback_jiffies_timer_stop_sync, + .close_substream = loopback_jiffies_timer_stop_sync, + .pos_update = loopback_jiffies_timer_pos_update, .dpcm_info = loopback_jiffies_timer_dpcm_info, }; From patchwork Tue Mar 26 07:49:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10870587 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9F6181708 for ; Tue, 26 Mar 2019 07:52:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8A0E228DB9 for ; Tue, 26 Mar 2019 07:52:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7E0962908B; Tue, 26 Mar 2019 07:52:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C131128D18 for ; Tue, 26 Mar 2019 07:52:46 +0000 (UTC) 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 E9AAE860; Tue, 26 Mar 2019 08:51:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz E9AAE860 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553586765; bh=5L07zTIKnUcR87DCKU4fKR7xGwkiytQDZRcq5Iq2G8g=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=QH0N/331xnGoH7wG+EdJjwn9A2j4FAbYd9MnqU413YJi2iBhywVWSZn7GtQrDFIgO ewWjYHm0Kib4RzTFoRxq0PUXHmSxwUw2kM+2xW0AGuVIt4UfxxFuSeXkieEH6Vjr82 HjpKerLscFwGwST9ePMUMmammuW40WKEHNx+qWCM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 2BB21F89718; Tue, 26 Mar 2019 08:51:08 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 3A256F89701; Tue, 26 Mar 2019 08:51:06 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9D601F89701; Tue, 26 Mar 2019 08:51:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 9D601F89701 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id BDD1C3C00DD; Tue, 26 Mar 2019 08:50:59 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vhQ56YlgwGgM; Tue, 26 Mar 2019 08:50:53 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 637973C014A; Tue, 26 Mar 2019 08:50:27 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Tue, 26 Mar 2019 08:50:26 +0100 From: To: , , , Date: Tue, 26 Mar 2019 08:49:31 +0100 Message-ID: <1553586574-18608-3-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 07/10] ALSA: aloop: Move CABLE_VALID_BOTH to the top of file 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer so all functions can use the same. Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 3105757..85a1519 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -69,6 +69,10 @@ MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels change #define NO_PITCH 100000 +#define CABLE_VALID_PLAYBACK BIT(SNDRV_PCM_STREAM_PLAYBACK) +#define CABLE_VALID_CAPTURE BIT(SNDRV_PCM_STREAM_CAPTURE) +#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK | CABLE_VALID_CAPTURE) + struct loopback_cable; struct loopback_pcm; @@ -238,10 +242,6 @@ static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) return 0; } -#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) -#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE) -#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE) - static int loopback_check_format(struct loopback_cable *cable, int stream) { struct snd_pcm_runtime *runtime, *cruntime; From patchwork Tue Mar 26 07:49:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10870601 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D54B61390 for ; Tue, 26 Mar 2019 07:54:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB80D28CD0 for ; Tue, 26 Mar 2019 07:54:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AF33328CDD; Tue, 26 Mar 2019 07:54:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 303AA28CD0 for ; Tue, 26 Mar 2019 07:54:22 +0000 (UTC) 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 40C0A87E; Tue, 26 Mar 2019 08:53:30 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 40C0A87E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553586860; bh=uzb8NrxrAmqG4jqvCUWGsGWXqaP2wOUAGAJuDisRqyk=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=NYYQSSVfSkiTiNgodJn6r99M/k8wRI43mebOWd39oQaVUh+OyqtP7DFG/hc9KOVdH 0GmyotrqZAjCscho5mgegtn8SqJC0Ak0BzCZV4Mu309vRahmoL/wbd1vUVK7CdAYAi pKDg9ASzTV9ddtkvuIPZLiAnbdk5ieqH2h/MrQ3E= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 0DAB4F8971C; Tue, 26 Mar 2019 08:51:19 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 973EAF8972A; Tue, 26 Mar 2019 08:51:17 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 26B8EF8971C; Tue, 26 Mar 2019 08:51:11 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 26B8EF8971C Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id 568703C013F; Tue, 26 Mar 2019 08:51:10 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Jw0JxbUWyEgB; Tue, 26 Mar 2019 08:50:59 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 57C733C014D; Tue, 26 Mar 2019 08:50:31 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Tue, 26 Mar 2019 08:50:30 +0100 From: To: , , , Date: Tue, 26 Mar 2019 08:49:32 +0100 Message-ID: <1553586574-18608-4-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 08/10] ALSA: aloop: Support selection of snd_timer instead of jiffies 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer to do synchronous audio forwarding between hardware sound card and aloop devices. Such an audio route could look like the following: Sound card -> Loopback application -> ALSA loop device -> arecord In this case the loopback device should use the sound timer of the sound card. Without this patch the loopback application has to implement an adaptive sample rate converter to align the different clocks of the different ALSA devices. The used sound card can be selected when loading the module: $ modprobe snd_aloop enable=1 timer_source=[card] [card] can be replaced by the name of the sound card (e.g. I82801AAICH) or a card number (e.g. 0). Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 409 insertions(+), 1 deletion(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 85a1519..a411aeb 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -36,12 +36,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("A loopback soundcard"); @@ -49,12 +51,15 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); #define MAX_PCM_SUBSTREAMS 8 +#define TIMER_SRC_JIFFIES -1 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; static int pcm_notify[SNDRV_CARDS]; +static char *timer_source[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = + __stringify(TIMER_SRC_JIFFIES)}; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for loopback soundcard."); @@ -67,6 +72,12 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver."); module_param_array(pcm_notify, int, NULL, 0444); MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes."); +/* This parameter has to be kept read only because switch between jiffies and + * sound timer is not supported. + */ +module_param_array(timer_source, charp, NULL, 0444); +MODULE_PARM_DESC(timer_source, "Sound card number of timer to be used (>=0). -2 jiffies timer [default]."); + #define NO_PITCH 100000 #define CABLE_VALID_PLAYBACK BIT(SNDRV_PCM_STREAM_PLAYBACK) @@ -116,6 +127,13 @@ struct loopback_cable { unsigned int pause; /* timer specific */ struct loopback_ops *ops; + /* When loopback.timer_source > TIMER_SRC_JIFFIES */ + struct { + int owner; + struct snd_timer_id id; + struct tasklet_struct event_tasklet; + struct snd_timer_instance *instance; + } snd_timer; }; struct loopback_setup { @@ -136,6 +154,8 @@ struct loopback { struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2]; struct snd_pcm *pcm[2]; struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2]; + char *timer_source_name; + int timer_source; }; struct loopback_pcm { @@ -159,6 +179,7 @@ struct loopback_pcm { unsigned int period_size_frac; /* period size in jiffies ticks */ unsigned int last_drift; unsigned long last_jiffies; + /* When loopback.timer_source <= TIMER_SRC_JIFFIES */ struct timer_list timer; }; @@ -227,6 +248,31 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm) } /* call in cable->lock */ +static int loopback_snd_timer_start(struct loopback_pcm *dpcm) +{ + int err; + + /* Loopback device has to use same period as timer card. Therefore + * wake up for each snd_pcm_period_elapsed() call of timer card. + */ + err = snd_timer_start(dpcm->cable->snd_timer.instance, 1); + if (err < 0) { + /* do not report error if trying to start but already + * running. For example called by opposit substream + * of the same cable + */ + if (err == -EBUSY) + return 0; + + pcm_err(dpcm->substream->pcm, "snd_timer_start(card %d) failed with %d", + dpcm->cable->snd_timer.id.card, err); + return err; + } + + return 0; +} + +/* call in cable->lock */ static inline int loopback_jiffies_timer_stop(struct loopback_pcm *dpcm) { del_timer(&dpcm->timer); @@ -235,6 +281,24 @@ static inline int loopback_jiffies_timer_stop(struct loopback_pcm *dpcm) return 0; } +/* call in cable->lock */ +static int loopback_snd_timer_stop(struct loopback_pcm *dpcm) +{ + int err; + + /* only stop if both devices (playback and capture) are not running */ + if (dpcm->cable->running) + return 0; + err = snd_timer_stop(dpcm->cable->snd_timer.instance); + if (err < 0) { + pcm_err(dpcm->substream->pcm, "snd_timer_stop(card %d) failed with %d", + dpcm->cable->snd_timer.id.card, err); + return err; + } + + return 0; +} + static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) { del_timer_sync(&dpcm->timer); @@ -242,6 +306,29 @@ static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) return 0; } +/* call in loopback->cable_lock */ +static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm) +{ + int err; + + /* wait till drain tasklet has finished if requested */ + tasklet_kill(&dpcm->cable->snd_timer.event_tasklet); + + /* will only be called from free_cable() when other stream was + * already closed. Other stream cannot be reopened as long as + * loopback->cable_lock is locked. Therefore no need to lock + * cable->lock; + */ + err = snd_timer_close(dpcm->cable->snd_timer.instance); + if (err < 0) { + pcm_err(dpcm->substream->pcm, "snd_timer_close(card %d) = %d", + dpcm->cable->snd_timer.id.card, err); + } + memset(&dpcm->cable->snd_timer, 0, sizeof(dpcm->cable->snd_timer)); + + return err; +} + static int loopback_check_format(struct loopback_cable *cable, int stream) { struct snd_pcm_runtime *runtime, *cruntime; @@ -368,6 +455,13 @@ static void params_change(struct snd_pcm_substream *substream) cable->hw.rate_max = runtime->rate; cable->hw.channels_min = runtime->channels; cable->hw.channels_max = runtime->channels; + + if (dpcm->loopback->timer_source > TIMER_SRC_JIFFIES) { + cable->hw.period_bytes_min = + frames_to_bytes(runtime, runtime->period_size); + cable->hw.period_bytes_max = cable->hw.period_bytes_min; + } + } static int loopback_prepare(struct snd_pcm_substream *substream) @@ -591,6 +685,160 @@ static void loopback_jiffies_timer_function(struct timer_list *t) spin_unlock_irqrestore(&dpcm->cable->lock, flags); } +/* call in cable->lock */ +static int loopback_snd_timer_check_resolution(struct snd_pcm_runtime *runtime, + unsigned long resolution) +{ + if (resolution != runtime->timer_resolution) { + struct loopback_pcm *dpcm = runtime->private_data; + struct loopback_cable *cable = dpcm->cable; + /* Worst case estimation of possible values for resolution + * resolution <= (512 * 1024) frames / 8kHz in nsec + * resolution <= 65.536.000.000 nsec + * + * period_size <= 65.536.000.000 nsec / 1000nsec/usec * 192kHz + + * 500.000 + * period_size <= 12.582.912.000.000 <64bit + * / 1.000.000 usec/sec + */ + const snd_pcm_uframes_t period_size_usec = resolution / 1000 * + runtime->rate; + /* round to nearest sample rate */ + const snd_pcm_uframes_t period_size = (period_size_usec + 500 * + 1000) / (1000 * 1000); + + pcm_err(dpcm->substream->pcm, "Period size (%lu frames) of loopback device is not corresponding to timer resolution (%lu nsec = %lu frames) of card %d. Use period size of %lu frames for loopback device.", + runtime->period_size, resolution, + period_size, cable->snd_timer.id.card, period_size); + return -EINVAL; + } + return 0; +} + +static void loopback_snd_timer_period_elapsed + (struct loopback_cable * const cable, const int event, + const unsigned long resolution) +{ + struct loopback_pcm *dpcm_play = + cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; + struct loopback_pcm *dpcm_capt = + cable->streams[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_pcm_runtime *valid_runtime; + unsigned int running, elapsed_bytes; + unsigned long flags; + + spin_lock_irqsave(&cable->lock, flags); + running = cable->running ^ cable->pause; + /* no need to do anything if no stream is running */ + if (!running) { + spin_unlock_irqrestore(&cable->lock, flags); + return; + } + + if (event == SNDRV_TIMER_EVENT_MSTOP) { + if (!dpcm_play || !dpcm_play->substream || + !dpcm_play->substream->runtime || + !dpcm_play->substream->runtime->status || + dpcm_play->substream->runtime->status->state != + SNDRV_PCM_STATE_DRAINING) { + spin_unlock_irqrestore(&cable->lock, flags); + return; + } + } + + valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? + dpcm_play->substream->runtime : + dpcm_capt->substream->runtime; + + /* resolution is only valid for SNDRV_TIMER_EVENT_TICK events */ + if (event == SNDRV_TIMER_EVENT_TICK) { + /* The hardware rules guarantee that playback and capture period + * are the same. Therefore only one device has to be checked + * here. + */ + if (loopback_snd_timer_check_resolution(valid_runtime, + resolution) < 0) { + spin_unlock_irqrestore(&cable->lock, flags); + if (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) + snd_pcm_stop_xrun(dpcm_play->substream); + if (cable->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) + snd_pcm_stop_xrun(dpcm_capt->substream); + return; + } + } + + elapsed_bytes = frames_to_bytes(valid_runtime, + valid_runtime->period_size); + /* The same timer interrupt is used for playback and capture device */ + if ((running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && + (running & (1 << SNDRV_PCM_STREAM_CAPTURE))) { + copy_play_buf(dpcm_play, dpcm_capt, elapsed_bytes); + bytepos_finish(dpcm_play, elapsed_bytes); + bytepos_finish(dpcm_capt, elapsed_bytes); + } else if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { + bytepos_finish(dpcm_play, elapsed_bytes); + } else if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { + clear_capture_buf(dpcm_capt, elapsed_bytes); + bytepos_finish(dpcm_capt, elapsed_bytes); + } + spin_unlock_irqrestore(&cable->lock, flags); + + if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) + snd_pcm_period_elapsed(dpcm_play->substream); + if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) + snd_pcm_period_elapsed(dpcm_capt->substream); +} + +static void loopback_snd_timer_function(struct snd_timer_instance *timeri, + unsigned long resolution, + unsigned long ticks) +{ + struct loopback_cable *cable = timeri->callback_data; + + loopback_snd_timer_period_elapsed(cable, SNDRV_TIMER_EVENT_TICK, + resolution); +} + +static void loopback_snd_timer_tasklet(unsigned long arg) +{ + struct snd_timer_instance *timeri = (struct snd_timer_instance *)arg; + struct loopback_cable *cable = timeri->callback_data; + + loopback_snd_timer_period_elapsed(cable, SNDRV_TIMER_EVENT_MSTOP, 0); +} + +static void loopback_snd_timer_event(struct snd_timer_instance * const timeri, + const int event, + struct timespec * const tstamp, + const unsigned long resolution) +{ + /* Do not lock cable->lock here because timer->lock is already hold. + * There are other functions which first lock cable->lock and than + * timer->lock e.g. + * loopback_trigger() + * spin_lock(&cable->lock) + * loopback_snd_timer_start() + * snd_timer_start() + * spin_lock(&timer->lock) + * Therefore when using the oposit order of locks here it could result + * in a deadlock. + */ + + if (event == SNDRV_TIMER_EVENT_MSTOP) { + struct loopback_cable *cable = timeri->callback_data; + + /* sound card of the timer was stopped. Therefore there will not + * be any further timer callbacks. Due to this forward audio + * data from here if in draining state. When still in running + * state the streaming will be aborted by the usual timeout. It + * should not be aborted here because may be the timer sound + * card does only a recovery and the timer is back soon. + * This tasklet triggers loopback_snd_timer_tasklet() + */ + tasklet_schedule(&cable->snd_timer.event_tasklet); + } +} + static void loopback_jiffies_timer_dpcm_info(struct loopback_pcm *dpcm, struct snd_info_buffer *buffer) { @@ -603,6 +851,18 @@ static void loopback_jiffies_timer_dpcm_info(struct loopback_pcm *dpcm, snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires); } +static void loopback_snd_timer_dpcm_info(struct loopback_pcm *dpcm, + struct snd_info_buffer *buffer) +{ + snd_iprintf(buffer, " sound timer:\thw:%d,%d,%d\n", + dpcm->cable->snd_timer.id.card, + dpcm->cable->snd_timer.id.device, + dpcm->cable->snd_timer.id.subdevice); + snd_iprintf(buffer, " owner:\t\t%s\n", + (dpcm->cable->snd_timer.owner == SNDRV_PCM_STREAM_CAPTURE) ? + "capture" : "playback"); +} + static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -721,6 +981,23 @@ static int rule_channels(struct snd_pcm_hw_params *params, return snd_interval_refine(hw_param_interval(params, rule->var), &t); } +static int rule_period_bytes(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct loopback_pcm *dpcm = rule->private; + struct loopback_cable *cable = dpcm->cable; + struct snd_interval t; + + mutex_lock(&dpcm->loopback->cable_lock); + t.min = cable->hw.period_bytes_min; + t.max = cable->hw.period_bytes_max; + mutex_unlock(&dpcm->loopback->cable_lock); + t.openmin = 0; + t.openmax = 0; + t.integer = 0; + return snd_interval_refine(hw_param_interval(params, rule->var), &t); +} + static void free_cable(struct snd_pcm_substream *substream) { struct loopback *loopback = substream->private_data; @@ -765,6 +1042,112 @@ static struct loopback_ops loopback_jiffies_timer_ops = { .dpcm_info = loopback_jiffies_timer_dpcm_info, }; +static int loopback_timer_source_by_name(const char * const name, + int * const number) +{ + return kstrtoint(name, 10, number); +} + +static int loopback_snd_card_by_name(const char * const name) +{ + int number; + + if (loopback_timer_source_by_name(name, &number) >= 0) + return number; + + for (number = 0; number < ARRAY_SIZE(snd_cards); number++) { + const struct snd_card * const card = snd_cards[number]; + + if (card && strcmp(card->id, name) == 0) + return number; + } + + return -EINVAL; +} + +/* call in loopback->cable_lock */ +static int loopback_snd_timer_open(struct loopback_pcm *dpcm) +{ + int err = 0; + unsigned long flags; + struct snd_timer_id tid = { + .dev_class = SNDRV_TIMER_CLASS_PCM, + .dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION, + .card = loopback_snd_card_by_name + (dpcm->loopback->timer_source_name), + .device = 0, + .subdevice = 0, + }; + struct snd_timer_instance *timer = NULL; + + spin_lock_irqsave(&dpcm->cable->lock, flags); + dpcm->cable->snd_timer.owner = dpcm->substream->stream; + dpcm->cable->snd_timer.id = tid; + + /* check if timer was already opened. It is only opened once + * per playback and capture subdevice (aka cable). + */ + if (dpcm->cable->snd_timer.instance) + goto unlock; + + /* snd_timer_close() and snd_timer_open() should not be called with + * locked spinlock because both functions can block on a mutex. The + * mutex loopback->cable_lock is kept locked. Therefore snd_timer_open() + * cannot be called a second time by the other device of the same cable. + * Therefore the following issue cannot happen: + * [proc1] Call loopback_timer_open() -> + * Unlock cable->lock for snd_timer_close/open() call + * [proc2] Call loopback_timer_open() -> snd_timer_open(), + * snd_timer_start() + * [proc1] Call snd_timer_open() and overwrite running timer + * instance + */ + spin_unlock_irqrestore(&dpcm->cable->lock, flags); + err = snd_timer_open(&timer, dpcm->loopback->card->id, + &dpcm->cable->snd_timer.id, + current->pid); + if (err < 0) { + pcm_err(dpcm->substream->pcm, "Opening sound timer of card %d failed with %d", + dpcm->cable->snd_timer.id.card, err); + return err; + } + spin_lock_irqsave(&dpcm->cable->lock, flags); + + /* The callback has to be called from another tasklet. If + * SNDRV_TIMER_IFLG_FAST is specified it will be called from the + * snd_pcm_period_elapsed() call of the selected sound card. + * snd_pcm_period_elapsed() helds snd_pcm_stream_lock_irqsave(). + * Due to our callback loopback_snd_timer_function() also calls + * snd_pcm_period_elapsed() which calls snd_pcm_stream_lock_irqsave(). + * This would end up in a dead lock. + */ + timer->flags |= SNDRV_TIMER_IFLG_AUTO; + timer->callback = loopback_snd_timer_function; + timer->callback_data = (void *)dpcm->cable; + timer->ccallback = loopback_snd_timer_event; + dpcm->cable->snd_timer.instance = timer; + + /* initialise a tasklet used for draining */ + tasklet_init(&dpcm->cable->snd_timer.event_tasklet, + loopback_snd_timer_tasklet, (unsigned long)timer); + +unlock: + spin_unlock_irqrestore(&dpcm->cable->lock, flags); + + return err; +} + +/* stop_sync() is not required for sound timer because it does not need to be + * restarted in loopback_prepare() on Xrun recovery + */ +static struct loopback_ops loopback_snd_timer_ops = { + .open = loopback_snd_timer_open, + .start = loopback_snd_timer_start, + .stop = loopback_snd_timer_stop, + .close_cable = loopback_snd_timer_close_cable, + .dpcm_info = loopback_snd_timer_dpcm_info, +}; + static int loopback_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -793,7 +1176,10 @@ static int loopback_open(struct snd_pcm_substream *substream) } spin_lock_init(&cable->lock); cable->hw = loopback_pcm_hardware; - cable->ops = &loopback_jiffies_timer_ops; + if (loopback->timer_source <= TIMER_SRC_JIFFIES) + cable->ops = &loopback_jiffies_timer_ops; + else + cable->ops = &loopback_snd_timer_ops; loopback->cables[substream->number][dev] = cable; } dpcm->cable = cable; @@ -829,6 +1215,19 @@ static int loopback_open(struct snd_pcm_substream *substream) if (err < 0) goto unlock; + /* In case of sound timer the period time of both devices of the same + * loop has to be the same. This rule only takes effect if a sound timer + * was chosen via the kernel parameter. + */ + if (loopback->timer_source > TIMER_SRC_JIFFIES) { + err = snd_pcm_hw_rule_add(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + rule_period_bytes, dpcm, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1); + if (err < 0) + goto unlock; + } + /* loopback_runtime_free() has not to be called if kfree(dpcm) was * already called here. Otherwise it will end up with a double free. */ @@ -1250,6 +1649,15 @@ static int loopback_probe(struct platform_device *devptr) pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; loopback->card = card; + loopback->timer_source_name = timer_source[dev]; + /* If it was not a number a sound card name was specified. Therefore a + * the sound timer of this card should be used. The right card name will + * be converted in loopback_snd_timer_open() + */ + if (loopback_timer_source_by_name(loopback->timer_source_name, + &loopback->timer_source) < 0) + loopback->timer_source = 0; + mutex_init(&loopback->cable_lock); err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]); From patchwork Tue Mar 26 07:49:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10870597 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E496B1390 for ; Tue, 26 Mar 2019 07:53:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CD97A28D18 for ; Tue, 26 Mar 2019 07:53:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C19DE29087; Tue, 26 Mar 2019 07:53:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E02A828D18 for ; Tue, 26 Mar 2019 07:53:31 +0000 (UTC) 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 A2648882; Tue, 26 Mar 2019 08:52:39 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A2648882 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553586809; bh=tntlWdy0N8HLcVvDYrdeH82pvXbM26nCgsAHCmUXeA4=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=FJcstAXQegTTGLTzraEdGUSpO4rWSwjBnP8JhBIea6W7xdHo+EuTyu7VsFb8nOfLA A5Ku2bjpbsAsWbr6FTwhSOpFL7ju0bH8IhP/zNapPwp1kdzpWJIALgsomD1mrIXXg/ MTY+/9it+5uGwpblZ+XUziYBU07Zo07Sckhs4pcg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 342B1F8971B; Tue, 26 Mar 2019 08:51:12 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id CF221F8971B; Tue, 26 Mar 2019 08:51:10 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id AE5A8F89713; Tue, 26 Mar 2019 08:51:06 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz AE5A8F89713 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id 5CF9F3C013A; Tue, 26 Mar 2019 08:51:06 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id m3kz7e6xXkoQ; Tue, 26 Mar 2019 08:50:59 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 695B33C02EC; Tue, 26 Mar 2019 08:50:34 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Tue, 26 Mar 2019 08:50:34 +0100 From: To: , , , Date: Tue, 26 Mar 2019 08:49:33 +0100 Message-ID: <1553586574-18608-5-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> <1553586574-18608-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 09/10] ALSA: pcm: Add snd_pcm_ops for snd_pcm_link() 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer snd_pcm_link() can be called by the user as long as the device is not yet started. Therefore currently a driver which wants to iterate over the linked substreams has to do this at the start trigger. But the start trigger should not block for a long time. Therefore there is no callback which can be used to iterate over the linked substreams without delaying the start trigger. This patch introduces a new callback function which will be called after the linked substream list was updated by snd_pcm_link(). This callback function is allowed to block for a longer time without interfering the synchronized start up of linked substreams. Signed-off-by: Timo Wischer --- include/sound/pcm.h | 1 + sound/core/pcm_native.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 18bd8c3..a7e5dd2 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -90,6 +90,7 @@ struct snd_pcm_ops { unsigned long offset); int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); int (*ack)(struct snd_pcm_substream *substream); + int (*link_changed)(struct snd_pcm_substream *substream); }; /* diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f731f90..57a8a66 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1981,6 +1981,27 @@ static bool is_pcm_file(struct file *file) /* * PCM link handling */ +/* Note: call with snd_pcm_link_rwsem locked */ +static int snd_pcm_link_changed(struct snd_pcm_substream * const substream) +{ + struct snd_pcm_substream *s; + + /* snd_pcm_link_rwsem is down whenever the link_list is changed. + * Therefore this lock is sufficent for the iteration. + */ + snd_pcm_group_for_each_entry(s, substream) { + int err; + + if (!s->ops->link_changed) + continue; + err = s->ops->link_changed(s); + if (err < 0) + return err; + } + + return 0; +} + static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) { int res = 0; @@ -2030,6 +2051,9 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) snd_pcm_group_assign(substream1, target_group); snd_pcm_stream_unlock(substream1); snd_pcm_group_unlock_irq(target_group, nonatomic); + + if (res >= 0) + res = snd_pcm_link_changed(substream); _end: up_write(&snd_pcm_link_rwsem); _nolock: @@ -2076,6 +2100,11 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) snd_pcm_group_unlock_irq(group, nonatomic); if (do_free) kfree(group); + if (res >= 0) + res = snd_pcm_link_changed(substream); + /* Also signal substream which was removed */ + if (res >= 0 && substream->ops->link_changed) + res = substream->ops->link_changed(substream); _end: up_write(&snd_pcm_link_rwsem); From patchwork Tue Mar 26 07:52:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Wischer X-Patchwork-Id: 10870603 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5049F1708 for ; Tue, 26 Mar 2019 07:54:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 36F9D28DCD for ; Tue, 26 Mar 2019 07:54:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 24C2228DE5; Tue, 26 Mar 2019 07:54:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CB77E28DCD for ; Tue, 26 Mar 2019 07:54:47 +0000 (UTC) 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 0845387B; Tue, 26 Mar 2019 08:53:56 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 0845387B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553586886; bh=Md016poavqk4f9z2fOb784gOISSGbWbV6P8DYKj72+s=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=oU8e8uchSVYBlZkFyEvsGnaPfDn6c2I26RaHzWn2dg+SZFq2nf6ImUNjDGmtL/Fte VA92ixErjIod2OIGo6ZilHZFakn4A754EnjRf+ti4xgZtD3FNVIHw2wQZUFuvpxBg4 RNgQNMEauVQlgwAvOR/E5zjTxYw88HfuZC+9GNV0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 0D898F89622; Tue, 26 Mar 2019 08:53:16 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 6CB08F8963B; Tue, 26 Mar 2019 08:53:15 +0100 (CET) Received: from smtp1.de.adit-jv.com (smtp1.de.adit-jv.com [93.241.18.167]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C5B6AF801D9; Tue, 26 Mar 2019 08:53:09 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C5B6AF801D9 Received: from localhost (smtp1.de.adit-jv.com [127.0.0.1]) by smtp1.de.adit-jv.com (Postfix) with ESMTP id 2A1DD3C00DD; Tue, 26 Mar 2019 08:53:09 +0100 (CET) Received: from smtp1.de.adit-jv.com ([127.0.0.1]) by localhost (smtp1.de.adit-jv.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qlnHBbYKqpuL; Tue, 26 Mar 2019 08:53:02 +0100 (CET) Received: from HI2EXCH01.adit-jv.com (hi2exch01.adit-jv.com [10.72.92.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp1.de.adit-jv.com (Postfix) with ESMTPS id 915D83C00C4; Tue, 26 Mar 2019 08:53:02 +0100 (CET) Received: from vmlxhi-087.adit-jv.com (10.72.93.172) by HI2EXCH01.adit-jv.com (10.72.92.24) with Microsoft SMTP Server (TLS) id 14.3.435.0; Tue, 26 Mar 2019 08:53:02 +0100 From: To: , , , Date: Tue, 26 Mar 2019 08:52:55 +0100 Message-ID: <1553586775-18902-1-git-send-email-twischer@de.adit-jv.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> References: <1553529644-5654-1-git-send-email-twischer@de.adit-jv.com> MIME-Version: 1.0 X-Originating-IP: [10.72.93.172] Cc: Timo Wischer , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [alsa-devel] [PATCH 10/10] ALSA: aloop: Use timer of linked card if chosen 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" X-Virus-Scanned: ClamAV using ClamSMTP From: Timo Wischer If there is a hardware sound card linked to the loopback device the sound timer of the hardware sound card will be used for this loopback device. Such a link will be created when snd_pcm_link() was called. Linked dummy and loopback devices will be ignored. This feature can be enabled when loading the module with the following command: $ modprobe snd_aloop enable=1 timer_source=-1 Signed-off-by: Timo Wischer --- sound/drivers/aloop.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 172 insertions(+), 15 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index a411aeb..e2f1d64 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -51,7 +51,8 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); #define MAX_PCM_SUBSTREAMS 8 -#define TIMER_SRC_JIFFIES -1 +#define TIMER_SRC_JIFFIES -2 +#define TIMER_SRC_AUTODETECT -1 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -76,7 +77,7 @@ MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels change * sound timer is not supported. */ module_param_array(timer_source, charp, NULL, 0444); -MODULE_PARM_DESC(timer_source, "Sound card number of timer to be used (>=0). -2 jiffies timer [default]."); +MODULE_PARM_DESC(timer_source, "Sound card number of timer to be used (>=0). -2 jiffies timer [default]. -1 auto detect sound timer."); #define NO_PITCH 100000 @@ -252,6 +253,14 @@ static int loopback_snd_timer_start(struct loopback_pcm *dpcm) { int err; + /* only in auto detect mode the sound timer will not be opened when the + * device was opened. It will be opened on the first snd_pcm_link() call + */ + if (!dpcm->cable->snd_timer.instance) { + pcm_err(dpcm->substream->pcm, "Sound timer not auto detected. At least one application of the same loopback cable has to call snd_pcm_link() to detect the sound timer."); + return -EINVAL; + } + /* Loopback device has to use same period as timer card. Therefore * wake up for each snd_pcm_period_elapsed() call of timer card. */ @@ -286,6 +295,10 @@ static int loopback_snd_timer_stop(struct loopback_pcm *dpcm) { int err; + /* no need to stop the timer if it was not yet opened */ + if (!dpcm->cable->snd_timer.instance) + return 0; + /* only stop if both devices (playback and capture) are not running */ if (dpcm->cable->running) return 0; @@ -307,10 +320,15 @@ static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) } /* call in loopback->cable_lock */ -static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm) +static int loopback_snd_timer_close(struct loopback_pcm *dpcm, + struct snd_timer_instance * const timer) { int err; + /* no need to close the timer if it was not yet opened */ + if (!timer) + return 0; + /* wait till drain tasklet has finished if requested */ tasklet_kill(&dpcm->cable->snd_timer.event_tasklet); @@ -319,7 +337,7 @@ static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm) * loopback->cable_lock is locked. Therefore no need to lock * cable->lock; */ - err = snd_timer_close(dpcm->cable->snd_timer.instance); + err = snd_timer_close(timer); if (err < 0) { pcm_err(dpcm->substream->pcm, "snd_timer_close(card %d) = %d", dpcm->cable->snd_timer.id.card, err); @@ -329,6 +347,12 @@ static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm) return err; } +/* call in loopback->cable_lock */ +static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm) +{ + return loopback_snd_timer_close(dpcm, dpcm->cable->snd_timer.instance); +} + static int loopback_check_format(struct loopback_cable *cable, int stream) { struct snd_pcm_runtime *runtime, *cruntime; @@ -1065,11 +1089,11 @@ static int loopback_snd_card_by_name(const char * const name) return -EINVAL; } -/* call in loopback->cable_lock */ -static int loopback_snd_timer_open(struct loopback_pcm *dpcm) +/* call in cable->lock */ +static int loopback_snd_timer_source_update(struct loopback_pcm *dpcm) { - int err = 0; - unsigned long flags; + int changed = 0; + struct snd_pcm_substream *s; struct snd_timer_id tid = { .dev_class = SNDRV_TIMER_CLASS_PCM, .dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION, @@ -1078,18 +1102,109 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm) .device = 0, .subdevice = 0, }; - struct snd_timer_instance *timer = NULL; - spin_lock_irqsave(&dpcm->cable->lock, flags); + /* Enforce kernel module parameter if not auto detect */ + if (tid.card != TIMER_SRC_AUTODETECT) { + dpcm->cable->snd_timer.owner = dpcm->substream->stream; + dpcm->cable->snd_timer.id = tid; + return 0; + } + + /* find the first HW device which is linked to this loop device */ + snd_pcm_group_for_each_entry(s, dpcm->substream) { + /* ignore all linked devices also using jiffies timer */ + if (strcmp(s->pcm->card->driver, "Loopback") == 0) + continue; + if (strcmp(s->pcm->card->driver, "Dummy") == 0) + continue; + + tid.card = s->pcm->card->number; + tid.device = s->pcm->device; + tid.subdevice = s->number; + break; + } + + /* check if a sound timer could already be detected */ + if (tid.card < 0) + return -ENODEV; + + /* check if timer source has changed */ + changed = (dpcm->cable->snd_timer.id.card != tid.card || + dpcm->cable->snd_timer.id.device != tid.device || + dpcm->cable->snd_timer.id.subdevice != tid.subdevice); + /* Do not change anything if we are the second device + * which calls snd_pcm_link() + */ + if (changed) { + if (dpcm->cable->snd_timer.owner > 0 && + dpcm->cable->snd_timer.owner != dpcm->substream->stream) { + pcm_warn(dpcm->substream->pcm, "Both devices of the same loopback cable are requesting different sound timers. May be the wrong one is used. (used hw:%d,%d,%d reqested hw:%d,%d,%d)", + dpcm->cable->snd_timer.id.card, + dpcm->cable->snd_timer.id.device, + dpcm->cable->snd_timer.id.subdevice, tid.card, + tid.device, tid.subdevice); + return 0; + } else if (dpcm->cable->running) { + pcm_warn(dpcm->substream->pcm, "Another sound timer was requested but at least one device is already running. May be the wrong one is used. (used hw:%d,%d,%d reqested hw:%d,%d,%d)", + dpcm->cable->snd_timer.id.card, + dpcm->cable->snd_timer.id.device, + dpcm->cable->snd_timer.id.subdevice, tid.card, + tid.device, tid.subdevice); + return 0; + } + } + + /* always return a valid timer id with defined classes. Also in case + * when it looks like card has not changed because hw:0,0,0 should be + * used + */ dpcm->cable->snd_timer.owner = dpcm->substream->stream; dpcm->cable->snd_timer.id = tid; - /* check if timer was already opened. It is only opened once - * per playback and capture subdevice (aka cable). + return changed; +} + +/* call in loopback->cable_lock */ +static int loopback_snd_timer_open(struct loopback_pcm *dpcm) +{ + int err = 0; + unsigned long flags; + struct snd_timer_instance *timer = NULL; + + spin_lock_irqsave(&dpcm->cable->lock, flags); + err = loopback_snd_timer_source_update(dpcm); + if (err < 0) { + /* Could not yet detect the right sound timer because no valid + * snd_pcm_link() exists. This should not be handled as an error + * because the right timer will be opened with the call to + * snd_pcm_link(). + */ + if (err == -ENODEV) + err = 0; + goto unlock; + } + /* do not reopen the timer if it is already opened and nothing has + * changed */ - if (dpcm->cable->snd_timer.instance) + if (dpcm->cable->snd_timer.instance && err < 1) goto unlock; + /* Avoids that any function accesses an invalid timer instance when + * reopening the sound timer. Reopening the sound timer is only + * supported in TIMER_SRC_AUTODETECT mode. snd_pcm_start() will fail on + * the second device when the first device currently reopens the_timer: + * [proc1] Calls snd_pcm_link() -> loopback_timer_open() -> + * Unlock cable->lock for snd_timer_close/open() call + * [proc2] Calls snd_pcm_start() when timer reopening is in progress + * But this is fine because snd_pcm_start() would also fail if + * snd_pcm_link() was not called from any device of the same cable in + * TIMER_SRC_AUTODETECT mode. Therefore the user has to guarantee in + * TIMER_SRC_AUTODETECT mode that snd_pcm_link() is called before anyone + * calls snd_pcm_start() of the same cable. + */ + timer = dpcm->cable->snd_timer.instance; + dpcm->cable->snd_timer.instance = NULL; + /* snd_timer_close() and snd_timer_open() should not be called with * locked spinlock because both functions can block on a mutex. The * mutex loopback->cable_lock is kept locked. Therefore snd_timer_open() @@ -1103,6 +1218,10 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm) * instance */ spin_unlock_irqrestore(&dpcm->cable->lock, flags); + /* close timer if there is already something open */ + err = loopback_snd_timer_close(dpcm, timer); + if (err < 0) + return err; err = snd_timer_open(&timer, dpcm->loopback->card->id, &dpcm->cable->snd_timer.id, current->pid); @@ -1137,6 +1256,19 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm) return err; } +static int loopback_snd_timer_link_changed(struct snd_pcm_substream *substream) +{ + int err; + struct loopback_pcm *dpcm = substream->runtime->private_data; + + mutex_lock(&dpcm->loopback->cable_lock); + /* Try to reopen the timer here if the link_list has changed. */ + err = loopback_snd_timer_open(dpcm); + mutex_unlock(&dpcm->loopback->cable_lock); + + return err; +} + /* stop_sync() is not required for sound timer because it does not need to be * restarted in loopback_prepare() on Xrun recovery */ @@ -1148,6 +1280,13 @@ static struct loopback_ops loopback_snd_timer_ops = { .dpcm_info = loopback_snd_timer_dpcm_info, }; +static struct loopback_ops loopback_snd_timer_auto_ops = { + .start = loopback_snd_timer_start, + .stop = loopback_snd_timer_stop, + .close_cable = loopback_snd_timer_close_cable, + .dpcm_info = loopback_snd_timer_dpcm_info, +}; + static int loopback_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -1178,6 +1317,8 @@ static int loopback_open(struct snd_pcm_substream *substream) cable->hw = loopback_pcm_hardware; if (loopback->timer_source <= TIMER_SRC_JIFFIES) cable->ops = &loopback_jiffies_timer_ops; + else if (loopback->timer_source == TIMER_SRC_AUTODETECT) + cable->ops = &loopback_snd_timer_auto_ops; else cable->ops = &loopback_snd_timer_ops; loopback->cables[substream->number][dev] = cable; @@ -1276,18 +1417,34 @@ static const struct snd_pcm_ops loopback_pcm_ops = { .page = snd_pcm_lib_get_vmalloc_page, }; +static const struct snd_pcm_ops loopback_pcm_auto_ops = { + .open = loopback_open, + .close = loopback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = loopback_hw_params, + .hw_free = loopback_hw_free, + .prepare = loopback_prepare, + .trigger = loopback_trigger, + .pointer = loopback_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .link_changed = loopback_snd_timer_link_changed, +}; + static int loopback_pcm_new(struct loopback *loopback, int device, int substreams) { struct snd_pcm *pcm; int err; + const struct snd_pcm_ops * const ops = + (loopback->timer_source == TIMER_SRC_AUTODETECT) ? + &loopback_pcm_auto_ops : &loopback_pcm_ops; err = snd_pcm_new(loopback->card, "Loopback PCM", device, substreams, substreams, &pcm); if (err < 0) return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_pcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops); pcm->private_data = loopback; pcm->info_flags = 0;