Commit 6bd0d979 authored by Detlev Casanova's avatar Detlev Casanova Committed by Wentao Guan
Browse files

ASoC: rockchip: i2s_tdm: Re-add the set_sysclk callback

stable inclusion
from stable-v6.6.76
commit 730071ea1ea76ca970eddb0dba9652fbe3dceb0e
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBW08Q

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=730071ea1ea76ca970eddb0dba9652fbe3dceb0e



--------------------------------

[ Upstream commit 5323186e2e8d33c073fad51e24f18e2d6dbae2da ]

In commit
9e2ab4b18ebd ("ASoC: rockchip: i2s-tdm: Fix inaccurate sampling rates"),
the set_sysclk callback was removed as considered unused as the mclk rate
can be set in the hw_params callback.
The difference between hw_params and set_sysclk is that the former is
called with the audio sampling rate set in the params (e.g.: 48000 Hz)
while the latter is called with a clock rate already computed with
  sampling_rate * mclk-fs (e.g.: 48000 * 256)

For HDMI audio using the Rockchip I2S TDM driver, the mclk-fs value must
be set to 128 instead of the default 256, and that value is set in the
device tree at the machine driver level (like a simple-audio-card
compatible node).
Therefore, the i2s_tdm driver has no idea that another mclk-fs value can
be configured and simply computes the mclk rate in the hw_params callback
with DEFAULT_MCLK_FS * params_rate(params), which is wrong for HDMI
audio.

Re-add the set_sysclk callback so that the mclk rate is computed by the
machine driver which has the correct mclk-fs value set in its device tree
node.

Fixes: 9e2ab4b18ebd ("ASoC: rockchip: i2s-tdm: Fix inaccurate sampling rates")
Signed-off-by: default avatarDetlev Casanova <detlev.casanova@collabora.com>
Link: https://patch.msgid.link/20250117163102.65807-1-detlev.casanova@collabora.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
(cherry picked from commit 730071ea1ea76ca970eddb0dba9652fbe3dceb0e)
Signed-off-by: default avatarWentao Guan <guanwentao@uniontech.com>
parent 97324d8d
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@

#define DRV_NAME "rockchip-i2s-tdm"

#define DEFAULT_MCLK_FS				256
#define CH_GRP_MAX				4  /* The max channel 8 / 2 */
#define MULTIPLEX_CH_MAX			10

@@ -72,6 +71,8 @@ struct rk_i2s_tdm_dev {
	bool has_playback;
	bool has_capture;
	struct snd_soc_dai_driver *dai;
	unsigned int mclk_rx_freq;
	unsigned int mclk_tx_freq;
};

static int to_ch_num(unsigned int val)
@@ -647,6 +648,27 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
	return 0;
}

static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream,
				       unsigned int freq, int dir)
{
	struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);

	if (i2s_tdm->clk_trcm) {
		i2s_tdm->mclk_tx_freq = freq;
		i2s_tdm->mclk_rx_freq = freq;
	} else {
		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
			i2s_tdm->mclk_tx_freq = freq;
		else
			i2s_tdm->mclk_rx_freq = freq;
	}

	dev_dbg(i2s_tdm->dev, "The target mclk_%s freq is: %d\n",
		stream ? "rx" : "tx", freq);

	return 0;
}

static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
				      struct snd_pcm_hw_params *params,
				      struct snd_soc_dai *dai)
@@ -661,15 +683,19 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,

		if (i2s_tdm->clk_trcm == TRCM_TX) {
			mclk = i2s_tdm->mclk_tx;
			mclk_rate = i2s_tdm->mclk_tx_freq;
		} else if (i2s_tdm->clk_trcm == TRCM_RX) {
			mclk = i2s_tdm->mclk_rx;
			mclk_rate = i2s_tdm->mclk_rx_freq;
		} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mclk = i2s_tdm->mclk_tx;
			mclk_rate = i2s_tdm->mclk_tx_freq;
		} else {
			mclk = i2s_tdm->mclk_rx;
			mclk_rate = i2s_tdm->mclk_rx_freq;
		}

		err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));
		err = clk_set_rate(mclk, mclk_rate);
		if (err)
			return err;

@@ -829,6 +855,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
	.hw_params = rockchip_i2s_tdm_hw_params,
	.set_bclk_ratio	= rockchip_i2s_tdm_set_bclk_ratio,
	.set_fmt = rockchip_i2s_tdm_set_fmt,
	.set_sysclk = rockchip_i2s_tdm_set_sysclk,
	.set_tdm_slot = rockchip_dai_tdm_slot,
	.trigger = rockchip_i2s_tdm_trigger,
};