Commit 53689f7f authored by Nicolas Frattaroli's avatar Nicolas Frattaroli Committed by Mark Brown

ASoC: rockchip: i2s_tdm: Dup static DAI template

Previously, the DAI template was used directly, which lead to
fun bugs such as "why is my channels_max changing?" when one
instantiated more than one i2s_tdm IP block in a device tree.

This change makes it so that we instead duplicate the template
struct, and then use that.

Fixes: 081068fd ("ASoC: rockchip: add support for i2s-tdm controller")
Signed-off-by: default avatarNicolas Frattaroli <frattaroli.nicolas@gmail.com>
Link: https://lore.kernel.org/r/20211125084900.417102-1-frattaroli.nicolas@gmail.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8a724d5f
...@@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev { ...@@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev {
spinlock_t lock; /* xfer lock */ spinlock_t lock; /* xfer lock */
bool has_playback; bool has_playback;
bool has_capture; bool has_capture;
struct snd_soc_dai_driver *dai;
}; };
static int to_ch_num(unsigned int val) static int to_ch_num(unsigned int val)
...@@ -1310,19 +1311,14 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = { ...@@ -1310,19 +1311,14 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = {
{}, {},
}; };
static struct snd_soc_dai_driver i2s_tdm_dai = { static const struct snd_soc_dai_driver i2s_tdm_dai = {
.probe = rockchip_i2s_tdm_dai_probe, .probe = rockchip_i2s_tdm_dai_probe,
.playback = {
.stream_name = "Playback",
},
.capture = {
.stream_name = "Capture",
},
.ops = &rockchip_i2s_tdm_dai_ops, .ops = &rockchip_i2s_tdm_dai_ops,
}; };
static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
{ {
struct snd_soc_dai_driver *dai;
struct property *dma_names; struct property *dma_names;
const char *dma_name; const char *dma_name;
u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
...@@ -1337,19 +1333,33 @@ static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) ...@@ -1337,19 +1333,33 @@ static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
i2s_tdm->has_capture = true; i2s_tdm->has_capture = true;
} }
dai = devm_kmemdup(i2s_tdm->dev, &i2s_tdm_dai,
sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
if (i2s_tdm->has_playback) { if (i2s_tdm->has_playback) {
i2s_tdm_dai.playback.channels_min = 2; dai->playback.stream_name = "Playback";
i2s_tdm_dai.playback.channels_max = 8; dai->playback.channels_min = 2;
i2s_tdm_dai.playback.rates = SNDRV_PCM_RATE_8000_192000; dai->playback.channels_max = 8;
i2s_tdm_dai.playback.formats = formats; dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
dai->playback.formats = formats;
} }
if (i2s_tdm->has_capture) { if (i2s_tdm->has_capture) {
i2s_tdm_dai.capture.channels_min = 2; dai->capture.stream_name = "Capture";
i2s_tdm_dai.capture.channels_max = 8; dai->capture.channels_min = 2;
i2s_tdm_dai.capture.rates = SNDRV_PCM_RATE_8000_192000; dai->capture.channels_max = 8;
i2s_tdm_dai.capture.formats = formats; dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
dai->capture.formats = formats;
} }
if (i2s_tdm->clk_trcm != TRCM_TXRX)
dai->symmetric_rate = 1;
i2s_tdm->dai = dai;
return 0;
} }
static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm, static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm,
...@@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) ...@@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
spin_lock_init(&i2s_tdm->lock); spin_lock_init(&i2s_tdm->lock);
i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data; i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data;
rockchip_i2s_tdm_init_dai(i2s_tdm);
i2s_tdm->frame_width = 64; i2s_tdm->frame_width = 64;
i2s_tdm->clk_trcm = TRCM_TXRX; i2s_tdm->clk_trcm = TRCM_TXRX;
...@@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) ...@@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
} }
i2s_tdm->clk_trcm = TRCM_RX; i2s_tdm->clk_trcm = TRCM_RX;
} }
if (i2s_tdm->clk_trcm != TRCM_TXRX)
i2s_tdm_dai.symmetric_rate = 1; ret = rockchip_i2s_tdm_init_dai(i2s_tdm);
if (ret)
return ret;
i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
if (IS_ERR(i2s_tdm->grf)) if (IS_ERR(i2s_tdm->grf))
...@@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) ...@@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_component(&pdev->dev, ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_tdm_component, &rockchip_i2s_tdm_component,
&i2s_tdm_dai, 1); i2s_tdm->dai, 1);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Could not register DAI\n"); dev_err(&pdev->dev, "Could not register DAI\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment