MAX98357 on IMX8

5.4.161-39955-g585dc27c53b6-dirty
Verdin IMX8MP Q

I am trying to get some audio out on I2S2 or sai3 on SODIMM 42,44,46,48

I added the MAX98357 to my Kernel config and tried to add this device to my device tree:

// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
 * Copyright 2020 Toradex
 */

/dts-v1/;

#include "imx8mp-verdin.dtsi"
#include "imx8mp-verdin-wifi.dtsi"
#include "imx8mp-verdin-dahlia.dtsi"


/ {
	model = "Toradex Verdin iMX8M Plus WB on Dahlia Board";
	compatible = "toradex,verdin-imx8mp-wifi-dahlia",
		     "toradex,verdin-imx8mp-wifi",
		     "toradex,verdin-imx8mp",
		     "fsl,imx8mp";

	codec_ext: max98357a@0 {
		compatible = "maxim,max98357a";
		#sound-dai-cells = <0>;
	};

	sound_ext {
		compatible = "simple-audio-card";
		simple-audio-card,name = "max98357a";
		simple-audio-card,format = "i2s";
		simple-audio-card,bitclock-master = <&dailink_master1>;
		simple-audio-card,frame-master = <&dailink_master1>;


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

		simple-audio-card,codec {
			sound-dai = <&codec_ext>;
			clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>;
		};


	};

};

&fec {
	status = "disabled";
};

&flexspi {
	status = "disabled";
};

&iomuxc {


	pinctrl_sai3: sai3grp {
		fsl,pins = <
			MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC	0x1d6	/* SODIMM 44 */
			MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK	0x1d6	/* SODIMM 42 */
			MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00	0x96	/* SODIMM 46 */
		>;
	};

	pinctrl_uart1: uart1grp {
		fsl,pins = <
			MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX		0x1c4	/* SODIMM 129 */
			MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX		0x1c4	/* SODIMM 131 */		
		>;
	};

	pinctrl_uart2: uart2grp {
		fsl,pins = <
			MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX		0x1c4	/* SODIMM 137 */
			MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX		0x1c4	/* SODIMM 139 */
		>;
	};

};



/* VERDIN I2S_2 */
&sai3 {
	status= "okay";
};

/* Verdin UART_1 */
&uart1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart1>;
};

/* Verdin UART_2 */
&uart2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart2>;
};

/* Verdin UART_3, used as the Linux Console */
&uart3 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart3>;
};



/* Verdin I2C_4_CSI */
&i2c3 {
	status= "okay";
	clock-frequency = <400000>;
	pinctrl-names = "default", "gpio";
	pinctrl-0 = <&pinctrl_i2c3>;
	pinctrl-1 = <&pinctrl_i2c3_gpio>;
	scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
	sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;

	ili251x@41 {
		status = "okay";
		compatible = "ili251x";
		reg = <0x41>;
		interrupt-parent = <&gpio1>;
		interrupts = <1 IRQ_TYPE_EDGE_RISING>;
		reset-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
		max-fingers = <6>;
		wakeup-source;
	};
};

The system seems to have some success in detecting the driver etc:

[ 2.522774] debugfs: Directory ‘30c30000.sai’ with parent ‘max98357a’ already present!
[ 2.530794] asoc-simple-card sound_ext: HiFi <-> 30c30000.sai mapping ok

[ 3.106274] ALSA device list:
[ 3.109271] #0: max98357a

Trying to play some music then gives me this error:
root@verdin-imx8mp-07129898:~# aplay PinkPanther60.wav
[ 45.214270] fsl-sai 30c30000.sai: failed to derive required Tx rate: 1411200
[ 45.221378] fsl-sai 30c30000.sai: ASoC: can’t set 30c30000.sai hw params: -22
ALSA lib …/…/…/alsa-lib-1.2.1.2/src/pcm/pcm_direct.c:1271:(snd1_pcm_direct_initialize_slave) unable to install hw params
ALSA lib …/…/…/alsa-lib-1.2.1.2/src/pcm/pcm_dmix.c:1101:(snd_pcm_dmix_open) unable to initialize slave
aplay: main:828: audio open error: Invalid argument

Any ideas what is going wrong?

Solved the sai3 peripheral was configured to use AUDIO PLL1, PLL1 was configured with the wrong base frequency so it could never get down to the audio rate of 44.1kHz or 1.4112 MHz BCLK rate.

Change SAI3 clock source to this and it works:

/* VERDIN I2S_2 */
&sai3 {
	#sound-dai-cells = <0>;
	assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
	assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>;
	assigned-clock-rates = <24576000>;
	clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_IPG>, <&clk IMX8MP_CLK_DUMMY>,
		 <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>, <&clk IMX8MP_CLK_DUMMY>,
		 <&clk IMX8MP_CLK_DUMMY>;
	clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
	fsl,sai-mclk-direction-output;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_sai3>;
};