Skip to content
Snippets Groups Projects
Commit ca20c40f authored by Detlev Casanova's avatar Detlev Casanova Committed by Frieder Schrempf
Browse files

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


[ Upstream commit 5323186e2e8d33c073fad51e24f18e2d6dbae2da ]

In commit
9e2ab4b1 ("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: 9e2ab4b1 ("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>
parent 394f04db
No related branches found
No related tags found
1 merge request!191🤖 Sync Bot: Update v6.1-ktn to Latest Stable Kernel (v6.1.129)
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#define DRV_NAME "rockchip-i2s-tdm" #define DRV_NAME "rockchip-i2s-tdm"
#define DEFAULT_MCLK_FS 256
#define CH_GRP_MAX 4 /* The max channel 8 / 2 */ #define CH_GRP_MAX 4 /* The max channel 8 / 2 */
#define MULTIPLEX_CH_MAX 10 #define MULTIPLEX_CH_MAX 10
...@@ -72,6 +71,8 @@ struct rk_i2s_tdm_dev { ...@@ -72,6 +71,8 @@ struct rk_i2s_tdm_dev {
bool has_playback; bool has_playback;
bool has_capture; bool has_capture;
struct snd_soc_dai_driver *dai; struct snd_soc_dai_driver *dai;
unsigned int mclk_rx_freq;
unsigned int mclk_tx_freq;
}; };
static int to_ch_num(unsigned int val) static int to_ch_num(unsigned int val)
...@@ -641,6 +642,27 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream, ...@@ -641,6 +642,27 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
return 0; 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, static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
...@@ -655,15 +677,19 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, ...@@ -655,15 +677,19 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
if (i2s_tdm->clk_trcm == TRCM_TX) { if (i2s_tdm->clk_trcm == TRCM_TX) {
mclk = i2s_tdm->mclk_tx; mclk = i2s_tdm->mclk_tx;
mclk_rate = i2s_tdm->mclk_tx_freq;
} else if (i2s_tdm->clk_trcm == TRCM_RX) { } else if (i2s_tdm->clk_trcm == TRCM_RX) {
mclk = i2s_tdm->mclk_rx; mclk = i2s_tdm->mclk_rx;
mclk_rate = i2s_tdm->mclk_rx_freq;
} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
mclk = i2s_tdm->mclk_tx; mclk = i2s_tdm->mclk_tx;
mclk_rate = i2s_tdm->mclk_tx_freq;
} else { } else {
mclk = i2s_tdm->mclk_rx; 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) if (err)
return err; return err;
...@@ -822,6 +848,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { ...@@ -822,6 +848,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
.hw_params = rockchip_i2s_tdm_hw_params, .hw_params = rockchip_i2s_tdm_hw_params,
.set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio, .set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio,
.set_fmt = rockchip_i2s_tdm_set_fmt, .set_fmt = rockchip_i2s_tdm_set_fmt,
.set_sysclk = rockchip_i2s_tdm_set_sysclk,
.set_tdm_slot = rockchip_dai_tdm_slot, .set_tdm_slot = rockchip_dai_tdm_slot,
.trigger = rockchip_i2s_tdm_trigger, .trigger = rockchip_i2s_tdm_trigger,
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment