Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp3620554imm; Mon, 25 Jun 2018 01:31:57 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJwzeyukMpue8fOeMT6Qo+z8gKPlxzNogjD9AXboqjp5Iepfg/MrrAiHkMXC5vODQVoJYy8 X-Received: by 2002:a17:902:728a:: with SMTP id d10-v6mr11465354pll.192.1529915517227; Mon, 25 Jun 2018 01:31:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529915517; cv=none; d=google.com; s=arc-20160816; b=SerjyD2jZ1CeFVPR4DQQXMAaD1HZYM/lKgvZy4CZAOGvhDjq6WOd8AxuE0G5UW+E8l B1ycqL2yqcpcYiOVFVqLIKUOMcW62f8+CUuyxnFqx50u5x5rYNN1Ctp476tjaH2jZMH1 cIzPxWBJ0DXFdJ01Z+VAv/HlU4YITP7Qsfxb548gC5RzEe3j5s3qw6U9jvMF4hMS2jiO fLoF9zvN5wTO6MsFfXKU5R9+njIG6NZbpfZA8UJyGXOn79zjQGPiiruMCuZjF5TpAvP4 s3VZfEFrrnt2ohRoMOawlAj/MwzuQW6y7bibiEw4d/q+h7Vyjf30JCaIOkt5boWuDUvJ O0zA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=++TCHwl/guPvkMV1hf+DsB+4uPX30e9QVrZWiSpKN3s=; b=RkO9lPtko9zTs9CvQHhRq7h4xRPzqkObX+vggQDT2f/D1Wcep0+Q58tpSyyFspA2Yq Kc5vp9X0VGD/6DPhVljxpJ+LuCSDufgYc4wFNhUgbx48rSgtCbtXeJO2NPcHOMIZ1Lhw 0GviuK0x3CcJ0qSA1WN3I/X66w5fOXbQ2Ig/THz7i+8Vt5esTdEi5ybAtHAYUh4XldY4 KWTM+/GzlZNSKGT7t961eKq1t8hODOd9LeYZPFfZwjEIOjHnbV+hkYJLQWt4dr3dzc0I GKlNjDP4aWu1PzoA1zI+c3Cz0wmv3q4/dxl+QfjXUgNXmz1cunH1LJcvXGm9Y6aJKhbB kHbQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=k5CxeZZL; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e39-v6si13552842plg.168.2018.06.25.01.31.42; Mon, 25 Jun 2018 01:31:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=k5CxeZZL; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754489AbeFYI3g (ORCPT + 99 others); Mon, 25 Jun 2018 04:29:36 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:37684 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754240AbeFYI3d (ORCPT ); Mon, 25 Jun 2018 04:29:33 -0400 Received: by mail-wm0-f68.google.com with SMTP id r125-v6so8919549wmg.2 for ; Mon, 25 Jun 2018 01:29:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=++TCHwl/guPvkMV1hf+DsB+4uPX30e9QVrZWiSpKN3s=; b=k5CxeZZLvF0JsvxpilbrH2zhJBl6YYRIMgjnjT60Io2ytkpyhR86zyug7IhkOMSzj7 EluTyMs31wN6XA6g9ZW+r0aMwCtA972bavAI//CybFXs3CE7cKejiyuH96uJHsoFFl0F tHn/oPg6Y062rbLM5GxHyjrZBibyNao6eepIbf9TxZ5IkIhzWDZZ/eUxAHCzY1745/8Z OoOY9D7me0lkFJMj3Jm0i10BNsop9WyFOYCp6KgGRmhNl89KsAK7XMoEUeS1eOAGXFXU vgnkYA6BDIEHacdxa8wU5vWSFL0Vperx/9Jlc4J85+0n9qzdxoXI41UeN7H0N3EXT6Ei REdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=++TCHwl/guPvkMV1hf+DsB+4uPX30e9QVrZWiSpKN3s=; b=HpAG8me+DrKxUlib1SB5Bz/sR7xZx4lPXeeFtvw/n/BSMUYHx/ibXGuoEFUkIaJVjK qBl6q3H/IbiE2vgiZXc4qo35rNW1k5o9lV4ylLH4+y30WJOsn0L+mwgmGCHA+Mra26rj e7kR5JP1lrezxtGro7rClOjW3jyww390u8tun+QOTkAHwAr98c11JhO9unAppKeqrun8 xSkIn0zz3+lRVuFgUs9Y18lHr9YtHMcsRcppLJR/4/BzlglklIb9CA3JoesMD3MdRP7G EpWxdYtbPkZGrJNtUdykPbAbehmJETGn2xaWrmrBGN6pF3xXvh/JHPqjq0RMGjIa0uvQ QuDg== X-Gm-Message-State: APt69E1u5aoYIGjVdn/EYrzv+UWZ1Ok4iSULbuBfhKaZfczmoSmX1622 utEu/2H7a24Md3DW8V+wtqFyfw== X-Received: by 2002:a1c:9253:: with SMTP id u80-v6mr222956wmd.52.1529915371797; Mon, 25 Jun 2018 01:29:31 -0700 (PDT) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id n17-v6sm12911855wmd.14.2018.06.25.01.29.30 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 25 Jun 2018 01:29:31 -0700 (PDT) From: Jerome Brunet To: Liam Girdwood , Mark Brown Cc: Jerome Brunet , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [PATCH] ASoC: dpcm: improve runtime update predictability Date: Mon, 25 Jun 2018 10:29:23 +0200 Message-Id: <20180625082923.25636-1-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As it is, dpcm_runtime_update() performs the old path and new path update of a frontend before going on to the next frontend DAI. Depending the order of the FEs within the rtd list, the result of the update might be different. For example: * Frontend A connected to backend C, with a 48kHz playback * Frontend B connected to backend D, with a 44.1kHz playback * FE A appears before FE B in the rtd list of the card. If we reparent BE C to FE B (disconnecting BE D): * old path update of FE A will run first, and BE C will get hw_free() and shutdown() * new path update of FE B will run after and BE C, which is stopped, so it will be configured at 44.1kHz, as expected If we reparent BE D to FE A (disconnecting BE C): * new path update of FE A will run first but since BE D is still running at 44.1kHz, it won't be reconfigured (no call to startup() or hw_params()) * old path update of FE B runs after, nothing happens * In this case, we end up with a BE playing at 44.1kHz a stream which is supposed to be played at 48Khz (too slow) To improve this situation, this patch performs all the FE old paths update before going on to update the new paths. With this, the result should no longer depend on the order of the FE within the card rtd list. Please note that there might be a small performance penalty since dpcm_process_paths() is called twice per stream direction. Signed-off-by: Jerome Brunet --- sound/soc/soc-pcm.c | 165 +++++++++++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 79 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5e7ae47a9658..5c2534414478 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2543,106 +2543,113 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) return ret; } -/* Called by DAPM mixer/mux changes to update audio routing between PCMs and - * any DAI links. - */ -int soc_dpcm_runtime_update(struct snd_soc_card *card) +int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) { - struct snd_soc_pcm_runtime *fe; - int old, new, paths; + struct snd_soc_dapm_widget_list *list; + int count, paths; - mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - list_for_each_entry(fe, &card->rtd_list, list) { - struct snd_soc_dapm_widget_list *list; + if (!fe->dai_link->dynamic) + return 0; - /* make sure link is FE */ - if (!fe->dai_link->dynamic) - continue; + /* only check active links */ + if (!fe->cpu_dai->active) + return 0; - /* only check active links */ - if (!fe->cpu_dai->active) - continue; + /* DAPM sync will call this to update DSP paths */ + dev_dbg(fe->dev, "ASoC: DPCM %s runtime update for FE %s\n", + new ? "new" : "old", fe->dai_link->name); - /* DAPM sync will call this to update DSP paths */ - dev_dbg(fe->dev, "ASoC: DPCM runtime update for FE %s\n", - fe->dai_link->name); + /* skip if FE doesn't have playback capability */ + if (!fe->cpu_dai->driver->playback.channels_min || + !fe->codec_dai->driver->playback.channels_min) + goto capture; - /* skip if FE doesn't have playback capability */ - if (!fe->cpu_dai->driver->playback.channels_min - || !fe->codec_dai->driver->playback.channels_min) - goto capture; - - /* skip if FE isn't currently playing */ - if (!fe->cpu_dai->playback_active - || !fe->codec_dai->playback_active) - goto capture; - - paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); - if (paths < 0) { - dev_warn(fe->dev, "ASoC: %s no valid %s path\n", - fe->dai_link->name, "playback"); - mutex_unlock(&card->mutex); - return paths; - } + /* skip if FE isn't currently playing */ + if (!fe->cpu_dai->playback_active || !fe->codec_dai->playback_active) + goto capture; - /* update any new playback paths */ - new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1); - if (new) { - dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK); - dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK); - dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); - } + paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); + if (paths < 0) { + dev_warn(fe->dev, "ASoC: %s no valid %s path\n", + fe->dai_link->name, "playback"); + return paths; + } - /* update any old playback paths */ - old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0); - if (old) { + /* update any playback paths */ + count = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, new); + if (count) { + if (new) + dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK); + else dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK); - dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK); - dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); - } - dpcm_path_put(&list); + dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK); + dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); + } + + dpcm_path_put(&list); + capture: - /* skip if FE doesn't have capture capability */ - if (!fe->cpu_dai->driver->capture.channels_min - || !fe->codec_dai->driver->capture.channels_min) - continue; + /* skip if FE doesn't have capture capability */ + if (!fe->cpu_dai->driver->capture.channels_min || + !fe->codec_dai->driver->capture.channels_min) + return 0; - /* skip if FE isn't currently capturing */ - if (!fe->cpu_dai->capture_active - || !fe->codec_dai->capture_active) - continue; + /* skip if FE isn't currently capturing */ + if (!fe->cpu_dai->capture_active || !fe->codec_dai->capture_active) + return 0; - paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); - if (paths < 0) { - dev_warn(fe->dev, "ASoC: %s no valid %s path\n", - fe->dai_link->name, "capture"); - mutex_unlock(&card->mutex); - return paths; - } + paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); + if (paths < 0) { + dev_warn(fe->dev, "ASoC: %s no valid %s path\n", + fe->dai_link->name, "capture"); + return paths; + } - /* update any new capture paths */ - new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1); - if (new) { + /* update any old capture paths */ + count = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, new); + if (count) { + if (new) dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE); - dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE); - dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE); - } - - /* update any old capture paths */ - old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0); - if (old) { + else dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE); - dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE); - dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE); - } - dpcm_path_put(&list); + dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE); + dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE); } - mutex_unlock(&card->mutex); + dpcm_path_put(&list); + return 0; } + +/* Called by DAPM mixer/mux changes to update audio routing between PCMs and + * any DAI links. + */ +int soc_dpcm_runtime_update(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *fe; + int ret = 0; + + mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + /* shutdown all old paths first */ + list_for_each_entry(fe, &card->rtd_list, list) { + ret = soc_dpcm_fe_runtime_update(fe, 0); + if (ret) + goto out; + } + + /* bring new paths up */ + list_for_each_entry(fe, &card->rtd_list, list) { + ret = soc_dpcm_fe_runtime_update(fe, 1); + if (ret) + goto out; + } + +out: + mutex_unlock(&card->mutex); + return ret; +} int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) { struct snd_soc_dpcm *dpcm; -- 2.14.4