一、环境介绍
linux 版本:6.6.52
soc:imx9331
codec:nau88c10
使用的内核文件为 Image,dtb 文件为:imx93-11x11-evk.dtb
二、硬件检查
-
i2s 信号线要接对
-
i2c 控制信号建议为 4.7k 上拉
-
codec 供电可以按参考设计来
三、驱动修改
先配置 sai 信号,我的板子使用的是 sai2,所以我配置如下
bash
&sai2 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_sai2>;
pinctrl-1 = <&pinctrl_sai2_sleep>;
assigned-clocks = <&clk IMX93_CLK_SAI2>;
assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>;
assigned-clock-rates = <12288000>;
fsl,sai-mclk-direction-output;
status = "okay";
};
pinctrl_sai2: sai2grp {
fsl,pins = <
MX93_PAD_ENET2_TX_CTL__SAI2_TX_SYNC 0x31e
MX93_PAD_ENET2_TXC__SAI2_TX_BCLK 0x31e
MX93_PAD_ENET2_RD2__SAI2_MCLK 0x31e
MX93_PAD_ENET2_RX_CTL__SAI2_TX_DATA00 0x31e
MX93_PAD_ENET2_TD3__SAI2_RX_DATA00 0x31e
>;
};
pinctrl_sai2_sleep: sai2grpsleep {
fsl,pins = <
MX93_PAD_ENET2_TX_CTL__GPIO4_IO20 0x51e
MX93_PAD_ENET2_TXC__GPIO4_IO21 0x51e
MX93_PAD_ENET2_RD2__GPIO4_IO26 0x51e
MX93_PAD_ENET2_RX_CTL__GPIO4_IO22 0x51e
MX93_PAD_ENET2_TD3__GPIO4_IO16 0x51e
>;
};
再配置 codec,codec 的 7 位读写地址为 0x1a;因为要用到 imx9331 给的 mclk;所以添加了一个时钟配置
bash
&lpi2c1 {
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <400000>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_lpi2c1>;
pinctrl-1 = <&pinctrl_lpi2c1>;
status = "okay";
codec: nau8810@1a {
#sound-dai-cells = <0>;
compatible = "nuvoton,nau8810";
reg = <0x1a>;
clocks = <&clk IMX93_CLK_SAI2>;
clock-name = "mclk";
};
};
再配置 machine 驱动的硬件信息,参考原先的 codec,修改如下
audio-routing 是更具 machine 驱动,和 codec 驱动的 struct snd_soc_dapm_widget 来填写的;
bash
sound-nau8810 {
compatible = "fsl,imx-audio-nau8810";
model = "nau8810-audio";
audio-cpu = <&sai2>;
audio-codec = <&codec>;
audio-routing =
"Ext Spk", "MONOOUT",
"Ext Spk", "SPKOUTP",
"Ext Spk", "SPKOUTN",
"AMIC", "MICN",
"AMIC", "MICP";
};
修改 machine 驱动,更具参考板的 compatible 字符串,找到驱动 fsl-asoc-card.c
cpp
// 添加头文件
#include "../codecs/nau8810.h"
// 注释掉以下代码
static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
{
......
#if 0
ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
codec_priv->pll_id, 0, 0, 0);
if (ret && ret != -ENOTSUPP) {
dev_err(dev, "failed to stop FLL: %d\n", ret);
return ret;
}
#endif
......
}
// 添加声卡 nau8810 的信息
static int fsl_asoc_card_probe(struct platform_device *pdev)
{
......
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8904")) {
codec_dai_name = "wm8904-hifi";
priv->codec_priv.mclk_id = WM8904_FLL_MCLK;
priv->codec_priv.fll_id = WM8904_CLK_FLL;
priv->codec_priv.pll_id = WM8904_FLL_MCLK;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
priv->card_type = CARD_WM8904;
} else if (of_device_is_compatible(np, "fsl,imx-audio-nau8810")) {
codec_dai_name = "nau8810-hifi";
priv->codec_priv.mclk_id = NAU8810_SCLK_MCLK;
priv->codec_priv.fll_id = NAU8810_SCLK_PLL;
priv->codec_priv.pll_id = NAU8810_SCLK_PLL;
priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
if (codec_dev) {
priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL);
printk("trans mclk rate %ld\n", clk_get_rate(priv->codec_priv.mclk));
}
} else {
dev_err(&pdev->dev, "unknown Device Tree compatible\n");
ret = -EINVAL;
goto asrc_fail;
}
......
}
四、测试声卡
可以通过 alsa 工具来测试声卡
bash
# 显示所有可以配置的控件
amixer controls
# SPKOUT 非静音
amixer cset numid=36 off
# SPKOUT 静音
amixer cset numid=36 on
# MONOOUT 非静音
amixer cset numid=39 off
# MONOOUT 静音
amixer cset numid=39 on
# 调整 MONOOUT 音量(SPKOUT 也会被一起调节)
amixer cset numid=7 220
# 调整 MIC 音量
amixer cset numid=11 230
# 调整 SPKOUT 音量
amixer cset numid=37 63
# 边录边放
arecord -f S16_LE -r 8000 -c 2 | aplay -