linux-samsung-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Runtime PM support for Exynos I2S driver
       [not found] <CGME20161229113425eucas1p2f95b915a9a66df3e3ff8431b5625b926@eucas1p2.samsung.com>
@ 2016-12-29 11:34 ` Marek Szyprowski
       [not found]   ` <CGME20161229113425eucas1p2600ba7e4337e90f65c0bc60bb4a9c2ec@eucas1p2.samsung.com>
                     ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Marek Szyprowski @ 2016-12-29 11:34 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Mark Brown, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

Exynos I2S audio controller was missing proper runtime PM implementation
and this patchset addresses this issue.

This patchset is a another step to add support for audio power domain on
Exynos5 SoCs.

Audio power domain on Exynos5 SoCs contains following hardware modules:
1. clock controller
2. pin controller
3. PL330 DMA controller
4. I2S audio controller

The other patches related to enabling full support for audio power domain
can be found here:
1. PL330 ADMA controller non-irqsafe runtime PM:
   https://www.spinics.net/lists/arm-kernel/msg550008.html
2. Runtime PM for clock controllers (Exynos Audio subsystem will be added
   in v4 soon): https://www.spinics.net/lists/arm-kernel/msg538122.html
3. Runtime PM support for pin controller:
   https://www.spinics.net/lists/linux-samsung-soc/msg56674.html

Patches are based on linux-next from 2016.12.24. Tested on Odroid U3
(Exynos4412), Odroid XU3 (Exynos5422) and TM2 (Exynos5433) boards.

Best regards
Marek Szyprowski
Samsung R&D Institute Poland


Patch summary:

