Problem with SGTL5000 audio codec and Simple Audio Card driver on i.MX8MM

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

Problem with SGTL5000 audio codec and Simple Audio Card driver on i.MX8MM

4,692 Views
martintownsend
Contributor I

Hi,

We are trying to get an SGTL5000 Audio Codec working, for recording audio
only, with our i.MX8MM board running the NXP linux-imx 4.14.98 Kernel.
We are using the Simple Audio Card driver and have set it up using the
following device tree fragment (which is included from arch/arm64/boot/dts/freescale/fsl-imx8mm-evk.dts):

/ {
regulators {
reg_3p3v: regulator-reg3v3 {
compatible = "regulator-fixed";
regulator-name = "reg_3p3v";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
reg_1p8v: regulator-reg1v8 {
compatible = "regulator-fixed";
regulator-name = "reg_1p8v";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
};

sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&codecdai>;
simple-audio-card,bitclock-master = <&codecdai>;
simple-audio-card,widgets =
"Line", "Line In Jack";
simple-audio-card,routing =
"LINE_IN", "Line In Jack";

cpudai: simple-audio-card,cpu {
sound-dai = <&sai3>;
};

codecdai: simple-audio-card,codec {
sound-dai = <&codec>;
clocks = <&clk IMX8MM_CLK_SAI3_ROOT>;
};
};
};

&iomuxc {
imx8mm-evk {
pinctrl_sai3_db: sai3grp {
fsl,pins = <
MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
>;
};
};
};

&i2c1 {
status = "okay";

codec: sgtl5000@a {
#sound-dai-cells = <0>;
compatible = "fsl,sgtl5000";
reg = <0xa>;
#if 0
micbias-resistor-k-ohms = <2>;
micbias-voltage-m-volts = <2250>;
#endif
VDDA-supply = <&reg_3p3v>;
VDDIO-supply = <&reg_3p3v>;
VDDD-supply = <&reg_1p8v>;
clocks = <&clk IMX8MM_CLK_SAI3_ROOT>;
clock-names = "sys_mclk";
};
};

&sai3 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3_db>;

#sound-dai-cells = <0>;
};

and added the following kernel configuration:

CONFIG_SND_SOC_IMX_SGTL5000=y
CONFIG_SND_SOC_SGTL5000=y

You may notice that the SGTL5000 is the I2S master, when we tried to use the
SAI as I2S master we would get the following error:

root@imx8mmevk:~# arecord -d 10 /tmp/test-mic.wav
[ 1343.737133] sgtl5000 0-000a: PLL not supported in slave mode
[ 1343.742855] sgtl5000 0-000a: sgtl5000->sysclk: 24576000 frame_rate: 44100
[ 1343.749691] sgtl5000 0-000a: 557 ratio is not supported. SYS_MCLK needs to be 256, 384 or 512 * fs
[ 1343.758698] sgtl5000 0-000a: ASoC: can't set sgtl5000 hw params: -22
ALSA lib ../../../alsa-lib-1.1.5/src/pcm/pcm_direct.c:1271:(snd1_pcm_direct_initialize_slave) unable to install hw params
ALSA lib ../../../alsa-lib-1.1.5/src/pcm/pcm_dsnoop.c:649:(snd_pcm_dsnoop_open) unable to initialize slave
arecord: main:828: audio open error: Invalid argument

I'm guessing that the SAI interface isn't dividing the clock down to the
expected value that the audio codec driver is expecting, ie a multiple of 256,
384 opr 512. With the SGTL5000 as I2S master I think it uses an internal PLL
and with this setup we don't get the above message but we get silence on the
captured audio. The I2C interface works as we can read the chip ID, we have
checked all the signals going into the audio codec and we see

MCLK : 24.5Mhz
LRCLK : 44.1Khz
SCLK : 1.4Mhz
DOUT : There is data here, it is not all 0’s

