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!