Marek Szyprowski (5):
  ASoC: samsung: i2s: Remove virtual device for secondary DAI
  ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device
  ASoC: samsung: i2s: Move saving and restoring regs to runtime pm
    operations
  ASoC: samsung: i2s: Let runtime PM operations to control op_clk too
  ASoC: samsung: i2s: Provide I2S device for registered clocks

 sound/soc/samsung/i2s.c | 193 +++++++++++++++++++++++-------------------------
 1 file changed, 92 insertions(+), 101 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] ASoC: samsung: i2s: Remove virtual device for secondary DAI
       [not found]   ` <CGME20161229113425eucas1p2600ba7e4337e90f65c0bc60bb4a9c2ec@eucas1p2.samsung.com>
@ 2016-12-29 11:34     ` Marek Szyprowski
  2016-12-31 18:31       ` Mark Brown
  2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Remove virtual device for secondary DAI" to the asoc tree Mark Brown
  0 siblings, 2 replies; 12+ messages in thread
From: Marek Szyprowski @ 2016-12-29 11:34 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Mark Brown, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

For some unknown (maybe historical?) reasons support for secondary I2S DAI
was implemented by adding additional virtual platform device, which was
then probed again with the main I2S driver. This pattern is really hard
to follow and provides no benefits, so lets remove this hack and register
both DAIs during linear probe of Exynos I2S controller driver.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 sound/soc/samsung/i2s.c | 102 ++++++++++++------------------------------------
 1 file changed, 26 insertions(+), 76 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index e00974bc5616..ce4e70ef5568 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -34,11 +34,6 @@
 
 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
 
-enum samsung_dai_type {
-	TYPE_PRI,
-	TYPE_SEC,
-};
-
 struct samsung_i2s_variant_regs {
 	unsigned int	bfs_off;
 	unsigned int	rfs_off;
@@ -54,7 +49,6 @@ struct samsung_i2s_variant_regs {
 };
 
 struct samsung_i2s_dai_data {
-	int dai_type;
 	u32 quirks;
 	const struct samsung_i2s_variant_regs *i2s_variant_regs;
 };
@@ -1066,7 +1060,6 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
 static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 {
 	struct i2s_dai *i2s;
-	int ret;
 
 	i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
 	if (i2s == NULL)
@@ -1091,28 +1084,10 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 		i2s->i2s_dai_drv.capture.channels_max = 2;
 		i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
 		i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
-		dev_set_drvdata(&i2s->pdev->dev, i2s);
-	} else {	/* Create a new platform_device for Secondary */
-		i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
-		if (!i2s->pdev)
-			return NULL;
-
-		i2s->pdev->dev.parent = &pdev->dev;
-
-		platform_set_drvdata(i2s->pdev, i2s);
-		ret = platform_device_add(i2s->pdev);
-		if (ret < 0)
-			return NULL;
 	}
-
 	return i2s;
 }
 
-static void i2s_free_sec_dai(struct i2s_dai *i2s)
-{
-	platform_device_del(i2s->pdev);
-}
-
 #ifdef CONFIG_PM
 static int i2s_runtime_suspend(struct device *dev)
 {
@@ -1231,22 +1206,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		i2s_dai_data = (struct samsung_i2s_dai_data *)
 				platform_get_device_id(pdev)->driver_data;
 
-	/* Call during the secondary interface registration */
-	if (i2s_dai_data->dai_type == TYPE_SEC) {
-		sec_dai = dev_get_drvdata(&pdev->dev);
-		if (!sec_dai) {
-			dev_err(&pdev->dev, "Unable to get drvdata\n");
-			return -EFAULT;
-		}
-		ret = samsung_asoc_dma_platform_register(&pdev->dev,
-					sec_dai->filter, "tx-sec", NULL);
-		if (ret != 0)
-			return ret;
-
-		return devm_snd_soc_register_component(&sec_dai->pdev->dev,
-						&samsung_i2s_component,
-						&sec_dai->i2s_dai_drv, 1);
-	}
 
 	pri_dai = i2s_alloc_dai(pdev, false);
 	if (!pri_dai) {
@@ -1318,6 +1277,12 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_disable_clk;
 
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					&samsung_i2s_component,
+					&pri_dai->i2s_dai_drv, 1);
+	if (ret < 0)
+		goto err_disable_clk;
+
 	if (quirks & QUIRK_SEC_DAI) {
 		sec_dai = i2s_alloc_dai(pdev, true);
 		if (!sec_dai) {
@@ -1342,6 +1307,17 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		sec_dai->idma_playback.addr = idma_addr;
 		sec_dai->pri_dai = pri_dai;
 		pri_dai->sec_dai = sec_dai;
+
+		ret = samsung_asoc_dma_platform_register(&pdev->dev,
+					sec_dai->filter, "tx-sec", NULL);
+		if (ret < 0)
+			goto err_disable_clk;
+
+		ret = devm_snd_soc_register_component(&pdev->dev,
+						&samsung_i2s_component,
+						&sec_dai->i2s_dai_drv, 1);
+		if (ret < 0)
+			goto err_disable_clk;
 	}
 
 	if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
@@ -1350,11 +1326,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		goto err_disable_clk;
 	}
 
-	ret = devm_snd_soc_register_component(&pri_dai->pdev->dev,
-					&samsung_i2s_component,
-					&pri_dai->i2s_dai_drv, 1);
-	if (ret < 0)
-		goto err_free_dai;
+	dev_set_drvdata(&pdev->dev, pri_dai);
 
 
 	pm_runtime_enable(&pdev->dev);
@@ -1364,9 +1336,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		return 0;
 
 	pm_runtime_disable(&pdev->dev);
-err_free_dai:
-	if (sec_dai)
-		i2s_free_sec_dai(sec_dai);
 err_disable_clk:
 	clk_disable_unprepare(pri_dai->clk);
 	return ret;
@@ -1374,25 +1343,18 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 
 static int samsung_i2s_remove(struct platform_device *pdev)
 {
-	struct i2s_dai *i2s, *other;
+	struct i2s_dai *pri_dai, *sec_dai;
 
-	i2s = dev_get_drvdata(&pdev->dev);
-	other = get_other_dai(i2s);
+	pri_dai = dev_get_drvdata(&pdev->dev);
+	sec_dai = pri_dai->sec_dai;
 
-	if (other) {
-		other->pri_dai = NULL;
-		other->sec_dai = NULL;
-	} else {
-		pm_runtime_disable(&pdev->dev);
-	}
+	pri_dai->sec_dai = NULL;
+	sec_dai->pri_dai = NULL;
 
-	if (!is_secondary(i2s)) {
-		i2s_unregister_clock_provider(pdev);
-		clk_disable_unprepare(i2s->clk);
-	}
+	pm_runtime_disable(&pdev->dev);
 
-	i2s->pri_dai = NULL;
-	i2s->sec_dai = NULL;
+	i2s_unregister_clock_provider(pdev);
+	clk_disable_unprepare(pri_dai->clk);
 
 	return 0;
 }
@@ -1454,49 +1416,37 @@ static int samsung_i2s_remove(struct platform_device *pdev)
 };
 
 static const struct samsung_i2s_dai_data i2sv3_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_NO_MUXPSR,
 	.i2s_variant_regs = &i2sv3_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv5_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
 			QUIRK_SUPPORTS_IDMA,
 	.i2s_variant_regs = &i2sv3_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv6_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
 			QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA,
 	.i2s_variant_regs = &i2sv6_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv7_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
 			QUIRK_SUPPORTS_TDM,
 	.i2s_variant_regs = &i2sv7_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR,
 	.i2s_variant_regs = &i2sv5_i2s1_regs,
 };
 
-static const struct samsung_i2s_dai_data samsung_dai_type_sec = {
-	.dai_type = TYPE_SEC,
-};
-
 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",
-		.driver_data    = (kernel_ulong_t)&samsung_dai_type_sec,
 	},
 	{},
 };
-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 2/5] ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device
       [not found]   ` <CGME20161229113426eucas1p2bc05fb68efd45e6af3ae7a2b8be5e481@eucas1p2.samsung.com>
