Integrating audio codec MAX98089 on i.MX8M Plus

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Integrating audio codec MAX98089 on i.MX8M Plus

Jump to solution
1,346 Views
ThKe93
Contributor II

Hello community,

in our project I have an i.MX8M Plus system on a S.M.A.R.C. module with a self-developed carrier board. On the carrier board we're using MAX98089 audio codec and I'm currently try to integrate this codec to this system. In my research I already found helpful information here:

https://community.nxp.com/t5/i-MX-Processors/Integration-of-MAX98089-audio-codec-on-i-mx6/m-p/427126

In a first step I had the same "problems" as described in the thread above. CODEC DAI driver for MAX98089 was available in kernel-sources in "sound/soc/codecs/max98088.c" but no DAI LINK driver (machine driver) was available in "sound/soc/fsl/". So I proceeded with using SGTL5000 machine driver as a template and modified it for the usage with MAX98089.

Attached you can find the appropriate patch as well as the device tree overlay:

fragment@3002 {
     target-path = "/";
     __overlay__ {
          sound_max98089: sound-max98089 {
               compatible = "fsl,imx-audio-max98089";
               model = "imx-max98089";
               fsl,no-audmux;
               ssi-controller = <&sai2>;
               audio-codec = <&codec_max98089>;
               audio-routing =
                            "MIC1", "Mic1 MEMS",
                            "MIC2", "Mic2 Elekt",
                            "External Speaker", "SPKR",
                            "External Speaker", "SPKL";
               status = "okay";
          };
     };
};


fragment@3003 {
     target = <&i2c1>;
     __overlay__ {
          // clock-frequency = <100000>;
          #address-cells = <1>
          #size-cells = <0>;
          codec_max98089: codec-max98089@10 {
               compatible = "maxim,max98089";
               reg = <0x10>;
               clocks = <&clkout1>;
               clock-names = "mclk";
               status = "okay";
          };
     };
};

fragment@3006 {
     target = <&sai2>;
     __overlay__ {
          pinctrl-names = "default";
          pinctrl-0 = <&pinctrl_sai2>;
          assigned-clocks = <&clk IMX8MP_CLK_SAI2>;
          assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
          assigned-clock-rates = <12288000>;
          clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI2_IPG>,
          <&clk IMX8MP_CLK_DUMMY>,
          <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI2_MCLK1>,
          <&clk IMX8MP_CLK_DUMMY>,
          <&clk IMX8MP_CLK_DUMMY>;
          clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
          fsl,sai-mclk-direction-output;
          status = "okay";
     };
};

Afterwards kernel built fine! Unfortunately sound card was not available after system boot and I got following kernel messages:

[ 7.638306] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 7.839314] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 8.134267] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 8.646973] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 8.661756] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered

Hence I added some further debug messages to my driver patch, also to the CODEC DAI driver (sound/soc/codecs/max98088.c), which you also can observe from the attached patch. Finally I got following kernel messages:

[ 0.357904] imx-max98088 sound-max98089: failed to find codec platform device
[ 0.383237] max98088 0-0010: max98088 probe function entered
[ 0.383361] max98088 0-0010: try to register max98088
[ 0.383385] max98088 0-0010: result of registering max98088: 0
[ 2.502021] max98088 0-0010: codec clk_frequency = 24000000
[ 2.876850] max98088 0-0010: codec clk_frequency = 24000000
[ 2.888556] max98088 0-0010: codec clk_frequency = 24000000
[ 2.983913] max98088 0-0010: codec clk_frequency = 24000000
[ 3.038974] max98088 0-0010: codec clk_frequency = 24000000
[ 3.080631] max98088 0-0010: codec clk_frequency = 24000000
[ 3.095586] max98088 0-0010: codec clk_frequency = 24000000
[ 3.420405] max98088 0-0010: codec clk_frequency = 24000000
[ 4.487781] max98088 0-0010: codec clk_frequency = 24000000
[ 7.460927] max98088 0-0010: codec clk_frequency = 24000000
[ 7.584261] max98088 0-0010: codec clk_frequency = 24000000
[ 7.610062] max98088 0-0010: codec clk_frequency = 24000000
[ 7.632269] max98088 0-0010: codec clk_frequency = 24000000
[ 7.638306] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 7.833342] max98088 0-0010: codec clk_frequency = 24000000
[ 7.839314] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 8.114279] max98088 0-0010: codec clk_frequency = 24000000
[ 8.134267] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 8.639081] max98088 0-0010: codec clk_frequency = 24000000
[ 8.646973] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered
[ 8.655446] max98088 0-0010: codec clk_frequency = 24000000
[ 8.661756] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered

So, regarding kernel messages probe function of CODEC DAI driver (sound/soc/codecs/max98088.c) as well as probe function of LINK DAI driver (sound/soc/fsl/imx-max98088.c) gets called. However, something fails when device should get registered. I've also done some measurements on my board and there is not any I2C access to the codec at all. Regarding the added kernel messages in the patch, it also can be observed, that probe function "max98089_i2c_probe" of CODEC DAI driver gets called but not function "max98089_probe" in which the first I2C bus accesses take place.

I'm new to this topic and I'm really stuck at this point, as I don't know how to further debug this issue.

Thanks and advance for your help!

Thomas

0 Kudos
1 Solution
1,132 Views
ThKe93
Contributor II

Problem finally solved...

The assumption above was correct and I also had to do a patch to fsl_sai driver and change SYWD in CR4 register as well as W0W in CR5 register to fixed 32. Now everything works as expected. Final patch attached.
Please note, that I'm using DAI1 with S2 port for which I also patched the codec driver. If you're using S1 port, you have to omit these lines of the patch.

Regards

Thomas

View solution in original post

0 Kudos
4 Replies
1,133 Views
ThKe93
Contributor II

Problem finally solved...

The assumption above was correct and I also had to do a patch to fsl_sai driver and change SYWD in CR4 register as well as W0W in CR5 register to fixed 32. Now everything works as expected. Final patch attached.
Please note, that I'm using DAI1 with S2 port for which I also patched the codec driver. If you're using S1 port, you have to omit these lines of the patch.

Regards

Thomas

0 Kudos
1,165 Views
ThKe93
Contributor II

I'd like to come back to this topic...

First of all: problem of card registration could already be solved. I had to do a patch in CODEC DAI driver max98088.c, because naming of DAI interface in this driver and in my DAI LINK driver (machine driver) differed. I've simply replaced .name = "HiFi" with .name = "max98088-HiFi" which corresponds to following line of my DAI LINK driver "imx-max98088.c":

data->dai.codecs->dai_name = "max98088-HiFi";

 

This is the patch for "max98088.c":

@@ -1379,7 +1460,7 @@ static const struct snd_soc_dai_ops max98088_dai2_ops = {

static struct snd_soc_dai_driver max98088_dai[] = {
{
-      .name = "HiFi",
+     .name = "max98088-HiFi",
       .playback = {
            .stream_name = "HiFi Playback",
            .channels_min = 1,

 

Instead of doing the patch in max98088.c it may be also possible to simply change the code line in imx-max98088.c to following:

data->dai.codecs->dai_name = "HiFi";

 

After doing the patch, sound-card gets registered successfully and I'm able to play audio files

===================

NEVERTHELESS: There is still a problem... In my case I have following settings:

Codec is master, SAI interface is slave

LRCLK = 44.1 kHz

BCLK = 2.822 MHz (64*Fs)

When playing the audio file which is 16bit, all data seems to be output on left audio channel and right channel is silent. I also have an EVAL board here which SGTL5000 mounted on it. Same audio file works well there on both audio-channels, but there is the difference that BCLK is only 32*Fs which means 1.411 MHz. So for me it seems, that all data is shifted out on the first channel due to the doubled BCLK frequency and SAI is not waiting for the rising edge of LRCLK before shifting out data of right audio channel.

What could be the problem here? Do I have missed something in device tree setting of SAI interface?

0 Kudos
1,255 Views
ThKe93
Contributor II

Some more detailed description and additional findings...

Function "devm_snd_soc_register_component()" - which is called in "sound/soc/codec/max98088.c" - returns with success as it can be seen by following kernel message:

[ 0.383385] max98088 0-0010: result of registering max98088: 0

However, another kernel messages says, that codec is not registered:

[ 7.638306] imx-max98088 sound-max98089: ASoC: CODEC DAI max98088 not registered

This kernel error message above is thrown by following function inside "sound/soc/soc-core.c":

int snd_soc_add_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
    struct snd_soc_pcm_runtime *rtd;
    struct snd_soc_dai_link_component *codec, *platform, *cpu;
    struct snd_soc_component *component;
    int i, ret;

    lockdep_assert_held(&client_mutex);

    /*
    * Notify the machine driver for extra initialization
    */
    ret = snd_soc_card_add_dai_link(card, dai_link);
    if (ret < 0)
        return ret;

    if (dai_link->ignore)
        return 0;

    dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);

    ret = soc_dai_link_sanity_check(card, dai_link);
    if (ret < 0)
        return ret;

    rtd = soc_new_pcm_runtime(card, dai_link);
    if (!rtd)
        return -ENOMEM;

    for_each_link_cpus(dai_link, i, cpu) {
        asoc_rtd_to_cpu(rtd, i) = snd_soc_find_dai(cpu);
        if (!asoc_rtd_to_cpu(rtd, i)) {
            dev_info(card->dev, "ASoC: CPU DAI %s not registered\n", cpu->dai_name);
            goto _err_defer;
        }
        snd_soc_rtd_add_component(rtd, asoc_rtd_to_cpu(rtd, i)->component);
    }

    /* Find CODEC from registered CODECs */
    for_each_link_codecs(dai_link, i, codec) {
        asoc_rtd_to_codec(rtd, i) = snd_soc_find_dai(codec);
        if (!asoc_rtd_to_codec(rtd, i)) {
            dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n", codec->dai_name);
            goto _err_defer;
        }

        snd_soc_rtd_add_component(rtd, asoc_rtd_to_codec(rtd, i)->component);
    }

    /* Find PLATFORM from registered PLATFORMs */
    for_each_link_platforms(dai_link, i, platform) {
        for_each_component(component) {
            if (!snd_soc_is_matching_component(platform, component))
                continue;

            snd_soc_rtd_add_component(rtd, component);
        }
    }

    return 0;

    _err_defer:
    snd_soc_remove_pcm_runtime(card, rtd);
        return -EPROBE_DEFER;
}
EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtime);

0 Kudos
1,286 Views
ThKe93
Contributor II

I've done some more research and have built the max98088/9 drivers as kernel modules to load them manually.

I really assume that there is some problem with max98088 codec driver in "sound/soc/codecs/max98088.c" because if I load it as module, still no I2C access takes place. However, I've also tried to load codec driver of sgtl5000 and there an I2C access to the appropriate address takes place.

Furhtermore I've checked used I2C addresses with i2cdetect and got following result:

0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
50: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

So as you can see, address 0x10 (max98089) is used by the codec driver but as I said, no I2C access takes place and regarding kernel messages, codec is not registered!

I use kernel version 5.15.52.

Has anybody an idea?

0 Kudos