Rockchip RK3399 - Codec驱动( Realtek ALC5651)

发布时间 2023-07-08 09:10:06作者: 大奥特曼打小怪兽

Codec driver提供了配置/使能Codec的能力,驱动代码位于sound/soc/codecs/rt5651.c文件。

一、设备节点

1.1 设备节点rt5651

我们在arch/arm64/boot/dts/rockchip/rk3399-evb.dts文件添加rt5651设备节点,该节点位于i2c1节点下:

&i2c1 {
    status = "okay";
    i2c-scl-rising-time-ns = <150>;
    i2c-scl-falling-time-ns = <30>;
    clock-frequency = <200000>;

    rt5651: rt5651@1a {
        #sound-dai-cells = <0>;
        compatible = "rockchip,rt5651";
        reg = <0x1a>;
        clocks = <&cru SCLK_I2S_8CH_OUT>;
        clock-names = "mclk";
        hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_LOW>;
        status = "okay";
    };
};

 其中:

  • status :指定设备状态为“正常”,表示该设备状态为正常运行;
  • i2c-scl-rising-time-ns:定义了SCL信号上升时间的最小值,单位是纳秒;
  • i2c-scl-falling-time-ns:定义了SCL信号下降时间的最小值,单位是纳秒;
  • clock-frequency:定义了I2C总线的时钟频率,单位是赫兹;

接着定义rt5651音频编解码器的设备树节点,其名称为 rt5651,内部的设备地址为0x1a;

  • #sound-dai-cells :指定DAI的单元格数量,这里为0表示不需要添加额外的 DAI 单元格(比如,不需要配置 SAI、PCM 等标志);
  • compatible:指定设备驱动程序的兼容性,即告诉内核该设备可以被哪些驱动程序所使用;
  • reg:指定了rt5651设备在I2C控制器上的地址;
  • clocks:定义了音频编解码器使用的时钟,这里使用了由 PPL(Phase Locked Loop)产生的 SCLK_I2S_8CH_OUT 时钟信号;
  • clock-names:定义了音频编解码器使用的时钟的名称,这里为mclk,表示主时钟;
  • pinctrl-names:指定设备pinctrl配置集合,例如“default”表示默认配置;
  • pinctrl-0:设置default状态对应的引脚配置为i2s0_8ch_mclk,这里主要配置I2C1相关引脚复用为I2C功能;
  • status :指定设备状态为“正常”,表示该设备状态为正常运行;

1.2 引脚配置节点i2s0_8ch_mclk

在arch/arm64/boot/dts/rockchip/rk3399.dtsi文件添加引脚配置节点i2s_8ch_bus,定义在pinctrl设备节点下:

i2s0 {
        i2s0_8ch_mclk: i2s0-8ch-mclk {
                rockchip,pins =
                        <3 RK_PC1 2 &pcfg_pull_none>;
        };
        
        ....
}

此处配置GPIO3_C1引脚功能为MAC_TXCLK,电气特性为pcfg_pull_none。

我们在前面的文章中介绍的ALC565接线中并没有使用GPIO3_C1,所以这个我认为是多余的。

二、Codec驱动

四、烧录测试

4.1 配置内核

修改sound/soc/codecs/Kconfig文件,搜索config SND_SOC_RT5651,将该项修

config SND_SOC_RT5651
        tristate
        depends on I2C

改为,如果不修改的话,make menuconfig是看不到该配置项的;

config SND_SOC_RT5651
        tristate "Realtek ALC5651 CODEC"
        depends on I2C

在linux内核根目录下执行make menuconfig配置以下选项:

Device Drivers --->
  <*> Sound card support  --->
     <*> Advanced Linux Sound Architecture  ---> 
         <*> ALSA for SoC audio support  ---> 
            <*>  ASoC support for Rockchip                                                                                      
            {*}  Rockchip I2S Device Driver
            CODEC drivers  --->
              <*> Realtek RT5651 CODEC
            <*>  ASoC Simple sound card support  

至于为啥配这些,可以看下面的介绍。

4.1.1 支持simple-audio-card驱动

要想将sound/soc/generic/simple-card.c文件对应的驱动编译到内核,我们需要配置CONFIG_SND_SIMPLE_CARD,我们定位到sound/soc/generic/Makefile文件;

# SPDX-License-Identifier: GPL-2.0
snd-soc-simple-card-utils-objs  := simple-card-utils.o
snd-soc-simple-card-objs        := simple-card.o
snd-soc-audio-graph-card-objs   := audio-graph-card.o

