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

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.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8a724d5f
Loading
Loading
Loading
Loading
+31 −21
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev {
	spinlock_t lock; /* xfer lock */
	bool has_playback;
	bool has_capture;
	struct snd_soc_dai_driver *dai;
};

static int to_ch_num(unsigned int val)
@@ -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,
	.playback = {
		.stream_name  = "Playback",
	},
	.capture = {
		.stream_name  = "Capture",
	},
	.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;
	const char *dma_name;
	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)
			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) {
		i2s_tdm_dai.playback.channels_min = 2;
		i2s_tdm_dai.playback.channels_max = 8;
		i2s_tdm_dai.playback.rates = SNDRV_PCM_RATE_8000_192000;
		i2s_tdm_dai.playback.formats = formats;
		dai->playback.stream_name  = "Playback";
		dai->playback.channels_min = 2;
		dai->playback.channels_max = 8;
		dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
		dai->playback.formats = formats;
	}

	if (i2s_tdm->has_capture) {
		i2s_tdm_dai.capture.channels_min = 2;
		i2s_tdm_dai.capture.channels_max = 8;
		i2s_tdm_dai.capture.rates = SNDRV_PCM_RATE_8000_192000;
		i2s_tdm_dai.capture.formats = formats;
		dai->capture.stream_name  = "Capture";
		dai->capture.channels_min = 2;
		dai->capture.channels_max = 8;
		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,
@@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
	spin_lock_init(&i2s_tdm->lock);
	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->clk_trcm = TRCM_TXRX;
@@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
		}
		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");
	if (IS_ERR(i2s_tdm->grf))
@@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)

	ret = devm_snd_soc_register_component(&pdev->dev,
					      &rockchip_i2s_tdm_component,
					      &i2s_tdm_dai, 1);
					      i2s_tdm->dai, 1);

	if (ret) {
		dev_err(&pdev->dev, "Could not register DAI\n");