From patchwork Wed Nov 20 11:58:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253721 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B61556C1 for ; Wed, 20 Nov 2019 12:10: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 3EED5224CE for ; Wed, 20 Nov 2019 12:10: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="MKRNkdoj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3EED5224CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 492D916DC; Wed, 20 Nov 2019 13:00:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 492D916DC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251304; bh=EDuPcEQJSCZfwQYZ3HV5Glfn5PjqOTSjaXSUgodQIMY=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=MKRNkdojl3AqPpS4gpNnhSTXeXGS/LuvD4yg+awBrfjFuYM5pCssegcHLj7+sfvfA WbsNsPOw1lc3hjBboPyxt6JSUHsbprwGAoYpsjTzUDtE6VRcNeCxJpgODD4bPrvtUn ehaAQOA6bbnZQVcPTjw0iTRfvwtFz+vBbGFTedO0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A8B8FF80157; Wed, 20 Nov 2019 12:59:56 +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 5C39CF800C1; Wed, 20 Nov 2019 12:59:53 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa1.mentor.iphmx.com (esa1.mentor.iphmx.com [68.232.129.153]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 2AC2CF800C1 for ; Wed, 20 Nov 2019 12:59:50 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 2AC2CF800C1 IronPort-SDR: QC1K7lLQVTScuMLiFA/9aMifbeTYXK+P4yDFwYtkmIymwvLwmun5qUv87MfNBzmLStZCgdL+3m RdtOD1d80xi17v9k6ECzb9+pvLpq1lRLLSu94JyCmV4GMHjcMBEjflQRDXAE/4vCkJVfX0SNeF utrqBg5rC03WbuYggoPERkt/rOn9HsljtNt3soj/D+XAfmCB1Bo5XL+WMunCFr7NO8gs5mQHUT EvjliFueuiH5dYjljD1LWXvT1R5HTC/UzJFV1pO0Py/J6OuNuxz0qpEjG8JSALsnV402vKfMjm 7Zg= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="45209991" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 20 Nov 2019 03:59:31 -0800 IronPort-SDR: 7yMYWojQMMkoRD8ElqrDdLnDTuAyTtWTooEofI/KqCiQxKMmESwrwHe0hlXGV/RqDX6LDrMTQz k75VSt+DODR6olCbVbr4FZ7lWUYZKwU7HGXiHSoE2BoamoOB/lDxbfwhXjqxrmMNWYDVhQCFBS 7hLRoeT2ImPlzz0/66c8cmrefBMUgjxQ7bR0NBjuv6fHfnUWYWSNcruC6a6+NLxJRn81H3I0SX 987ZC1IfiNSay7sy454QvJeZmCmr/4Kwsdzz7EMv8d0VvnkX9BJGbHiOHigHVMW/4dOOGaa2/C M+A= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:50 -0600 Message-ID: <20191120115856.4125-2-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-1-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 1/7] 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" From: Timo Wischer Describe the unit of the variables used to calculate the hw pointer depending on jiffies ticks. Signed-off-by: Timo Wischer Signed-off-by: Andrew Gabbasov --- 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 54f8b17476a1..573b06cf7cf5 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -102,8 +102,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 Wed Nov 20 11:58:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253727 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D642318B8 for ; Wed, 20 Nov 2019 12:10: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 5EC82224DE for ; Wed, 20 Nov 2019 12:10: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="WS7uqt/f" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5EC82224DE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 838B116EC; Wed, 20 Nov 2019 13:01:38 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 838B116EC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251348; bh=/NTSQ1T/fDBSHcyy6BXIYdKKf5Ipn078xF1jfN4qyrQ=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=WS7uqt/fdW/hJHzcbiKUF7wo9+Rb4VdcXsiKtFTzKOtFFeC0aQ0r8hchh9j+ZcFT2 c+jBPEvEl30AVhRBmTZeTD3A1Guxpo1CTmaaeZh4uKL4G+Su53fRvAcHLSzetiXacV 4Pbgv+QhR6sQLDkTFpjTl/4xIyU6CuhLgMc2B2AQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 1F1ACF8015B; Wed, 20 Nov 2019 12:59:58 +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 D158EF80159; Wed, 20 Nov 2019 12:59:54 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS,SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa1.mentor.iphmx.com (esa1.mentor.iphmx.com [68.232.129.153]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 416B2F8013C for ; Wed, 20 Nov 2019 12:59:50 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 416B2F8013C IronPort-SDR: QW7+d2BCuyM4m9WwZR5vJnwBiV4gXgk4/KFvAmnVcXtOL1WXlmGzv2je/QiabOJESeGkL3Zi1Q fRmXP3vHaq5FYPnIIqkE8CejEoz0sfWnVH4Me+vruJoFSRylgdxhNV6ZthA8N6en9ePD8vjw1q WR/z4gc7yMhnlMDtODvlUzKRDXG3VkwHOGAh39tbcZ4lTIuHNCN4j3W5jRpyDb1egjJC3cFxZN dJYrcOXrhtcAwV4PcAm6ZoQ2pmANgJ74+/0DMJu8IMO/bSftgVBJCmGEJFBmDXccbCkxhJHmH6 bIg= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="45209993" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 20 Nov 2019 03:59:36 -0800 IronPort-SDR: XwqksmcSCIE7apZvJfkFswyV8Z1R3oEfxhH8tByp40mAe1oy/Z9hNmSMqFpNirF+hys46sVfJv mnAt4EW4drXyH8nh/a5qQtHLFsT/lhT+4I33yvNbJ8NGq5gnvBJuxR1MhJubBHXN5GpZjBSdkp 2P4lqAzWKC1dIpUySRL3GFAYi2Fw8+5eRbkW7a2Vv0oN+9zi0h+4yz6m300RwmttvZ9IHRLQka /EQx0XzL8aiNQLE6sS4c8NkSsUaiMsDqMD9RQDXZLSRcA7v8uqqd3JJXzaCaitKXX1Zny2h8Vj y4c= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:51 -0600 Message-ID: <20191120115856.4125-3-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-2-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> <20191120115856.4125-2-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 2/7] ALSA: aloop: Support return of error code for timer start and stop 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: Timo Wischer This is required for additional timer implementations which could detect errors and want to throw them. Signed-off-by: Timo Wischer Signed-off-by: Andrew Gabbasov --- sound/drivers/aloop.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 573b06cf7cf5..7919006f70a5 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -155,7 +155,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); @@ -171,18 +171,24 @@ 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 */ -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) @@ -251,7 +257,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: @@ -264,7 +270,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); @@ -273,7 +279,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); @@ -282,7 +288,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); @@ -292,7 +298,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); @@ -300,7 +306,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) @@ -321,9 +327,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_physical_width(runtime->format) * runtime->channels) / 8; From patchwork Wed Nov 20 11:58:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253725 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D308B14ED for ; Wed, 20 Nov 2019 12:10: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 63789224E1 for ; Wed, 20 Nov 2019 12:10: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="lrwWYP6H" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 63789224E1 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 AD25C16DE; Wed, 20 Nov 2019 13:02:24 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz AD25C16DE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251394; bh=8A0lFkCITVAh0RyEv2vwWWQ8qptP3tiJzzEOfGMP8YI=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=lrwWYP6HhAxtEGQpQQTa2eIvBP6KpTgphEHBhxN3NU90u4zMUpIb+ao5jgAYokaxp yMZ9u0bdMc5qRu1YGK/YQiNmP7tXlF/8Yjb0yxc6JPrchKn0wlaNJQ+JPJQBxxV41j Ut3rpsBZLnoUIHYWFccwLEqnwS2nim6h8fbgVAcg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3B601F80161; Wed, 20 Nov 2019 13:00:00 +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 38AE5F80159; Wed, 20 Nov 2019 12:59:56 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS,SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa1.mentor.iphmx.com (esa1.mentor.iphmx.com [68.232.129.153]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 0C59EF8013F for ; Wed, 20 Nov 2019 12:59:51 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 0C59EF8013F IronPort-SDR: 67Qgs6MdMmP37IhF2EfLd/AdECAn5TfUNdy0kjakd80DNYHlWYfawVP/9YAQOzlLlFLbwT7ZWA WF0prOBAIE6sXzFlZCjt8BOT9jZYRWA+dHbwi8HoWjnLvFZxw6WHjEm3WqFpWj4li5ZUYgQOkB mVQvUOV0zJkPKDnY2uk4qDbMlQj6YRd+hQ1XE3meAwtMm1jw1KMrCccuVIAV+SNU8rQeXEzMwu wkeM0Wy869QPTzmfpyGQMKTQlwBfq58T7jY6frJ0AZYXHLOx6AXB9beTjNk1IUAfDPa39yXiYy 9Y4= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="45210013" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 20 Nov 2019 03:59:39 -0800 IronPort-SDR: Mdf9IwEDzPNNXIuWnuo+++pif6FGgNPUQEVs7wPamekTX6vEgh8BZlQ3jzj/dFqDvvzas0Yym6 tVubTn/vmowF6JcDL1iz9nvpEvAKkncvjYTjBNy2lZ4IEPM5ESoekFHTPJpZTJrA6zXMiIPPHq 3r8DsDf4gQQuRu7h8otgVRisPV3JNXHVbuG2v4dGZLnmq1+lPSYGIxtNIFNLPt+AYSgkb/0FEW 9QYDNU7miFY8gqeZBnAqPEW2ZP5cRcPMyVXWSdMtbJJeW7OKwcXgeNd89hs0aoeAgWHeIwFny3 QGE= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:52 -0600 Message-ID: <20191120115856.4125-4-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-3-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> <20191120115856.4125-2-andrew_gabbasov@mentor.com> <20191120115856.4125-3-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 3/7] 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" From: Timo Wischer This commit only refactors the implementation. It does not change the behaviour. It is required to support other timers (e.g sound timer). Signed-off-by: Timo Wischer Signed-off-by: Andrew Gabbasov --- 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 7919006f70a5..3bfd7c32803c 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -55,8 +55,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]; @@ -65,6 +96,8 @@ struct loopback_cable { unsigned int valid; unsigned int running; unsigned int pause; + /* timer specific */ + struct loopback_ops *ops; }; struct loopback_setup { @@ -270,7 +303,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); cable->running |= stream; cable->pause &= ~stream; - err = loopback_timer_start(dpcm); + err = cable->ops->start(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -279,7 +312,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); cable->running &= ~stream; cable->pause &= ~stream; - err = loopback_timer_stop(dpcm); + err = cable->ops->stop(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -288,7 +321,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: spin_lock(&cable->lock); cable->pause |= stream; - err = loopback_timer_stop(dpcm); + err = cable->ops->stop(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -298,7 +331,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); dpcm->last_jiffies = jiffies; cable->pause &= ~stream; - err = loopback_timer_start(dpcm); + err = cable->ops->start(dpcm); spin_unlock(&cable->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); @@ -329,9 +362,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_physical_width(runtime->format) * runtime->channels) / 8; @@ -539,6 +574,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; @@ -546,7 +593,8 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) snd_pcm_uframes_t pos; spin_lock(&dpcm->cable->lock); - loopback_pos_update(dpcm->cable); + if (dpcm->cable->ops->pos_update) + dpcm->cable->ops->pos_update(dpcm->cable); pos = dpcm->buf_pos; spin_unlock(&dpcm->cable->lock); return bytes_to_frames(runtime, pos); @@ -671,12 +719,33 @@ static void free_cable(struct snd_pcm_substream *substream) cable->streams[substream->stream] = NULL; spin_unlock_irq(&cable->lock); } 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; @@ -694,7 +763,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) { @@ -705,9 +773,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); @@ -733,7 +809,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; @@ -757,12 +835,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 = { @@ -1086,13 +1166,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 Wed Nov 20 11:58:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253723 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B969C1871 for ; Wed, 20 Nov 2019 12:10: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 4D701224D2 for ; Wed, 20 Nov 2019 12:10: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="kPW5AK10" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4D701224D2 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 487E516C9; Wed, 20 Nov 2019 13:02:47 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 487E516C9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251417; bh=dV9ShE1wTsUCiqFwE6oOZ4mA+oYik9ZtBTY7TgRLpA0=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=kPW5AK10Y6WcJJ0f4VqqJZFYsRGuQrkKUI0RfpdetQT2TuTkpFDTl5TWgc+yWo6fm 5m5jdisDQHk3/wvW/VdGDYzJ/FEjPIDd6BHrpYQyV8HMWA3IhEqlWN6Y+lfKD1dPFI sGExUzLfqo/q/JMZ1Ndi6FH+2PLraKRor9JxFWJ0= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 41618F80171; Wed, 20 Nov 2019 13:00:01 +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 912B0F8015D; Wed, 20 Nov 2019 12:59:57 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_NONE,SPF_PASS, SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa1.mentor.iphmx.com (esa1.mentor.iphmx.com [68.232.129.153]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 1DBE9F8014B for ; Wed, 20 Nov 2019 12:59:52 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 1DBE9F8014B IronPort-SDR: pitpD4nUsKMBnmkfrBGCJGmRzmZOKD8MAf/uEMgSIR6H4T6bN0anb/2xb32xe1eE8md3DtNFvc ABaQGKfaeC7YW4gGSFAqeYDuImOI8aLw3n/WmOqy3vw1k/yUGs/DbvsGvxEH3uETbcST4pQh6R dhqzqFvvfDqoa1FJ5cVk5jhWpJVkdYMVu82vVwzroDqPVJo5ZoLxxw3+3HDTOdkYQfZHdoPddJ kRnit/ufG3OAD7kD8068w1dI8exnZ9klMLKiuTRfDMiboFb9cNzcUmlWJ/guLROG1PC0RZHjn/ OPc= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="45210015" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa1.mentor.iphmx.com with ESMTP; 20 Nov 2019 03:59:41 -0800 IronPort-SDR: pCvBI8xIi0vp5o3BR5Sn30iM9XY485jycBzR9roKDd4Zwk6TBDWL0EgxHn9Nz5Rmk/EM1nE0kA 7Yn+ePeJVVeq4opuYexNaoH7/Pla2Jt3xW76YFYGNP4350N5N07scXYCWndnRvJuT3qw/nhvF7 lvSXDleLMjagY+8Weym84JFxvdwXJGXhZsnmXsUeaYENZmK2OcgQshR4zXfiuIYlULWQxpu6ec aYAMGf+QmRHVrmRNtXcBLdrsrBNBQ7Ea03+wnuzz2bkwOVWYOOyLe+aUPPUwwD96ySxPFghZ14 OB0= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:53 -0600 Message-ID: <20191120115856.4125-5-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-4-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> <20191120115856.4125-2-andrew_gabbasov@mentor.com> <20191120115856.4125-3-andrew_gabbasov@mentor.com> <20191120115856.4125-4-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 4/7] 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" From: Timo Wischer This commit does not change the behaviour. It only separates the jiffies timer specific implementation from the generic part. Signed-off-by: Timo Wischer Signed-off-by: Andrew Gabbasov --- 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 3bfd7c32803c..2f208aaa54cf 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -188,7 +188,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); @@ -209,7 +209,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; @@ -217,7 +217,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); @@ -502,7 +502,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]; @@ -555,14 +556,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); @@ -731,18 +733,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 Wed Nov 20 11:58:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253729 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B8CFD14E5 for ; Wed, 20 Nov 2019 12:10: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 4D2D2224C6 for ; Wed, 20 Nov 2019 12:10: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="bs9xOt3B" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4D2D2224C6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 D655C16ED; Wed, 20 Nov 2019 13:03:29 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D655C16ED DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251460; bh=hwlVRCrW6Ynhewv6WX3f6tGv16Et+l1IYyn+CtwwcQs=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=bs9xOt3BoA+Y2r2RhxCrtUkU9UTCrqUNiFsYEYd//e7Ng7Fjwm0CpMFC30jd6ui/0 gohcNpN+g0RyfLcIXMYM0Xqx1ZPQo71Df1sBTrv7uxFkLR785/qDlUlpmKiSCYkUgW DXOwFUDp8PHpan5CT6Ua3eC7hXGY20VhoeUf+68E= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6989BF801F8; Wed, 20 Nov 2019 13:00:10 +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 207A3F801F7; Wed, 20 Nov 2019 13:00:09 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_NONE,SPF_PASS, SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa2.mentor.iphmx.com (esa2.mentor.iphmx.com [68.232.141.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id CB2BBF801EC for ; Wed, 20 Nov 2019 13:00:04 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz CB2BBF801EC IronPort-SDR: 29RKMHRbGrj3DgUd7PIsTEMtoVK8l2m1qCWikHhZfAs0udrOICeKhpMMEMfU+//nxbVoTDUw0y 32Q5Aeb/o0MlsdSo/eAq9M6fcgp55XP20rRCusRQx5bpGYq1Pbrk8526vOeSk84Bg6SLb0vT2p 8VdzXoLKEud9FJ+80HUtjM9/IchMN9Zf3j/3Vur65LoIVhMGxJgCW3PEKAZRnNXN8z6GfgZZsJ VHGdh0Vl33LxgGsXEtkfasduk67/BSaSXBanVvIUXClgPAEI8twwjJwKeUxizCtJloTaBYxyCJ M4k= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="43282939" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 20 Nov 2019 04:00:02 -0800 IronPort-SDR: M1RGJJYL1O4xfWcRR3qoAvqTVwR7qqWdH+Jd3iuqh7Yo+ZCJGQngPf0MhlnX4erpKXvVpz8IKE JoP5CVmiueKYN0xUlDIGHkqvNh2sb5x1kkBDl40VJEwLPEJTwY7KRk1dMe1TWpO2JR5rRzFLsv 1dILFDKGd5pxoN9HrCPBOW+W1nrqAOTbLCkyqO5hB4i4sxcRZ2hoYsmfCvOdwdvjvZYR4PsJfo Xlvxex/6BUBkml1lI1Gmm7qs7VXSEjTvhMLm7owk9+Nc8DrUz04ve3PIw68WoagRpRiccGhRfd H0c= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:54 -0600 Message-ID: <20191120115856.4125-6-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-5-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> <20191120115856.4125-2-andrew_gabbasov@mentor.com> <20191120115856.4125-3-andrew_gabbasov@mentor.com> <20191120115856.4125-4-andrew_gabbasov@mentor.com> <20191120115856.4125-5-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 5/7] 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" From: Timo Wischer so all functions can use the same. Signed-off-by: Timo Wischer Signed-off-by: Andrew Gabbasov --- 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 2f208aaa54cf..0eacaa9d7862 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -55,6 +55,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; @@ -224,10 +228,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 Wed Nov 20 11:58:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253713 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7FADD6C1 for ; Wed, 20 Nov 2019 12:05: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 10E5122419 for ; Wed, 20 Nov 2019 12:05: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="vMtJvnoo" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 10E5122419 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 3B6F516F3; Wed, 20 Nov 2019 13:05:04 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 3B6F516F3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251554; bh=iXDlwNXk6JFe1czBpTr2hL3a+eWXx5NAOIIYAvM3RS8=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=vMtJvnooSM/YrgOkvelhxzeAGEgESIf/+TtDOAjOKfPWcEs+4rUKHVAiFIfqPWDKO AH0Kjw+sZKVZdB+zzdV7l2ykFXVbH2cg37PUSteOxYIti5kQazWIFUg2CWqPa/GJhy v8whLWsdCZ3eNE6owsuZpTrg50ty8tNhdznl5jYA= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6965BF8021C; Wed, 20 Nov 2019 13:00: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 E9B9FF80214; Wed, 20 Nov 2019 13:00:13 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_NONE,SPF_PASS, SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa2.mentor.iphmx.com (esa2.mentor.iphmx.com [68.232.141.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 66D4BF801EC for ; Wed, 20 Nov 2019 13:00:07 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 66D4BF801EC IronPort-SDR: BASJzY8DSIjHjhSAG80Ve3B2zlkrO/QIwMJhFbe0ugsrnTzF1N55rqD7VqXPzaWLCCzArY26vy J9e+nc4ThqpKWMN2EV4ReL0MEMgNVX5Y9nVoYvn2xbOFHCLfTSjmfinYtxmUC1bNj5Prq/Lcuh ErMUFgGSdOGcUcGVWc7rXt9AwWtCRrFIVyNpm7ExK9hvKUpcxlXL4IeHKxh/g0V8fJ0KZPpUR/ Kj65qum3pm7o3iEuKSdWlIPk1yRVC2jy5+QGUfL4EkaHs1vyYr683fy/zCKx7BbgHrDfr65EAb yZA= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="43282950" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 20 Nov 2019 04:00:05 -0800 IronPort-SDR: YnWYy/SA22YfIRgWrF0u6nKhTGzUZTvtY5yXGan2JZRcbUqOsjYyyC7+HvAGDmnYcclB4OG44c 7S42/2YUBQ0m73Mzkb20cOKXncHzPMS0fXYslGQpZmIgkagLKrjhq8fZVNSkWYy548mMlaB/gV wS9SeaYLHhE9+pMXw8nVNrjyM9rfEHjf9u3Lm4LGprm3QRoy/JYVn71X+RzGNRKCQz3Z4zDlW7 5qy4L1f37n+2GelP5/Hycofeau2XH6zxgsMEe2LXW+ODPyEyDEOcB/YTksKXBirRaXYKd6Vyrz 2nk= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:55 -0600 Message-ID: <20191120115856.4125-7-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-6-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> <20191120115856.4125-2-andrew_gabbasov@mentor.com> <20191120115856.4125-3-andrew_gabbasov@mentor.com> <20191120115856.4125-4-andrew_gabbasov@mentor.com> <20191120115856.4125-5-andrew_gabbasov@mentor.com> <20191120115856.4125-6-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 6/7] 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" 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 timer can be selected by referring to a sound card, its device and subdevice, when loading the module: $ modprobe snd_aloop enable=1 timer_source=[[.[.]]] is the name (id) of the sound card or a card number. and are device and subdevice numbers (defaults are 0). Empty string as a value of timer_source= parameter enables previous functionality (using jiffies timer). Signed-off-by: Timo Wischer Signed-off-by: Andrew Gabbasov --- sound/drivers/aloop.c | 477 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 476 insertions(+), 1 deletion(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 0eacaa9d7862..67ebbd510e1b 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -28,6 +28,7 @@ #include #include #include +#include MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("A loopback soundcard"); @@ -41,6 +42,7 @@ 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]; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for loopback soundcard."); @@ -52,6 +54,8 @@ module_param_array(pcm_substreams, int, NULL, 0444); 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."); +module_param_array(timer_source, charp, NULL, 0444); +MODULE_PARM_DESC(timer_source, "Sound card name or number and device/subdevice number of timer to be used. Empty string for jiffies timer [default]."); #define NO_PITCH 100000 @@ -102,6 +106,13 @@ struct loopback_cable { unsigned int pause; /* timer specific */ struct loopback_ops *ops; + /* If sound timer is used */ + struct { + int stream; + struct snd_timer_id id; + struct tasklet_struct event_tasklet; + struct snd_timer_instance *instance; + } snd_timer; }; struct loopback_setup { @@ -122,6 +133,7 @@ struct loopback { struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2]; struct snd_pcm *pcm[2]; struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2]; + const char *timer_source; }; struct loopback_pcm { @@ -145,6 +157,7 @@ struct loopback_pcm { unsigned int period_size_frac; /* period size in jiffies ticks */ unsigned int last_drift; unsigned long last_jiffies; + /* If jiffies timer is used */ struct timer_list timer; }; @@ -212,6 +225,35 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm) return 0; } +/* call in cable->lock */ +static int loopback_snd_timer_start(struct loopback_pcm *dpcm) +{ + struct loopback_cable *cable = dpcm->cable; + 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(cable->snd_timer.instance, 1); + if (err < 0) { + /* do not report error if trying to start but already + * running. For example called by opposite substream + * of the same cable + */ + if (err == -EBUSY) + return 0; + + pcm_err(dpcm->substream->pcm, + "snd_timer_start(%d,%d,%d) failed with %d", + cable->snd_timer.id.card, + cable->snd_timer.id.device, + cable->snd_timer.id.subdevice, + err); + } + + return err; +} + /* call in cable->lock */ static inline int loopback_jiffies_timer_stop(struct loopback_pcm *dpcm) { @@ -221,6 +263,29 @@ 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) +{ + struct loopback_cable *cable = dpcm->cable; + int err; + + /* only stop if both devices (playback and capture) are not running */ + if (cable->running ^ cable->pause) + return 0; + + err = snd_timer_stop(cable->snd_timer.instance); + if (err < 0) { + pcm_err(dpcm->substream->pcm, + "snd_timer_stop(%d,%d,%d) failed with %d", + cable->snd_timer.id.card, + cable->snd_timer.id.device, + cable->snd_timer.id.subdevice, + err); + } + + return err; +} + static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) { del_timer_sync(&dpcm->timer); @@ -228,6 +293,30 @@ 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) +{ + struct loopback_cable *cable = dpcm->cable; + + /* snd_timer was not opened */ + if (!cable->snd_timer.instance) + return 0; + + /* wait till drain tasklet has finished if requested */ + tasklet_kill(&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; + */ + snd_timer_close(cable->snd_timer.instance); + snd_timer_instance_free(cable->snd_timer.instance); + memset(&cable->snd_timer, 0, sizeof(cable->snd_timer)); + + return 0; +} + static int loopback_check_format(struct loopback_cable *cable, int stream) { struct snd_pcm_runtime *runtime, *cruntime; @@ -353,6 +442,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 (cable->snd_timer.instance) { + 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) @@ -576,6 +672,167 @@ 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 + */ + snd_pcm_uframes_t period_size_usec = + resolution / 1000 * runtime->rate; + /* round to nearest sample rate */ + 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 timer %d,%d,%d. Use period size of %lu frames for loopback device.", + runtime->period_size, resolution, period_size, + cable->snd_timer.id.card, + cable->snd_timer.id.device, + cable->snd_timer.id.subdevice, + period_size); + return -EINVAL; + } + return 0; +} + +static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable, + int event, + unsigned long resolution) +{ + struct loopback_pcm *dpcm_play, *dpcm_capt; + struct snd_pcm_substream *substream_play, *substream_capt; + 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; + } + + dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; + dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; + substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? + dpcm_play->substream : NULL; + substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ? + dpcm_capt->substream : NULL; + + if (event == SNDRV_TIMER_EVENT_MSTOP) { + if (!dpcm_play || + 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 (substream_play) + snd_pcm_stop_xrun(substream_play); + if (substream_capt) + snd_pcm_stop_xrun(substream_capt); + 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 (substream_play) + snd_pcm_period_elapsed(substream_play); + if (substream_capt) + snd_pcm_period_elapsed(substream_capt); +} + +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 *timeri, + int event, + struct timespec *tstamp, + 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) { @@ -588,6 +845,20 @@ 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) +{ + struct loopback_cable *cable = dpcm->cable; + + snd_iprintf(buffer, " sound timer:\thw:%d,%d,%d\n", + cable->snd_timer.id.card, + cable->snd_timer.id.device, + cable->snd_timer.id.subdevice); + snd_iprintf(buffer, " timer open:\t\t%s\n", + (cable->snd_timer.stream == 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; @@ -706,6 +977,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; @@ -748,6 +1036,163 @@ static struct loopback_ops loopback_jiffies_timer_ops = { .dpcm_info = loopback_jiffies_timer_dpcm_info, }; +static int loopback_parse_timer_id(const char *str, + struct snd_timer_id *tid) +{ + /* [:](|)[{.,}[{.,}]] */ + const char * const sep_dev = ".,"; + const char * const sep_pref = ":"; + const char *name = str; + char *sep, save = '\0'; + int card_idx = 0, dev = 0, subdev = 0; + int err; + + sep = strpbrk(str, sep_pref); + if (sep) + name = sep + 1; + sep = strpbrk(name, sep_dev); + if (sep) { + save = *sep; + *sep = '\0'; + } + err = kstrtoint(name, 0, &card_idx); + if (err == -EINVAL) { + /* Must be the name, not number */ + for (card_idx = 0; card_idx < snd_ecards_limit; card_idx++) { + struct snd_card *card = snd_card_ref(card_idx); + + if (card) { + if (!strcmp(card->id, name)) + err = 0; + snd_card_unref(card); + } + if (!err) + break; + } + } + if (sep) { + *sep = save; + if (!err) { + char *sep2, save2 = '\0'; + + sep2 = strpbrk(sep + 1, sep_dev); + if (sep2) { + save2 = *sep2; + *sep2 = '\0'; + } + err = kstrtoint(sep + 1, 0, &dev); + if (sep2) { + *sep2 = save2; + if (!err) + err = kstrtoint(sep2 + 1, 0, &subdev); + } + } + } + if (!err && tid) { + tid->card = card_idx; + tid->device = dev; + tid->subdevice = subdev; + } + return err; +} + +/* call in loopback->cable_lock */ +static int loopback_snd_timer_open(struct loopback_pcm *dpcm) +{ + int err = 0; + struct snd_timer_id tid = { + .dev_class = SNDRV_TIMER_CLASS_PCM, + .dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION, + }; + struct snd_timer_instance *timeri; + struct loopback_cable *cable = dpcm->cable; + + spin_lock_irq(&cable->lock); + + /* check if timer was already opened. It is only opened once + * per playback and capture subdevice (aka cable). + */ + if (cable->snd_timer.instance) + goto unlock; + + err = loopback_parse_timer_id(dpcm->loopback->timer_source, &tid); + if (err < 0) { + pcm_err(dpcm->substream->pcm, + "Parsing timer source \'%s\' failed with %d", + dpcm->loopback->timer_source, err); + goto unlock; + } + + cable->snd_timer.stream = dpcm->substream->stream; + cable->snd_timer.id = tid; + + timeri = snd_timer_instance_new(dpcm->loopback->card->id); + if (!timeri) { + err = -ENOMEM; + goto unlock; + } + /* 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. + */ + timeri->flags |= SNDRV_TIMER_IFLG_AUTO; + timeri->callback = loopback_snd_timer_function; + timeri->callback_data = (void *)cable; + timeri->ccallback = loopback_snd_timer_event; + + /* 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_irq(&cable->lock); + err = snd_timer_open(timeri, &cable->snd_timer.id, current->pid); + if (err < 0) { + pcm_err(dpcm->substream->pcm, + "snd_timer_open (%d,%d,%d) failed with %d", + cable->snd_timer.id.card, + cable->snd_timer.id.device, + cable->snd_timer.id.subdevice, + err); + snd_timer_instance_free(timeri); + return err; + } + spin_lock_irq(&cable->lock); + + cable->snd_timer.instance = timeri; + + /* initialise a tasklet used for draining */ + tasklet_init(&cable->snd_timer.event_tasklet, + loopback_snd_timer_tasklet, (unsigned long)timeri); + +unlock: + spin_unlock_irq(&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 + */ +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; @@ -775,7 +1220,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) + cable->ops = &loopback_snd_timer_ops; + else + cable->ops = &loopback_jiffies_timer_ops; loopback->cables[substream->number][dev] = cable; } dpcm->cable = cable; @@ -811,6 +1259,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 + */ + if (cable->snd_timer.instance) { + 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. */ @@ -1214,6 +1675,18 @@ static int loopback_proc_new(struct loopback *loopback, int cidx) print_cable_info); } +static void loopback_set_timer_source(struct loopback *loopback, + const char *value) +{ + if (loopback->timer_source) { + devm_kfree(loopback->card->dev, loopback->timer_source); + loopback->timer_source = NULL; + } + if (value && *value) + loopback->timer_source = devm_kstrdup(loopback->card->dev, + value, GFP_KERNEL); +} + static int loopback_probe(struct platform_device *devptr) { struct snd_card *card; @@ -1233,6 +1706,8 @@ static int loopback_probe(struct platform_device *devptr) pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; loopback->card = card; + loopback_set_timer_source(loopback, timer_source[dev]); + mutex_init(&loopback->cable_lock); err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]); From patchwork Wed Nov 20 11:58:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11253711 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5014A109A for ; Wed, 20 Nov 2019 12:05:13 +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 D378022419 for ; Wed, 20 Nov 2019 12:05:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="ovB8liM3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D378022419 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mentor.com 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 1E2DA1719; Wed, 20 Nov 2019 13:04:21 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 1E2DA1719 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1574251511; bh=UpwEboLxEwQ7+kxVwiMfoEqj3vEJJ81t196S/O/OWLE=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=ovB8liM3XkMXExEH8ZOJn1f8eCxkxWKGFPhvsLWDQ5C5WW6pMUJH8zui5CYw6/xiD L6CjRCEeREFkxMf4EBEbnosvO7RemXJ27kdotOY1OGf8vq97xzA9179sZUL5Eduawm 7YBKB5GiUvU3Vt9xCSjYGb83H6+oRmDhGDUFeqiE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 64360F80217; Wed, 20 Nov 2019 13:00:14 +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 6BECBF80212; Wed, 20 Nov 2019 13:00:13 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_NONE,SPF_PASS, SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from esa2.mentor.iphmx.com (esa2.mentor.iphmx.com [68.232.141.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 2E747F801F4 for ; Wed, 20 Nov 2019 13:00:09 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 2E747F801F4 IronPort-SDR: 9kCgK+uTckNFiX1G4h50skMBQgE94zL/1Gmlnnblz1sDcjMWim7eg4grSdHibAU9+3F7N7PwJn VB5ZaGyNNqLgWad+DUf6FystE1Azr57udoAo5TqVdFbF5jbNIV6hbOukz0Oxt2NSosFG0pZLIK YLVexZlMYDClFJYKWi6eAOeudzVqE9kT/6xT0cxPqEz3+HaJhBhb+PVMWMNa+nmoQEUuzDxuhk zNji0TaB+yTKzIwtRZVyZcd4eoezJUMcVfWMysDJUAmJE3TF4mPKYzTZ35GZAvXf56y6BD+VHp b3E= X-IronPort-AV: E=Sophos;i="5.69,221,1571731200"; d="scan'208";a="43282952" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 20 Nov 2019 04:00:08 -0800 IronPort-SDR: 9BO8PS76rbrX3Nz2edhwu25bV/lNGy5OVzZ82kkpPmuBSUmne1ciXaMMTik1y/dT7hhYCDLAcE O3McfE/mi3Zo3TzPIJRNJGS6K4OD5xfw1JmYoMHkEhORHgKo2PUArPGtbNioHRJ0r93y0W+/Jj 5AjQ49duS247wxUG1VI5D4G6mjHHvzRaMM70sVk2wYGf/l9KoPARleWoX5g5ykMVmb0+bANGd5 Cmz1tkEw0uSR+sMbA+KPecpkmyt12hlPJ4xrsvqfizfBoq71OJ9ErnFBfdok0koyaiA0TC/6Rf Ync= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Wed, 20 Nov 2019 05:58:56 -0600 Message-ID: <20191120115856.4125-8-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191120115856.4125-7-andrew_gabbasov@mentor.com> References: <20191120115856.4125-1-andrew_gabbasov@mentor.com> <20191120115856.4125-2-andrew_gabbasov@mentor.com> <20191120115856.4125-3-andrew_gabbasov@mentor.com> <20191120115856.4125-4-andrew_gabbasov@mentor.com> <20191120115856.4125-5-andrew_gabbasov@mentor.com> <20191120115856.4125-6-andrew_gabbasov@mentor.com> <20191120115856.4125-7-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v4 7/7] ALSA: aloop: Support runtime change of snd_timer via info interface 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" Show and change sound card timer source with read-write info file in proc filesystem. Initial string can still be set as module parameter. The timer source string value can be changed at any time, but it is latched by PCM substream open callback (the first one for a particular cable). At this point it is actually used, that is the string is parsed, and the timer is looked up and opened. The timer source is set for a loopback card (the same as initial setting by module parameter), but every cable uses the value, current at the moment of open. Setting the value to empty string switches the timer to jiffies. Signed-off-by: Andrew Gabbasov --- sound/drivers/aloop.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 67ebbd510e1b..626a8b642b63 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1666,7 +1666,7 @@ static void print_cable_info(struct snd_info_entry *entry, mutex_unlock(&loopback->cable_lock); } -static int loopback_proc_new(struct loopback *loopback, int cidx) +static int loopback_cable_proc_new(struct loopback *loopback, int cidx) { char name[32]; @@ -1687,6 +1687,36 @@ static void loopback_set_timer_source(struct loopback *loopback, value, GFP_KERNEL); } +static void print_timer_source_info(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) +{ + struct loopback *loopback = entry->private_data; + + mutex_lock(&loopback->cable_lock); + snd_iprintf(buffer, "%s\n", + loopback->timer_source ? loopback->timer_source : ""); + mutex_unlock(&loopback->cable_lock); +} + +static void change_timer_source_info(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) +{ + struct loopback *loopback = entry->private_data; + char line[64]; + + mutex_lock(&loopback->cable_lock); + if (!snd_info_get_line(buffer, line, sizeof(line))) + loopback_set_timer_source(loopback, strim(line)); + mutex_unlock(&loopback->cable_lock); +} + +static int loopback_timer_source_proc_new(struct loopback *loopback) +{ + return snd_card_rw_proc_new(loopback->card, "timer_source", loopback, + print_timer_source_info, + change_timer_source_info); +} + static int loopback_probe(struct platform_device *devptr) { struct snd_card *card; @@ -1719,8 +1749,9 @@ static int loopback_probe(struct platform_device *devptr) err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0); if (err < 0) goto __nodev; - loopback_proc_new(loopback, 0); - loopback_proc_new(loopback, 1); + loopback_cable_proc_new(loopback, 0); + loopback_cable_proc_new(loopback, 1); + loopback_timer_source_proc_new(loopback); strcpy(card->driver, "Loopback"); strcpy(card->shortname, "Loopback"); sprintf(card->longname, "Loopback %i", dev + 1);