From 24a3d132294163f3476c25c17d92b5d730323379 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 10:37:39 +0100 Subject: [PATCH 01/16] ASoC: samsung: i2s: Get rid of a static spinlock This patch makes the spinlock serializing access to the primary/secondary PCM a per I2S controller lock, rather than a global one. There is no need to have a global lock across multiple I2S controllers in the SoC. Change-Id: I6b56296ce45e219ed5f37af85fd352ff51af617a Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 1be3547..766a049 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -88,9 +88,6 @@ struct i2s_dai { struct samsung_i2s_priv *priv; }; -/* Lock for cross i/f checks */ -static DEFINE_SPINLOCK(lock); - struct samsung_i2s_priv { struct platform_device *pdev; struct platform_device *pdev_sec; @@ -101,6 +98,9 @@ struct samsung_i2s_priv { /* Spinlock protecting access to the device's registers */ spinlock_t lock; + /* Lock for cross i/f checks */ + spinlock_t pcm_lock; + /* CPU DAIs and their corresponding drivers */ struct i2s_dai *dai; struct snd_soc_dai_driver *dai_drv; @@ -831,7 +831,7 @@ static int i2s_startup(struct snd_pcm_substream *substream, pm_runtime_get_sync(dai->dev); - spin_lock_irqsave(&lock, flags); + spin_lock_irqsave(&priv->pcm_lock, flags); i2s->mode |= DAI_OPENED; @@ -843,7 +843,7 @@ static int i2s_startup(struct snd_pcm_substream *substream, if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR)) writel(CON_RSTCLR, i2s->priv->addr + I2SCON); - spin_unlock_irqrestore(&lock, flags); + spin_unlock_irqrestore(&priv->pcm_lock, flags); return 0; } @@ -851,11 +851,12 @@ static int i2s_startup(struct snd_pcm_substream *substream, static void i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); struct i2s_dai *i2s = to_info(dai); struct i2s_dai *other = get_other_dai(i2s); unsigned long flags; - spin_lock_irqsave(&lock, flags); + spin_lock_irqsave(&priv->pcm_lock, flags); i2s->mode &= ~DAI_OPENED; i2s->mode &= ~DAI_MANAGER; @@ -867,7 +868,7 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, i2s->rfs = 0; i2s->bfs = 0; - spin_unlock_irqrestore(&lock, flags); + spin_unlock_irqrestore(&priv->pcm_lock, flags); pm_runtime_put(dai->dev); } @@ -1405,6 +1406,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1]; spin_lock_init(&priv->lock); + spin_lock_init(&priv->pcm_lock); if (!np) { if (i2s_pdata == NULL) { -- 2.7.4 From 8b17eb5cd2d23bd7de57188142fbb5cfb0bbf09b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 10:37:41 +0100 Subject: [PATCH 02/16] ASoC: samsung: Specify DMA channel names through custom DMA config This is a part of conversion of Samsung platforms to use the custom DMA config for specifying DMA channel names, in addition to passing custom DMA device for the secondary CPU DAI's "PCM" component for some variants of the I2S controller. We also don't set the SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME any more as setting it wouldn't allow to specify DMA channels through the custom DMA config. Change-Id: Ia7e4da88746788c6fd56e1781160328bdaa224b8 Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/dmaengine.c | 12 ++++-------- sound/soc/samsung/i2s.c | 2 +- sound/soc/samsung/s3c2412-i2s.c | 2 +- sound/soc/samsung/s3c24xx-i2s.c | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index 84601fa..3028719 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c @@ -28,7 +28,6 @@ int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter, const char *tx, const char *rx, struct device *dma_dev) { - unsigned int flags = SND_DMAENGINE_PCM_FLAG_COMPAT; struct snd_dmaengine_pcm_config *pcm_conf; pcm_conf = devm_kzalloc(dev, sizeof(*pcm_conf), GFP_KERNEL); @@ -39,14 +38,11 @@ int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter, pcm_conf->compat_filter_fn = filter; pcm_conf->dma_dev = dma_dev; - if (dev->of_node) { - pcm_conf->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = tx; - pcm_conf->chan_names[SNDRV_PCM_STREAM_CAPTURE] = rx; - } else { - flags |= SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME; - } + pcm_conf->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = tx; + pcm_conf->chan_names[SNDRV_PCM_STREAM_CAPTURE] = rx; - return devm_snd_dmaengine_pcm_register(dev, pcm_conf, flags); + return devm_snd_dmaengine_pcm_register(dev, pcm_conf, + SND_DMAENGINE_PCM_FLAG_COMPAT); } EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 766a049..c446e07 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1459,7 +1459,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai->drv->playback.channels_max = 6; ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, - NULL, NULL, NULL); + "tx", "rx", NULL); if (ret < 0) goto err_disable_clk; diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 67dfa27..c08638b 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -177,7 +177,7 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev, pdata->dma_filter, - NULL, NULL, NULL); + "tx", "rx", NULL); if (ret) { pr_err("failed to register the DMA: %d\n", ret); return ret; diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index ba0f2b9..a8026b6 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -446,7 +446,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; ret = samsung_asoc_dma_platform_register(&pdev->dev, NULL, - NULL, NULL, NULL); + "tx", "rx", NULL); if (ret) { dev_err(&pdev->dev, "Failed to register the DMA: %d\n", ret); return ret; -- 2.7.4 From 95425ac00de835df5b9f734ff342e6eecba9447b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 10:37:44 +0100 Subject: [PATCH 03/16] ASoC: samsung: i2s: Simplify pri_dai, sec_dai pointers usage If the probe call is on the primary DAI we can use 'other' in place of i2s->sec_dai, if the probe call is on the secondary DAI we can use 'i2s' in place of other->sec_dai. While at it fix one whitespace issue. Change-Id: Idbe9190d87f628f4d8fab77dbdbe433c8cd7825d Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index c446e07..79965fc 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1056,18 +1056,17 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) 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); + snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL); } else { snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, - &i2s->dma_capture); + &i2s->dma_capture); if (priv->quirks & QUIRK_NEED_RSTCLR) writel(CON_RSTCLR, priv->addr + I2SCON); if (priv->quirks & QUIRK_SUPPORTS_IDMA) idma_reg_addr_init(priv->addr, - i2s->sec_dai->idma_playback.addr); + other->idma_playback.addr); } /* Reset any constraint on RFS and BFS */ -- 2.7.4 From b1d7acb5f6056bf7d1773dff0e5242ac11190288 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 10:37:45 +0100 Subject: [PATCH 04/16] ASoC: samsung: i2s: Change indentation in SAMSUNG_I2S_FMTS definition Change indentation so this macro definition spans 2 rows and looks more consistent with surrounding code. Change-Id: I747acdce454a660c637d29ab34450081e02084d2 Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 79965fc..846e506 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1149,9 +1149,8 @@ static const struct snd_soc_component_driver samsung_i2s_component = { .num_dapm_routes = ARRAY_SIZE(samsung_i2s_dapm_routes), }; -#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE) +#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) static int i2s_alloc_dais(struct samsung_i2s_priv *priv, const struct samsung_i2s_dai_data *i2s_dai_data, -- 2.7.4 From beb985932da87029eeeed309caebba9fb73735be Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 3 Aug 2018 11:33:57 -0500 Subject: [PATCH 05/16] ASoC: samsung: i2s: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Change-Id: I030b163708ab40f17cf500cff7a8f326b890b7f5 Addresses-Coverity-ID: 1381093 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 846e506..07f815a 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -742,6 +742,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, switch (params_channels(params)) { case 6: val |= MOD_DC2_EN; + /* fall through */ case 4: val |= MOD_DC1_EN; break; -- 2.7.4 From 0e3c6872eff35018e90a522cff8298f36d92ebd2 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 10:37:46 +0100 Subject: [PATCH 06/16] ASoC: samsung: i2s: Comments clean up Spelling error fixes, upper/lower case letter changes. Change-Id: Id1060cbb859c6da4480a0dd6f676a6614b64da8c Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 07f815a..84cfa2c 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1,5 +1,4 @@ -/* sound/soc/samsung/i2s.c - * +/* * ALSA SoC Audio Layer - Samsung I2S Controller driver * * Copyright (c) 2010 Samsung Electronics Co. Ltd. @@ -61,10 +60,10 @@ struct i2s_dai { /* Platform device for this DAI */ struct platform_device *pdev; - /* Frame Clock */ + /* Frame clock */ unsigned frmclk; /* - * Specifically requested RCLK,BCLK by MACHINE Driver. + * Specifically requested RCLK, BCLK by machine driver. * 0 indicates CPU driver is free to choose any value. */ unsigned rfs, bfs; @@ -72,8 +71,9 @@ struct i2s_dai { struct i2s_dai *pri_dai; /* Pointer to the Secondary_Fifo if it has one, NULL otherwise */ struct i2s_dai *sec_dai; -#define DAI_OPENED (1 << 0) /* Dai is opened */ -#define DAI_MANAGER (1 << 1) /* Dai is the manager */ + +#define DAI_OPENED (1 << 0) /* DAI is opened */ +#define DAI_MANAGER (1 << 1) /* DAI is the manager */ unsigned mode; /* Driver for this DAI */ @@ -98,7 +98,7 @@ struct samsung_i2s_priv { /* Spinlock protecting access to the device's registers */ spinlock_t lock; - /* Lock for cross i/f checks */ + /* Lock for cross interface checks */ spinlock_t pcm_lock; /* CPU DAIs and their corresponding drivers */ @@ -309,7 +309,7 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) writel(mod, priv->addr + I2SMOD); } -/* Read Bit-Clock of I2S (in multiples of LRCLK) */ +/* Read bit-clock of I2S (in multiples of LRCLK) */ static inline unsigned get_bfs(struct i2s_dai *i2s) { struct samsung_i2s_priv *priv = i2s->priv; @@ -331,7 +331,7 @@ static inline unsigned get_bfs(struct i2s_dai *i2s) } } -/* Write Bit-Clock of I2S (in multiples of LRCLK) */ +/* Write bit-clock of I2S (in multiples of LRCLK) */ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) { struct samsung_i2s_priv *priv = i2s->priv; @@ -383,7 +383,7 @@ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) writel(mod, priv->addr + I2SMOD); } -/* Sample-Size */ +/* Sample size */ static inline int get_blc(struct i2s_dai *i2s) { int blc = readl(i2s->priv->addr + I2SMOD); @@ -397,7 +397,7 @@ static inline int get_blc(struct i2s_dai *i2s) } } -/* TX Channel Control */ +/* TX channel control */ static void i2s_txctrl(struct i2s_dai *i2s, int on) { struct samsung_i2s_priv *priv = i2s->priv; @@ -742,7 +742,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, switch (params_channels(params)) { case 6: val |= MOD_DC2_EN; - /* fall through */ + /* Fall through */ case 4: val |= MOD_DC1_EN; break; @@ -821,7 +821,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, return 0; } -/* We set constraints on the substream acc to the version of I2S */ +/* We set constraints on the substream according to the version of I2S */ static int i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -1056,7 +1056,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) pm_runtime_get_sync(dai->dev); - if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ + if (is_secondary(i2s)) { + /* If this is probe on the secondary DAI */ snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL); } else { snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, -- 2.7.4 From c7b52e5da4517c05d97eee3a7ad120d8580d218d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 10:37:47 +0100 Subject: [PATCH 07/16] ASoC: samsung: i2s: Convert to SPDX License Indentifier Replace GPL v2.0 license statements with SPDX license identifier. Change-Id: Iaf0ae489d7d55dc949ba70e956afe3642cdfaeb4 Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 84cfa2c..03fff1c 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1,13 +1,9 @@ -/* - * ALSA SoC Audio Layer - Samsung I2S Controller driver - * - * Copyright (c) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Audio Layer - Samsung I2S Controller driver +// +// Copyright (c) 2010 Samsung Electronics Co. Ltd. +// Jaswinder Singh #include #include -- 2.7.4 From 890838a2f4d0a07299e4622af9a21d21e8c66538 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 16:58:40 +0100 Subject: [PATCH 08/16] ASoC: samsung: i2s: Prevent potential NULL platform data dereference When np is NULL i2s_pdata could also be NULL but i2s_pdata is now being dereferenced without proper check. Fix this and shorten the error message so we don't exceed 80 characters limit. Change-Id: I5d5b14ff953d4a2617500f50e81eb459d56a6e4f Reported-by: Dan Carpenter Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 03fff1c..02472f5 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1369,7 +1369,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) struct i2s_dai *pri_dai, *sec_dai = NULL; struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; struct resource *res; - u32 regs_base, quirks = 0, idma_addr = 0; + u32 regs_base, idma_addr = 0; struct device_node *np = pdev->dev.of_node; const struct samsung_i2s_dai_data *i2s_dai_data; int num_dais, ret; @@ -1389,11 +1389,19 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - quirks = np ? i2s_dai_data->quirks : i2s_pdata->type.quirks; - num_dais = (quirks & QUIRK_SEC_DAI) ? 2 : 1; + if (np) { + priv->quirks = i2s_dai_data->quirks; + } else { + if (!i2s_pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -EINVAL; + } + priv->quirks = i2s_pdata->type.quirks; + } + + num_dais = (priv->quirks & QUIRK_SEC_DAI) ? 2 : 1; priv->pdev = pdev; priv->variant_regs = i2s_dai_data->i2s_variant_regs; - priv->quirks = quirks; ret = i2s_alloc_dais(priv, i2s_dai_data, num_dais); if (ret < 0) @@ -1405,11 +1413,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) spin_lock_init(&priv->pcm_lock); if (!np) { - if (i2s_pdata == NULL) { - dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n"); - return -EINVAL; - } - pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback; pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture; pri_dai->filter = i2s_pdata->dma_filter; @@ -1418,7 +1421,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) } else { if (of_property_read_u32(np, "samsung,idma-addr", &idma_addr)) { - if (quirks & QUIRK_SUPPORTS_IDMA) { + if (priv->quirks & QUIRK_SUPPORTS_IDMA) { dev_info(&pdev->dev, "idma address is not"\ "specified"); } @@ -1451,7 +1454,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai->dma_capture.addr_width = 4; pri_dai->priv = priv; - if (quirks & QUIRK_PRI_6CHAN) + if (priv->quirks & QUIRK_PRI_6CHAN) pri_dai->drv->playback.channels_max = 6; ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter, @@ -1459,7 +1462,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (ret < 0) goto err_disable_clk; - if (quirks & QUIRK_SEC_DAI) { + if (priv->quirks & QUIRK_SEC_DAI) { sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1]; sec_dai->dma_playback.addr = regs_base + I2STXDS; -- 2.7.4 From 88f9017acba5b213d082eda016e84f1c53cf85f8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 17:00:11 +0100 Subject: [PATCH 09/16] ASoC: samsung: odroid: Ensure proper sample rate on pri/sec PCM Currently when playing sound with different sample rates actual sample rate will be determined by audio stream which starts first on either primary or secondary PCM. The audio root clock will be configured appropriately only for the first stream. As the hardware is limited to same sample rate on both interfaces we need to disallow streams with different sample rates. It is done by this patch by returning error in FE hw_params if there is already active stream running with different sample rate. Change-Id: I643d02d38acf20a7711ba5930e6bceceeaafc087 Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 18bb3bf..941e8c3 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -20,6 +20,11 @@ struct odroid_priv { struct snd_soc_card card; struct clk *clk_i2s_bus; struct clk *sclk_i2s; + + /* Spinlock protecting fields below */ + spinlock_t lock; + unsigned int be_sample_rate; + bool be_active; }; static int odroid_card_fe_startup(struct snd_pcm_substream *substream) @@ -31,8 +36,25 @@ static int odroid_card_fe_startup(struct snd_pcm_substream *substream) return 0; } +static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->be_active && priv->be_sample_rate != params_rate(params)) + ret = -EINVAL; + spin_unlock_irqrestore(&priv->lock, flags); + + return ret; +} + static const struct snd_soc_ops odroid_card_fe_ops = { .startup = odroid_card_fe_startup, + .hw_params = odroid_card_fe_hw_params, }; static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, @@ -41,6 +63,7 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned int pll_freq, rclk_freq, rfs; + unsigned long flags; int ret; switch (params_rate(params)) { @@ -87,11 +110,43 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, return ret; } + spin_lock_irqsave(&priv->lock, flags); + priv->be_sample_rate = params_rate(params); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + priv->be_active = true; + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + priv->be_active = false; + break; + } + + spin_unlock_irqrestore(&priv->lock, flags); + return 0; } static const struct snd_soc_ops odroid_card_be_ops = { .hw_params = odroid_card_be_hw_params, + .trigger = odroid_card_be_trigger, }; static struct snd_soc_dai_link odroid_card_dais[] = { @@ -150,6 +205,7 @@ static int odroid_audio_probe(struct platform_device *pdev) card->owner = THIS_MODULE; card->fully_routed = true; + spin_lock_init(&priv->lock); snd_soc_card_set_drvdata(card, priv); ret = snd_soc_of_parse_card_name(card, "model"); -- 2.7.4 From 769d3be463ba1fe1cf7ef8b59e8e969e00cd7efc Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 15 Feb 2019 13:04:22 +0100 Subject: [PATCH 10/16] ASoC: samsung: odroid: Add missing DAPM routes With old DTS there will be missing DAPM routes linking BE with CODECs. Add those routes in the card driver so sound works properly on Odroid XU3/4 also without DTS updates enabling the secondary PCM. Change-Id: I0a2a8e59859cdaf46da0563e30278dc9a8fe2376 Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 941e8c3..5b2bcd1 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -149,6 +149,12 @@ static const struct snd_soc_ops odroid_card_be_ops = { .trigger = odroid_card_be_trigger, }; +/* DAPM routes for backward compatibility with old DTS */ +static const struct snd_soc_dapm_route odroid_dapm_routes[] = { + { "I2S Playback", NULL, "Mixer DAI TX" }, + { "HiFi Playback", NULL, "Mixer DAI TX" }, +}; + static struct snd_soc_dai_link odroid_card_dais[] = { { /* Primary FE <-> BE link */ @@ -237,11 +243,15 @@ static int odroid_audio_probe(struct platform_device *pdev) /* * For backwards compatibility create the secondary CPU DAI link only * if there are 2 CPU DAI entries in the cpu sound-dai property in DT. + * Also add required DAPM routes not available in old DTS. */ num_pcms = of_count_phandle_with_args(cpu, "sound-dai", "#sound-dai-cells"); - if (num_pcms == 1) + if (num_pcms == 1) { + card->dapm_routes = odroid_dapm_routes; + card->num_dapm_routes = ARRAY_SIZE(odroid_dapm_routes); card->num_links--; + } for (i = 0; i < num_pcms; i++, link += 2) { ret = of_parse_phandle_with_args(cpu, "sound-dai", -- 2.7.4 From d34667c7f4ab779cece08f75c44b0a832c04be0c Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 19 Feb 2019 16:19:40 +0100 Subject: [PATCH 11/16] ASoC: samsung: i2s: Fix secondary platform device unregistration This fixes unregistration of the secondary platform device so all resources are properly released. Additionally the removal sequence is corrected so it is in reverse order comparing to probe sequence. The test against NULL priv->pdev_sec is removed as it is not necessary. Change-Id: If325e11b4109fbc61fbb2df3ac012f2c1e9f0cb5 Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 02472f5..cd92bb6 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1359,11 +1359,10 @@ static int i2s_create_secondary_device(struct samsung_i2s_priv *priv) static void i2s_delete_secondary_device(struct samsung_i2s_priv *priv) { - if (priv->pdev_sec) { - platform_device_del(priv->pdev_sec); - priv->pdev_sec = NULL; - } + platform_device_unregister(priv->pdev_sec); + priv->pdev_sec = NULL; } + static int samsung_i2s_probe(struct platform_device *pdev) { struct i2s_dai *pri_dai, *sec_dai = NULL; @@ -1487,14 +1486,14 @@ static int samsung_i2s_probe(struct platform_device *pdev) sec_dai->filter, "tx-sec", NULL, &pdev->dev); if (ret < 0) - goto err_disable_clk; + goto err_del_sec; } if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { dev_err(&pdev->dev, "Unable to configure gpio\n"); ret = -EINVAL; - goto err_disable_clk; + goto err_del_sec; } dev_set_drvdata(&pdev->dev, priv); @@ -1503,7 +1502,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) &samsung_i2s_component, priv->dai_drv, num_dais); if (ret < 0) - goto err_disable_clk; + goto err_del_sec; pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); @@ -1518,9 +1517,10 @@ static int samsung_i2s_probe(struct platform_device *pdev) err_disable_pm: pm_runtime_disable(&pdev->dev); +err_del_sec: + i2s_delete_secondary_device(priv); err_disable_clk: clk_disable_unprepare(priv->clk); - i2s_delete_secondary_device(priv); return ret; } @@ -1536,9 +1536,10 @@ static int samsung_i2s_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); i2s_unregister_clock_provider(priv); + i2s_delete_secondary_device(priv); clk_disable_unprepare(priv->clk); + pm_runtime_put_noidle(&pdev->dev); - i2s_delete_secondary_device(priv); return 0; } -- 2.7.4 From 8ca75efad82ff82b0c352f04f39db9b9c6e0ff8b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 19 Feb 2019 16:19:41 +0100 Subject: [PATCH 12/16] ASoC: samsung: i2s: Fix multiple "IIS multi" devices initialization On some SoCs (e.g. Exynos5433) there are multiple "IIS multi audio interfaces" and the driver will try to register there multiple times same platform device for the secondary FIFO, which of course fails miserably. To fix this we derive the secondary platform device name from the primary device name. The secondary device name will now be -sec instead of fixed "samsung-i2s-sec". The fixed platform_device_id table entry is removed as the secondary device name is now dynamic and device/driver matching is done through driver_override. Change-Id: I49ed3e20279af198cdce11c08cc11bd6536dddad Reported-by: Marek Szyprowski Suggested-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 50 ++++++++++++++++++++++++++++++---------------- sound/soc/samsung/odroid.c | 2 +- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index cd92bb6..4231001 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1339,20 +1339,35 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) /* Create platform device for the secondary PCM */ static int i2s_create_secondary_device(struct samsung_i2s_priv *priv) { - struct platform_device *pdev; + struct platform_device *pdev_sec; + const char *devname; int ret; - pdev = platform_device_register_simple("samsung-i2s-sec", -1, NULL, 0); - if (!pdev) + devname = devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, "%s-sec", + dev_name(&priv->pdev->dev)); + if (!devname) return -ENOMEM; - ret = device_attach(&pdev->dev); + pdev_sec = platform_device_alloc(devname, -1); + if (!pdev_sec) + return -ENOMEM; + + pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); + + ret = platform_device_add(pdev_sec); if (ret < 0) { - dev_info(&pdev->dev, "device_attach() failed\n"); + platform_device_put(pdev_sec); return ret; } - priv->pdev_sec = pdev; + ret = device_attach(&pdev_sec->dev); + if (ret <= 0) { + platform_device_unregister(priv->pdev_sec); + dev_info(&pdev_sec->dev, "device_attach() failed\n"); + return ret; + } + + priv->pdev_sec = pdev_sec; return 0; } @@ -1367,22 +1382,25 @@ static int samsung_i2s_probe(struct platform_device *pdev) { struct i2s_dai *pri_dai, *sec_dai = NULL; struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; - struct resource *res; u32 regs_base, idma_addr = 0; struct device_node *np = pdev->dev.of_node; const struct samsung_i2s_dai_data *i2s_dai_data; - int num_dais, ret; + const struct platform_device_id *id; struct samsung_i2s_priv *priv; + struct resource *res; + int num_dais, ret; - if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { i2s_dai_data = of_device_get_match_data(&pdev->dev); - else - i2s_dai_data = (struct samsung_i2s_dai_data *) - platform_get_device_id(pdev)->driver_data; + } else { + id = platform_get_device_id(pdev); - /* Nothing to do if it is the secondary device probe */ - if (!i2s_dai_data) - return 0; + /* Nothing to do if it is the secondary device probe */ + if (!id) + return 0; + + i2s_dai_data = (struct samsung_i2s_dai_data *)id->driver_data; + } priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -1637,8 +1655,6 @@ static const struct platform_device_id samsung_i2s_driver_ids[] = { { .name = "samsung-i2s", .driver_data = (kernel_ulong_t)&i2sv3_dai_type, - }, { - .name = "samsung-i2s-sec", }, {}, }; diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 5b2bcd1..bd2c516 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -185,7 +185,7 @@ static struct snd_soc_dai_link odroid_card_dais[] = { .ops = &odroid_card_fe_ops, .name = "Secondary", .stream_name = "Secondary", - .platform_name = "samsung-i2s-sec", + .platform_name = "3830000.i2s-sec", .dynamic = 1, .dpcm_playback = 1, } -- 2.7.4 From d78ff27418486a7462ea27f1ad5c86ca72556431 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 20 Feb 2019 12:06:07 +0100 Subject: [PATCH 13/16] ASoC: samsung: odroid: Fix of_node refcount unbalance In odroid_audio_probe() some OF nodes are left without reference count decrease after use. Fix it by ensuring required of_node_calls() are done before exiting probe. Change-Id: Ifbcb6294331acc59028e675d8ab1143394508d66 Reported-by: Takashi Iwai Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index bd2c516..c3b0f6c 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -257,27 +257,31 @@ static int odroid_audio_probe(struct platform_device *pdev) ret = of_parse_phandle_with_args(cpu, "sound-dai", "#sound-dai-cells", i, &args); if (ret < 0) - return ret; + break; if (!args.np) { dev_err(dev, "sound-dai property parse error: %d\n", ret); - return -EINVAL; + ret = -EINVAL; + break; } ret = snd_soc_get_dai_name(&args, &link->cpu_dai_name); of_node_put(args.np); if (ret < 0) - return ret; + break; } + if (ret == 0) + cpu_dai = of_parse_phandle(cpu, "sound-dai", 0); - cpu_dai = of_parse_phandle(cpu, "sound-dai", 0); of_node_put(cpu); of_node_put(codec); + if (ret < 0) + return ret; ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link); if (ret < 0) - goto err_put_codec_n; + goto err_put_cpu_dai; /* Set capture capability only for boards with the MAX98090 CODEC */ if (codec_link->num_codecs > 1) { @@ -288,7 +292,7 @@ static int odroid_audio_probe(struct platform_device *pdev) priv->sclk_i2s = of_clk_get_by_name(cpu_dai, "i2s_opclk1"); if (IS_ERR(priv->sclk_i2s)) { ret = PTR_ERR(priv->sclk_i2s); - goto err_put_codec_n; + goto err_put_cpu_dai; } priv->clk_i2s_bus = of_clk_get_by_name(cpu_dai, "iis"); @@ -310,7 +314,8 @@ err_put_clk_i2s: clk_put(priv->clk_i2s_bus); err_put_sclk: clk_put(priv->sclk_i2s); -err_put_codec_n: +err_put_cpu_dai: + of_node_put(cpu_dai); snd_soc_of_put_dai_link_codecs(codec_link); return ret; } -- 2.7.4 From 48e666b5772d8c5e9bc4423474cccc75270fec61 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 21 Feb 2019 10:42:28 +0100 Subject: [PATCH 14/16] ASoC: samsung: odroid: Prevent uninitialized variable use MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This addresses an issue pointed out by compiler warning: sound/soc/samsung/odroid.c: In function ‘odroid_audio_probe’: sound/soc/samsung/odroid.c:298:22: warning: ‘cpu_dai’ may be used uninitialized in this function [-Wmaybe-uninitialized] priv->clk_i2s_bus = of_clk_get_by_name(cpu_dai, "iis"); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Change-Id: I39c6dd0a1aa5ec68bfc17c895988c21a1a34733e Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index c3b0f6c..694512f 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -194,7 +194,8 @@ static struct snd_soc_dai_link odroid_card_dais[] = { static int odroid_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *cpu, *cpu_dai, *codec; + struct device_node *cpu_dai = NULL; + struct device_node *cpu, *codec; struct odroid_priv *priv; struct snd_soc_card *card; struct snd_soc_dai_link *link, *codec_link; @@ -271,8 +272,11 @@ static int odroid_audio_probe(struct platform_device *pdev) if (ret < 0) break; } - if (ret == 0) + if (ret == 0) { cpu_dai = of_parse_phandle(cpu, "sound-dai", 0); + if (!cpu_dai) + ret = -EINVAL; + } of_node_put(cpu); of_node_put(codec); -- 2.7.4 From 509991a0d84159f4ff7cbe0d00188156243fa9f2 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 14 Feb 2019 16:45:55 +0100 Subject: [PATCH 15/16] ASoC: dmaengine: Remove unused SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME flag There is now no users of this flag so remove it together with related code. The chan_name field of snd_dmaengine_dai_dma_data data structure is not removed as it is still in use by the PXA platform. Change-Id: Ia8bb6022ce7c5e85abb7c5410459130666785f45 Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 4 ---- sound/soc/soc-generic-dmaengine-pcm.c | 21 ++++----------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 67be244..3e43b89 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -107,10 +107,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data( * playback. */ #define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) -/* - * The PCM streams have custom channel names specified. - */ -#define SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME BIT(4) /** * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 06d4dfc..8a55d3f 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -263,7 +263,6 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); const struct snd_dmaengine_pcm_config *config = pcm->config; struct device *dev = rtd->platform->dev; - struct snd_dmaengine_dai_dma_data *dma_data; struct snd_pcm_substream *substream; size_t prealloc_buffer_size; size_t max_buffer_size; @@ -283,19 +282,9 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) if (!substream) continue; - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - if (!pcm->chan[i] && - ((pcm->flags & SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME) || - (config && config->chan_names[i]))) { - const char *chan_name = dma_data->chan_name; - - if (config && config->chan_names[i]) - chan_name = config->chan_names[i]; - + if (!pcm->chan[i] && config && config->chan_names[i]) pcm->chan[i] = dma_request_slave_channel(dev, - chan_name); - } + config->chan_names[i]); if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) { pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, @@ -365,10 +354,8 @@ static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, const char *name; struct dma_chan *chan; - if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | - SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || - (!dev->of_node && !(config && config->dma_dev && - config->dma_dev->of_node))) + if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || (!dev->of_node && + !(config && config->dma_dev && config->dma_dev->of_node))) return 0; if (config && config->dma_dev) { -- 2.7.4 From 132495eca68055477c61edc9a98bdbe526baa004 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 27 Feb 2019 11:47:39 +0100 Subject: [PATCH 16/16] LOCAL: ASoC: temporary workaround for i2s/prepare_lock deadlock This reverts commit 00ffa8a3b1a60a89ab0ef5ae1d8e41269c30a3bd. Change-Id: I396b1250a748fdb8219abf6d0bf71c5fab119658 Signed-off-by: Marek Szyprowski --- sound/soc/samsung/i2s.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 4231001..d3d250e 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -618,11 +618,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, writel(mod, priv->addr + I2SMOD); spin_unlock_irqrestore(&priv->lock, flags); done: - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); return 0; err: - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); return ret; } @@ -706,7 +706,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) if (any_active(i2s) && ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { spin_unlock_irqrestore(&priv->lock, flags); - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); dev_err(&i2s->pdev->dev, "%s:%d Other DAI busy\n", __func__, __LINE__); return -EAGAIN; @@ -716,7 +716,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) mod |= tmp; writel(mod, priv->addr + I2SMOD); spin_unlock_irqrestore(&priv->lock, flags); - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); return 0; } @@ -867,7 +867,7 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, spin_unlock_irqrestore(&priv->pcm_lock, flags); - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); } static int config_setup(struct i2s_dai *i2s) @@ -973,7 +973,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, } spin_unlock_irqrestore(&priv->lock, flags); - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); break; } @@ -991,13 +991,13 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai, 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); + pm_runtime_put_sync(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); + pm_runtime_put_sync(dai->dev); break; default: dev_err(&i2s->pdev->dev, @@ -1083,7 +1083,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); + pm_runtime_put_sync(dai->dev); return 0; } @@ -1104,7 +1104,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) } } - pm_runtime_put(dai->dev); + pm_runtime_put_sync(dai->dev); return 0; } -- 2.7.4