文章目录

  • 写在前面
  • ALSA代码架构
  • 重要概念
  • a Kcontrol
  • b widget
  • c route
  • 工具使用
  • amixer 的用法
  • arecord
  • aplay
  • alsactrl
  • 如何设置通路
  • 1 确认出入口
  • 2 mic通路
  • 3 speaker通路
  • 耳机拔插检测
  • 遇到mic不收声的问题


写在前面

这一章节主要是介绍px30移植5640驱动的过程,实现的目标如下
1 rt5640驱动移植
2 alsa通路配置
3 alsa通路保存默认配置信息
如果对alsa框架想详细了解可以参考这位大神的博客。


ALSA代码架构

kernel/sound

目录

内容

/aoa

苹果主板驱动

/arm

arm架构相关驱动

/atmel

atmel设备驱动

/core

该目录包含了ALSA驱动的中间层,它是整个ALSA驱动的核心部分

/drivers

不同架构中一些驱动共享文件放置一些与CPU、BUS架构无关的公用代码

/i2c

ALSA自己的I2C控制代码

/isa

isa声卡的上层模块

/mips

MIPS声卡设备驱动

/oos

oos架构

/parisc

gsc声卡驱动

/pci

pci声卡

/ppc

powerPC架构有关

/sh

SUPERH声卡驱动

/soc

system-on-chip

/sparc

Sparc声卡驱动

/synth

synth中间层

/usb

usb-audio驱动

名词解释:
CPU DAI : 主控端的 Audio Data Interface,比如 I²S,Spdif,Pdm,Tdm (就是通常所说的platform层)
CODEC DAI:即 Codec (通常所说的codec层)
DAI_LINK : 绑定 Cpu_Dai 和 Codec_Dai 为一个声卡,等同于 Machine Driver (platform
层)。
DMAENGINE:用于 Cpu 和 I²S/Spdif 等 Dai 之间的 Dma 传输引擎,实际是通过 Dma
来进行数据的搬运。
DAPM:动态音频电源管理,用于动态管理 Codec 等的电源管理,根据通路的开启配置开
关,以达到保证功能的前提下功耗尽量小。
JACK:耳机的接口检测,大部分使用 Codec 自身的检测机制,小部分使用 IO 来进行模拟。

rx560无供电版本bios_linux


rx560无供电版本bios_rx560无供电版本bios_02


目录层级结构

框架

代码

codec层

kernel/sound/soc/codecs/rt5640.c

platfrom层

Machine

Driver 层 kernel/sound/soc/rockchip/rockchip_px30_rt5640.c

重要概念

DAPM
DAPM是Dynamic Audio Power Management的缩写,直译过来就是动态音频电源管理的意思,DAPM是为了使基于linux的移动设备上的
音频子系统,在任何时候都工作在最小功耗状态下。DAPM对用户空间的应用程序来说是透明的,所有与电源相关的开关都在ASoc core
中完成。用户空间的应用程序无需对代码做出修改,也无需重新编译,DAPM根据当前激活的音频流(playback/capture)和声卡中的
mixer等的配置来决定那些音频控件的电源开关被打开或关闭。

a Kcontrol

一个kcontrol代表着一个mixer(混音器),或者是一个mux(多路开关),又或者是一个音量控制器等等

b widget

可以理解为对kcontrol的进一步升级和封装,同样指音频系统中的某个部件,如mixer,mux;

c route

一个路径的连接至少包含以下几个元素:起始端widget,跳线path,到达端widget,其实route就是连接起各个widget

可以看出,这三大组件的关系是由点及面的。

工具使用

我的linux系统中自带了aplay arecord amixer 使用这个测试,不详细介绍工具的使用了,网上资料太多了,只是介绍个简单的用法

amixer 的用法

总结来说就是
amixer controls 查看命令
amixer cget 得到命令
amixer cset 设置命令

重点是分析下音频流如何打开,并且流向自己想要的方向

arecord

arecord -D hw:0,0 -d 10 -f dat -t wav test.wav

-D :指定声卡
-d: 指定录制时间
-f : 指定音频格式
-t :指定录制文件格式

aplay

aplay play.wav

alsactrl

保存设置

alsactl store

恢复设置

alsactl restore

要实现所有的通路 ,可以打开之后,使用alsactl store 保存配置,默认路径在:/var/lib/alsa/asound.state 之后开机时通过将alsactl restore写入脚本恢复

如何设置通路

重难点再次,根据官方手册,讲解一下如何配置通路。

1 确认出入口

先看一下原理图,将收音和放音的设备接到哪里,即先确认下这张图的入口和出口

rx560无供电版本bios_电源管理_03


我就以入口是IN2P 出口为SPORP为例,说明一下通路配置

2 mic通路

步骤 根据mx-[n] 查找rtl5640.h 然后查找相应的Kcontrol 或者route

rx560无供电版本bios_声卡驱动_04

amixer cset name="RECMIXL BST2 Switch" 1 #MX-3C[1]
amixer cset name="Stereo ADC MIXL ADC1 Switch" 1 #MX-27[14]
amixer cset name="ADC Capture Switch" 1 #MX-1C[15]

amixer cset name="RECMIXR OUT MIXR Switch" 1 # MX-3E[0]

3 speaker通路

rx560无供电版本bios_声卡驱动_05

amixer cset name="DAI select" 0 
amixer cset name='DAC MIXR INF1 Switch' 1  #MX-29 [6]
amixer cset name="Stereo DAC MIXR DAC R1 Switch" 1 # MX-2A[6]
amixer cset name="OUT MIXR DAC R1 Switch" 1 #MX-52 [0]

amixer cset name="SPK MIXR OUT MIXR Switch" 1 # MX-47 [1]

amixer cset name="Speaker Channel Switch" 1 #MX-01[6]
amixer cset name="SPOR MIX SPKVOL R Switch" 1 #MX-49[12]
amixer cset name="Speaker R Playback Switch" 1 #MX-01[7]
amixer cset name="Speaker Playback Volume" 26

耳机拔插检测

设备树 : kernel/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-rgb-v10-linux.dts

rk_headset: rk-headset {
    compatible = "rockchip_headset";
    headset_gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
    pinctrl-names = "default";
    pinctrl-0 = <&hp_det>;
    status ="okay";
};

kernel/arch/arm64/configs/px30_linux_defconfig

CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RK_HEADSET=y

涉及文件夹
/kernel/drivers/headset_observe/

文件名

功能

rk_headset.c

检测耳机拔插

rockchip_headset_core.c

核心函数

rk_headset_irq_hook_adc.c

简单的调用流程

rx560无供电版本bios_rx560无供电版本bios_06

遇到mic不收声的问题

我再调试过程中,rt5640遇到了录音这块死活没有声音的问题,查了好久,发现我手里的驱动代码DAPM好像有点问题

rx560无供电版本bios_rx560无供电版本bios_07


这个代码里没有描述MICBIAS1和IN1P IN2P IN3P,修改了一下代码

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c

static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
+       {"IN1P", NULL, "MICBIAS1"},
+       {"IN2P", NULL, "MICBIAS1"},
+       {"IN3P", NULL, "MICBIAS1"},
}