Dear NXP experts:
Now I'm using SPDIF as the primary audio card of Android 10 on iMX8QXP mek board. I don't need the codec code and just output the SPDIF signal form SPDIF0_TX pin. The SDK version is imx8_10_2.2.0 .
My DTS config like this:
// imx8x-mek.dtsi
&spdif0 {
compatible = "fsl,imx8qm-spdif";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spdif0>;
assigned-clocks = <&acm IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
<&spdif0_lpcg 0>;
assigned-clock-parents = <&aud_pll_div0_lpcg 0>;
assigned-clock-rates = <0>, <786432000>, <49152000>, <24576000>, <49152000>;
status = "okay";
};
pinctrl_spdif0: spdif0grp {
fsl,pins = <
IMX8QXP_SPDIF0_TX_ADMA_SPDIF0_TX 0xc6000040
IMX8QXP_SPDIF0_RX_ADMA_SPDIF0_RX 0xc6000040
>;
};
// imxqxp-mek.dts
sound-dummy {
compatible = "fsl,imx-audio-dummy";
model = "imx-dummy";
dai-controller = <&sai0>, <&sai1>, <&esai0>, <&spdif0>;
dai-codec = <&codec_dummy>;
status = "okay";
};
The driver modified from NXP dummy codec example, and the part of SPDIF copy from kernel/sound/soc/fsl/imx-spdif.c like this:
// imx-dummy.c
static int imx_dummy_spdif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct device *dev = rtd->card->dev;
int ret = 0;
unsigned int freq;
printk("run in %s\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
u64 rate = params_rate(params);
freq = do_div(rate, 8000) ? CLK_11K_FREQ : CLK_8K_FREQ;
ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, STC_TXCLK_SPDIF_ROOT,
freq, SND_SOC_CLOCK_OUT);
if (ret)
dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
}
return ret;
}
static struct snd_soc_ops imx_aif_spdif_ops = {
.hw_params = imx_dummy_spdif_hw_params,
};
static int imx_dummy_probe(struct platform_device *pdev)
{
...
for (i = 0; i < num_dai; i++) {
...
priv->dai[i].stream_name = "SAI S/PDIF PCM";
priv->dai[i].codecs->dai_name = "snd-soc-dummy-dai";
priv->dai[i].codecs->name = "snd-soc-dummy";
...
if (strstr(cpu_np->name, "spdif")) {
priv->dai[i].ops = &imx_aif_spdif_ops;
} else {
...
...
}
But it seems not work when I use tinyplay to play wav files:
mek_8q:/sdcard/Music # cat /proc/asound/cards
0 [imxdummy ]: imx-dummy - imx-dummy
imx-dummy
mek_8q:/sdcard/Music # ls /dev/snd/
controlC0 pcmC0D0p pcmC0D1p pcmC0D2p pcmC0D3p
pcmC0D0c pcmC0D1c pcmC0D2c pcmC0D3c timer
mek_8q:/sdcard/Music # tinyplay ./1khz-16000-16-1.wav -D 0 -d 3 -p 1024 -n 3
Sample is 1 channels, device only supports >= 2 channels
Bitrate is 16 bits, device only supports >= 32 bits
mek_8q:/sdcard/Music # tinyplay ./1khz-16000-32-2.wav -D 0 -d 3 -p 1024 -n 3
Sample rate is 16000Hz, device only supports >= 32000Hz
mek_8q:/sdcard/Music # tinyplay ./1khz-48000-32-2.wav -D 0 -d 3 -p 1024 -n 3
Unable to open PCM device 3 (cannot set hw params: Invalid argument)
mek_8q:/sdcard/Music # tinymix
Mixer name: 'imx-dummy'
Number of controls: 9
ctl type num name value
0 IEC958 1 IEC958 Playback Default unknown
1 IEC958 1 IEC958 Capture Default unknown
2 IEC958 1 IEC958 Subcode Capture Default unknown
Failed to mixer_ctl_get_array
3 BYTE 12 IEC958 Q-subcode Capture Default 4 BOOL 1 IEC958 Rx V-Bit Errors Off
5 BOOL 1 IEC958 Tx V-Bit Off
6 INT 1 RX Sample Rate 0
7 BOOL 1 IEC958 USyncMode CDText Off
8 BOOL 1 IEC958 Rx Raw Capture Mode Bit Off
After configured the SPDIF(/dev/snd/pcmC0D3x, port = 3) as the primary card in vendor/nxp-opensource/imx/alsa/tinyalsa_hal.cpp, the logcat like this when playing audio in app:
02-01 07:15:14.972 371 2137 I audio_hw_primary: start_output_stream: out: 0xe8f47600, device: 2, address: , mode: 0, flags 0x2
02-01 07:15:14.972 371 2137 I audio_hw_primary: select_output_device(), headphone 0 ,headset 0 ,speaker 2
02-01 07:15:14.972 371 2137 I audio_hw_primary: start_output_stream: set to pcm_config_mm_out, rate 48000, chn 2, format 0x0
02-01 07:15:14.972 371 2137 D audio_hw_primary: start_output_stream: pcm_open: card: 0, rate: 48000, channel: 2, format: 0, period_size: 0x400, flag: 8
02-01 07:15:14.980 371 2137 E audio_hw_primary: start_output_stream: pcm_open error: cannot set hw params: Invalid argument
02-01 07:15:14.981 371 2137 V audio_hw_primary: write error, sleep few ms
Is there anything else I need to do for this problem? Thank you!
Hi Buridan
such configuration (without codec) is not supported in nxp bsps, in general one
can try to follow similar example with "simple-audio-card "
Use Chapter 7 Audio i.MX Linux Reference Manual describing all linux ALSA software layers
Best regards
igor
Dear igor:
Do you mean the S/PDIF can only be used in "simple-audio-card" framework? Currently I am using the custom machine driver to create audio card.
I may posted the wrong information that the codec of the sound card is dummy audio codec which is refer to the Dummy audio codec - play & record on i.MX8MM.
And if I just use the S/PDIF driver at kernel/sound/soc/fsl/imx-spdif.c (block the imx-dummy.c) refer to the i.MX Linux Reference Manual in capter 7.4.2~7.4.5, the dts:
sound-spdif {
compatible = "fsl,imx-audio-spdif";
model = "imx-spdif";
spdif-controller = <&spdif0>;
spdif-in;
spdif-out;
};
Then I will get the same problem in the main post. Except the S/PDIF, the SAI/ESAI has already worked with dummy codec.
I opend the DEBUG macro and the printf output:
mek_8q:/ # dmesg | grep dai
[ 5.169054] fsl-spdif-dai 59020000.spdif: use rxtx1 as tx clock source for 32000Hz sample rate
[ 5.169066] fsl-spdif-dai 59020000.spdif: use txclk df 24 for 32000Hz sample rate
[ 5.169072] fsl-spdif-dai 59020000.spdif: the best rate for 32000Hz sample rate is 32000Hz
[ 5.176404] fsl-spdif-dai 59020000.spdif: use rxtx5 as tx clock source for 44100Hz sample rate
[ 5.176411] fsl-spdif-dai 59020000.spdif: use txclk df 19 for 44100Hz sample rate
[ 5.176419] fsl-spdif-dai 59020000.spdif: use sysclk df 3 for 44100Hz sample rate
[ 5.176426] fsl-spdif-dai 59020000.spdif: the best rate for 44100Hz sample rate is 43859Hz
[ 5.176438] fsl-spdif-dai 59020000.spdif: use rxtx1 as tx clock source for 48000Hz sample rate
[ 5.176444] fsl-spdif-dai 59020000.spdif: use txclk df 16 for 48000Hz sample rate
[ 5.176451] fsl-spdif-dai 59020000.spdif: the best rate for 48000Hz sample rate is 48000Hz
[ 5.176460] fsl-spdif-dai 59020000.spdif: use rxtx1 as tx clock source for 96000Hz sample rate
[ 5.176466] fsl-spdif-dai 59020000.spdif: use txclk df 8 for 96000Hz sample rate
[ 5.176474] fsl-spdif-dai 59020000.spdif: the best rate for 96000Hz sample rate is 96000Hz
[ 5.176482] fsl-spdif-dai 59020000.spdif: use rxtx1 as tx clock source for 192000Hz sample rate
[ 5.176489] fsl-spdif-dai 59020000.spdif: use txclk df 4 for 192000Hz sample rate
[ 5.176497] fsl-spdif-dai 59020000.spdif: the best rate for 192000Hz sample rate is 192000Hz
[ 5.188105] imx-dummy sound-dummy: snd-soc-dummy-dai <-> 59040000.sai mapping ok
[ 5.198172] imx-dummy sound-dummy: snd-soc-dummy-dai <-> 59050000.sai mapping ok
[ 5.208096] imx-dummy sound-dummy: snd-soc-dummy-dai <-> 59010000.esai mapping ok
[ 5.222350] imx-dummy sound-dummy: snd-soc-dummy-dai <-> 59020000.spdif mapping ok
mek_8q:/ # tinyplay /sdcard/Music/1
1khz-16000-16-1.wav 1khz-32000-32-2.wav 1khz-8000-8-2.wav
1khz-16000-32-2.wav 1khz-48000-32-2.wav
mek_8q:/ # tinyplay /sdcard/Music/1khz-48000-32-2.wav -D 0 -d 3 -p 1024 -n 3
Unable to open PCM device 3 (cannot set hw params: Invalid argument)