@ 2016-12-29 11:34     ` Marek Szyprowski
  2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device" to the asoc tree Mark Brown
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Szyprowski @ 2016-12-29 11:34 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Mark Brown, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

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 <m.szyprowski@samsung.com>
---
 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;
 }
-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 3/5] ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations
       [not found]   ` <CGME20161229113427eucas1p166db5239bd7b17ebaba8b248f06cffe8@eucas1p1.samsung.com>
@ 2016-12-29 11:34     ` Marek Szyprowski
  2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations" to the asoc tree Mark Brown
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Szyprowski @ 2016-12-29 11:34 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Mark Brown, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

This patch moves saving and restoring I2S registers to runtime PM
operations, what prepares the driver to operate with audio power domain.
When support for audio power domain is enabled and the domain is being
turned off, the I2S module will loose its context (registers), so runtime
callbacks have to handle it. System sleep suspend/resume operation are
implemented on top of runtime PM operations with generic
pm_runtime_force_suspend/resume helpers.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 sound/soc/samsung/i2s.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 2aa800b99938..47a5650aaa66 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -983,24 +983,12 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai,
 #ifdef CONFIG_PM
 static int i2s_suspend(struct snd_soc_dai *dai)
 {
-	struct i2s_dai *i2s = to_info(dai);
-
-	i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
-	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
-	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
-
-	return 0;
+	return pm_runtime_force_suspend(dai->dev);
 }
 
 static int i2s_resume(struct snd_soc_dai *dai)
 {
-	struct i2s_dai *i2s = to_info(dai);
-
-	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
-	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
-	writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
-
-	return 0;
+	return pm_runtime_force_resume(dai->dev);
 }
 #else
 #define i2s_suspend NULL
@@ -1129,6 +1117,10 @@ static int i2s_runtime_suspend(struct device *dev)
 {
 	struct i2s_dai *i2s = dev_get_drvdata(dev);
 
+	i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
+	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
+	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
+
 	clk_disable_unprepare(i2s->clk);
 
 	return 0;
@@ -1140,6 +1132,10 @@ static int i2s_runtime_resume(struct device *dev)
 
 	clk_prepare_enable(i2s->clk);
 
+	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
+	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
+	writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
+
 	return 0;
 }
 #endif /* CONFIG_PM */
@@ -1516,6 +1512,8 @@ static int samsung_i2s_remove(struct platform_device *pdev)
 static const struct dev_pm_ops samsung_i2s_pm = {
 	SET_RUNTIME_PM_OPS(i2s_runtime_suspend,
 				i2s_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
 };
 
 static struct platform_driver samsung_i2s_driver = {
-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 4/5] ASoC: samsung: i2s: Let runtime PM operations to control op_clk too
       [not found]   ` <CGME20161229113427eucas1p20e91adee0da640e2a5847d53f3c6e443@eucas1p2.samsung.com>