obj-$(CONFIG_SND_SIMPLE_CARD_UTILS)     += snd-soc-simple-card-utils.o
obj-$(CONFIG_SND_SIMPLE_CARD)           += snd-soc-simple-card.o
obj-$(CONFIG_SND_AUDIO_GRAPH_CARD)      += snd-soc-audio-graph-card.o

这里定义了snd-soc-simple-card.o的生成规则:

snd-soc-simple-card-objs := simple-card.o

它表示将当前目录下的 simple-card.o文件编译成一个snd-soc-simple-card.o。我们可以查看sound/soc/generic/.snd-soc-simple-card.o.cmd文件找到编译命令:

root@zhengyang:/work/sambashare/rk3399/linux-5.2.8# cat  sound/soc/generic/.snd-soc-simple-card.o.cmd
cmd_sound/soc/generic/snd-soc-simple-card.o := arm-linux-ld  -EL  -maarch64elf    -r -o sound/soc/generic/snd-soc-simple-card.o sound/soc/generic/simple-card.o
4.1.2 支持I2S驱动

要想将sound/soc/rockchip/rockchip_i2s.c文件对应的驱动编译到内核,我们需要配置CONFIG_SND_SOC_ROCKCHIP_I2S,我们定位到sound/soc/rockchip/Makefile文件;

# SPDX-License-Identifier: GPL-2.0
# ROCKCHIP Platform Support
snd-soc-rockchip-i2s-objs := rockchip_i2s.o
snd-soc-rockchip-pcm-objs := rockchip_pcm.o
snd-soc-rockchip-pdm-objs := rockchip_pdm.o
snd-soc-rockchip-spdif-objs := rockchip_spdif.o

obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o snd-soc-rockchip-pcm.o
obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o
obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o

这里定义了snd-soc-rockchip-i2s.o的生成规则:

snd-soc-rockchip-i2s-objs := rockchip_i2s.o

它表示将当前目录下的rockchip_i2s.o文件编译成一个snd-soc-rockchip-i2s.o。

4.1.2 支持rt5651驱动

要想将sound/soc/codecs/rt5651.c文件对应的驱动编译到内核,我们需要配置CONFIG_SND_SOC_RT5651,我们定位到sound/soc/codecs/文件;

snd-soc-rt5651-objs := rt5651.o
obj-$(CONFIG_SND_SOC_RT5651)    += snd-soc-rt5651.o

这里定义了snd-soc-rt5651.o的生成规则:

snd-soc-rt5651-objs := rt5651.o

它表示将当前目录下的rt5651.o文件编译成一个snd-soc-rt5651.o。

4.2 保存配置

配置完内核之后记得保存配置:

存档:

root@zhengyang:/work/sambashare/rk3399/linux-6.3# mv rk3399_defconfig ./arch/arm64/configs/

重新配置内核:

root@zhengyang:/work/sambashare/rk3399/linux-6.3# make rk3399_defconfig

4.3 编译内核

在linux内核根目录下执行如下命令进行编译内核:

root@zhengyang:/work/sambashare/rk3399/linux-6.3# make -j8

u-boot-2023.04路径下的mkimage工具拷贝过来,然后在命令行使用mkimage工具编译即可:

root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp ../u-boot-2023.04/tools/mkimage ./
root@zhengyang:/work/sambashare/rk3399/linux-6.3# ./mkimage -f kernel.its kernel.itb

4.4 通过tftp烧录内核

给开发板上电,同时连接上网线,进入uboot命令行。我们将内核拷贝到tftp文件目录:

root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp kernel.itb /work/tftpboot/

接着给开发板上电。通过uboot命令行将kernel.itb下到内存地址0x10000000处:

=> tftp 0x10000000 kernel.itb

通过mmc write命令将内核镜像烧录到eMMC第0x8000个扇区处:

=> mmc erase 0x8000 0xA000
=> mmc write 0x10000000 0x8000 0xA000

4.5 启动内核

我们重新启动开发板,如果声卡驱动正常加载,我们会看到类似下面的日志:

[    3.442742] rt5651 1-001a: Failed to reguest IRQ 0: -22
[    4.035868] asoc-simple-card rt5651-sound: ASoC: DAPM unknown pin Headphones
[    4.049408] asoc-simple-card rt5651-sound: ASoC: Failed to add route MICBIAS1(*) -> Mic Jack

 

参考文章

[1] 理解ALSA(三):从零写ASoC驱动