I2s connected to MIKROE-506 (WM8731)

I was able to successfully connect the MIKROE-506 breakout board to i2s_8ch_0. Since it wasn’t straight forward and needed a small patch to simple-card, I’d like to share my results.

Per default, simple-card wants to set sysclock with id 0. This is hardcoded and causes an error in the wm8731 driver. We need a patch to make it configurable via devicetree:

diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h
index 69c66991eb1e..2bdf78813add 100644
--- a/include/sound/simple_card.h
+++ b/include/sound/simple_card.h
@@ -17,6 +17,7 @@
 struct asoc_simple_dai {
 	const char *name;
 	unsigned int sysclk;
+	int sysclk_id;
 	int slots;
 	int slot_width;
 	unsigned int tx_slot_mask;
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 974bfaa3f271..d591640b647e 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -79,6 +79,7 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
+	struct asoc_simple_dai *set;
 	struct simple_dai_props *dai_props =
 		&priv->dai_props[rtd - rtd->card->rtd];
 	unsigned int mclk, mclk_fs = 0;
@@ -91,12 +92,14 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,
 
 	if (mclk_fs) {
 		mclk = params_rate(params) * mclk_fs;
-		ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+		set = &dai_props->codec_dai;
+		ret = snd_soc_dai_set_sysclk(codec_dai, set->sysclk_id, mclk,
 					     SND_SOC_CLOCK_IN);
 		if (ret && ret != -ENOTSUPP)
 			goto err;
 
-		ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
+		set = &dai_props->cpu_dai;
+		ret = snd_soc_dai_set_sysclk(cpu_dai, set->sysclk_id, mclk,
 					     SND_SOC_CLOCK_OUT);
 		if (ret && ret != -ENOTSUPP)
 			goto err;
@@ -150,7 +153,7 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
 	int ret;
 
 	if (set->sysclk) {
-		ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
+		ret = snd_soc_dai_set_sysclk(dai, set->sysclk_id, set->sysclk, 0);
 		if (ret && ret != -ENOTSUPP) {
 			dev_err(dai->dev, "simple-card: set_sysclk error\n");
 			goto err;
@@ -266,6 +269,10 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
 	if (ret)
 		return ret;
 
+	ret = of_property_read_u32(np, "system-clock-id", &val);
+	if (ret == 0)
+		dai->sysclk_id = val;
+
 	/*
 	 * Parse dai->sysclk come from "clocks = <&xxx>"
 	 * (if system has common clock)

In the devicetree overlay, we want to set the system clock id of the codec to 1, which enables the onboard 12.288MHz oscillator as external clock. We also only want to use the I2S0_8CH_LRCK_TX clock signal an need to set rockchip,clk-trcm = <1> in the &i2s_8ch_0 section:

/dts-v1/;
/plugin/;

/ {
  compatible = "rockchip,rk3308";

  fragment@0 {
    target = <&i2s_8ch_0>;

    __overlay__ {
      #sound-dai-cells = <0>;
      rockchip,clk-trcm = <1>;
      status = "okay";
    };
  };

  fragment@1 {
    target = <&i2c1>;

    __overlay__ {
      #address-cells = <1>;
      #size-cells = <0>;
      status = "okay";

      wm8731: wm8731@1a {
        #sound-dai-cells = <0>;
        compatible = "wlf,wm8731";
        reg = <0x1a>;
        status = "okay";
      };
    };
  };

  fragment@2 {
    target-path = "/";

    __overlay__ {
      sound {
        #address-cells = <1>;
        #size-cells = <0>;
        status = "okay";
        compatible = "simple-audio-card";
        simple-audio-card,name = "wm8731-codec";

        simple-audio-card,widgets =
          "Microphone", "Mic Jack",
          "Headphone", "Headphone Jack";
        simple-audio-card,routing =
          "Mic Jack", "MICIN",
          "Headphone Jack", "LHPOUT",
          "Headphone Jack", "RHPOUT";

        simple-audio-card,format = "i2s";
        simple-audio-card,cpu {
          sound-dai = <&i2s_8ch_0>;
          system-clock-id = <0>;
          system-clock-frequency = <12288000>;
        };

        simple-audio-card,codec {
          sound-dai = <&wm8731>;
          system-clock-id = <1>;
          system-clock-frequency = <12288000>;
          frame-master;
          bitclock-master;
        };
      };
    };
  };
};

Here is the wireing:

Mikroe-506        RockPiS
----------        -------
SCK         <-->  Pin 12 (I2S0_8CH_SCLK_TX)
MISO        <-->  Pin 28 (I2S0_8CH_SDI0)
MOSI        <-->  Pin 18 (I2S0_8CH_SDO0)
ADCL        <-->  Pin 22 (I2S0_8CH_LRCK_TX)
DACL        <-->  Pin 22 (I2S0_8CH_LRCK_TX)
SDA         <-->  Pin 3  (I2C1_SDA)
SCL         <-->  Pin 5  (I2C1_SCL)
3.3V        <-->  Pin 1  (+3.3V)
GND         <-->  Pin 6  (GND)

I hope someone might find this helpful.

1 Like