@ 2016-12-29 11:34     ` Marek Szyprowski
  2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Let runtime PM operations to control op_clk too" to the asoc tree Mark Brown
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Szyprowski @ 2016-12-29 11:34 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Mark Brown, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

This patch adds handling of parent operational clock to runtime PM
callbacks. This way it is ensured that when I2S module is in runtime
suspended state, all its parent clocks are disabled and unprepared.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 sound/soc/samsung/i2s.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 47a5650aaa66..07728b93f56e 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -546,6 +546,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
 
 			if (WARN_ON(IS_ERR(i2s->op_clk))) {
 				ret = PTR_ERR(i2s->op_clk);
+				i2s->op_clk = NULL;
 				goto err;
 			}
 
@@ -1121,6 +1122,8 @@ static int i2s_runtime_suspend(struct device *dev)
 	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
 	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
 
+	if (i2s->op_clk)
+		clk_disable_unprepare(i2s->op_clk);
 	clk_disable_unprepare(i2s->clk);
 
 	return 0;
@@ -1131,6 +1134,8 @@ static int i2s_runtime_resume(struct device *dev)
 	struct i2s_dai *i2s = dev_get_drvdata(dev);
 
 	clk_prepare_enable(i2s->clk);
+	if (i2s->op_clk)
+		clk_prepare_enable(i2s->op_clk);
 
 	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
 	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 5/5] ASoC: samsung: i2s: Provide I2S device for registered clocks
       [not found]   ` <CGME20161229113427eucas1p21ee586b73029410d0860a22ce4a21e0c@eucas1p2.samsung.com>
@ 2016-12-29 11:34     ` Marek Szyprowski
  2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Provide I2S device for registered clocks" to the asoc tree Mark Brown
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Szyprowski @ 2016-12-29 11:34 UTC (permalink / raw)
  To: alsa-devel, linux-samsung-soc
  Cc: Marek Szyprowski, Mark Brown, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

This patch adds pointer to I2S device to clk_register_* functions.
This in the future allow clock framework to ensure proper runtime state
of the I2S device during all operations on the clocks provided by I2S
module.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 sound/soc/samsung/i2s.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 07728b93f56e..d24b825dc298 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1191,13 +1191,13 @@ static int i2s_register_clock_provider(struct platform_device *pdev)
 		u32 val = readl(i2s->addr + I2SPSR);
 		writel(val | PSR_PSREN, i2s->addr + I2SPSR);
 
-		i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(NULL,
+		i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev,
 				"i2s_rclksrc", p_names, ARRAY_SIZE(p_names),
 				CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
 				i2s->addr + I2SMOD, reg_info->rclksrc_off,
 				1, 0, i2s->lock);
 
-		i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(NULL,
+		i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev,
 				"i2s_presc", "i2s_rclksrc",
 				CLK_SET_RATE_PARENT,
 				i2s->addr + I2SPSR, 8, 6, 0, i2s->lock);
@@ -1208,7 +1208,7 @@ static int i2s_register_clock_provider(struct platform_device *pdev)
 	of_property_read_string_index(dev->of_node,
 				"clock-output-names", 0, &clk_name[0]);
 
-	i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(NULL, clk_name[0],
+	i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, clk_name[0],
 				p_names[0], CLK_SET_RATE_PARENT,
 				i2s->addr + I2SMOD, reg_info->cdclkcon_off,
 				CLK_GATE_SET_TO_DISABLE, i2s->lock);
-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/5] ASoC: samsung: i2s: Remove virtual device for secondary DAI
  2016-12-29 11:34     ` [PATCH 1/5] ASoC: samsung: i2s: Remove virtual device for secondary DAI Marek Szyprowski
@ 2016-12-31 18:31       ` Mark Brown
  2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Remove virtual device for secondary DAI" to the asoc tree Mark Brown
  1 sibling, 0 replies; 12+ messages in thread
From: Mark Brown @ 2016-12-31 18:31 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: alsa-devel, linux-samsung-soc, Sylwester Nawrocki, Sangbeom Kim,
	Krzysztof Kozlowski, Bartlomiej Zolnierkiewicz, Inki Dae,
	Javier Martinez Canillas

[-- Attachment #1: Type: text/plain, Size: 549 bytes --]

On Thu, Dec 29, 2016 at 12:34:03PM +0100, Marek Szyprowski wrote:
> For some unknown (maybe historical?) reasons support for secondary I2S DAI
> was implemented by adding additional virtual platform device, which was
> then probed again with the main I2S driver. This pattern is really hard
> to follow and provides no benefits, so lets remove this hack and register
> both DAIs during linear probe of Exynos I2S controller driver.

It's historical, there used to be limitations that made it impossible to
register multiple devices to one DAI IIRC.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Applied "ASoC: samsung: i2s: Provide I2S device for registered clocks" to the asoc tree
  2016-12-29 11:34     ` [PATCH 5/5] ASoC: samsung: i2s: Provide I2S device for registered clocks Marek Szyprowski