Here's the recorded audio:
root@imx8mmevk:~# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: D30030000saisgt [30030000.sai-sgtl5000], device 0: 30030000.sai-sgtl5000 sgtl5000-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
root@imx8mmevk:~# arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
pulse
PulseAudio Sound Server
sysdefault:CARD=D30030000saisgt
30030000.sai-sgtl5000,
Default Audio Device
root@imx8mmevk:~# arecord -f cd -d 2 -D sysdefault:CARD=D30030000saisgt /tmp/test-mic.wav
Recording WAVE '/tmp/test-mic.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
root@imx8mmevk:~# hexdump -C /tmp/test-mic.wav
00000000 52 49 46 46 44 62 05 00 57 41 56 45 66 6d 74 20 |RIFFDb..WAVEfmt |
00000010 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 |........D.......|
00000020 04 00 10 00 64 61 74 61 20 62 05 00 00 00 00 00 |....data b......|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00056240 00 00 00 00 00 00 00 00 00 00 00 00 |............|
0005624c


Also, if we change the sample rate to say between 8Mhz and 16Mhz, it doesn’t seem
to change the above LRCLK and SCLK to match accordingly.

Can you see anything that we are doing wrong? Is the Simple Audio Card Driver
supported on your vendor specific kernel (4.14.98)? Are their patches available
for SAI or SGTL5000 for this kernel that we may require?

Many Thanks in Advance,
Martin.

Labels (1)
0 Kudos
8 Replies

3,563 Views
martintownsend
Contributor I

Hi,

After looking through the machine driver imx-sgtl5000.c I could see it was setup for the codec being the master so I modified it so that the format was codec slave.  I also set the capture_only flag on the DAI. 

data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM;
+ SND_SOC_DAIFMT_CBS_CFS;

+ data->dai.capture_only = 1;

I found the commands to capture from the Line Input

amixer set 'Capture' 12
amixer set 'Capture Mux' 'LINE_IN'

Recording with

arecord -v -V mono -D sysdefault:CARD=sgtl5000audio -f S16_LE -r 48000 mic.wav

will capture audio but like before it's complete silence

