stm32mp157 wm8960 audio driver debugging notes

Keywords: Linux stm32

The debugging wm8960 audio driver encountered a lot of pits. After several days of research, it was finally debugged.

Drive commissioning steps

Whether the driver can be loaded successfully is not only the first step of debugging, but also one of the most critical steps.
1. View the hardware schematic diagram:

2. Open the corresponding device tree (stm32mp157a XXX. Dtsi):
Because wm8960 is mounted on I2C4, add wm8960 device node on I2C4 node of device tree.

wm8960: wm8960@1a {
        compatible = "wlf,wm8960";
        reg = <0x1a>;
        #sound-dai-cells = <0>;
        status = "okay";
		wlf,shared-lrclk;
	 	clocks = <&sai2a>;
		clock-names = "mclk";
	        port {
	            #address-cells = <1>;
	            #size-cells = <0>;
		wm8960_tx_endpoint: endpoint@0 {
						reg = <0x0>;
						remote-endpoint = <&sai2b_endpoint>;
						frame-master;
						bitclock-master;
					};
	
		wm8960_rx_endpoint: endpoint@1 {
						reg = <0x1>;
						remote-endpoint = <&sai2a_endpoint>;
						frame-master;
						bitclock-master;
					};
	        };
    };

The node clocks = < SAI2A > depends on whether the schematic uses SAI2A or SAI2B as the master clock.

3.SAI2 configuration:

&sai2 {
    clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>;
    clock-names = "pclk", "x8k", "x11k";
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>;
    pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>;
    status = "okay";

    sai2a: audio-controller@4400b004 {
    dma-names = "rx";
	#clock-cells = <0>;
        clocks = <&rcc SAI2_K>;
        clock-names = "sai_ck";
        status = "okay";

        sai2a_port: port {
            sai2a_endpoint: endpoint {
                remote-endpoint = <&wm8960_rx_endpoint>;
                format = "i2s";
                mclk-fs = <256>; 
                dai-tdm-slot-num = <2>;
                dai-tdm-slot-width = <16>;
            };
        };
    };
    sai2b: audio-controller@4400b024 {
        dma-names = "tx";
        st,sync = <&sai2a 2>;
        clocks = <&rcc SAI2_K>, <&sai2a>;
        clock-names = "sai_ck", "MCLK";
        status = "okay";
        sai2b_port: port {
            sai2b_endpoint: endpoint {
                remote-endpoint = <&wm8960_tx_endpoint>;
                format = "i2s";
                mclk-fs = <256>;
                dai-tdm-slot-num = <2>;
                dai-tdm-slot-width = <16>;
            };
        };
    };
};

The more important one is the input and output problem of sai2a and sai2b. The above schematic diagram describes sai2a as ADC (capture) and sai2b as DAC(playback). Therefore, at this time, DMA names in sai2a node = 'tx', sai2b is DMA names = 'rx', and St, sync = < & sai2a 2 >;
Here you can refer to the kernel source code path: Documentation/devicetree/bindings/sound/st,stm32-sai.txt document

4.sound node configuration

  sound: sound {
        compatible = "audio-graph-card";
        label = "wm8960-audio";
       	mclk-fs = <256>;
	dai-format = "i2s";
	widgets =
            "Microphone", "Mic Jack",
            "Line", "Line In",
            "Line", "Line Out",
            "Speaker", "Speaker",
            "Headphone", "Headphone Jack";
        routing =
            "Headphone Jack", "HP_L",
            "Headphone Jack", "HP_R",
            "Speaker", "SPK_LP",
            "Speaker", "SPK_LN",
            "Speaker", "SPK_RP",
            "Speaker", "SPK_RN",
            "LINPUT1", "MICB",
            "LINPUT3", "MICB";
        dais = <&sai2a_port &sai2b_port>; 
        status = "okay";
    };

5. Configuration pin (stm32mp15 pinctrl. Dtsi):