@ 2016-12-31 19:19       ` Mark Brown
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2016-12-31 19:19 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Mark Brown, alsa-devel, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Sangbeom Kim, Krzysztof Kozlowski,
	Inki Dae, Javier Martinez Canillas

The patch

   ASoC: samsung: i2s: Provide I2S device for registered clocks

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 9b41da80e09128574f09bed8dc5a5fc6f72a8239 Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 29 Dec 2016 12:34:07 +0100
Subject: [PATCH] ASoC: samsung: i2s: Provide I2S device for registered clocks

This patch adds pointer to I2S device to clk_register_* functions.
This in the future allow clock framework to ensure proper runtime state
of the I2S device during all operations on the clocks provided by I2S
module.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/samsung/i2s.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index b2b9ee4a177a..2a5b92c672fb 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1191,13 +1191,13 @@ static int i2s_register_clock_provider(struct platform_device *pdev)
 		u32 val = readl(i2s->addr + I2SPSR);
 		writel(val | PSR_PSREN, i2s->addr + I2SPSR);
 
-		i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(NULL,
+		i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev,
 				"i2s_rclksrc", p_names, ARRAY_SIZE(p_names),
 				CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
 				i2s->addr + I2SMOD, reg_info->rclksrc_off,
 				1, 0, i2s->lock);
 
-		i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(NULL,
+		i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev,
 				"i2s_presc", "i2s_rclksrc",
 				CLK_SET_RATE_PARENT,
 				i2s->addr + I2SPSR, 8, 6, 0, i2s->lock);
@@ -1208,7 +1208,7 @@ static int i2s_register_clock_provider(struct platform_device *pdev)
 	of_property_read_string_index(dev->of_node,
 				"clock-output-names", 0, &clk_name[0]);
 
-	i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(NULL, clk_name[0],
+	i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, clk_name[0],
 				p_names[0], CLK_SET_RATE_PARENT,
 				i2s->addr + I2SMOD, reg_info->cdclkcon_off,
 				CLK_GATE_SET_TO_DISABLE, i2s->lock);
-- 
2.11.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Applied "ASoC: samsung: i2s: Let runtime PM operations to control op_clk too" to the asoc tree
  2016-12-29 11:34     ` [PATCH 4/5] ASoC: samsung: i2s: Let runtime PM operations to control op_clk too Marek Szyprowski
@ 2016-12-31 19:19       ` Mark Brown
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2016-12-31 19:19 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Mark Brown, alsa-devel, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Sangbeom Kim, Krzysztof Kozlowski,
	Inki Dae, Javier Martinez Canillas

The patch

   ASoC: samsung: i2s: Let runtime PM operations to control op_clk too

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From afa99da863e8e00efd8ce2f8840ed31d50abb889 Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 29 Dec 2016 12:34:06 +0100
Subject: [PATCH] ASoC: samsung: i2s: Let runtime PM operations to control
 op_clk too

This patch adds handling of parent operational clock to runtime PM
callbacks. This way it is ensured that when I2S module is in runtime
suspended state, all its parent clocks are disabled and unprepared.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/samsung/i2s.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index df3fae862665..b2b9ee4a177a 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -546,6 +546,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
 
 			if (WARN_ON(IS_ERR(i2s->op_clk))) {
 				ret = PTR_ERR(i2s->op_clk);
+				i2s->op_clk = NULL;
 				goto err;
 			}
 
@@ -1121,6 +1122,8 @@ static int i2s_runtime_suspend(struct device *dev)
 	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
 	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
 
+	if (i2s->op_clk)
+		clk_disable_unprepare(i2s->op_clk);
 	clk_disable_unprepare(i2s->clk);
 
 	return 0;
@@ -1131,6 +1134,8 @@ static int i2s_runtime_resume(struct device *dev)
 	struct i2s_dai *i2s = dev_get_drvdata(dev);
 
 	clk_prepare_enable(i2s->clk);
+	if (i2s->op_clk)
+		clk_prepare_enable(i2s->op_clk);
 
 	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
 	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
-- 
2.11.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Applied "ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations" to the asoc tree
  2016-12-29 11:34     ` [PATCH 3/5] ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations Marek Szyprowski
