[alsa-devel] [PATCH v2 00/21] ASoC: dmaengine updates, secondary CPU DAI for Odroid boards
This series restores support for the secondary CPU DAI in samsung/i2s.c driver and adds support for secondary CPU DAI on Odroid boards.
I have added 4 more clean up patches comparing to first version of the patch set (16/22...19/22).
The first patch adds new platform device for the secondary PCM, I tried to avoid registering new platform device in probe() as it doesn't play well with deferred probing but couldn't find a way to avoid that new device, unique devices are needed to register "PCM" components for each CPU DAI.
Patches 2/21...11/21 are mostly a clean up, following conversion to single component with multiple DAIs, allowing to reference both primary/secondary DAI in DT.
The patch set has been tested on Odroid U3, XU3, XU4 and Mini2440 (s3c2440 non-DT) boards.
Changes since v1 ((addressing Krzysztof's review comments): - added a comment, whitespace change in patch 1/21 - dropped unnecessary new line addition from patch 1/21
Sylwester Nawrocki (21): ASoC: samsung: i2s: Restore support for the secondary PCM ASoC: samsung: i2s: Move clk supplier data to common driver data structure ASoC: samsung: i2s: Add widgets and routes for DPCM support ASoC: samsung: i2s: Move core clk to the driver common data structure ASoC: samsung: i2s: Move opclk data to common driver data structure ASoC: samsung: i2s: Move registers cache to common driver data structure ASoC: samsung: i2s: Move SFR pointer to common driver data structure ASoC: samsung: i2s: Drop spinlock pointer from i2s_dai data structure ASoC: samsung: i2s: Move IP variant data to common driver data structure ASoC: samsung: i2s: Move quirks data to common driver data structure ASoC: samsung: i2s: Get rid of a static spinlock ASoC: samsung: odroid: Add support for secondary CPU DAI ASoC: samsung: Specify DMA channel names through custom DMA config ASoC: samsung: Drop DAI DMA data chan_name assignments ASoC: dmaengine: Remove unused SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME flag ASoC: samsung: i2s: Simplify pri_dai, sec_dai pointers usage ASoC: samsung: i2s: Change indentation in SAMSUNG_I2S_FMTS definition ASoC: samsung: i2s: Comments clean up ASoC: samsung: i2s: Convert to SPDX License Indentifier ARM: dts: exynos5422-odroidxu3: Add support for secondary DAI ARM: dts: exynos5422-odroidxu4: Add support for secondary DAI
.../boot/dts/exynos5422-odroidxu3-audio.dtsi | 6 +- arch/arm/boot/dts/exynos5422-odroidxu4.dts | 4 +- include/sound/dmaengine_pcm.h | 6 - sound/soc/samsung/dmaengine.c | 12 +- sound/soc/samsung/i2s.c | 543 ++++++++++-------- sound/soc/samsung/odroid.c | 131 +++-- sound/soc/samsung/s3c2412-i2s.c | 4 +- sound/soc/samsung/s3c24xx-i2s.c | 4 +- sound/soc/soc-generic-dmaengine-pcm.c | 21 +- 9 files changed, 413 insertions(+), 318 deletions(-)
-- 2.20.1
This patch introduces again registration of additional platform device as we still need it for registering the secondary dmaengine PCM component.
This patch in most part is a revert of changes done in commit be2c92eb64023e ("ASoC: samsung: i2s: Remove virtual device for secondary DAI")
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 52 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 4bc3b181f1c2..273620914471 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -109,6 +109,7 @@ static DEFINE_SPINLOCK(lock);
struct samsung_i2s_priv { struct platform_device *pdev; + struct platform_device *pdev_sec;
/* Spinlock protecting access to the device's registers */ spinlock_t spinlock; @@ -1312,6 +1313,34 @@ static int i2s_register_clock_provider(struct platform_device *pdev) return ret; }
+/* Create platform device for the secondary PCM */ +static int i2s_create_secondary_device(struct samsung_i2s_priv *priv) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_register_simple("samsung-i2s-sec", -1, NULL, 0); + if (!pdev) + return -ENOMEM; + + ret = device_attach(&pdev->dev); + if (ret < 0) { + dev_info(&pdev->dev, "device_attach() failed\n"); + return ret; + } + + priv->pdev_sec = pdev; + + return 0; +} + +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; + } +} static int samsung_i2s_probe(struct platform_device *pdev) { struct i2s_dai *pri_dai, *sec_dai = NULL; @@ -1329,13 +1358,15 @@ static int samsung_i2s_probe(struct platform_device *pdev) i2s_dai_data = (struct samsung_i2s_dai_data *) platform_get_device_id(pdev)->driver_data;
+ /* Nothing to do if it is the secondary device probe */ + if (!i2s_dai_data) + return 0; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
quirks = np ? i2s_dai_data->quirks : i2s_pdata->type.quirks; - quirks &= ~(QUIRK_SEC_DAI | QUIRK_SUPPORTS_IDMA); - num_dais = (quirks & QUIRK_SEC_DAI) ? 2 : 1; priv->pdev = pdev;
@@ -1425,8 +1456,13 @@ static int samsung_i2s_probe(struct platform_device *pdev) 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, NULL); + ret = i2s_create_secondary_device(priv); + if (ret < 0) + goto err_disable_clk; + + ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev, + sec_dai->filter, "tx-sec", NULL, + &pdev->dev); if (ret < 0) goto err_disable_clk;
@@ -1461,6 +1497,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); err_disable_clk: clk_disable_unprepare(pri_dai->clk); + i2s_delete_secondary_device(priv); return ret; }
@@ -1469,12 +1506,17 @@ static int samsung_i2s_remove(struct platform_device *pdev) struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); struct i2s_dai *pri_dai = samsung_i2s_get_pri_dai(&pdev->dev);
+ /* The secondary device has no driver data assigned */ + if (!priv) + return 0; + 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); + i2s_delete_secondary_device(priv);
return 0; } @@ -1572,6 +1614,8 @@ 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", }, {}, };
The patch
ASoC: samsung: i2s: Restore support for the secondary PCM
has been applied to the asoc tree at
https://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 7196c64c7d0c6d421c9bb721d8d66c6d0edc5385 Mon Sep 17 00:00:00 2001
From: Sylwester Nawrocki s.nawrocki@samsung.com Date: Tue, 12 Feb 2019 19:03:22 +0100 Subject: [PATCH] ASoC: samsung: i2s: Restore support for the secondary PCM
This patch introduces again registration of additional platform device as we still need it for registering the secondary dmaengine PCM component.
This patch in most part is a revert of changes done in commit be2c92eb64023e ("ASoC: samsung: i2s: Remove virtual device for secondary DAI")
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/samsung/i2s.c | 52 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 455bc65d115a..cc983afae735 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -109,6 +109,7 @@ static DEFINE_SPINLOCK(lock);
struct samsung_i2s_priv { struct platform_device *pdev; + struct platform_device *pdev_sec;
/* Spinlock protecting access to the device's registers */ spinlock_t spinlock; @@ -1306,6 +1307,34 @@ static int i2s_register_clock_provider(struct platform_device *pdev) return ret; }
+/* Create platform device for the secondary PCM */ +static int i2s_create_secondary_device(struct samsung_i2s_priv *priv) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_register_simple("samsung-i2s-sec", -1, NULL, 0); + if (!pdev) + return -ENOMEM; + + ret = device_attach(&pdev->dev); + if (ret < 0) { + dev_info(&pdev->dev, "device_attach() failed\n"); + return ret; + } + + priv->pdev_sec = pdev; + + return 0; +} + +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; + } +} static int samsung_i2s_probe(struct platform_device *pdev) { struct i2s_dai *pri_dai, *sec_dai = NULL; @@ -1323,13 +1352,15 @@ static int samsung_i2s_probe(struct platform_device *pdev) i2s_dai_data = (struct samsung_i2s_dai_data *) platform_get_device_id(pdev)->driver_data;
+ /* Nothing to do if it is the secondary device probe */ + if (!i2s_dai_data) + return 0; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
quirks = np ? i2s_dai_data->quirks : i2s_pdata->type.quirks; - quirks &= ~(QUIRK_SEC_DAI | QUIRK_SUPPORTS_IDMA); - num_dais = (quirks & QUIRK_SEC_DAI) ? 2 : 1; priv->pdev = pdev;
@@ -1419,8 +1450,13 @@ static int samsung_i2s_probe(struct platform_device *pdev) 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, NULL); + ret = i2s_create_secondary_device(priv); + if (ret < 0) + goto err_disable_clk; + + ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev, + sec_dai->filter, "tx-sec", NULL, + &pdev->dev); if (ret < 0) goto err_disable_clk;
@@ -1455,6 +1491,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); err_disable_clk: clk_disable_unprepare(pri_dai->clk); + i2s_delete_secondary_device(priv); return ret; }
@@ -1463,12 +1500,17 @@ static int samsung_i2s_remove(struct platform_device *pdev) struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); struct i2s_dai *pri_dai = samsung_i2s_get_pri_dai(&pdev->dev);
+ /* The secondary device has no driver data assigned */ + if (!priv) + return 0; + 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); + i2s_delete_secondary_device(priv);
return 0; } @@ -1566,6 +1608,8 @@ 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", }, {}, };
Having the clocks provider data in struct samsung_i2s_priv, i.e. per the I2S controller instance, rather than per CPU DAI better models the hardware and simplifies the code a little. The clock provider is common for both DAIs.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 68 ++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 35 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 273620914471..fffc76ab60da 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -99,9 +99,7 @@ struct i2s_dai {
spinlock_t *lock;
- /* Below fields are only valid if this is the primary FIFO */ - struct clk *clk_table[3]; - struct clk_onecell_data clk_data; + struct samsung_i2s_priv *priv; };
/* Lock for cross i/f checks */ @@ -118,6 +116,10 @@ struct samsung_i2s_priv { struct i2s_dai *dai; struct snd_soc_dai_driver *dai_drv; int num_dais; + + /* The clock provider's data */ + struct clk *clk_table[3]; + struct clk_onecell_data clk_data; };
struct i2s_dai *samsung_i2s_get_pri_dai(struct device *dev) @@ -625,11 +627,10 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, return ret; }
-static int i2s_set_fmt(struct snd_soc_dai *dai, - unsigned int fmt) +static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { + 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); int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave; u32 mod, tmp = 0; unsigned long flags; @@ -687,8 +688,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any * clock configuration assigned in DT is not overwritten. */ - if (i2s->rclk_srcrate == 0 && i2s->clk_data.clks == NULL && - other->clk_data.clks == NULL) + if (i2s->rclk_srcrate == 0 && priv->clk_data.clks == NULL) i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0, 0, SND_SOC_CLOCK_IN); break; @@ -725,8 +725,8 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, static int i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, 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); u32 mod, mask = 0, val = 0; struct clk *rclksrc; unsigned long flags; @@ -811,10 +811,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
i2s->frmclk = params_rate(params);
- rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC]; - if (!rclksrc || IS_ERR(rclksrc)) - rclksrc = other->clk_table[CLK_I2S_RCLK_SRC]; - + rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC]; if (rclksrc && !IS_ERR(rclksrc)) i2s->rclk_srcrate = clk_get_rate(rclksrc);
@@ -1221,31 +1218,30 @@ static int i2s_runtime_resume(struct device *dev) } #endif /* CONFIG_PM */
-static void i2s_unregister_clocks(struct i2s_dai *i2s) +static void i2s_unregister_clocks(struct samsung_i2s_priv *priv) { int i;
- for (i = 0; i < i2s->clk_data.clk_num; i++) { - if (!IS_ERR(i2s->clk_table[i])) - clk_unregister(i2s->clk_table[i]); + for (i = 0; i < priv->clk_data.clk_num; i++) { + if (!IS_ERR(priv->clk_table[i])) + clk_unregister(priv->clk_table[i]); } }
-static void i2s_unregister_clock_provider(struct platform_device *pdev) +static void i2s_unregister_clock_provider(struct samsung_i2s_priv *priv) { - struct i2s_dai *i2s = samsung_i2s_get_pri_dai(&pdev->dev); - - of_clk_del_provider(pdev->dev.of_node); - i2s_unregister_clocks(i2s); + of_clk_del_provider(priv->pdev->dev.of_node); + i2s_unregister_clocks(priv); }
-static int i2s_register_clock_provider(struct platform_device *pdev) + +static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) {
const char * const i2s_clk_desc[] = { "cdclk", "rclk_src", "prescaler" }; const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" }; const char *p_names[2] = { NULL }; - struct device *dev = &pdev->dev; + struct device *dev = &priv->pdev->dev; struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev); const struct samsung_i2s_variant_regs *reg_info = i2s->variant_regs; const char *i2s_clk_name[ARRAY_SIZE(i2s_clk_desc)]; @@ -1277,37 +1273,37 @@ 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(dev, + priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev, i2s_clk_name[CLK_I2S_RCLK_SRC], 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(dev, + priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev, i2s_clk_name[CLK_I2S_RCLK_PSR], i2s_clk_name[CLK_I2S_RCLK_SRC], CLK_SET_RATE_PARENT, i2s->addr + I2SPSR, 8, 6, 0, i2s->lock);
p_names[0] = i2s_clk_name[CLK_I2S_RCLK_PSR]; - i2s->clk_data.clk_num = 2; + priv->clk_data.clk_num = 2; }
- i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, + priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, i2s_clk_name[CLK_I2S_CDCLK], p_names[0], CLK_SET_RATE_PARENT, i2s->addr + I2SMOD, reg_info->cdclkcon_off, CLK_GATE_SET_TO_DISABLE, i2s->lock);
- i2s->clk_data.clk_num += 1; - i2s->clk_data.clks = i2s->clk_table; + priv->clk_data.clk_num += 1; + priv->clk_data.clks = priv->clk_table;
ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, - &i2s->clk_data); + &priv->clk_data); if (ret < 0) { dev_err(dev, "failed to add clock provider: %d\n", ret); - i2s_unregister_clocks(i2s); + i2s_unregister_clocks(priv); }
return ret; @@ -1426,6 +1422,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai->dma_capture.addr_width = 4; pri_dai->quirks = quirks; pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs; + pri_dai->priv = priv;
if (quirks & QUIRK_PRI_6CHAN) pri_dai->drv->playback.channels_max = 6; @@ -1454,6 +1451,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) sec_dai->quirks = quirks; sec_dai->idma_playback.addr = idma_addr; sec_dai->pri_dai = pri_dai; + sec_dai->priv = priv; pri_dai->sec_dai = sec_dai;
ret = i2s_create_secondary_device(priv); @@ -1485,11 +1483,11 @@ static int samsung_i2s_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev);
- ret = i2s_register_clock_provider(pdev); + ret = i2s_register_clock_provider(priv); if (ret < 0) goto err_disable_pm;
- pri_dai->op_clk = clk_get_parent(pri_dai->clk_table[CLK_I2S_RCLK_SRC]); + pri_dai->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]);
return 0;
@@ -1513,7 +1511,7 @@ static int samsung_i2s_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev);
- i2s_unregister_clock_provider(pdev); + i2s_unregister_clock_provider(priv); clk_disable_unprepare(pri_dai->clk); pm_runtime_put_noidle(&pdev->dev); i2s_delete_secondary_device(priv);
This patch adds DAPM widgets required to model the internal mixer of the I2S controller merging audio streams from the primary and from the secondary PCM interface.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index fffc76ab60da..29bcfca20572 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1116,8 +1116,31 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = { .delay = i2s_delay, };
+static const struct snd_soc_dapm_widget samsung_i2s_widgets[] = { + /* Backend DAI */ + SND_SOC_DAPM_AIF_OUT("Mixer DAI TX", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("Mixer DAI RX", NULL, 0, SND_SOC_NOPM, 0, 0), + + /* Playback Mixer */ + SND_SOC_DAPM_MIXER("Playback Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route samsung_i2s_dapm_routes[] = { + { "Playback Mixer", NULL, "Primary" }, + { "Playback Mixer", NULL, "Secondary" }, + + { "Mixer DAI TX", NULL, "Playback Mixer" }, + { "Playback Mixer", NULL, "Mixer DAI RX" }, +}; + static const struct snd_soc_component_driver samsung_i2s_component = { - .name = "samsung-i2s", + .name = "samsung-i2s", + + .dapm_widgets = samsung_i2s_widgets, + .num_dapm_widgets = ARRAY_SIZE(samsung_i2s_widgets), + + .dapm_routes = samsung_i2s_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(samsung_i2s_dapm_routes), };
#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ @@ -1129,6 +1152,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, int num_dais) { static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" }; + static const char *stream_names[] = { "Primary", "Secondary" }; struct snd_soc_dai_driver *dai_drv; struct i2s_dai *dai; int i; @@ -1158,6 +1182,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, dai_drv->playback.channels_max = 2; dai_drv->playback.rates = i2s_dai_data->pcm_rates; dai_drv->playback.formats = SAMSUNG_I2S_FMTS; + dai_drv->playback.stream_name = stream_names[i];
dai_drv->id = i + 1; dai_drv->name = dai_names[i];
The core clock is also common for both CPU DAIs so move it to the driver's private data structure.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 29bcfca20572..159c19fdb662 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -71,8 +71,6 @@ struct i2s_dai { * 0 indicates CPU driver is free to choose any value. */ unsigned rfs, bfs; - /* I2S Controller's core clock */ - struct clk *clk; /* Clock for generating I2S signals */ struct clk *op_clk; /* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */ @@ -117,6 +115,9 @@ struct samsung_i2s_priv { struct snd_soc_dai_driver *dai_drv; int num_dais;
+ /* The I2S controller's core clock */ + struct clk *clk; + /* The clock provider's data */ struct clk *clk_table[3]; struct clk_onecell_data clk_data; @@ -1205,6 +1206,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, #ifdef CONFIG_PM static int i2s_runtime_suspend(struct device *dev) { + struct samsung_i2s_priv *priv = dev_get_drvdata(dev); struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev);
i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); @@ -1213,24 +1215,25 @@ static int i2s_runtime_suspend(struct device *dev)
if (i2s->op_clk) clk_disable_unprepare(i2s->op_clk); - clk_disable_unprepare(i2s->clk); + clk_disable_unprepare(priv->clk);
return 0; }
static int i2s_runtime_resume(struct device *dev) { + struct samsung_i2s_priv *priv = dev_get_drvdata(dev); struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev); int ret;
- ret = clk_prepare_enable(i2s->clk); + ret = clk_prepare_enable(priv->clk); if (ret) return ret;
if (i2s->op_clk) { ret = clk_prepare_enable(i2s->op_clk); if (ret) { - clk_disable_unprepare(i2s->clk); + clk_disable_unprepare(priv->clk); return ret; } } @@ -1428,13 +1431,13 @@ static int samsung_i2s_probe(struct platform_device *pdev)
regs_base = res->start;
- pri_dai->clk = devm_clk_get(&pdev->dev, "iis"); - if (IS_ERR(pri_dai->clk)) { + priv->clk = devm_clk_get(&pdev->dev, "iis"); + if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "Failed to get iis clock\n"); - return PTR_ERR(pri_dai->clk); + return PTR_ERR(priv->clk); }
- ret = clk_prepare_enable(pri_dai->clk); + ret = clk_prepare_enable(priv->clk); if (ret != 0) { dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); return ret; @@ -1472,7 +1475,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
sec_dai->dma_playback.addr_width = 4; sec_dai->addr = pri_dai->addr; - sec_dai->clk = pri_dai->clk; sec_dai->quirks = quirks; sec_dai->idma_playback.addr = idma_addr; sec_dai->pri_dai = pri_dai; @@ -1519,7 +1521,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) err_disable_pm: pm_runtime_disable(&pdev->dev); err_disable_clk: - clk_disable_unprepare(pri_dai->clk); + clk_disable_unprepare(priv->clk); i2s_delete_secondary_device(priv); return ret; } @@ -1527,7 +1529,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); - struct i2s_dai *pri_dai = samsung_i2s_get_pri_dai(&pdev->dev);
/* The secondary device has no driver data assigned */ if (!priv) @@ -1537,7 +1538,7 @@ static int samsung_i2s_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev);
i2s_unregister_clock_provider(priv); - clk_disable_unprepare(pri_dai->clk); + clk_disable_unprepare(priv->clk); pm_runtime_put_noidle(&pdev->dev); i2s_delete_secondary_device(priv);
The patch
ASoC: samsung: i2s: Move core clk to the driver common data structure
has been applied to the asoc tree at
https://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 b5d015e68e6ce36e0373cda3537009aaa96b5902 Mon Sep 17 00:00:00 2001
From: Sylwester Nawrocki s.nawrocki@samsung.com Date: Tue, 12 Feb 2019 19:03:25 +0100 Subject: [PATCH] ASoC: samsung: i2s: Move core clk to the driver common data structure
The core clock is also common for both CPU DAIs so move it to the driver's private data structure.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/samsung/i2s.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 29bcfca20572..159c19fdb662 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -71,8 +71,6 @@ struct i2s_dai { * 0 indicates CPU driver is free to choose any value. */ unsigned rfs, bfs; - /* I2S Controller's core clock */ - struct clk *clk; /* Clock for generating I2S signals */ struct clk *op_clk; /* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */ @@ -117,6 +115,9 @@ struct samsung_i2s_priv { struct snd_soc_dai_driver *dai_drv; int num_dais;
+ /* The I2S controller's core clock */ + struct clk *clk; + /* The clock provider's data */ struct clk *clk_table[3]; struct clk_onecell_data clk_data; @@ -1205,6 +1206,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, #ifdef CONFIG_PM static int i2s_runtime_suspend(struct device *dev) { + struct samsung_i2s_priv *priv = dev_get_drvdata(dev); struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev);
i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); @@ -1213,24 +1215,25 @@ static int i2s_runtime_suspend(struct device *dev)
if (i2s->op_clk) clk_disable_unprepare(i2s->op_clk); - clk_disable_unprepare(i2s->clk); + clk_disable_unprepare(priv->clk);
return 0; }
static int i2s_runtime_resume(struct device *dev) { + struct samsung_i2s_priv *priv = dev_get_drvdata(dev); struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev); int ret;
- ret = clk_prepare_enable(i2s->clk); + ret = clk_prepare_enable(priv->clk); if (ret) return ret;
if (i2s->op_clk) { ret = clk_prepare_enable(i2s->op_clk); if (ret) { - clk_disable_unprepare(i2s->clk); + clk_disable_unprepare(priv->clk); return ret; } } @@ -1428,13 +1431,13 @@ static int samsung_i2s_probe(struct platform_device *pdev)
regs_base = res->start;
- pri_dai->clk = devm_clk_get(&pdev->dev, "iis"); - if (IS_ERR(pri_dai->clk)) { + priv->clk = devm_clk_get(&pdev->dev, "iis"); + if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "Failed to get iis clock\n"); - return PTR_ERR(pri_dai->clk); + return PTR_ERR(priv->clk); }
- ret = clk_prepare_enable(pri_dai->clk); + ret = clk_prepare_enable(priv->clk); if (ret != 0) { dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); return ret; @@ -1472,7 +1475,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
sec_dai->dma_playback.addr_width = 4; sec_dai->addr = pri_dai->addr; - sec_dai->clk = pri_dai->clk; sec_dai->quirks = quirks; sec_dai->idma_playback.addr = idma_addr; sec_dai->pri_dai = pri_dai; @@ -1519,7 +1521,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) err_disable_pm: pm_runtime_disable(&pdev->dev); err_disable_clk: - clk_disable_unprepare(pri_dai->clk); + clk_disable_unprepare(priv->clk); i2s_delete_secondary_device(priv); return ret; } @@ -1527,7 +1529,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev); - struct i2s_dai *pri_dai = samsung_i2s_get_pri_dai(&pdev->dev);
/* The secondary device has no driver data assigned */ if (!priv) @@ -1537,7 +1538,7 @@ static int samsung_i2s_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev);
i2s_unregister_clock_provider(priv); - clk_disable_unprepare(pri_dai->clk); + clk_disable_unprepare(priv->clk); pm_runtime_put_noidle(&pdev->dev); i2s_delete_secondary_device(priv);
The clock for generating I2S signals is also common for both CPU DAIs so move it to the driver's common data structure.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 70 +++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 37 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 159c19fdb662..d8414d781f83 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -62,8 +62,6 @@ struct i2s_dai { struct platform_device *pdev; /* Memory mapped SFR region */ void __iomem *addr; - /* Rate of RCLK source clock */ - unsigned long rclk_srcrate; /* Frame Clock */ unsigned frmclk; /* @@ -71,8 +69,6 @@ struct i2s_dai { * 0 indicates CPU driver is free to choose any value. */ unsigned rfs, bfs; - /* Clock for generating I2S signals */ - struct clk *op_clk; /* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */ struct i2s_dai *pri_dai; /* Pointer to the Secondary_Fifo if it has one, NULL otherwise */ @@ -118,6 +114,12 @@ struct samsung_i2s_priv { /* The I2S controller's core clock */ struct clk *clk;
+ /* Clock for generating I2S signals */ + struct clk *op_clk; + + /* Rate of RCLK source clock */ + unsigned long rclk_srcrate; + /* The clock provider's data */ struct clk *clk_table[3]; struct clk_onecell_data clk_data; @@ -496,9 +498,10 @@ static inline void i2s_fifo(struct i2s_dai *i2s, u32 flush) writel(readl(fic) & ~flush, fic); }
-static int i2s_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int rfs, int dir) +static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, + int dir) { + 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); const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; @@ -554,44 +557,39 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, clk_id = 1;
if (!any_active(i2s)) { - if (i2s->op_clk && !IS_ERR(i2s->op_clk)) { + if (priv->op_clk && !IS_ERR(priv->op_clk)) { if ((clk_id && !(mod & rsrc_mask)) || (!clk_id && (mod & rsrc_mask))) { - clk_disable_unprepare(i2s->op_clk); - clk_put(i2s->op_clk); + clk_disable_unprepare(priv->op_clk); + clk_put(priv->op_clk); } else { - i2s->rclk_srcrate = - clk_get_rate(i2s->op_clk); + priv->rclk_srcrate = + clk_get_rate(priv->op_clk); goto done; } }
if (clk_id) - i2s->op_clk = clk_get(&i2s->pdev->dev, + priv->op_clk = clk_get(&i2s->pdev->dev, "i2s_opclk1"); else - i2s->op_clk = clk_get(&i2s->pdev->dev, + priv->op_clk = clk_get(&i2s->pdev->dev, "i2s_opclk0");
- if (WARN_ON(IS_ERR(i2s->op_clk))) { - ret = PTR_ERR(i2s->op_clk); - i2s->op_clk = NULL; + if (WARN_ON(IS_ERR(priv->op_clk))) { + ret = PTR_ERR(priv->op_clk); + priv->op_clk = NULL; goto err; }
- ret = clk_prepare_enable(i2s->op_clk); + ret = clk_prepare_enable(priv->op_clk); if (ret) { - clk_put(i2s->op_clk); - i2s->op_clk = NULL; + clk_put(priv->op_clk); + priv->op_clk = NULL; goto err; } - i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); + priv->rclk_srcrate = clk_get_rate(priv->op_clk);
- /* Over-ride the other's */ - if (other) { - other->op_clk = i2s->op_clk; - other->rclk_srcrate = i2s->rclk_srcrate; - } } else if ((!clk_id && (mod & rsrc_mask)) || (clk_id && !(mod & rsrc_mask))) { dev_err(&i2s->pdev->dev, @@ -600,8 +598,6 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, goto err; } else { /* Call can't be on the active DAI */ - i2s->op_clk = other->op_clk; - i2s->rclk_srcrate = other->rclk_srcrate; goto done; }
@@ -689,7 +685,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any * clock configuration assigned in DT is not overwritten. */ - if (i2s->rclk_srcrate == 0 && priv->clk_data.clks == NULL) + if (priv->rclk_srcrate == 0 && priv->clk_data.clks == NULL) i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0, 0, SND_SOC_CLOCK_IN); break; @@ -814,7 +810,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC]; if (rclksrc && !IS_ERR(rclksrc)) - i2s->rclk_srcrate = clk_get_rate(rclksrc); + priv->rclk_srcrate = clk_get_rate(rclksrc);
return 0; } @@ -872,6 +868,7 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
static int config_setup(struct i2s_dai *i2s) { + struct samsung_i2s_priv *priv = i2s->priv; struct i2s_dai *other = get_other_dai(i2s); unsigned rfs, bfs, blc; u32 psr; @@ -920,11 +917,11 @@ static int config_setup(struct i2s_dai *i2s) return 0;
if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { - psr = i2s->rclk_srcrate / i2s->frmclk / rfs; + psr = priv->rclk_srcrate / i2s->frmclk / rfs; writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR); dev_dbg(&i2s->pdev->dev, "RCLK_SRC=%luHz PSR=%u, RCLK=%dfs, BCLK=%dfs\n", - i2s->rclk_srcrate, psr, rfs, bfs); + priv->rclk_srcrate, psr, rfs, bfs); }
return 0; @@ -1067,7 +1064,6 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) /* Reset any constraint on RFS and BFS */ i2s->rfs = 0; i2s->bfs = 0; - i2s->rclk_srcrate = 0;
spin_lock_irqsave(i2s->lock, flags); i2s_txctrl(i2s, 0); @@ -1213,8 +1209,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); + if (priv->op_clk) + clk_disable_unprepare(priv->op_clk); clk_disable_unprepare(priv->clk);
return 0; @@ -1230,8 +1226,8 @@ static int i2s_runtime_resume(struct device *dev) if (ret) return ret;
- if (i2s->op_clk) { - ret = clk_prepare_enable(i2s->op_clk); + if (priv->op_clk) { + ret = clk_prepare_enable(priv->op_clk); if (ret) { clk_disable_unprepare(priv->clk); return ret; @@ -1514,7 +1510,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (ret < 0) goto err_disable_pm;
- pri_dai->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]); + priv->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]);
return 0;
There is no need to keep the PM suspend/resume register cache separate for each DAI as those registers are common, move related i2s_dai data structure to the driver's common data structure. This will allow us to simplify the code a little eventually and to make it easier to follow.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index d8414d781f83..72f0cb7abb30 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -86,9 +86,6 @@ struct i2s_dai { struct snd_dmaengine_dai_dma_data idma_playback; dma_filter_fn filter; u32 quirks; - u32 suspend_i2smod; - u32 suspend_i2scon; - u32 suspend_i2spsr; const struct samsung_i2s_variant_regs *variant_regs;
spinlock_t *lock; @@ -120,6 +117,11 @@ struct samsung_i2s_priv { /* Rate of RCLK source clock */ unsigned long rclk_srcrate;
+ /* Cache of selected I2S registers for system suspend */ + u32 suspend_i2smod; + u32 suspend_i2scon; + u32 suspend_i2spsr; + /* The clock provider's data */ struct clk *clk_table[3]; struct clk_onecell_data clk_data; @@ -1205,9 +1207,9 @@ static int i2s_runtime_suspend(struct device *dev) struct samsung_i2s_priv *priv = dev_get_drvdata(dev); struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev);
- i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); - i2s->suspend_i2scon = readl(i2s->addr + I2SCON); - i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); + priv->suspend_i2smod = readl(i2s->addr + I2SMOD); + priv->suspend_i2scon = readl(i2s->addr + I2SCON); + priv->suspend_i2spsr = readl(i2s->addr + I2SPSR);
if (priv->op_clk) clk_disable_unprepare(priv->op_clk); @@ -1234,9 +1236,9 @@ static int i2s_runtime_resume(struct device *dev) } }
- writel(i2s->suspend_i2scon, i2s->addr + I2SCON); - writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); - writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); + writel(priv->suspend_i2scon, i2s->addr + I2SCON); + writel(priv->suspend_i2smod, i2s->addr + I2SMOD); + writel(priv->suspend_i2spsr, i2s->addr + I2SPSR);
return 0; }
The SFR region is common for both DAIs so move related data structure field from struct i2s_dai to the common driver data structure.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 105 ++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 47 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 72f0cb7abb30..05f1de208307 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -60,8 +60,7 @@ struct samsung_i2s_dai_data { struct i2s_dai { /* Platform device for this DAI */ struct platform_device *pdev; - /* Memory mapped SFR region */ - void __iomem *addr; + /* Frame Clock */ unsigned frmclk; /* @@ -100,6 +99,9 @@ struct samsung_i2s_priv { struct platform_device *pdev; struct platform_device *pdev_sec;
+ /* Memory mapped SFR region */ + void __iomem *addr; + /* Spinlock protecting access to the device's registers */ spinlock_t spinlock;
@@ -143,7 +145,9 @@ static inline bool is_secondary(struct i2s_dai *i2s) /* If operating in SoC-Slave mode */ static inline bool is_slave(struct i2s_dai *i2s) { - u32 mod = readl(i2s->addr + I2SMOD); + struct samsung_i2s_priv *priv = i2s->priv; + + u32 mod = readl(priv->addr + I2SMOD); return (mod & (1 << i2s->variant_regs->mss_off)) ? true : false; }
@@ -155,7 +159,7 @@ static inline bool tx_active(struct i2s_dai *i2s) if (!i2s) return false;
- active = readl(i2s->addr + I2SCON); + active = readl(i2s->priv->addr + I2SCON);
if (is_secondary(i2s)) active &= CON_TXSDMA_ACTIVE; @@ -193,7 +197,7 @@ static inline bool rx_active(struct i2s_dai *i2s) if (!i2s) return false;
- active = readl(i2s->addr + I2SCON) & CON_RXDMA_ACTIVE; + active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE;
return active ? true : false; } @@ -256,8 +260,10 @@ static inline bool is_manager(struct i2s_dai *i2s) /* Read RCLK of I2S (in multiples of LRCLK) */ static inline unsigned get_rfs(struct i2s_dai *i2s) { + struct samsung_i2s_priv *priv = i2s->priv; u32 rfs; - rfs = readl(i2s->addr + I2SMOD) >> i2s->variant_regs->rfs_off; + + rfs = readl(priv->addr + I2SMOD) >> i2s->variant_regs->rfs_off; rfs &= i2s->variant_regs->rfs_mask;
switch (rfs) { @@ -275,7 +281,8 @@ static inline unsigned get_rfs(struct i2s_dai *i2s) /* Write RCLK of I2S (in multiples of LRCLK) */ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) { - u32 mod = readl(i2s->addr + I2SMOD); + struct samsung_i2s_priv *priv = i2s->priv; + u32 mod = readl(priv->addr + I2SMOD); int rfs_shift = i2s->variant_regs->rfs_off;
mod &= ~(i2s->variant_regs->rfs_mask << rfs_shift); @@ -307,14 +314,16 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) break; }
- writel(mod, i2s->addr + I2SMOD); + writel(mod, priv->addr + I2SMOD); }
/* 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; u32 bfs; - bfs = readl(i2s->addr + I2SMOD) >> i2s->variant_regs->bfs_off; + + bfs = readl(priv->addr + I2SMOD) >> i2s->variant_regs->bfs_off; bfs &= i2s->variant_regs->bfs_mask;
switch (bfs) { @@ -333,7 +342,8 @@ static inline unsigned get_bfs(struct i2s_dai *i2s) /* Write Bit-Clock of I2S (in multiples of LRCLK) */ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) { - u32 mod = readl(i2s->addr + I2SMOD); + struct samsung_i2s_priv *priv = i2s->priv; + u32 mod = readl(priv->addr + I2SMOD); int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM; int bfs_shift = i2s->variant_regs->bfs_off;
@@ -378,13 +388,13 @@ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) return; }
- writel(mod, i2s->addr + I2SMOD); + writel(mod, priv->addr + I2SMOD); }
/* Sample-Size */ static inline int get_blc(struct i2s_dai *i2s) { - int blc = readl(i2s->addr + I2SMOD); + int blc = readl(i2s->priv->addr + I2SMOD);
blc = (blc >> 13) & 0x3;
@@ -398,7 +408,8 @@ static inline int get_blc(struct i2s_dai *i2s) /* TX Channel Control */ static void i2s_txctrl(struct i2s_dai *i2s, int on) { - void __iomem *addr = i2s->addr; + struct samsung_i2s_priv *priv = i2s->priv; + void __iomem *addr = priv->addr; int txr_off = i2s->variant_regs->txr_off; u32 con = readl(addr + I2SCON); u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off); @@ -448,7 +459,8 @@ static void i2s_txctrl(struct i2s_dai *i2s, int on) /* RX Channel Control */ static void i2s_rxctrl(struct i2s_dai *i2s, int on) { - void __iomem *addr = i2s->addr; + struct samsung_i2s_priv *priv = i2s->priv; + void __iomem *addr = priv->addr; int txr_off = i2s->variant_regs->txr_off; u32 con = readl(addr + I2SCON); u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off); @@ -485,9 +497,9 @@ static inline void i2s_fifo(struct i2s_dai *i2s, u32 flush) return;
if (is_secondary(i2s)) - fic = i2s->addr + I2SFICS; + fic = i2s->priv->addr + I2SFICS; else - fic = i2s->addr + I2SFIC; + fic = i2s->priv->addr + I2SFIC;
/* Flush the FIFO */ writel(readl(fic) | flush, fic); @@ -516,7 +528,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, pm_runtime_get_sync(dai->dev);
spin_lock_irqsave(i2s->lock, flags); - mod = readl(i2s->addr + I2SMOD); + mod = readl(priv->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags);
switch (clk_id) { @@ -613,9 +625,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, }
spin_lock_irqsave(i2s->lock, flags); - mod = readl(i2s->addr + I2SMOD); + mod = readl(priv->addr + I2SMOD); mod = (mod & ~mask) | val; - writel(mod, i2s->addr + I2SMOD); + writel(mod, priv->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags); done: pm_runtime_put(dai->dev); @@ -698,7 +710,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
pm_runtime_get_sync(dai->dev); spin_lock_irqsave(i2s->lock, flags); - mod = readl(i2s->addr + I2SMOD); + mod = readl(priv->addr + I2SMOD); /* * Don't change the I2S mode if any controller is active on this * channel. @@ -714,7 +726,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
mod &= ~(sdf_mask | lrp_rlow | mod_slave); mod |= tmp; - writel(mod, i2s->addr + I2SMOD); + writel(mod, priv->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags); pm_runtime_put(dai->dev);
@@ -801,9 +813,9 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, }
spin_lock_irqsave(i2s->lock, flags); - mod = readl(i2s->addr + I2SMOD); + mod = readl(priv->addr + I2SMOD); mod = (mod & ~mask) | val; - writel(mod, i2s->addr + I2SMOD); + writel(mod, priv->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags);
snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); @@ -837,7 +849,7 @@ static int i2s_startup(struct snd_pcm_substream *substream, i2s->mode |= DAI_MANAGER;
if (!any_active(i2s) && (i2s->quirks & QUIRK_NEED_RSTCLR)) - writel(CON_RSTCLR, i2s->addr + I2SCON); + writel(CON_RSTCLR, i2s->priv->addr + I2SCON);
spin_unlock_irqrestore(&lock, flags);
@@ -920,7 +932,7 @@ static int config_setup(struct i2s_dai *i2s)
if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { psr = priv->rclk_srcrate / i2s->frmclk / rfs; - writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR); + writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR); dev_dbg(&i2s->pdev->dev, "RCLK_SRC=%luHz PSR=%u, RCLK=%dfs, BCLK=%dfs\n", priv->rclk_srcrate, psr, rfs, bfs); @@ -1008,8 +1020,9 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai, static snd_pcm_sframes_t i2s_delay(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); - u32 reg = readl(i2s->addr + I2SFIC); + u32 reg = readl(priv->addr + I2SFIC); snd_pcm_sframes_t delay; const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
@@ -1018,7 +1031,7 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) delay = FIC_RXCOUNT(reg); else if (is_secondary(i2s)) - delay = FICS_TXCOUNT(readl(i2s->addr + I2SFICS)); + delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS)); else delay = (reg >> i2s_regs->ftx0cnt_off) & 0x7f;
@@ -1042,6 +1055,7 @@ static int i2s_resume(struct snd_soc_dai *dai)
static int samsung_i2s_dai_probe(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; @@ -1056,10 +1070,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) &i2s->dma_capture);
if (i2s->quirks & QUIRK_NEED_RSTCLR) - writel(CON_RSTCLR, i2s->addr + I2SCON); + writel(CON_RSTCLR, priv->addr + I2SCON);
if (i2s->quirks & QUIRK_SUPPORTS_IDMA) - idma_reg_addr_init(i2s->addr, + idma_reg_addr_init(priv->addr, i2s->sec_dai->idma_playback.addr); }
@@ -1094,7 +1108,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) if (!is_secondary(i2s)) { if (i2s->quirks & QUIRK_NEED_RSTCLR) { spin_lock_irqsave(i2s->lock, flags); - writel(0, i2s->addr + I2SCON); + writel(0, i2s->priv->addr + I2SCON); spin_unlock_irqrestore(i2s->lock, flags); } } @@ -1205,11 +1219,10 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, static int i2s_runtime_suspend(struct device *dev) { struct samsung_i2s_priv *priv = dev_get_drvdata(dev); - struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev);
- priv->suspend_i2smod = readl(i2s->addr + I2SMOD); - priv->suspend_i2scon = readl(i2s->addr + I2SCON); - priv->suspend_i2spsr = readl(i2s->addr + I2SPSR); + priv->suspend_i2smod = readl(priv->addr + I2SMOD); + priv->suspend_i2scon = readl(priv->addr + I2SCON); + priv->suspend_i2spsr = readl(priv->addr + I2SPSR);
if (priv->op_clk) clk_disable_unprepare(priv->op_clk); @@ -1221,7 +1234,6 @@ static int i2s_runtime_suspend(struct device *dev) static int i2s_runtime_resume(struct device *dev) { struct samsung_i2s_priv *priv = dev_get_drvdata(dev); - struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev); int ret;
ret = clk_prepare_enable(priv->clk); @@ -1236,9 +1248,9 @@ static int i2s_runtime_resume(struct device *dev) } }
- writel(priv->suspend_i2scon, i2s->addr + I2SCON); - writel(priv->suspend_i2smod, i2s->addr + I2SMOD); - writel(priv->suspend_i2spsr, i2s->addr + I2SPSR); + writel(priv->suspend_i2scon, priv->addr + I2SCON); + writel(priv->suspend_i2smod, priv->addr + I2SMOD); + writel(priv->suspend_i2spsr, priv->addr + I2SPSR);
return 0; } @@ -1296,21 +1308,21 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv)
if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { /* Activate the prescaler */ - u32 val = readl(i2s->addr + I2SPSR); - writel(val | PSR_PSREN, i2s->addr + I2SPSR); + u32 val = readl(priv->addr + I2SPSR); + writel(val | PSR_PSREN, priv->addr + I2SPSR);
priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev, i2s_clk_name[CLK_I2S_RCLK_SRC], p_names, ARRAY_SIZE(p_names), CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, - i2s->addr + I2SMOD, reg_info->rclksrc_off, + priv->addr + I2SMOD, reg_info->rclksrc_off, 1, 0, i2s->lock);
priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev, i2s_clk_name[CLK_I2S_RCLK_PSR], i2s_clk_name[CLK_I2S_RCLK_SRC], CLK_SET_RATE_PARENT, - i2s->addr + I2SPSR, 8, 6, 0, i2s->lock); + priv->addr + I2SPSR, 8, 6, 0, i2s->lock);
p_names[0] = i2s_clk_name[CLK_I2S_RCLK_PSR]; priv->clk_data.clk_num = 2; @@ -1319,7 +1331,7 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev, i2s_clk_name[CLK_I2S_CDCLK], p_names[0], CLK_SET_RATE_PARENT, - i2s->addr + I2SMOD, reg_info->cdclkcon_off, + priv->addr + I2SMOD, reg_info->cdclkcon_off, CLK_GATE_SET_TO_DISABLE, i2s->lock);
priv->clk_data.clk_num += 1; @@ -1423,9 +1435,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pri_dai->addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pri_dai->addr)) - return PTR_ERR(pri_dai->addr); + priv->addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->addr)) + return PTR_ERR(priv->addr);
regs_base = res->start;
@@ -1472,7 +1484,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) }
sec_dai->dma_playback.addr_width = 4; - sec_dai->addr = pri_dai->addr; sec_dai->quirks = quirks; sec_dai->idma_playback.addr = idma_addr; sec_dai->pri_dai = pri_dai;
As we now have the 'priv' pointer in most of the places we can use priv->lock directly, dropping extra indirection in the SFR region spinlock access.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 51 +++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 27 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 05f1de208307..0da07975d59b 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -87,8 +87,6 @@ struct i2s_dai { u32 quirks; const struct samsung_i2s_variant_regs *variant_regs;
- spinlock_t *lock; - struct samsung_i2s_priv *priv; };
@@ -103,7 +101,7 @@ struct samsung_i2s_priv { void __iomem *addr;
/* Spinlock protecting access to the device's registers */ - spinlock_t spinlock; + spinlock_t lock;
/* CPU DAIs and their corresponding drivers */ struct i2s_dai *dai; @@ -527,9 +525,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs,
pm_runtime_get_sync(dai->dev);
- spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags); mod = readl(priv->addr + I2SMOD); - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags);
switch (clk_id) { case SAMSUNG_I2S_OPCLK: @@ -624,11 +622,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, goto err; }
- spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags); mod = readl(priv->addr + I2SMOD); mod = (mod & ~mask) | val; writel(mod, priv->addr + I2SMOD); - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); done: pm_runtime_put(dai->dev);
@@ -709,7 +707,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) }
pm_runtime_get_sync(dai->dev); - spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags); mod = readl(priv->addr + I2SMOD); /* * Don't change the I2S mode if any controller is active on this @@ -717,7 +715,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(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); pm_runtime_put(dai->dev); dev_err(&i2s->pdev->dev, "%s:%d Other DAI busy\n", __func__, __LINE__); @@ -727,7 +725,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) mod &= ~(sdf_mask | lrp_rlow | mod_slave); mod |= tmp; writel(mod, priv->addr + I2SMOD); - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); pm_runtime_put(dai->dev);
return 0; @@ -812,11 +810,11 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; }
- spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags); mod = readl(priv->addr + I2SMOD); mod = (mod & ~mask) | val; writel(mod, priv->addr + I2SMOD); - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags);
snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
@@ -944,6 +942,7 @@ static int config_setup(struct i2s_dai *i2s) static int i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { + struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); struct snd_soc_pcm_runtime *rtd = substream->private_data; struct i2s_dai *i2s = to_info(rtd->cpu_dai); @@ -954,10 +953,10 @@ static int i2s_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: pm_runtime_get_sync(dai->dev); - spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags);
if (config_setup(i2s)) { - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return -EINVAL; }
@@ -966,12 +965,12 @@ static int i2s_trigger(struct snd_pcm_substream *substream, else i2s_txctrl(i2s, 1);
- spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags);
if (capture) { i2s_rxctrl(i2s, 0); @@ -981,7 +980,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, i2s_fifo(i2s, FIC_TXFLUSH); }
- spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); pm_runtime_put(dai->dev); break; } @@ -1081,13 +1080,13 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) i2s->rfs = 0; i2s->bfs = 0;
- spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags); i2s_txctrl(i2s, 0); i2s_rxctrl(i2s, 0); i2s_fifo(i2s, FIC_TXFLUSH); i2s_fifo(other, FIC_TXFLUSH); i2s_fifo(i2s, FIC_RXFLUSH); - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags);
/* Gate CDCLK by default */ if (!is_opened(other)) @@ -1107,9 +1106,9 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
if (!is_secondary(i2s)) { if (i2s->quirks & QUIRK_NEED_RSTCLR) { - spin_lock_irqsave(i2s->lock, flags); + spin_lock_irqsave(&priv->lock, flags); writel(0, i2s->priv->addr + I2SCON); - spin_unlock_irqrestore(i2s->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } }
@@ -1316,13 +1315,13 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) ARRAY_SIZE(p_names), CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, priv->addr + I2SMOD, reg_info->rclksrc_off, - 1, 0, i2s->lock); + 1, 0, &priv->lock);
priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev, i2s_clk_name[CLK_I2S_RCLK_PSR], i2s_clk_name[CLK_I2S_RCLK_SRC], CLK_SET_RATE_PARENT, - priv->addr + I2SPSR, 8, 6, 0, i2s->lock); + priv->addr + I2SPSR, 8, 6, 0, &priv->lock);
p_names[0] = i2s_clk_name[CLK_I2S_RCLK_PSR]; priv->clk_data.clk_num = 2; @@ -1332,7 +1331,7 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) i2s_clk_name[CLK_I2S_CDCLK], p_names[0], CLK_SET_RATE_PARENT, priv->addr + I2SMOD, reg_info->cdclkcon_off, - CLK_GATE_SET_TO_DISABLE, i2s->lock); + CLK_GATE_SET_TO_DISABLE, &priv->lock);
priv->clk_data.clk_num += 1; priv->clk_data.clks = priv->clk_table; @@ -1410,8 +1409,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1];
- spin_lock_init(&priv->spinlock); - pri_dai->lock = &priv->spinlock; + spin_lock_init(&priv->lock);
if (!np) { if (i2s_pdata == NULL) { @@ -1473,7 +1471,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (quirks & QUIRK_SEC_DAI) { sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1];
- sec_dai->lock = &priv->spinlock; sec_dai->variant_regs = pri_dai->variant_regs; sec_dai->dma_playback.addr = regs_base + I2STXDS; sec_dai->dma_playback.chan_name = "tx-sec";
On Tue, Feb 12, 2019 at 07:03:29PM +0100, Sylwester Nawrocki wrote:
As we now have the 'priv' pointer in most of the places we can use priv->lock directly, dropping extra indirection in the SFR region spinlock access.
This doesn't build for me:
CC sound/soc/samsung/i2s.o In file included from ./include/linux/spinlock.h:309, from ./include/linux/mmzone.h:8, from ./include/linux/gfp.h:6, from ./include/linux/slab.h:15, from sound/soc/samsung/i2s.c:15: sound/soc/samsung/i2s.c: In function ‘samsung_i2s_dai_remove’: sound/soc/samsung/i2s.c:1109:23: error: ‘priv’ undeclared (first use in this function); did you mean ‘pid’? spin_lock_irqsave(&priv->lock, flags); ^~~~
The IP variant data is another thing common for both DAIs, move it to the driver's common data structure.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 0da07975d59b..8352f610ce35 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -85,7 +85,6 @@ struct i2s_dai { struct snd_dmaengine_dai_dma_data idma_playback; dma_filter_fn filter; u32 quirks; - const struct samsung_i2s_variant_regs *variant_regs;
struct samsung_i2s_priv *priv; }; @@ -122,6 +121,8 @@ struct samsung_i2s_priv { u32 suspend_i2scon; u32 suspend_i2spsr;
+ const struct samsung_i2s_variant_regs *variant_regs; + /* The clock provider's data */ struct clk *clk_table[3]; struct clk_onecell_data clk_data; @@ -146,7 +147,7 @@ static inline bool is_slave(struct i2s_dai *i2s) struct samsung_i2s_priv *priv = i2s->priv;
u32 mod = readl(priv->addr + I2SMOD); - return (mod & (1 << i2s->variant_regs->mss_off)) ? true : false; + return (mod & (1 << priv->variant_regs->mss_off)) ? true : false; }
/* If this interface of the controller is transmitting data */ @@ -261,8 +262,8 @@ static inline unsigned get_rfs(struct i2s_dai *i2s) struct samsung_i2s_priv *priv = i2s->priv; u32 rfs;
- rfs = readl(priv->addr + I2SMOD) >> i2s->variant_regs->rfs_off; - rfs &= i2s->variant_regs->rfs_mask; + rfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->rfs_off; + rfs &= priv->variant_regs->rfs_mask;
switch (rfs) { case 7: return 192; @@ -281,9 +282,9 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) { struct samsung_i2s_priv *priv = i2s->priv; u32 mod = readl(priv->addr + I2SMOD); - int rfs_shift = i2s->variant_regs->rfs_off; + int rfs_shift = priv->variant_regs->rfs_off;
- mod &= ~(i2s->variant_regs->rfs_mask << rfs_shift); + mod &= ~(priv->variant_regs->rfs_mask << rfs_shift);
switch (rfs) { case 192: @@ -321,8 +322,8 @@ static inline unsigned get_bfs(struct i2s_dai *i2s) struct samsung_i2s_priv *priv = i2s->priv; u32 bfs;
- bfs = readl(priv->addr + I2SMOD) >> i2s->variant_regs->bfs_off; - bfs &= i2s->variant_regs->bfs_mask; + bfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->bfs_off; + bfs &= priv->variant_regs->bfs_mask;
switch (bfs) { case 8: return 256; @@ -343,7 +344,7 @@ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) struct samsung_i2s_priv *priv = i2s->priv; u32 mod = readl(priv->addr + I2SMOD); int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM; - int bfs_shift = i2s->variant_regs->bfs_off; + int bfs_shift = priv->variant_regs->bfs_off;
/* Non-TDM I2S controllers do not support BCLK > 48 * FS */ if (!tdm && bfs > 48) { @@ -351,7 +352,7 @@ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) return; }
- mod &= ~(i2s->variant_regs->bfs_mask << bfs_shift); + mod &= ~(priv->variant_regs->bfs_mask << bfs_shift);
switch (bfs) { case 48: @@ -408,7 +409,7 @@ static void i2s_txctrl(struct i2s_dai *i2s, int on) { struct samsung_i2s_priv *priv = i2s->priv; void __iomem *addr = priv->addr; - int txr_off = i2s->variant_regs->txr_off; + int txr_off = priv->variant_regs->txr_off; u32 con = readl(addr + I2SCON); u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);
@@ -459,7 +460,7 @@ static void i2s_rxctrl(struct i2s_dai *i2s, int on) { struct samsung_i2s_priv *priv = i2s->priv; void __iomem *addr = priv->addr; - int txr_off = i2s->variant_regs->txr_off; + int txr_off = priv->variant_regs->txr_off; u32 con = readl(addr + I2SCON); u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);
@@ -516,7 +517,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, 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); - const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; + const struct samsung_i2s_variant_regs *i2s_regs = priv->variant_regs; unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; u32 mod, mask, val = 0; @@ -644,9 +645,9 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) u32 mod, tmp = 0; unsigned long flags;
- lrp_shift = i2s->variant_regs->lrp_off; - sdf_shift = i2s->variant_regs->sdf_off; - mod_slave = 1 << i2s->variant_regs->mss_off; + lrp_shift = priv->variant_regs->lrp_off; + sdf_shift = priv->variant_regs->sdf_off; + mod_slave = 1 << priv->variant_regs->mss_off;
sdf_mask = MOD_SDF_MASK << sdf_shift; lrp_rlow = MOD_LR_RLOW << lrp_shift; @@ -1023,7 +1024,6 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) struct i2s_dai *i2s = to_info(dai); u32 reg = readl(priv->addr + I2SFIC); snd_pcm_sframes_t delay; - const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
WARN_ON(!pm_runtime_active(dai->dev));
@@ -1032,7 +1032,7 @@ i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) else if (is_secondary(i2s)) delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS)); else - delay = (reg >> i2s_regs->ftx0cnt_off) & 0x7f; + delay = (reg >> priv->variant_regs->ftx0cnt_off) & 0x7f;
return delay; } @@ -1280,7 +1280,7 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) const char *p_names[2] = { NULL }; struct device *dev = &priv->pdev->dev; struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev); - const struct samsung_i2s_variant_regs *reg_info = i2s->variant_regs; + const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs; const char *i2s_clk_name[ARRAY_SIZE(i2s_clk_desc)]; struct clk *rclksrc; int ret, i; @@ -1399,6 +1399,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (!priv) return -ENOMEM;
+ priv->variant_regs = i2s_dai_data->i2s_variant_regs; + quirks = np ? i2s_dai_data->quirks : i2s_pdata->type.quirks; num_dais = (quirks & QUIRK_SEC_DAI) ? 2 : 1; priv->pdev = pdev; @@ -1457,7 +1459,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai->dma_playback.addr_width = 4; pri_dai->dma_capture.addr_width = 4; pri_dai->quirks = quirks; - pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs; pri_dai->priv = priv;
if (quirks & QUIRK_PRI_6CHAN) @@ -1471,7 +1472,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (quirks & QUIRK_SEC_DAI) { sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1];
- sec_dai->variant_regs = pri_dai->variant_regs; sec_dai->dma_playback.addr = regs_base + I2STXDS; sec_dai->dma_playback.chan_name = "tx-sec";
The quirk flags are common for the primary and the secondary DAI so move respective field from struct i2s_dai to common driver data structure.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 8352f610ce35..14d9fd658cfd 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -84,7 +84,6 @@ struct i2s_dai { struct snd_dmaengine_dai_dma_data dma_capture; struct snd_dmaengine_dai_dma_data idma_playback; dma_filter_fn filter; - u32 quirks;
struct samsung_i2s_priv *priv; }; @@ -122,19 +121,13 @@ struct samsung_i2s_priv { u32 suspend_i2spsr;
const struct samsung_i2s_variant_regs *variant_regs; + u32 quirks;
/* The clock provider's data */ struct clk *clk_table[3]; struct clk_onecell_data clk_data; };
-struct i2s_dai *samsung_i2s_get_pri_dai(struct device *dev) -{ - struct samsung_i2s_priv *priv = dev_get_drvdata(dev); - - return &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1]; -} - /* Returns true if this is the 'overlay' stereo DAI */ static inline bool is_secondary(struct i2s_dai *i2s) { @@ -343,7 +336,7 @@ static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) { struct samsung_i2s_priv *priv = i2s->priv; u32 mod = readl(priv->addr + I2SMOD); - int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM; + int tdm = priv->quirks & QUIRK_SUPPORTS_TDM; int bfs_shift = priv->variant_regs->bfs_off;
/* Non-TDM I2S controllers do not support BCLK > 48 * FS */ @@ -563,7 +556,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */ mask = 1 << i2s_regs->rclksrc_off;
- if ((i2s->quirks & QUIRK_NO_MUXPSR) + if ((priv->quirks & QUIRK_NO_MUXPSR) || (clk_id == SAMSUNG_I2S_RCLKSRC_0)) clk_id = 0; else @@ -832,6 +825,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, static int i2s_startup(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; @@ -847,7 +841,7 @@ static int i2s_startup(struct snd_pcm_substream *substream, else i2s->mode |= DAI_MANAGER;
- if (!any_active(i2s) && (i2s->quirks & QUIRK_NEED_RSTCLR)) + if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR)) writel(CON_RSTCLR, i2s->priv->addr + I2SCON);
spin_unlock_irqrestore(&lock, flags); @@ -929,7 +923,7 @@ static int config_setup(struct i2s_dai *i2s) if (is_slave(i2s)) return 0;
- if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { + if (!(priv->quirks & QUIRK_NO_MUXPSR)) { psr = priv->rclk_srcrate / i2s->frmclk / rfs; writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR); dev_dbg(&i2s->pdev->dev, @@ -1068,10 +1062,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
- if (i2s->quirks & QUIRK_NEED_RSTCLR) + if (priv->quirks & QUIRK_NEED_RSTCLR) writel(CON_RSTCLR, priv->addr + I2SCON);
- if (i2s->quirks & QUIRK_SUPPORTS_IDMA) + if (priv->quirks & QUIRK_SUPPORTS_IDMA) idma_reg_addr_init(priv->addr, i2s->sec_dai->idma_playback.addr); } @@ -1099,13 +1093,14 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) { + struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); struct i2s_dai *i2s = to_info(dai); unsigned long flags;
pm_runtime_get_sync(dai->dev);
if (!is_secondary(i2s)) { - if (i2s->quirks & QUIRK_NEED_RSTCLR) { + if (priv->quirks & QUIRK_NEED_RSTCLR) { spin_lock_irqsave(&priv->lock, flags); writel(0, i2s->priv->addr + I2SCON); spin_unlock_irqrestore(&priv->lock, flags); @@ -1279,7 +1274,6 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" }; const char *p_names[2] = { NULL }; struct device *dev = &priv->pdev->dev; - struct i2s_dai *i2s = samsung_i2s_get_pri_dai(dev); const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs; const char *i2s_clk_name[ARRAY_SIZE(i2s_clk_desc)]; struct clk *rclksrc; @@ -1305,7 +1299,7 @@ static int i2s_register_clock_provider(struct samsung_i2s_priv *priv) return -ENOMEM; }
- if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { + if (!(priv->quirks & QUIRK_NO_MUXPSR)) { /* Activate the prescaler */ u32 val = readl(priv->addr + I2SPSR); writel(val | PSR_PSREN, priv->addr + I2SPSR); @@ -1399,11 +1393,11 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (!priv) return -ENOMEM;
- priv->variant_regs = i2s_dai_data->i2s_variant_regs; - quirks = np ? i2s_dai_data->quirks : i2s_pdata->type.quirks; num_dais = (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) @@ -1458,7 +1452,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai->dma_capture.chan_name = "rx"; pri_dai->dma_playback.addr_width = 4; pri_dai->dma_capture.addr_width = 4; - pri_dai->quirks = quirks; pri_dai->priv = priv;
if (quirks & QUIRK_PRI_6CHAN) @@ -1481,7 +1474,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) }
sec_dai->dma_playback.addr_width = 4; - sec_dai->quirks = quirks; sec_dai->idma_playback.addr = idma_addr; sec_dai->pri_dai = pri_dai; sec_dai->priv = priv;
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.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- 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 14d9fd658cfd..1156d63ce923 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; @@ -832,7 +832,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;
@@ -844,7 +844,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; } @@ -852,11 +852,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; @@ -868,7 +869,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); } @@ -1406,6 +1407,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) {
This patch adds DPCM links in order to support the secondary I2S interface. For the secondary PCM interface to be actually available one more entry should be added to the sound-dai property in sound/cpu node in DT. The changes in driver are done in a way so we are backwards compatible with existing DTS/DTB, i.e. if the cpu sound-dai property contains only one entry only one PCM will be registered.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/odroid.c | 131 +++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 36 deletions(-)
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index e7b371b07230..18bb3bfe0300 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -7,6 +7,7 @@ */
#include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/module.h> @@ -17,21 +18,24 @@
struct odroid_priv { struct snd_soc_card card; - struct snd_soc_dai_link dai_link; - struct clk *clk_i2s_bus; struct clk *sclk_i2s; };
-static int odroid_card_startup(struct snd_pcm_substream *substream) +static int odroid_card_fe_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); + return 0; }
-static int odroid_card_hw_params(struct snd_pcm_substream *substream, +static const struct snd_soc_ops odroid_card_fe_ops = { + .startup = odroid_card_fe_startup, +}; + +static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -86,19 +90,55 @@ static int odroid_card_hw_params(struct snd_pcm_substream *substream, return 0; }
-static const struct snd_soc_ops odroid_card_ops = { - .startup = odroid_card_startup, - .hw_params = odroid_card_hw_params, +static const struct snd_soc_ops odroid_card_be_ops = { + .hw_params = odroid_card_be_hw_params, +}; + +static struct snd_soc_dai_link odroid_card_dais[] = { + { + /* Primary FE <-> BE link */ + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .ops = &odroid_card_fe_ops, + .name = "Primary", + .stream_name = "Primary", + .platform_name = "3830000.i2s", + .dynamic = 1, + .dpcm_playback = 1, + }, { + /* BE <-> CODECs link */ + .name = "I2S Mixer", + .cpu_name = "snd-soc-dummy", + .cpu_dai_name = "snd-soc-dummy-dai", + .platform_name = "snd-soc-dummy", + .ops = &odroid_card_be_ops, + .no_pcm = 1, + .dpcm_playback = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, { + /* Secondary FE <-> BE link */ + .playback_only = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .ops = &odroid_card_fe_ops, + .name = "Secondary", + .stream_name = "Secondary", + .platform_name = "samsung-i2s-sec", + .dynamic = 1, + .dpcm_playback = 1, + } };
static int odroid_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *cpu, *codec; + struct device_node *cpu, *cpu_dai, *codec; struct odroid_priv *priv; - struct snd_soc_dai_link *link; struct snd_soc_card *card; - int ret; + struct snd_soc_dai_link *link, *codec_link; + int num_pcms, ret, i; + struct of_phandle_args args = {};
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -130,45 +170,67 @@ static int odroid_audio_probe(struct platform_device *pdev) return ret; }
- link = &priv->dai_link; - - link->ops = &odroid_card_ops; - link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; - - card->dai_link = &priv->dai_link; - card->num_links = 1; + card->dai_link = odroid_card_dais; + card->num_links = ARRAY_SIZE(odroid_card_dais);
cpu = of_get_child_by_name(dev->of_node, "cpu"); codec = of_get_child_by_name(dev->of_node, "codec"); + link = card->dai_link; + codec_link = &card->dai_link[1];
- link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); - if (!link->cpu_of_node) { - dev_err(dev, "Failed parsing cpu/sound-dai property\n"); - return -EINVAL; + /* + * 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. + */ + num_pcms = of_count_phandle_with_args(cpu, "sound-dai", + "#sound-dai-cells"); + if (num_pcms == 1) + card->num_links--; + + for (i = 0; i < num_pcms; i++, link += 2) { + ret = of_parse_phandle_with_args(cpu, "sound-dai", + "#sound-dai-cells", i, &args); + if (ret < 0) + return ret; + + if (!args.np) { + dev_err(dev, "sound-dai property parse error: %d\n", ret); + return -EINVAL; + } + + ret = snd_soc_get_dai_name(&args, &link->cpu_dai_name); + of_node_put(args.np); + + if (ret < 0) + return ret; }
- ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); + cpu_dai = of_parse_phandle(cpu, "sound-dai", 0); + of_node_put(cpu); + of_node_put(codec); + + ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link); if (ret < 0) goto err_put_codec_n;
- link->platform_of_node = link->cpu_of_node; - - link->name = "Primary"; - link->stream_name = link->name; - + /* Set capture capability only for boards with the MAX98090 CODEC */ + if (codec_link->num_codecs > 1) { + card->dai_link[0].dpcm_capture = 1; + card->dai_link[1].dpcm_capture = 1; + }
- priv->sclk_i2s = of_clk_get_by_name(link->cpu_of_node, "i2s_opclk1"); + 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_i2s_n; + goto err_put_codec_n; }
- priv->clk_i2s_bus = of_clk_get_by_name(link->cpu_of_node, "iis"); + priv->clk_i2s_bus = of_clk_get_by_name(cpu_dai, "iis"); if (IS_ERR(priv->clk_i2s_bus)) { ret = PTR_ERR(priv->clk_i2s_bus); goto err_put_sclk; } + of_node_put(cpu_dai);
ret = devm_snd_soc_register_card(dev, card); if (ret < 0) { @@ -182,10 +244,8 @@ static int odroid_audio_probe(struct platform_device *pdev) clk_put(priv->clk_i2s_bus); err_put_sclk: clk_put(priv->sclk_i2s); -err_put_i2s_n: - of_node_put(link->cpu_of_node); err_put_codec_n: - snd_soc_of_put_dai_link_codecs(link); + snd_soc_of_put_dai_link_codecs(codec_link); return ret; }
@@ -193,8 +253,7 @@ static int odroid_audio_remove(struct platform_device *pdev) { struct odroid_priv *priv = platform_get_drvdata(pdev);
- of_node_put(priv->dai_link.cpu_of_node); - snd_soc_of_put_dai_link_codecs(&priv->dai_link); + snd_soc_of_put_dai_link_codecs(&priv->card.dai_link[1]); clk_put(priv->sclk_i2s); clk_put(priv->clk_i2s_bus);
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.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- 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 84601fa9aa46..302871974cb3 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 1156d63ce923..72282d08d2c1 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1460,7 +1460,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 67dfa27ae321..c08638b0e458 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 ba0f2b94f8d4..a8026b640c95 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;
There is now no need to pass DMA channel names through the DAI DMA data, custom DMA config of the PCM is now used for this purpose.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- sound/soc/samsung/i2s.c | 4 ---- sound/soc/samsung/s3c2412-i2s.c | 2 -- sound/soc/samsung/s3c24xx-i2s.c | 2 -- 3 files changed, 8 deletions(-)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 72282d08d2c1..f438558c4d21 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1450,8 +1450,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) } pri_dai->dma_playback.addr = regs_base + I2STXD; pri_dai->dma_capture.addr = regs_base + I2SRXD; - pri_dai->dma_playback.chan_name = "tx"; - pri_dai->dma_capture.chan_name = "rx"; pri_dai->dma_playback.addr_width = 4; pri_dai->dma_capture.addr_width = 4; pri_dai->priv = priv; @@ -1466,9 +1464,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
if (quirks & QUIRK_SEC_DAI) { sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1]; - sec_dai->dma_playback.addr = regs_base + I2STXDS; - sec_dai->dma_playback.chan_name = "tx-sec";
if (!np) { sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec; diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index c08638b0e458..a00e35147e50 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -35,12 +35,10 @@ #include <linux/platform_data/asoc-s3c.h>
static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_out = { - .chan_name = "tx", .addr_width = 4, };
static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_in = { - .chan_name = "rx", .addr_width = 4, };
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index a8026b640c95..600b3b4cdb5b 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -31,12 +31,10 @@ #include "s3c24xx-i2s.h"
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { - .chan_name = "tx", .addr_width = 2, };
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = { - .chan_name = "rx", .addr_width = 2, };
There is now no users of this flag so remove it together with related data structure field.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Acked-by: Krzysztof Kozlowski krzk@kernel.org --- include/sound/dmaengine_pcm.h | 6 ------ sound/soc/soc-generic-dmaengine-pcm.c | 21 ++++----------------- 2 files changed, 4 insertions(+), 23 deletions(-)
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 2c4cfaa135a6..764c787928a4 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -63,7 +63,6 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) * @slave_id: Slave requester id for the DMA channel. * @filter_data: Custom DMA channel filter data, this will usually be used when * requesting the DMA channel. - * @chan_name: Custom channel name to use when requesting DMA channel. * @fifo_size: FIFO size of the DAI controller in bytes * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now */ @@ -73,7 +72,6 @@ struct snd_dmaengine_dai_dma_data { u32 maxburst; unsigned int slave_id; void *filter_data; - const char *chan_name; unsigned int fifo_size; unsigned int flags; }; @@ -99,10 +97,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 1b44e363c50c..f1ab6285a085 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -265,7 +265,6 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) struct dmaengine_pcm *pcm = soc_component_to_pcm(component); const struct snd_dmaengine_pcm_config *config = pcm->config; struct device *dev = component->dev; - struct snd_dmaengine_dai_dma_data *dma_data; struct snd_pcm_substream *substream; size_t prealloc_buffer_size; size_t max_buffer_size; @@ -285,19 +284,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, @@ -420,10 +409,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) {
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.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com --- 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 f438558c4d21..097c641fc1b9 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1057,18 +1057,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 */
On Tue, 12 Feb 2019 at 19:05, Sylwester Nawrocki s.nawrocki@samsung.com wrote:
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.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
sound/soc/samsung/i2s.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
Acked-by: Krzysztof Kozlowski krzk@kernel.org
Best regards, Krzysztof
Change indentation so this macro definition spans 2 rows and looks more consistent with surrounding code.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com --- 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 097c641fc1b9..debeaf51cc7e 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1150,9 +1150,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.20.1
On Tue, 12 Feb 2019 at 19:05, Sylwester Nawrocki s.nawrocki@samsung.com wrote:
Change indentation so this macro definition spans 2 rows and looks more consistent with surrounding code.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
sound/soc/samsung/i2s.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
Acked-by: Krzysztof Kozlowski krzk@kernel.org
Best regards, Krzysztof
Spelling error fixes, upper/lower case letter changes.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com --- 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 debeaf51cc7e..77c0f70beab1 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,
On Tue, 12 Feb 2019 at 19:05, Sylwester Nawrocki s.nawrocki@samsung.com wrote:
Spelling error fixes, upper/lower case letter changes.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
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 debeaf51cc7e..77c0f70beab1 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 */
Just to be sure - did you check whether this passes GCC -Wimplicit-fallthrough=3 (you need GCC v7)? It looks correct - like one of accepted patterns (https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html).
Rest looks good so: Acked-by: Krzysztof Kozlowski krzk@kernel.org
Best regards, Krzysztof
On 2/13/19 09:06, Krzysztof Kozlowski wrote:
@@ -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 */
Just to be sure - did you check whether this passes GCC -Wimplicit-fallthrough=3 (you need GCC v7)? It looks correct - like one of accepted patterns (https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html).
I just checked it now and with comment in upper case the warning is also being suppressed.
Replace GPL v2.0 license statements with SPDX license identifier.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com --- 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 77c0f70beab1..e820d95a86be 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 jassisinghbrar@gmail.com - * - * 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 jassisinghbrar@gmail.com
#include <dt-bindings/sound/samsung-i2s.h> #include <linux/delay.h>
On Tue, 12 Feb 2019 at 19:05, Sylwester Nawrocki s.nawrocki@samsung.com wrote:
Replace GPL v2.0 license statements with SPDX license identifier.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
sound/soc/samsung/i2s.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
Acked-by: Krzysztof Kozlowski krzk@kernel.org
Best regards, Krzysztof
This patch extends DAPM routing and adds secondary CPU DAI entry to support the secondary audio PCM interface on Odroid XU3.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com --- arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi index e84544b220b9..51a843bd65ed 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi @@ -24,7 +24,9 @@ "Headphone Jack", "MICBIAS", "IN1", "Headphone Jack", "Speakers", "SPKL", - "Speakers", "SPKR"; + "Speakers", "SPKR", + "I2S Playback", "Mixer DAI TX", + "HiFi Playback", "Mixer DAI TX";
assigned-clocks = <&clock CLK_MOUT_EPLL>, <&clock CLK_MOUT_MAU_EPLL>, @@ -51,7 +53,7 @@ <196608000>;
cpu { - sound-dai = <&i2s0 0>; + sound-dai = <&i2s0 0>, <&i2s0 1>; }; codec { sound-dai = <&hdmi>, <&max98090>;
On Tue, Feb 12, 2019 at 07:03:41PM +0100, Sylwester Nawrocki wrote:
This patch extends DAPM routing and adds secondary CPU DAI entry to support the secondary audio PCM interface on Odroid XU3.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi | 6 ++++--
Thanks, applied.
Best regards, Krzysztof
This patch extends DAPM routing and adds secondary CPU DAI entry to support the secondary audio PCM interface on Odroid XU4.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com --- arch/arm/boot/dts/exynos5422-odroidxu4.dts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/exynos5422-odroidxu4.dts index 122174ea9e0a..892d389d6d09 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu4.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu4.dts @@ -33,6 +33,8 @@ compatible = "samsung,odroid-xu3-audio"; model = "Odroid-XU4";
+ samsung,audio-routing = "I2S Playback", "Mixer DAI TX"; + assigned-clocks = <&clock CLK_MOUT_EPLL>, <&clock CLK_MOUT_MAU_EPLL>, <&clock CLK_MOUT_USER_MAU_EPLL>, @@ -58,7 +60,7 @@ <196608000>;
cpu { - sound-dai = <&i2s0 0>; + sound-dai = <&i2s0 0>, <&i2s0 1>; };
codec {
On Tue, Feb 12, 2019 at 07:03:42PM +0100, Sylwester Nawrocki wrote:
This patch extends DAPM routing and adds secondary CPU DAI entry to support the secondary audio PCM interface on Odroid XU4.
Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
arch/arm/boot/dts/exynos5422-odroidxu4.dts | 4 +++-
Thanks, applied.
Best regards, Krzysztof
participants (3)
-
Krzysztof Kozlowski
-
Mark Brown
-
Sylwester Nawrocki