Received: by 2002:a25:b323:0:0:0:0:0 with SMTP id l35csp3034387ybj; Mon, 23 Sep 2019 13:37:04 -0700 (PDT) X-Google-Smtp-Source: APXvYqzoE7YUpiUvYdNZ8jzpNPWhNWOy9o3Uwih6KVmlyQ5HTRlKEHN/S2gQJcwQytQGZOkCNRL2 X-Received: by 2002:a50:c209:: with SMTP id n9mr2051401edf.215.1569271024234; Mon, 23 Sep 2019 13:37:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1569271024; cv=none; d=google.com; s=arc-20160816; b=LYm8Q/vnhyqqThkI/YzpudiNm7Bd0LqX8tZsd1pDYKxzyKDU5OaFMWI5gFpW3/J19D GlE/qJ9NiDCccldPLbSvivO68MEq8fozksDP4T2ndgE8cRef2MrzQ40rCgpnL5LMc/Bt PnnihIsVSoVVtfAl79sUl4RXzt+lpvthdNyrbiFuxPpRCeGkiUIz7aH9JcNfOAk3zmP0 xcBvqzCiAdOmBjpuVPU0hxEeCbWvvFl2CvxEVZN9N7MF/QjdO44vvpTVHzE8+pvNlUF/ K35IVEUy1HJrKqPM04rYFd6zdzFY4jjZVj/0aTjO/5Rkb4m2Rv7tS1sfqXl98WU9mjRj nFCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=bruuS/LpPiYPfnlu+Mqb7G85ZFEy2D5HYhxaTaQjWH4=; b=r0oAofEjGcZ579W+JcmVaVlJe6w4LyHGif/3YoDiG7edctVB6thztNGbKhpnxm8iyB MRWbWJiUP9HweXCFFzV4DABsfL5yHDgceStl91Vg7FUQZGmKWT+gYq/txtHsNvURZsu+ UAoJYM1RZj+42iuPGRpopi/wV52ExJeGXoRvsDnpzhoOTv2GmVCbC6WhEBpCHGmTKZHU ujr6YuXA75/DD0q+qQ+NN2s1JWxAO2cqpB63vzmH1nxl4is2kQjqYc4iN0lGoPxq3xpq 3HczNEz+zIU03DEIB4lTk724oaCf+YwQ9LxfuS0xfcVkqki/R8wA7Zlrd7A2vgjWLZql OMwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=ijeDUZdL; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e27si7696562edj.295.2019.09.23.13.36.40; Mon, 23 Sep 2019 13:37:04 -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=@kernel.org header.s=default header.b=ijeDUZdL; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388869AbfIVSoq (ORCPT + 99 others); Sun, 22 Sep 2019 14:44:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:39856 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388703AbfIVSoJ (ORCPT ); Sun, 22 Sep 2019 14:44:09 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 78F4221BE5; Sun, 22 Sep 2019 18:44:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1569177848; bh=qyvPGPthlv7IWQeOy+355+CuuoZBoH+UE9kvtZXQ8ng=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ijeDUZdLGzh014wJv7wh4umDb4falrQfMZpnynYTxgVAe5oDUAcYiF8Km/JjPJjOQ xlgXG7UM7kzWa1A883hV1OOCRT5eVUY6f0BckeV4u9m9Bfp74v0VIPOtY3tHh4oAH6 4i1qG9emBgk+p+DdFCwRmirf+CSU70i89mJFLKBo= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Kai Vehmanen , Pierre-Louis Bossart , Mark Brown , Sasha Levin Subject: [PATCH AUTOSEL 5.3 014/203] ASoC: SOF: reset DMA state in prepare Date: Sun, 22 Sep 2019 14:40:40 -0400 Message-Id: <20190922184350.30563-14-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190922184350.30563-1-sashal@kernel.org> References: <20190922184350.30563-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kai Vehmanen [ Upstream commit 04c8027764bc82a325d3abc6f39a6a4642a937cb ] When application goes through SUSPEND/STOP->PREPARE->START cycle, we should always reprogram the SOF device to start DMA from a known state so that hw_ptr/appl_ptrs remain valid. This is expected by ALSA core as it resets the buffer state as part of prepare (see snd_pcm_do_prepare()). Fix the issue by forcing reconfiguration of the FW with STREAM_PCM_PARAMS in prepare(). Use combined logic to handle prepare and the existing flow to reprogram hw-params after system suspend. Without the fix, first call to pcm pointer() will return an invalid hw_ptr and application may immediately observe XRUN status, unless "start_threshold" SW parameter is set to maximum value by the application. Signed-off-by: Kai Vehmanen Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20190722141402.7194-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/sof/pcm.c | 27 +++++++++++++++------------ sound/soc/sof/pm.c | 2 +- sound/soc/sof/sof-priv.h | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 334e9d59b1baf..3b8955e755b24 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -208,12 +208,11 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + spcm->prepared[substream->stream] = true; + /* save pcm hw_params */ memcpy(&spcm->params[substream->stream], params, sizeof(*params)); - /* clear hw_params_upon_resume flag */ - spcm->hw_params_upon_resume[substream->stream] = 0; - return ret; } @@ -236,6 +235,9 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) if (!spcm) return -EINVAL; + if (!spcm->prepared[substream->stream]) + return 0; + dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); @@ -258,6 +260,8 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) if (ret < 0) dev_err(sdev->dev, "error: platform hw free failed\n"); + spcm->prepared[substream->stream] = false; + return ret; } @@ -278,11 +282,7 @@ static int sof_pcm_prepare(struct snd_pcm_substream *substream) if (!spcm) return -EINVAL; - /* - * check if hw_params needs to be set-up again. - * This is only needed when resuming from system sleep. - */ - if (!spcm->hw_params_upon_resume[substream->stream]) + if (spcm->prepared[substream->stream]) return 0; dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id, @@ -311,6 +311,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_sof_pcm *spcm; struct sof_ipc_stream stream; struct sof_ipc_reply reply; + bool reset_hw_params = false; int ret; /* nothing to do for BE */ @@ -351,6 +352,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; + reset_hw_params = true; break; default: dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd); @@ -363,17 +365,17 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, sizeof(stream), &reply, sizeof(reply)); - if (ret < 0 || cmd != SNDRV_PCM_TRIGGER_SUSPEND) + if (ret < 0 || !reset_hw_params) return ret; /* - * The hw_free op is usually called when the pcm stream is closed. - * Since the stream is not closed during suspend, the DSP needs to be - * notified explicitly to free pcm to prevent errors upon resume. + * In case of stream is stopped, DSP must be reprogrammed upon + * restart, so free PCM here. */ stream.hdr.size = sizeof(stream); stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; stream.comp_id = spcm->stream[substream->stream].comp_id; + spcm->prepared[substream->stream] = false; /* send IPC to the DSP */ return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, @@ -481,6 +483,7 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) spcm->stream[substream->stream].posn.host_posn = 0; spcm->stream[substream->stream].posn.dai_posn = 0; spcm->stream[substream->stream].substream = substream; + spcm->prepared[substream->stream] = false; ret = snd_sof_pcm_platform_open(sdev, substream); if (ret < 0) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 278abfd10490d..48c6d78d72e2e 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -233,7 +233,7 @@ static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) state = substream->runtime->status->state; if (state == SNDRV_PCM_STATE_SUSPENDED) - spcm->hw_params_upon_resume[dir] = 1; + spcm->prepared[dir] = false; } } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index b8c0b2a226845..fa5cb7d2a6602 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -297,7 +297,7 @@ struct snd_sof_pcm { struct snd_sof_pcm_stream stream[2]; struct list_head list; /* list in sdev pcm list */ struct snd_pcm_hw_params params[2]; - int hw_params_upon_resume[2]; /* set up hw_params upon resume */ + bool prepared[2]; /* PCM_PARAMS set successfully */ }; /* ALSA SOF Kcontrol device */ -- 2.20.1