@ 2016-12-31 19:19       ` Mark Brown
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2016-12-31 19:19 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Mark Brown, alsa-devel, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Sangbeom Kim, Krzysztof Kozlowski,
	Inki Dae, Javier Martinez Canillas

The patch

   ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From e7e52dfc68a2160570c7ec51415e391961160edb Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 29 Dec 2016 12:34:05 +0100
Subject: [PATCH] ASoC: samsung: i2s: Move saving and restoring regs to runtime
 pm operations

This patch moves saving and restoring I2S registers to runtime PM
operations, what prepares the driver to operate with audio power domain.
When support for audio power domain is enabled and the domain is being
turned off, the I2S module will loose its context (registers), so runtime
callbacks have to handle it. System sleep suspend/resume operation are
implemented on top of runtime PM operations with generic
pm_runtime_force_suspend/resume helpers.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/samsung/i2s.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 8d8965e7107c..df3fae862665 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -983,24 +983,12 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
 #ifdef CONFIG_PM
 static int i2s_suspend(struct snd_soc_dai *dai)
 {
-	struct i2s_dai *i2s = to_info(dai);
-
-	i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
-	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
-	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
-
-	return 0;
+	return pm_runtime_force_suspend(dai->dev);
 }
 
 static int i2s_resume(struct snd_soc_dai *dai)
 {
-	struct i2s_dai *i2s = to_info(dai);
-
-	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
-	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
-	writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
-
-	return 0;
+	return pm_runtime_force_resume(dai->dev);
 }
 #else
 #define i2s_suspend NULL
@@ -1129,6 +1117,10 @@ static int i2s_runtime_suspend(struct device *dev)
 {
 	struct i2s_dai *i2s = dev_get_drvdata(dev);
 
+	i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
+	i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
+	i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
+
 	clk_disable_unprepare(i2s->clk);
 
 	return 0;
@@ -1140,6 +1132,10 @@ static int i2s_runtime_resume(struct device *dev)
 
 	clk_prepare_enable(i2s->clk);
 
+	writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
+	writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
+	writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
+
 	return 0;
 }
 #endif /* CONFIG_PM */
@@ -1510,6 +1506,8 @@ MODULE_DEVICE_TABLE(of, exynos_i2s_match);
 static const struct dev_pm_ops samsung_i2s_pm = {
 	SET_RUNTIME_PM_OPS(i2s_runtime_suspend,
 				i2s_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
 };
 
 static struct platform_driver samsung_i2s_driver = {
-- 
2.11.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Applied "ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device" to the asoc tree
  2016-12-29 11:34     ` [PATCH 2/5] ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device Marek Szyprowski
@ 2016-12-31 19:19       ` Mark Brown
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2016-12-31 19:19 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Mark Brown, alsa-devel, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Sangbeom Kim, Krzysztof Kozlowski,
	Inki Dae, Javier Martinez Canillas

The patch

   ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From dc938ddb56283a0b71d987e7ecd4be90390985d6 Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 29 Dec 2016 12:34:04 +0100
Subject: [PATCH] ASoC: samsung: i2s: Ensure proper runtime PM state of I2S
 device

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 <m.szyprowski@samsung.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 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 10b19a4afe86..8d8965e7107c 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 @@ i2s_delay(struct snd_pcm_substream *substream, 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;
 }
 
@@ -1322,7 +1358,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);
@@ -1345,10 +1381,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;
 }
-- 
2.11.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Applied "ASoC: samsung: i2s: Remove virtual device for secondary DAI" to the asoc tree
  2016-12-29 11:34     ` [PATCH 1/5] ASoC: samsung: i2s: Remove virtual device for secondary DAI Marek Szyprowski
  2016-12-31 18:31       ` Mark Brown
@ 2016-12-31 19:19       ` Mark Brown
  1 sibling, 0 replies; 12+ messages in thread
From: Mark Brown @ 2016-12-31 19:19 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Mark Brown, alsa-devel, linux-samsung-soc,
	Bartlomiej Zolnierkiewicz, Sangbeom Kim, Krzysztof Kozlowski,
	Inki Dae, Javier Martinez Canillas

The patch

   ASoC: samsung: i2s: Remove virtual device for secondary DAI

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From be2c92eb64023e294d6bb9232578963670bb121b Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 29 Dec 2016 12:34:03 +0100
Subject: [PATCH] ASoC: samsung: i2s: Remove virtual device for secondary DAI

For some unknown (maybe historical?) reasons support for secondary I2S DAI
was implemented by adding additional virtual platform device, which was
then probed again with the main I2S driver. This pattern is really hard
to follow and provides no benefits, so lets remove this hack and register
both DAIs during linear probe of Exynos I2S controller driver.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/samsung/i2s.c | 102 ++++++++++++------------------------------------
 1 file changed, 26 insertions(+), 76 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index d55326289a4a..10b19a4afe86 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -34,11 +34,6 @@
 
 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
 