00000000 52 49 46 46 84 2b 0b 00 57 41 56 45 66 6d 74 20 |RIFF.+..WAVEfmt |
00000010 10 00 00 00 01 00 01 00 80 bb 00 00 00 77 01 00 |.............w..|
00000020 02 00 10 00 64 61 74 61 60 2b 0b 00 00 00 00 00 |....data`+......|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000b2b80 00 00 00 00 00 00 00 00 00 00 00 00 |............|
000b2b8c

I've tried setting the symmetric_channels in SAI to 0 as seen on another post but still silence. 

@@ -1466,7 +1466,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
sai->synchronous[RX] = true;
sai->synchronous[TX] = false;
fsl_sai_dai.symmetric_rates = 1;
- fsl_sai_dai.symmetric_channels = 1;
+ fsl_sai_dai.symmetric_channels = 0;

The HW engineers have proved that the line input does have a signal.

Looking at the pinmux

&iomuxc {
  imx8mm-evk {
    pinctrl_sai3_db: sai3grp {
      fsl,pins = <
        MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
        MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
        MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
        MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
        MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
      >;
    };
  };
};

Not sure what to do next, I'll check the signals again with a scope and check we still see the correct clocks and data on the MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 pin.  Do you know where in the code that the data is read out of the SAI?  Maybe I could put some debug around this?

Do I need to set any of the 

fsl,sai-synchronous-rx;
fsl,sai-asynchronous;

device tree properties?  I don't think I do as we only have the TX_SYNC and TX_BCLK connected to the codec.

Many Thanks,

Martin. 

0 Kudos

3,563 Views
martintownsend
Contributor I

Hi,

I got sidetracked with some other project but I'm back looking into this.
I went back and checked the schematic and the setup is similar to the WM8524
that you support on the EVK, ie the SAI is the I2S master and the codec is the
slave. This means the SAI is the transmitter so the Tx clock signals are
connected to the codec. The only difference is that we are trying to
capture audio and not playback audio.

I took out the audmux code from the imx-sgtl5000.c file as that post described.

The SGTL5000 failed to probe so I had to add the following

ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg);
if (ret) {
dev_err(&client->dev, "Error reading chip id %d\n", ret);
+ ret = -EPROBE_DEFER;
goto disable_clk;
}

I Had to force the SGTL into slave mode:

/* set codec format */
static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
u16 i2sctl = 0;

fmt = 0x4001;
printk(KERN_ERR "SGTL5000: sgtl5000_set_dai_fmt: %08x\n", fmt);

So the setup should be correct now but I get the following error:

# arecord -v -f cd -d 2 -D sysdefault:CARD=sgtl5000audio /tmp/test-mic.wav
Recording WAVE '/tmp/test-mic.wav[ 14.935520] sgtl5000 0-000a: PLL not supported in slave mode
' : Signed 16 bit Little Endian, [ 14.943109] sgtl5000 0-000a: sgtl5000->sysclk: 24576000 frame_rate: 44100
Rate 44100 Hz, Stereo
[ 14.952800] sgtl5000 0-000a: 557 ratio is not supported. SYS_MCLK needs to be 256, 384 or 512 * fs
[ 14.963721] sgtl5000 0-000a: ASoC: can't set sgtl5000 hw params: -22
arecord: set_params:1403: Unable to install hw params:
ACCESS: RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 44100
PERIOD_TIME: (92879 92880)
PERIOD_SIZE: 4096
PERIOD_BYTES: 16384
PERIODS: 4
BUFFER_TIME: (371519 371520)
BUFFER_SIZE: 16384
BUFFER_BYTES: 65536
TICK_TIME: 0

So it looks like the MCLK coming out of the AUDIO PLL on the i.MX8MM is
staying at 24576000Hz and MCLK needs to be synchronous to the frame clock which in this
instance is 44100 (44.1KHz CD quality). 24576000/44100 is 557 (rounded down)
which is not the ratio that the audio codec is expecting (256, 384 or 512)

First question is why is the SAI not providing an MCLK that is synchronous to
the Frame Clock.

So if MCLK is staying at 25.576MHz then 48KHz should work 24576000/48000 = 512,
so using the dat format should get us past this hurdle

arecord -v -f dat ot@imx8mmevk:~# arecord -v -f dat -d 2 -D sysdefault:CARD=sgtl5000audio /tmp/tes sysdefault:CARD=sgtl5000audio /tmp/testsysdefault:CARD=sgtl5000audio /tmp/test-mic.wav

Recording WAVE '/tmp/test-mic.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Plug PCM: Hardware PCM card 0 'sgtl5000-audio' device 0 subdevice 0audio /tmp/tes
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : S16_LE
subformat : STD
channels : 2
rate : 48000
exact rate : 48000 (48000/1)
msbits : 16
buffer_size : 16384
period_size : 4096
period_time : 85333
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 4096
period_event : 0
start_threshold : 1
stop_threshold : 16384
silence_threshold: 0
silence_size : 0
boundary : 4611686018427387904
appl_ptr : 0
hw_ptr : 0

Then after 6 or so seconds

arecord: pcm_read:2143: read error: Input/output error

There is a file but it only contains the header:
~# hexdump -C /tmp/test-mic.wav
00000000 52 49 46 46 24 dc 05 00 57 41 56 45 66 6d 74 20 |RIFF$...WAVEfmt |
00000010 10 00 00 00 01 00 02 00 80 bb 00 00 00 ee 02 00 |................|
00000020 04 00 10 00 64 61 74 61 00 dc 05 00 |....data....|
0000002c

I found the following undocumented device tree binding in the SAI driver

fsl,txm-rxs;

so I added this and it sets
sai->masterflag[FSL_FMT_TRANSMITTER] = SND_SOC_DAIFMT_CBS_CFS;

which should be what we want (codec bit and frame clocks slave)

Now I get overruns

evk:~# arecord -v -f dat -d 2 -D sysdefault:CARD=sgtl5000audio /tmp/test-mic.wav
Recording WAVE '/tmp/test-mic.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Plug PCM: Hardware PCM card 0 'sgtl5000-audio' device 0 subdevice 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : S16_LE
subformat : STD
channels : 2
rate : 48000
exact rate : 48000 (48000/1)
msbits : 16
buffer_size : 16384
period_size : 4096
period_time : 85333
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 4096
period_event : 0
start_threshold : 1
stop_threshold : 16384
silence_threshold: 0
silence_size : 0
boundary : 4611686018427387904
appl_ptr : 0
hw_ptr : 0
overrun!!! (at least 0.024 ms long)
Status:
state : XRUN
trigger_time: 18.783263
tstamp : 0.000000
delay : 0
avail : 16384
avail_max : 16384
overrun!!! (at least 0.012 ms long)
Status:
state : XRUN
trigger_time: 19.198746
tstamp : 0.000000
delay : 0
avail : 16384
avail_max : 16384
overrun!!! (at least 0.010 ms long)
Status:
state : XRUN
trigger_time: 19.614743
tstamp : 0.000000
delay : 0
avail : 16384
avail_max : 16384
overrun!!! (at least 0.013 ms long)

[..snip]

Any help appreciated,

Many Thanks,
Martin.

0 Kudos

3,563 Views
igorpadykov
NXP Employee
NXP Employee

Hi Martin

for sgtl5000 slave mode one can look at

[alsa-devel] No sound captured with SGTL5000 on i.MX6 in I²S master mode 

Best regards
igor

0 Kudos

3,563 Views
martintownsend
Contributor I

Hi Igor,

I'm looking at the device tree bindings for the The SGTL5000 ALSA SoC Machine Driver for i.MX

Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt

And it has the following required properties

---

Required properties:

[snip]

- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)

- mux-ext-port : The external port of the i.MX audio muxer

Note: The AUDMUX port numbering should start at 1, which is consistent with
hardware manual.

---

As far as I can see the AUDMUX isn't available on the i.MX8MM, it's not in the reference manual and I can't see any reference to it in the device tree.

I'm not sure how to get this working, any ideas?

Many Thanks,

Martin.

0 Kudos

3,563 Views
igorpadykov
NXP Employee
NXP Employee

Hi Martin

it can be done using sai module as in

[PATCH 0/2] ASoC: fsl: make snd-soc-imx-sgtl5000 driver useable on i.MX6UL 

Best regards
igor

0 Kudos

3,563 Views
martintownsend
Contributor I

Hi Igor,

Thank you for the response.  Does the kernel support the more convoluted method of defining an audio sound device: ie Platform driver, Machine driver and Codec driver? Something like

/ { 

    sound-sgtl5000 { 

        compatible = "fsl,imx-audio-sgtl5000"; 

        model = "sgtl5000-audio"; 

        cpu-dai = <&sai3>; 

        audio-codec = <&sgtl5000>; 

        audio-routing =
            "MIC_IN", "Mic Jack",
            "Mic Jack", "Mic Bias";

        mux-int-port = <2>; 

        mux-ext-port = <3>; 

    }; 

};  

&i2c1 { 

    sgtl5000: codec@0a { 

        compatible = "fsl,sgtl5000"; 

        reg = <0x0a>; 

        ... 
    }; 
}; 

 

&sai3 {                                                                         
    fsl,mode = "i2s-slave";                                                 
    status = "okay";                                                        
}; 

 

Also do you know whether the kernel will work with the SGTL5000?

Many Thanks,

Martin.

0 Kudos

3,563 Views
igorpadykov
NXP Employee
NXP Employee

Hi Martin

yes it supports that, for example "sound-wm8524" in

linux/arch/arm64/boot/dts/freescale/fsl-imx8mm-evk.dts

fsl-imx8mm-evk.dts\freescale\dts\boot\arm64\arch - linux-imx - i.MX Linux kernel 

Alsa drivers are described in Chapter 7 Audio attached Linux Manual.

Best regards
igor

0 Kudos

3,563 Views
igorpadykov
NXP Employee
NXP Employee

Hi Martin

unfortunately Simple Audio Card Driver is not supported by NXP 
in its linux kernels (including 4.14.98), no patches available for SAI or SGTL5000.

One can try to develop it himself using example below and linux documentation

Eight channels audio on i.MX7 with PCM3168 - Bootlin's blog 

Linux L4.14.98_2.0.0 Documentation

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos