From patchwork Mon Nov 11 11:08:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236767 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 3F6671390 for ; Mon, 11 Nov 2019 11:11:24 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8CE9C2190F for ; Mon, 11 Nov 2019 11:11:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="InhboaEc" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8CE9C2190F 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 61B0F167D; Mon, 11 Nov 2019 12:10:30 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 61B0F167D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470680; bh=kFFn8ISQ0kW31uPYPk751hKhq7lg8Upm/GPI9ZRh71o=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=InhboaEcoJx115O9aOa+UzzoQyid1LE1Y+4UHv/HXqt1vipbfOxHh7le2SITD5t5u RSFO7aDBuFkye6MEA2WfnKegqCEEWK0f0Jme9G1dItcEwFWhrxxtwxQnleUgXdENDX de2vAHRojTOUuAo29HZAxwDDYLVF4WPwqFA1ZXSU= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 01A8BF804FF; Mon, 11 Nov 2019 12:09:38 +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 7CD8EF80518; Mon, 11 Nov 2019 12:09:34 +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 autolearn=disabled version=3.4.0 Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) (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 22FC2F802E0 for ; Mon, 11 Nov 2019 12:09:30 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 22FC2F802E0 IronPort-SDR: nGJK1LQfrdlH9LLDr/C45eSnThorlfXpJQmX/RxkSdCHwq8bhGOE9cQ73Uj51ABV4ImYMJR37H d5pIdua2XETxJN9zemdeasjjpAEvWlna5JhrNYhEzX/7lVEr3LmmtGngFho9tsP5kQn3HWwuNn nHPxW3lCZVW7Bk9NlzPAfhZ2VV+fEONndlT/nK42AnhnQlt8olvHvfxLPWofja4wDfEvzJGTFY I6sbYft33sYfDVbDN51ocnuYhlJBHtN8w5o0z54viWfVoddKfeDHA6kzOrsFiw6eq1+ENLi30B egs= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="43051105" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:09:29 -0800 IronPort-SDR: Ljtjv3fR9c7VCXF6BWzclaR6POPzKc2fpoySZPWSobspxQvozd16o0PhBz+DrD1mfF+rvgwOly ZOiC9GtS97L5RpSfDMYVwZ2lgiBxMMCqwPU/KzMgK/RqgXVKa00MmgOkZYMpG2bx5+yD2ASQMm 4+7ecwEpdOZvH3wgPH4L6z4cQlPc/lZdlbz81wHLInZm87OaCqncRoqEYGuT84YWKxF3gJTPPq lwGCZ1dwhxzCZVZKzy+ogg43Kdhshfl47DnBYOO8o9HgxfvWunyH4RmmbXeOplmbU0umkEJ0Ol w2k= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:40 -0600 Message-ID: <20191111110846.18223-2-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-1-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-07.mgc.mentorg.com (139.181.222.7) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 9ccdad89c288..1f5982e09025 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 Mon Nov 11 11:08:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236769 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 6390D1390 for ; Mon, 11 Nov 2019 11:12:10 +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 B3A6C2184C for ; Mon, 11 Nov 2019 11:12:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="dwq8bgtC" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B3A6C2184C 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 7D3E61687; Mon, 11 Nov 2019 12:11:16 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 7D3E61687 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470726; bh=okgKcMep5dewtFp2UKa+c3ZNJq55vIZQcohQEUsMacE=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=dwq8bgtCUfPdQIELg+HAduYZX3TW1zN2Hb/1dUbVTdpvM20nZVRKHdWhWeP5r2Y47 uWoI+kC/uDmvzYYf1xt8MHP6tB1TI7+5R21fB6Ma5tZo0DNyBrd82m3vv2sCAReqGD OlgpB0J4HQfxipPkcVtdCEDC6chwc1XSQusS54yM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BD3B4F80600; Mon, 11 Nov 2019 12:09:39 +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 8D9E5F8053A; Mon, 11 Nov 2019 12:09:35 +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 autolearn=disabled version=3.4.0 Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) (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 392E5F8045D for ; Mon, 11 Nov 2019 12:09:32 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 392E5F8045D IronPort-SDR: NQuoIU7vtJ/5/cHIWuwdZwQBlbH6BsoIk2oNG5fr52Bdl+nObFaFXwEEH6udMuV8GiwlFJAI9N NqTGQJ7DKlFQVaOs3v1PXeQXENtUTePjzTMhBktMCyRcZ5E+xGQ934eXI3l3S9g6zuMCygQTeu fUPQDvAD2shHjvm3J0gBcq+8rIkrvDGnYcAasVHQDQuhrxjXDnct0B1+zLDiK5RWfR/mvI5Gky AIAtmcEG1szDZn59rbDpIoqe6qiKS4YYnFdsQr6KI2rdlZ3M/0+uZCUyBBq2uXxdmJJPrWBfFv cdU= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="43051109" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:09:31 -0800 IronPort-SDR: 5idUWUzRCps92YlOKu+Y9QijUPKmgHKOAVjG/lH9VUeOQo0pfyDuZHKlHpeenr1oU/hXSvlCBj rWFLPGUUoJ29Us2ZvxftSLFlatpqQffvENakmC0c0p163000xpMfX9Jx05YU1qTI55xB8f4yY5 Q9MN1NvTkEoHhYkwnQfSr07Nv/0t3V2o/0LuXiL+twlRGwN7D0cO66EIN3N0kpzOz/wMacyuvB lQ8dqVjaFsw92TrlItlCxyfDxcxndtDT1DIBShNsOgUiNWiH+FFvb2+uAls96LylWC7Fu3QKyI pzk= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:41 -0600 Message-ID: <20191111110846.18223-3-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-2-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> <20191111110846.18223-2-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-07.mgc.mentorg.com (139.181.222.7) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 1f5982e09025..dc9154662d5b 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 Mon Nov 11 11:08:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236773 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 80D8014E5 for ; Mon, 11 Nov 2019 11:12:58 +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 0CAFF2184C for ; Mon, 11 Nov 2019 11:12:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="doajfaGQ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0CAFF2184C 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 2EE301674; Mon, 11 Nov 2019 12:12:06 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2EE301674 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470776; bh=NLcPmm6s4l3J8FFEZNkFLsOA9X6bL6lI1k9RxmkUwF8=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=doajfaGQL9QxE2QnQkvWtGXwflS05WJmFjzGEf2MzGFEMfmZ+GS5gU+XftUF9ZZ17 Rs06PkEAFKHpv/JkCSrE0P2t+yT3U2rrbVK4RvrJvUy/N4MLNjMXVfYJdFiiQ7FSHK WaSX7e2RcXBqwjRhw0BJ7cWUqhZ5ZfBi2De5fuaw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 63591F8060F; Mon, 11 Nov 2019 12:09:41 +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 DF861F8060D; Mon, 11 Nov 2019 12:09:39 +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 autolearn=disabled version=3.4.0 Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) (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 77A5FF80519 for ; Mon, 11 Nov 2019 12:09:36 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 77A5FF80519 IronPort-SDR: dQOB+25Ac7ZZ8MfaYzW0jBmtURtzsIhGsy59wUB05O0G++zMBjM+7PYcgIEeCecIpnJI1ckkGv YaBQyHqoe0Xbi3R4MhrlDAYbM2mXjvIBjKsjKfee5W+NFVNbLj+yv8clRhT3AVKCaCmVRQdhjG TelnXEM11pD0soQSupcpGLWzq7IX2HOO37LHQdWbueOGk7I6voEHdJTYZcZc/508LMWfIuEmjo tMW5RXsi+PmcP9WaV5bqGMQUWIX3Yc78OPuAkbd+jnZteVkA85Fo05LuFQ6Q5p8tl5KzhKBTnO Dgo= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="43051113" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:09:34 -0800 IronPort-SDR: bhf9RHemiZhEYgxTK31Avuj5LGYWOl/nNODdaj0rfXD31YWteLlg8W1NCDt3L3qw5PQyn8u4Ob guQ2OmHz/m9HA+Rtuh3CeW/LiviTduNyuAYNk6SUfuIre+zfugIDJg4gJsziE08uGCN9PWwyJ5 2/KXzc0jtqaJ6df1rn6QWMXVL4Edcug60IALKzrdGrHMivjADQz5z6JqNWPWeKiWDrmu7Btb0G IlkAEi8rXV+cUoYYkVBL4kPQCyRsZ/mBhqI1qLJObaZrClaIpqBgmLapsfGfOekoeYYPfzBKme l+U= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:42 -0600 Message-ID: <20191111110846.18223-4-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-3-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> <20191111110846.18223-2-andrew_gabbasov@mentor.com> <20191111110846.18223-3-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-07.mgc.mentorg.com (139.181.222.7) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 dc9154662d5b..92134e9c6ea7 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); @@ -672,12 +720,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; @@ -695,7 +764,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) { @@ -706,9 +774,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); @@ -734,7 +810,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; @@ -758,12 +836,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 Mon Nov 11 11:08:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236775 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 2136E1390 for ; Mon, 11 Nov 2019 11:13:25 +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 6C5E521925 for ; Mon, 11 Nov 2019 11:13:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="KqLnUxFx" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6C5E521925 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 881031675; Mon, 11 Nov 2019 12:12:32 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 881031675 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470802; bh=uq1qC5PvNIq7saKCbyjF8Wkl3q+cUzcmbb29zOgAEfQ=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=KqLnUxFxA0r1pkQAwYDXT1r4lLNo4HAfBtxAmdpbcsQUq/eDL8Lujb0NGaMPP5Bhj w3okGAsUnrBA67ui2JNmH/wnWZHhZmOQzeJs/Ce7n4upIF10fVxPmbWxOwkvNDWqPZ Mq2JEgtdhhwPhK5f7T4ahsRYuhX/rNiE2SBtECFE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 5C73CF80634; Mon, 11 Nov 2019 12:09:48 +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 4E24AF80610; Mon, 11 Nov 2019 12:09:41 +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 autolearn=disabled version=3.4.0 Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) (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 4D7A4F805FB for ; Mon, 11 Nov 2019 12:09:38 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4D7A4F805FB IronPort-SDR: r1aGAvGQE/tH+Pcd5Y44rHItfwPizhct/j/OekRCjBdNUTigkGF9zpNQdE86hptjyyr5l7wmI0 /e81ZFGyWT7jM+M1gFBlw6/mNrTc5/UqVxrN+x5jzxFTzJ1f4wyjT0arS3cclQDcgRbVuDHXN9 8t2ipDFeVsjBxhMSBRvC9p3h0SXOHZ6GZV8z2HipHiTjHiuTgWiqOGG1lIgfGhUZWHos/vo0z8 OmRcqbFY7Pqr/JjsgezqWpxcKADVKtqQfB8uVHOnUIZWiMUz0jZI35y1WyU0lDcD2kxtCA6oQk Apk= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="43051117" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:09:37 -0800 IronPort-SDR: i+TPsAImEE5GlGWViRIeQPLFaDwwF7MsQ1DLCo7Nb+szL+5GjTtIjsFc4ddON7yfahRuLTFMh1 bufTFF15HH68e+F9e8AI4yGWl2Q6u7+OfuyN5xyjZ6OEUEE7qmwb6yIZ6GKevrVtpL473EzYNf MvkVhMBKjxLrUMmi4WmTsPJp+KTn6QVcWBYWHqSwnwpjTfA+4NXFBZ7QYd9pKS4hfbNtsDnvr/ wjZ5DlHomSeKaPPVtBUyDjMI21HfKLl8dtlx6LZ6/F487vBrouI6kQGZXSowX0AFwAiQSmoeHc lUE= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:43 -0600 Message-ID: <20191111110846.18223-5-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-4-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> <20191111110846.18223-2-andrew_gabbasov@mentor.com> <20191111110846.18223-3-andrew_gabbasov@mentor.com> <20191111110846.18223-4-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-07.mgc.mentorg.com (139.181.222.7) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 92134e9c6ea7..178f7260a650 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); @@ -732,18 +734,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 Mon Nov 11 11:08:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236777 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 8323E1390 for ; Mon, 11 Nov 2019 11:14:15 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0F6062190F for ; Mon, 11 Nov 2019 11:14:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="CNklChgU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0F6062190F 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 1965B1680; Mon, 11 Nov 2019 12:13:23 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 1965B1680 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470853; bh=5qtaS+RqEhFPDCNLyPm0lnDcpfMV7raz5PKWGoOcJ7M=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=CNklChgU8KyosS7W695y4xsUlDg32wDt0Bvj5GzRSoKeMEJIv0hnfPsYPlnUDxOrq 7+r0vh0JKu9bmmZs3r+tM1XV5omuodzhq8y23u3+K7btlr53QHbfYixQYrvF8uROaP 54KuhVu1QVF4yEkO/oEmCVWQJgmCrqfeAqsvg7m4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id E8663F80649; Mon, 11 Nov 2019 12:10:07 +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 DC449F8064C; Mon, 11 Nov 2019 12:10:05 +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=1.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 1E160F8063D for ; Mon, 11 Nov 2019 12:10:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 1E160F8063D IronPort-SDR: fQZSBLZpICWoXdKfSUDWtp5qoIocOiuGiDq/ukVMUo48dn8b9UMdTXm6YHH5U8NtIj5E1u4QvD aGIA8TkydwrjMMoiC6l1iTfhAkR6Zart2ZbEGpAtr95w9YISfVHjTT6kmFAclk5mr1K7Aua01C J1QP/CAkXI3gZnrg+WH54b0LFva9xIMbkRGQ+mUK/LhksbJEBmCcfr2tOuXAk6eVIOaCrn2Knx fwpFZJqTp+0EUZ8z5oef2sj7F7zjHcdo1rIMEEsuofteZglktpHxFakh6+6rhPahjkM9sxhup7 AiQ= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="42981211" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:09:58 -0800 IronPort-SDR: 5QwQpd2UBT/k2p5OLkV4ejgc/1AkE/uU0DLu5z1Syzg70AHcDId4OS5HpEaormtYqgyzbWYxxH NCvm7gPSm9C/Pdc7gYshOFvrzzdji4AaSSM/rTQCnwbh2hL+GOkpOxplzeEVVz/4S2sXPjnPfy lzlu+uNsr5EujyWzTazE0vCsHcDX7vFcmwfhj1jIQrv4Mkc/BvWvSId6GJGQdekrjuWRncPLzZ 7XsdK/4E3hnWyipHfBGna7D0soX/QnshmeCfqtAWYB6hhrfrBabEUTY4Bi9muwlqDEMvYiYcQz 2uU= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:44 -0600 Message-ID: <20191111110846.18223-6-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-5-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> <20191111110846.18223-2-andrew_gabbasov@mentor.com> <20191111110846.18223-3-andrew_gabbasov@mentor.com> <20191111110846.18223-4-andrew_gabbasov@mentor.com> <20191111110846.18223-5-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-05.mgc.mentorg.com (139.181.222.5) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 178f7260a650..313d7ffe6c91 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 Mon Nov 11 11:08:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236781 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 CA81414E5 for ; Mon, 11 Nov 2019 11:15:34 +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 585F82184C for ; Mon, 11 Nov 2019 11:15:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="MdEeZozi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 585F82184C 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 89FDD1673; Mon, 11 Nov 2019 12:14:42 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 89FDD1673 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470932; bh=A0chIt9woMbTXDSBGUGbBcmdKs2+cN4PGvoaweDn5Ic=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=MdEeZozityhoeO0ffRFEhoLjVZdNVCwX+wvs9RQXs8ncFvGrVdm+Uw7RZ384IuA+8 jseAtjzPovg+mEppKAwx7UCp/5pCoQbLdK/BRnKDGZ7ii5W6wl056XYD96cUJMfAqu dWWRz62dW6ZAoO9ftMMzqNOa9d6r9JxvAf/hn2Lc= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B7E02F80672; Mon, 11 Nov 2019 12:10:13 +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 5145AF8063E; Mon, 11 Nov 2019 12:10: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=1.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 5EB04F8063E for ; Mon, 11 Nov 2019 12:10:02 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 5EB04F8063E IronPort-SDR: 5IlGKc38GqlIdpy+weJCZ4ldsxJndQD0TxbyIma6L7Eoqdw1ryHXlu++CT4yUAA/OSShB4M/A9 aAlngjPZ99Bptjhv9EtTNq83oKX0Znhzx0S55Ex5mY0vCC1yS7HNqGp1V1yKUnnEvIOmgBvt6F VqoKCaCZsWdxOD3guzjXGgzu5BbiciaG8sbrk9CL3vmZ96lNpXmjv/gGn9pbrlv4jpwRBKkU7o 4sskgDRVfInhkfyU46aXeM3Ai1C5Z9utI1EgubAt5fyn/mdpXDG2APFSEUIe7/5nXo19Dw2Lm/ 9F0= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="42981214" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:10:01 -0800 IronPort-SDR: 2wxHjq5EHCDS6TW0WW5JbB4oyPrcUH8VypkpG09cIJaptoD6CqoQuRPz8s/dhiMInjDyk2OlBn MF0BN5ssCGx/yLjXV0MyxugxFtnudCsVcUc8qxxQKQQvk3BMgvqLp+oezFmUf2u861uFie3qfL 7Pj+JIOxYGD0bJCeWLaaNMahHsJmZMZWbEDQePmuet60zO7hgN1awvYrNXjigPgyrNtN6nKDDg vNH4zqdz8gjxrt3QeLAyj6Uis7fsuZ83ayyGtsBw0kUYumYpzOpNmMIeAiZzpWw5ub9qOowFFt oE8= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:45 -0600 Message-ID: <20191111110846.18223-7-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-6-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> <20191111110846.18223-2-andrew_gabbasov@mentor.com> <20191111110846.18223-3-andrew_gabbasov@mentor.com> <20191111110846.18223-4-andrew_gabbasov@mentor.com> <20191111110846.18223-5-andrew_gabbasov@mentor.com> <20191111110846.18223-6-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-05.mgc.mentorg.com (139.181.222.5) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 | 478 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 477 insertions(+), 1 deletion(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 313d7ffe6c91..2f08038f8792 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,38 @@ 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; + int err; + + /* 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; + */ + err = snd_timer_close(cable->snd_timer.instance); + if (err < 0) { + pcm_err(dpcm->substream->pcm, + "snd_timer_close(%d,%d,%d) failed with %d", + cable->snd_timer.id.card, + cable->snd_timer.id.device, + cable->snd_timer.id.subdevice, + err); + } + memset(&cable->snd_timer, 0, sizeof(cable->snd_timer)); + + return err; +} + static int loopback_check_format(struct loopback_cable *cable, int stream) { struct snd_pcm_runtime *runtime, *cruntime; @@ -353,6 +450,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 +680,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 + */ + 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 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 * const cable, + const int event, const 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 * 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) { @@ -588,6 +853,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; @@ -707,6 +986,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; @@ -749,6 +1045,156 @@ static struct loopback_ops loopback_jiffies_timer_ops = { .dpcm_info = loopback_jiffies_timer_dpcm_info, }; +static int loopback_parse_timer_id(const char * const 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 *timer; + 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; + + /* 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(&timer, dpcm->loopback->card->id, + &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); + return err; + } + spin_lock_irq(&cable->lock); + + /* 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 *)cable; + timer->ccallback = loopback_snd_timer_event; + cable->snd_timer.instance = timer; + + /* initialise a tasklet used for draining */ + tasklet_init(&cable->snd_timer.event_tasklet, + loopback_snd_timer_tasklet, (unsigned long)timer); + +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; @@ -776,7 +1222,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; @@ -812,6 +1261,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 +1676,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 +1707,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 Mon Nov 11 11:08:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabbasov, Andrew" X-Patchwork-Id: 11236779 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 7492A1390 for ; Mon, 11 Nov 2019 11:14:49 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 039FC2190F for ; Mon, 11 Nov 2019 11:14: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="DngpmC2i" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 039FC2190F 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 2AB791671; Mon, 11 Nov 2019 12:13:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2AB791671 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573470887; bh=lYJFe0GSf/w8K6z8aUWfCqp0Er8pDxg109+PDinXzrY=; h=From:To:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=DngpmC2iXsvNimp52Dbya0JjtlmGkSPLFhYZkfKsE33L+GSWrNMOkY0PH7qvR1Fzv 1SeV/Y/338r80/4ZKvKqsk+mCI9ltp2L1EZM1KoH2JBvU0VEbgpngV3s/R1PkzXD2c jKSO/XmHURN27MO2/KPChdVlFDNDHzaNYp2N6AdE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 59577F8065B; Mon, 11 Nov 2019 12:10: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 43641F8065D; Mon, 11 Nov 2019 12:10: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 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 0B857F80642 for ; Mon, 11 Nov 2019 12:10:04 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 0B857F80642 IronPort-SDR: 5TWeOyzTEjBbR10WhG1jVNusbhRwojVkX/NIoiNN6pEahfqTetOVnjgMX9z016tGMQRfrEPXYS 3EI/yaEnrrPBX5K304sltFELgSvqk9XgUQMq/xmX5f4aLwx16OuTH/lN/UG6Oez0RYwZ+B4U7z f0B7XDTftcko7hvCuW1v93Lf01POHm4JgW2gYhBNu4m3Bs8zsuN4TEe685/K8o2Q55X0hVTVX9 a60F1yYpp+36qQQhu4Ksznl54DiAUAxFZeetphLRKf9jAXVmO0GNCRsAVCY+J6qYByG6oOK7UU wRM= X-IronPort-AV: E=Sophos;i="5.68,292,1569312000"; d="scan'208";a="42981218" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 11 Nov 2019 03:10:04 -0800 IronPort-SDR: i5nuYU4PmjFemi4jFGKxgJ8k6bM8E2x1VCxSi3kJn+hQ3M4horDJCv6WX/JqWmawukx4De5s9K FUuP0TT/JIZ3kYj+Z8GmoUIcitoCgXh6oxNswWbUo410HGX2aeT65TsZWknHqF2/yriz5gPvsm 9E8Tux54li/18A2Wb8lrzpUVJspnLB14/JDVaud40SAwitylW0jAuFwsVfUr3PkrhCfkA6r7ev dp6TDN8T/Il1WHsFp5C9kI/pJ/hscUVa3GN6zmLPX9G00/KkBLLwVBfiDdT9tzwDAREUSQX/MC NyA= From: Andrew Gabbasov To: , , Jaroslav Kysela , Takashi Iwai , Timo Wischer , Andrew Gabbasov Date: Mon, 11 Nov 2019 05:08:46 -0600 Message-ID: <20191111110846.18223-8-andrew_gabbasov@mentor.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191111110846.18223-7-andrew_gabbasov@mentor.com> References: <20191111110846.18223-1-andrew_gabbasov@mentor.com> <20191111110846.18223-2-andrew_gabbasov@mentor.com> <20191111110846.18223-3-andrew_gabbasov@mentor.com> <20191111110846.18223-4-andrew_gabbasov@mentor.com> <20191111110846.18223-5-andrew_gabbasov@mentor.com> <20191111110846.18223-6-andrew_gabbasov@mentor.com> <20191111110846.18223-7-andrew_gabbasov@mentor.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-05.mgc.mentorg.com (139.181.222.5) To svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) Subject: [alsa-devel] [PATCH v3 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 | 45 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 2f08038f8792..430ab757a4c4 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1667,7 +1667,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]; @@ -1688,6 +1688,44 @@ 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) +{ + struct snd_info_entry *entry; + int err; + + err = snd_card_proc_new(loopback->card, "timer_source", &entry); + if (err < 0) + return err; + + snd_info_set_text_ops(entry, loopback, print_timer_source_info); + entry->mode |= S_IWUSR; + entry->c.text.write = change_timer_source_info; + return 0; +} + static int loopback_probe(struct platform_device *devptr) { struct snd_card *card; @@ -1720,8 +1758,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);