-enum samsung_dai_type {
-	TYPE_PRI,
-	TYPE_SEC,
-};
-
 struct samsung_i2s_variant_regs {
 	unsigned int	bfs_off;
 	unsigned int	rfs_off;
@@ -54,7 +49,6 @@ struct samsung_i2s_variant_regs {
 };
 
 struct samsung_i2s_dai_data {
-	int dai_type;
 	u32 quirks;
 	const struct samsung_i2s_variant_regs *i2s_variant_regs;
 };
@@ -1066,7 +1060,6 @@ static const struct snd_soc_component_driver samsung_i2s_component = {
 static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 {
 	struct i2s_dai *i2s;
-	int ret;
 
 	i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
 	if (i2s == NULL)
@@ -1091,28 +1084,10 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 		i2s->i2s_dai_drv.capture.channels_max = 2;
 		i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
 		i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
-		dev_set_drvdata(&i2s->pdev->dev, i2s);
-	} else {	/* Create a new platform_device for Secondary */
-		i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
-		if (!i2s->pdev)
-			return NULL;
-
-		i2s->pdev->dev.parent = &pdev->dev;
-
-		platform_set_drvdata(i2s->pdev, i2s);
-		ret = platform_device_add(i2s->pdev);
-		if (ret < 0)
-			return NULL;
 	}
-
 	return i2s;
 }
 
-static void i2s_free_sec_dai(struct i2s_dai *i2s)
-{
-	platform_device_del(i2s->pdev);
-}
-
 #ifdef CONFIG_PM
 static int i2s_runtime_suspend(struct device *dev)
 {
@@ -1230,22 +1205,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		i2s_dai_data = (struct samsung_i2s_dai_data *)
 				platform_get_device_id(pdev)->driver_data;
 
-	/* Call during the secondary interface registration */
-	if (i2s_dai_data->dai_type == TYPE_SEC) {
-		sec_dai = dev_get_drvdata(&pdev->dev);
-		if (!sec_dai) {
-			dev_err(&pdev->dev, "Unable to get drvdata\n");
-			return -EFAULT;
-		}
-		ret = samsung_asoc_dma_platform_register(&pdev->dev,
-					sec_dai->filter, "tx-sec", NULL);
-		if (ret != 0)
-			return ret;
-
-		return devm_snd_soc_register_component(&sec_dai->pdev->dev,
-						&samsung_i2s_component,
-						&sec_dai->i2s_dai_drv, 1);
-	}
 
 	pri_dai = i2s_alloc_dai(pdev, false);
 	if (!pri_dai) {
@@ -1312,6 +1271,12 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_disable_clk;
 
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					&samsung_i2s_component,
+					&pri_dai->i2s_dai_drv, 1);
+	if (ret < 0)
+		goto err_disable_clk;
+
 	if (quirks & QUIRK_SEC_DAI) {
 		sec_dai = i2s_alloc_dai(pdev, true);
 		if (!sec_dai) {
@@ -1336,6 +1301,17 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		sec_dai->idma_playback.addr = idma_addr;
 		sec_dai->pri_dai = pri_dai;
 		pri_dai->sec_dai = sec_dai;
+
+		ret = samsung_asoc_dma_platform_register(&pdev->dev,
+					sec_dai->filter, "tx-sec", NULL);
+		if (ret < 0)
+			goto err_disable_clk;
+
+		ret = devm_snd_soc_register_component(&pdev->dev,
+						&samsung_i2s_component,
+						&sec_dai->i2s_dai_drv, 1);
+		if (ret < 0)
+			goto err_disable_clk;
 	}
 
 	if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
@@ -1344,11 +1320,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		goto err_disable_clk;
 	}
 
-	ret = devm_snd_soc_register_component(&pri_dai->pdev->dev,
-					&samsung_i2s_component,
-					&pri_dai->i2s_dai_drv, 1);
-	if (ret < 0)
-		goto err_free_dai;
+	dev_set_drvdata(&pdev->dev, pri_dai);
 
 
 	pm_runtime_enable(&pdev->dev);
@@ -1358,9 +1330,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 		return 0;
 
 	pm_runtime_disable(&pdev->dev);
-err_free_dai:
-	if (sec_dai)
-		i2s_free_sec_dai(sec_dai);
 err_disable_clk:
 	clk_disable_unprepare(pri_dai->clk);
 	return ret;
@@ -1368,25 +1337,18 @@ static int samsung_i2s_probe(struct platform_device *pdev)
 
 static int samsung_i2s_remove(struct platform_device *pdev)
 {
-	struct i2s_dai *i2s, *other;
+	struct i2s_dai *pri_dai, *sec_dai;
 
-	i2s = dev_get_drvdata(&pdev->dev);
-	other = get_other_dai(i2s);
+	pri_dai = dev_get_drvdata(&pdev->dev);
+	sec_dai = pri_dai->sec_dai;
 
-	if (other) {
-		other->pri_dai = NULL;
-		other->sec_dai = NULL;
-	} else {
-		pm_runtime_disable(&pdev->dev);
-	}
+	pri_dai->sec_dai = NULL;
+	sec_dai->pri_dai = NULL;
 
-	if (!is_secondary(i2s)) {
-		i2s_unregister_clock_provider(pdev);
-		clk_disable_unprepare(i2s->clk);
-	}
+	pm_runtime_disable(&pdev->dev);
 
-	i2s->pri_dai = NULL;
-	i2s->sec_dai = NULL;
+	i2s_unregister_clock_provider(pdev);
+	clk_disable_unprepare(pri_dai->clk);
 
 	return 0;
 }
@@ -1448,49 +1410,37 @@ static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = {
 };
 
 static const struct samsung_i2s_dai_data i2sv3_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_NO_MUXPSR,
 	.i2s_variant_regs = &i2sv3_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv5_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
 			QUIRK_SUPPORTS_IDMA,
 	.i2s_variant_regs = &i2sv3_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv6_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
 			QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA,
 	.i2s_variant_regs = &i2sv6_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv7_dai_type = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
 			QUIRK_SUPPORTS_TDM,
 	.i2s_variant_regs = &i2sv7_regs,
 };
 
 static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = {
-	.dai_type = TYPE_PRI,
 	.quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR,
 	.i2s_variant_regs = &i2sv5_i2s1_regs,
 };
 
-static const struct samsung_i2s_dai_data samsung_dai_type_sec = {
-	.dai_type = TYPE_SEC,
-};
-
 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",
-		.driver_data    = (kernel_ulong_t)&samsung_dai_type_sec,
 	},
 	{},
 };
-- 
2.11.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2016-12-31 19:19 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20161229113425eucas1p2f95b915a9a66df3e3ff8431b5625b926@eucas1p2.samsung.com>
2016-12-29 11:34 ` [PATCH 0/5] Runtime PM support for Exynos I2S driver Marek Szyprowski
     [not found]   ` <CGME20161229113425eucas1p2600ba7e4337e90f65c0bc60bb4a9c2ec@eucas1p2.samsung.com>
2016-12-29 11:34     ` [PATCH 1/5] ASoC: samsung: i2s: Remove virtual device for secondary DAI Marek Szyprowski
2016-12-31 18:31       ` Mark Brown
2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Remove virtual device for secondary DAI" to the asoc tree Mark Brown
     [not found]   ` <CGME20161229113426eucas1p2bc05fb68efd45e6af3ae7a2b8be5e481@eucas1p2.samsung.com>
2016-12-29 11:34     ` [PATCH 2/5] ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device Marek Szyprowski
2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Ensure proper runtime PM state of I2S device" to the asoc tree Mark Brown
     [not found]   ` <CGME20161229113427eucas1p166db5239bd7b17ebaba8b248f06cffe8@eucas1p1.samsung.com>
2016-12-29 11:34     ` [PATCH 3/5] ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations Marek Szyprowski
2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Move saving and restoring regs to runtime pm operations" to the asoc tree Mark Brown
     [not found]   ` <CGME20161229113427eucas1p20e91adee0da640e2a5847d53f3c6e443@eucas1p2.samsung.com>
2016-12-29 11:34     ` [PATCH 4/5] ASoC: samsung: i2s: Let runtime PM operations to control op_clk too Marek Szyprowski
2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Let runtime PM operations to control op_clk too" to the asoc tree Mark Brown
     [not found]   ` <CGME20161229113427eucas1p21ee586b73029410d0860a22ce4a21e0c@eucas1p2.samsung.com>
2016-12-29 11:34     ` [PATCH 5/5] ASoC: samsung: i2s: Provide I2S device for registered clocks Marek Szyprowski
2016-12-31 19:19       ` Applied "ASoC: samsung: i2s: Provide I2S device for registered clocks" to the asoc tree Mark Brown

This is a public inbox, see mirroring instructions
on how to clone and mirror all data and code used for this inbox