]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ASoC: rockchip: i2s_tdm: Re-add the set_sysclk callback
authorDetlev Casanova <detlev.casanova@collabora.com>
Fri, 17 Jan 2025 16:31:02 +0000 (11:31 -0500)
committerMark Brown <broonie@kernel.org>
Tue, 21 Jan 2025 15:21:49 +0000 (15:21 +0000)
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: Detlev Casanova <detlev.casanova@collabora.com>
Link: https://patch.msgid.link/20250117163102.65807-1-detlev.casanova@collabora.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/rockchip/rockchip_i2s_tdm.c

index bd0dc586e24a3c80d4883e123d9314fc0a37060f..7f5fcaecee4b628a4d53c9405859a6ad68729a40 100644 (file)
@@ -22,7 +22,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
 
@@ -70,6 +69,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)
@@ -617,6 +618,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)
@@ -631,15 +653,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;
 
@@ -799,6 +825,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,
 };