From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-bl2nam02on0136.outbound.protection.outlook.com ([104.47.38.136]:51875 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753271AbeDIARy (ORCPT ); Sun, 8 Apr 2018 20:17:54 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Matthias Reichl , Mark Brown , Sasha Levin Subject: [PATCH AUTOSEL for 4.15 044/189] ASoC: bcm2835: fix hw_params error when device is in prepared state Date: Mon, 9 Apr 2018 00:17:20 +0000 Message-ID: <20180409001637.162453-44-alexander.levin@microsoft.com> References: <20180409001637.162453-1-alexander.levin@microsoft.com> In-Reply-To: <20180409001637.162453-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Matthias Reichl [ Upstream commit 8d5737a5f53902a916ee1e1cb248c9b8b883b2ea ] If bcm2835 is configured as bitclock master calling hw_params() after prepare() fails with EBUSY. This also makes it impossible to use bcm2835 in full duplex mode. The error is caused by the split clock setup: clk_set_rate is called in hw_params, clk_prepare_enable in prepare. As hw_params doesn't check if the clock was already enabled clk_set_rate fails with EBUSY. Fix this by moving clock startup from prepare to hw_params and let hw_params properly deal with an already set up or enabled clock. Signed-off-by: Matthias Reichl Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/bcm/bcm2835-i2s.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 2e449d7173fc..d5f73a8ab893 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -130,6 +130,7 @@ struct bcm2835_i2s_dev { struct regmap *i2s_regmap; struct clk *clk; bool clk_prepared; + int clk_rate; }; =20 static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) @@ -419,10 +420,19 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_subst= ream *substream, } =20 /* Clock should only be set up here if CPU is clock master */ - if (bit_clock_master) { - ret =3D clk_set_rate(dev->clk, bclk_rate); - if (ret) - return ret; + if (bit_clock_master && + (!dev->clk_prepared || dev->clk_rate !=3D bclk_rate)) { + if (dev->clk_prepared) + bcm2835_i2s_stop_clock(dev); + + if (dev->clk_rate !=3D bclk_rate) { + ret =3D clk_set_rate(dev->clk, bclk_rate); + if (ret) + return ret; + dev->clk_rate =3D bclk_rate; + } + + bcm2835_i2s_start_clock(dev); } =20 /* Setup the frame format */ @@ -618,8 +628,6 @@ static int bcm2835_i2s_prepare(struct snd_pcm_substream= *substream, struct bcm2835_i2s_dev *dev =3D snd_soc_dai_get_drvdata(dai); uint32_t cs_reg; =20 - bcm2835_i2s_start_clock(dev); - /* * Clear both FIFOs if the one that should be started * is not empty at the moment. This should only happen --=20 2.15.1