From patchwork Thu Dec 29 11:34:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 9491155 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 61DFE62AB8 for ; Thu, 29 Dec 2016 11:34:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 54DD41FF15 for ; Thu, 29 Dec 2016 11:34:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 43B6E201BC; Thu, 29 Dec 2016 11:34:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D3DD1FF15 for ; Thu, 29 Dec 2016 11:34:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751839AbcL2Led (ORCPT ); Thu, 29 Dec 2016 06:34:33 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:43977 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751750AbcL2Leb (ORCPT ); Thu, 29 Dec 2016 06:34:31 -0500 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OIY00FLL2TG4B00@mailout2.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Thu, 29 Dec 2016 11:34:28 +0000 (GMT) Received: from eusmges1.samsung.com (unknown [203.254.199.239]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20161229113427eucas1p21dee6bc368a48c2cb9edff403c337b7b~UtuPgWL6G0547105471eucas1p2P; Thu, 29 Dec 2016 11:34:27 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges1.samsung.com (EUCPMTA) with SMTP id DE.0A.32567.4C4F4685; Thu, 29 Dec 2016 11:34:28 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20161229113426eucas1p2bc05fb68efd45e6af3ae7a2b8be5e481~UtuOyJvUL0547105471eucas1p2O; Thu, 29 Dec 2016 11:34:26 +0000 (GMT) X-AuditID: cbfec7ef-f79336d000007f37-2a-5864f4c43d8f Received: from eusync2.samsung.com ( [203.254.199.212]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id CE.4F.03557.AE4F4685; Thu, 29 Dec 2016 11:35:06 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OIY00CMD2T7BA50@eusync2.samsung.com>; Thu, 29 Dec 2016 11:34:26 +0000 (GMT) From: Marek Szyprowski To: alsa-devel@alsa-project.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Mark Brown , Sylwester Nawrocki , Sangbeom Kim , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Inki Dae , Javier Martinez Canillas Subject: [PATCH 2/5] ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device Date: Thu, 29 Dec 2016 12:34:04 +0100 Message-id: <1483011247-21613-3-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1483011247-21613-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrBIsWRmVeSWpSXmKPExsWy7djPc7pHvqREGCw7KWxx5eIhJouNM9az Wkx9+ITNYtL9CSwWb96uYbI4f34Du8WM8/uYLNYeuctucfhNO6vFxRVfmBy4PDZ8bmLz2LSq k81jS/9ddo++LasYPT5vkgtgjeKySUnNySxLLdK3S+DKuNHQyljQbF3x7fJfpgbGZfpdjJwc EgImEisX7WWCsMUkLtxbz9bFyMUhJLCMUeLlocPsEM5nRolnjdNYYTr27DjIClc1++8dqJYG JomOd+/YQKrYBAwlut52gdkiAk4SM+e8BytiFrjFJNHddIGli5GDQ1ggXGL2xwiQGhYBVYm/ L3Ywg9i8Ah4SHy+/YobYJidx8thksM2cAp4SLR+bmEDmSAi0s0u0TehiB5kjISArsekAVL2L xIqpS6AuFZZ4dXwLO4QtI9HZcRDqz35GiaZWbQh7BqPEube8ELa1xOHjF8F6mQX4JCZtm84M MZ5XoqNNCKLEQ2L5/iNQ4x0lJi/9Dg2hOYwS24/9YZzAKLOAkWEVo0hqaXFuemqxoV5xYm5x aV66XnJ+7iZGYHyf/nf8/Q7Gp80hhxgFOBiVeHglZFIihFgTy4orcw8xSnAwK4nwfvkEFOJN SaysSi3Kjy8qzUktPsQozcGiJM67d8GVcCGB9MSS1OzU1ILUIpgsEwenVANjoObHv7uP6S2d OoV9+5Kstt1eqy88yl9bHR3b/OKJZs31hTwFeyeUb4+e+Df4amKNPXPCCqcZb0R2FzixyO/5 rV1yY9Fpqc8Hjzulc8h9smGJ/JC1Y7PWl2kun99/vVPPduPz5MQDn0zWTpCKejkz2iDuzrrQ Y849i9O1JrO6Pz195oVwRZDCciWW4oxEQy3mouJEAI3zsRrrAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrJLMWRmVeSWpSXmKPExsVy+t/xK7qvvqREGEz5bGJx5eIhJouNM9az Wkx9+ITNYtL9CSwWb96uYbI4f34Du8WM8/uYLNYeuctucfhNO6vFxRVfmBy4PDZ8bmLz2LSq k81jS/9ddo++LasYPT5vkgtgjXKzyUhNTEktUkjNS85PycxLt1UKDXHTtVBSyEvMTbVVitD1 DQlSUihLzCkF8owM0ICDc4B7sJK+XYJbxo2GVsaCZuuKb5f/MjUwLtPvYuTkkBAwkdiz4yAr hC0mceHeerYuRi4OIYEljBKHvkxihHCamCT2XTzKBlLFJmAo0fW2C8wWEXCSmDnnPVgHs8Ad JonvjxaxgCSEBcIl/r95wAhiswioSvx9sYMZxOYV8JD4ePkVM8Q6OYmTxyaDreYU8JRo+djE BGILAdX8efWPaQIj7wJGhlWMIqmlxbnpucWGesWJucWleel6yfm5mxiBwb7t2M/NOxgvbQw+ xCjAwajEwyshkxIhxJpYVlyZe4hRgoNZSYT3yyegEG9KYmVValF+fFFpTmrxIUZToKMmMkuJ JucDIzGvJN7QxNDc0tDI2MLC3MhISZy35MOVcCGB9MSS1OzU1ILUIpg+Jg5OqQbGGBejTzW9 15cJB6xaP1PV74l/zD3ZXWHX1e4f3Oi6WrOi8NfF3h4jjtW3X7PuK7bwerY9f8LCptjQG5en uUw++fDZc8FLC8/9WvyX+0AvT13FqWf75//qmV/2sViK2yHdXIU9UWvmzy1Jefe4dX5ExkhU PrjddTy+7ZbS08pk7je6OnxfF8ftU2Ipzkg01GIuKk4EALOYybGMAgAA X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20161229113426eucas1p2bc05fb68efd45e6af3ae7a2b8be5e481 X-Msg-Generator: CA X-Sender-IP: 182.198.249.179 X-Local-Sender: =?UTF-8?B?TWFyZWsgU3p5cHJvd3NraRtTUlBPTC1LZXJuZWwgKFRQKRs=?= =?UTF-8?B?7IK87ISx7KCE7J6QG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Global-Sender: =?UTF-8?B?TWFyZWsgU3p5cHJvd3NraRtTUlBPTC1LZXJuZWwgKFRQKRtT?= =?UTF-8?B?YW1zdW5nIEVsZWN0cm9uaWNzG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTI=?= CMS-TYPE: 201P X-HopCount: 7 X-CMS-RootMailID: 20161229113426eucas1p2bc05fb68efd45e6af3ae7a2b8be5e481 X-RootMTR: 20161229113426eucas1p2bc05fb68efd45e6af3ae7a2b8be5e481 References: <1483011247-21613-1-git-send-email-m.szyprowski@samsung.com> Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds calls to pm_runtime_get/put to ensure that any access to I2S registers is done with proper (active) runtime PM state of I2S device. Till now the driver enabled runtime PM, but didn't manage the state during driver operation. The driver worked fine only because the runtime PM callbacks managed device clock, which was enabled all the time because of the additional enable call in the driver's probe function. Signed-off-by: Marek Szyprowski --- sound/soc/samsung/i2s.c | 54 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index ce4e70ef5568..2aa800b99938 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -477,6 +477,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; u32 mod, mask, val = 0; unsigned long flags; + int ret = 0; + + pm_runtime_get_sync(dai->dev); spin_lock_irqsave(i2s->lock, flags); mod = readl(i2s->addr + I2SMOD); @@ -501,7 +504,8 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, && (mod & cdcon_mask))))) { dev_err(&i2s->pdev->dev, "%s:%d Other DAI busy\n", __func__, __LINE__); - return -EAGAIN; + ret = -EAGAIN; + goto err; } if (dir == SND_SOC_CLOCK_IN) @@ -529,7 +533,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, } else { i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); - return 0; + goto done; } } @@ -540,8 +544,10 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, i2s->op_clk = clk_get(&i2s->pdev->dev, "i2s_opclk0"); - if (WARN_ON(IS_ERR(i2s->op_clk))) - return PTR_ERR(i2s->op_clk); + if (WARN_ON(IS_ERR(i2s->op_clk))) { + ret = PTR_ERR(i2s->op_clk); + goto err; + } clk_prepare_enable(i2s->op_clk); i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); @@ -555,12 +561,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, || (clk_id && !(mod & rsrc_mask))) { dev_err(&i2s->pdev->dev, "%s:%d Other DAI busy\n", __func__, __LINE__); - return -EAGAIN; + ret = -EAGAIN; + goto err; } else { /* Call can't be on the active DAI */ i2s->op_clk = other->op_clk; i2s->rclk_srcrate = other->rclk_srcrate; - return 0; + goto done; } if (clk_id == 1) @@ -568,7 +575,8 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, break; default: dev_err(&i2s->pdev->dev, "We don't serve that!\n"); - return -EINVAL; + ret = -EINVAL; + goto err; } spin_lock_irqsave(i2s->lock, flags); @@ -576,8 +584,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, mod = (mod & ~mask) | val; writel(mod, i2s->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags); +done: + pm_runtime_put(dai->dev); return 0; +err: + pm_runtime_put(dai->dev); + return ret; } static int i2s_set_fmt(struct snd_soc_dai *dai, @@ -646,6 +659,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } + pm_runtime_get_sync(dai->dev); spin_lock_irqsave(i2s->lock, flags); mod = readl(i2s->addr + I2SMOD); /* @@ -655,6 +669,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, if (any_active(i2s) && ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { spin_unlock_irqrestore(i2s->lock, flags); + pm_runtime_put(dai->dev); dev_err(&i2s->pdev->dev, "%s:%d Other DAI busy\n", __func__, __LINE__); return -EAGAIN; @@ -664,6 +679,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, mod |= tmp; writel(mod, i2s->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags); + pm_runtime_put(dai->dev); return 0; } @@ -675,6 +691,8 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, u32 mod, mask = 0, val = 0; unsigned long flags; + WARN_ON(!pm_runtime_active(dai->dev)); + if (!is_secondary(i2s)) mask |= (MOD_DC2_EN | MOD_DC1_EN); @@ -763,6 +781,8 @@ static int i2s_startup(struct snd_pcm_substream *substream, struct i2s_dai *other = get_other_dai(i2s); unsigned long flags; + pm_runtime_get_sync(dai->dev); + spin_lock_irqsave(&lock, flags); i2s->mode |= DAI_OPENED; @@ -800,6 +820,8 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, i2s->bfs = 0; spin_unlock_irqrestore(&lock, flags); + + pm_runtime_put(dai->dev); } static int config_setup(struct i2s_dai *i2s) @@ -874,6 +896,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + pm_runtime_get_sync(dai->dev); spin_lock_irqsave(i2s->lock, flags); if (config_setup(i2s)) { @@ -902,6 +925,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, } spin_unlock_irqrestore(i2s->lock, flags); + pm_runtime_put(dai->dev); break; } @@ -916,13 +940,16 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai, switch (div_id) { case SAMSUNG_I2S_DIV_BCLK: + pm_runtime_get_sync(dai->dev); if ((any_active(i2s) && div && (get_bfs(i2s) != div)) || (other && other->bfs && (other->bfs != div))) { + pm_runtime_put(dai->dev); dev_err(&i2s->pdev->dev, "%s:%d Other DAI busy\n", __func__, __LINE__); return -EAGAIN; } i2s->bfs = div; + pm_runtime_put(dai->dev); break; default: dev_err(&i2s->pdev->dev, @@ -941,6 +968,8 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai, snd_pcm_sframes_t delay; const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; + WARN_ON(!pm_runtime_active(dai->dev)); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) delay = FIC_RXCOUNT(reg); else if (is_secondary(i2s)) @@ -984,6 +1013,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) struct i2s_dai *other = get_other_dai(i2s); unsigned long flags; + pm_runtime_get_sync(dai->dev); + if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback, NULL); @@ -1016,6 +1047,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) if (!is_opened(other)) i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, 0, SND_SOC_CLOCK_IN); + pm_runtime_put(dai->dev); return 0; } @@ -1025,6 +1057,8 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); unsigned long flags; + pm_runtime_get_sync(dai->dev); + if (!is_secondary(i2s)) { if (i2s->quirks & QUIRK_NEED_RSTCLR) { spin_lock_irqsave(i2s->lock, flags); @@ -1033,6 +1067,8 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) } } + pm_runtime_put(dai->dev); + return 0; } @@ -1328,7 +1364,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, pri_dai); - + pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); ret = i2s_register_clock_provider(pdev); @@ -1351,10 +1387,12 @@ static int samsung_i2s_remove(struct platform_device *pdev) pri_dai->sec_dai = NULL; sec_dai->pri_dai = NULL; + pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); i2s_unregister_clock_provider(pdev); clk_disable_unprepare(pri_dai->clk); + pm_runtime_put_noidle(&pdev->dev); return 0; }