sai2a_pins_a: sai2a-0 {
		pins {
			pinmux = <STM32_PINMUX('I', 6, AF10)>; /* SAI2_SD_A */		 
			bias-disable;
			drive-push-pull;
			slew-rate = <0>;
		};
	};

	sai2a_sleep_pins_a: sai2a-1 {
		pins {
			pinmux = <STM32_PINMUX('I', 6, ANALOG)>; /* SAI2_SD_A */
			
		};
	};
	sai2b_pins_b: sai2b-2 {
		pins {
			pinmux = <STM32_PINMUX('E', 11, AF10)>, /* SAI2_SD_B */
				 <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */ 
				 <STM32_PINMUX('I', 7, AF10)>, /* SAI2_FS_A */
				 <STM32_PINMUX('E', 0, AF10)>; /* SAI2_MCLK_A */
				bias-disable;
				drive-push-pull;
				slew-rate = <0>;
		};
	};

	sai2b_sleep_pins_b: sai2b-3 {
		pins {
			pinmux = <STM32_PINMUX('E', 11, ANALOG)>, /* SAI2_SD_B */
				  <STM32_PINMUX('I', 5, ANALOG)>, /* SAI2_SCK_A */ 
				 <STM32_PINMUX('I', 7, ANALOG)>, /* SAI2_FS_A */
				 <STM32_PINMUX('E', 0, ANALOG)>; /* SAI2_MCLK_A */
				
		};
	};

6. View startup information:

If the above start printing message appears, it proves that wm8960 driver loading is successful. Next, let's see if there are any sound card nodes.

[root@stm32mp157]:~# ls /dev/snd/
by-path/   controlC0  pcmC0D0c   pcmC0D1p   timer

pcmC0D0c is a recording device
pcmC0D1p is a playback device

[root@stm32mp157]:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: wm8960audio [wm8960-audio], device 1: 4400b024.audio-controller-wm8960-hifi wm8960-hifi-1 [4400b024.audio-controller-wm8960-hifi wm8960-hifi-1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
[root@stm32mp157]:~# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: wm8960audio [wm8960-audio], device 0: 4400b004.audio-controller-wm8960-hifi wm8960-hifi-0 [4400b004.audio-controller-wm8960-hifi wm8960-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Sound card 0, device 0 -- > is a recording device
Sound card 0, device 1 -- > is a playback device

7. Fault problem
If you use the command: aplay xxx.wav, it is stuck in the command line all the time and there is no error message. You need to check the schematic diagram and whether it corresponds to the configuration problem of the device tree.
If aplay xxx.wav, the following error message appears:
[root@-stm32mp157]:~# aplay -Dhw:0.0 /usr/share/sounds/alsa/Rear_Right.wav
ALSA lib .../.../.../alsa-lib-1.2.1.2/src/pcm/pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card
aplay: main:828: audio open error: No such device
You need to use aplay -l to check the playing device number and check whether / etc/asound.conf is configured correctly. You can use the command aplay -Dhw:0.1 xxx.wav to specify the device playback.

asound.conf configuration file

Once the driver was loaded successfully, but there was no sound. After checking the hardware and driver, there was no problem. alsamixer also set the sound level, but it still didn't work. It was found that asound.conf would also have a certain impact.

pcm.dmix_44100{
type dmix
ipc_key 5678293
ipc_key_add_uid yes
slave{
pcm "hw:0,0"
period_time 40000
buffer_time 360000
format S16_LE
rate 44100
}
}
pcm.!dsnoop_44100{
type dsnoop
ipc_key 5778293
ipc_key_add_uid yes
slave{
pcm "hw:0,1"
period_time 40000
buffer_time 360000
format S16_LE
rate 44100
}
}
pcm.asymed{
type asym
playback.pcm "dmix_44100"
capture.pcm "dsnoop_44100"
}

pcm.dsp0{
type plug
slave.pcm "asymed"
}

pcm.!default{
type plug
route_policy "average"
slave.pcm "asymed"
}

ctl.!default{
type hw
card 0
}

ctl.mixer0{
type hw
card 0
}

experience

When you encounter a problem, don't worry. Driving the printing information will help you find the cause of the failure. If it doesn't work, you can refer to the successful cases of others and change the hardware circuit to the same one to see whether it is a hardware or chip problem.

Attach wm8960 driver file and asound.conf configuration file link:

Posted by boiy on Fri, 17 Sep 2021 07:52:39 -0700