这里先说下rk3288 HDMIin音频通路:

hdmiin:
HDMIIn声音直接通过codec输出到喇叭、耳机,不需要送到主控进行处理:
TC358749XBG-> alc5651 i2s2 -> alc5651 dac -> hp/lineout

alsa HAL 层

RK平台 android 5.1 BOX MID的SDK之后统一使用这个目录下面的代码
\hardware\rockchip\audio\tinyalsa_hal

嵌入式设备的音频系统可以被划分为板载硬件(Machine)、Soc(Platform)、Codec 三大部分

1、音频编解码器 Codec 负责处理音频信息,包括 ADC,DAC,Mixer,DSP,输入输出以及音量控制等所有
与音频相关的功能。
Codec 与处理器之间通过 I2C 总线和数字音频接口 DAI 进行通信。
I2C 总线 - 实现对 Codec 寄存器数据的读写。

2、DAI –(digital audio interface)实现音频数据在 CPU 和 Codec 间的通信,包括 I2S、PCM 和 AC97
等。
蓝牙立体声音乐播放走的是蓝牙跟 CPU 直接的 UART 接口。
在只有一组 I2S 的主控上面,蓝牙通话 SCO 暂时是通过 Codec 中继,即通过 codec 来路由选择是
否走通话,走的是 I2S 接口 。如果主控有两组 I2S,那么可以将 BT PCM 直接接到主控的 PCM 接
口上。
S/DIF(Sony/Philips Digital Interface Format),通过光纤或同轴电缆传输音频,保证音频质量。

Codec 内部通路举例 RK616

同时音频驱动有三部分:
Machine driver
sound/soc/rockchip/rk_rk616.c
其中的 Machine 驱动负责 Platform 和 Codec 之间的耦合以及部分和设备或板子特定的代码采样率
时钟配置

Platform driver
sound/soc/ rockchip /rk30_i2s.c
I2S 控制器驱动 采样率时钟 DMA 等配置

Codec driver
sound/soc/codecs/rk616_codec.c
codec 的寄存器通路的配置

android audio route通路介绍

android定义了很多的音频devices:在frameworks/base/media/java/android/media/AudioSystem.java文件中

349     // output devices, be sure to update AudioManager.java also
350     public static final int DEVICE_OUT_EARPIECE = 0x1;
351     public static final int DEVICE_OUT_SPEAKER = 0x2;
352     public static final int DEVICE_OUT_WIRED_HEADSET = 0x4;
353     public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8;
354     public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10;
355     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20;
356     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40;
357     public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80;
358     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
359     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
360     public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
361     public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;
362     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
363     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
364     public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
365     public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
366     public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
367     public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;
368     public static final int DEVICE_OUT_LINE = 0x20000;
369     public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
370     public static final int DEVICE_OUT_SPDIF = 0x80000;
371     public static final int DEVICE_OUT_FM = 0x100000;
372     public static final int DEVICE_OUT_AUX_LINE = 0x200000;
373     public static final int DEVICE_OUT_SPEAKER_SAFE = 0x400000;
374     public static final int DEVICE_OUT_IP = 0x800000;
375     public static final int DEVICE_OUT_BUS = 0x1000000;

HAL层通过一定转换跟android上层对应

在hardware/rockchip/audio/tinyalsa_hal/alsa_route.c 中通过route_set_controls(route)中通过 get_route_config(int route)将以上的各个route值转换为codec_config中的xxx.h配置文件。

文件:./hardware/rockchip/audio/tinyalsa_hal/alsa_route.c
282 const struct config_route *get_route_config(unsigned route)  //即在这里获取音频路由设备
283 {284     ALOGV("get_route_config() route %d", route);
285
286
287     if (!route_table) {288         ALOGE("get_route_config() route_table is NULL!");
289         return NULL;
290     }
291     switch (route) {292     case SPEAKER_NORMAL_ROUTE:
293         return &(route_table->speaker_normal);......

HAL层中定义的 route table,再通过route_set_controls将这些table配置,最终设置到codec的寄存器

 文件:./hardware/rockchip/audio/tinyalsa_hal/codec_config/rt5651_config.h1110 const struct config_route_table rt5651_config_table = {1111     //speaker1112     .speaker_normal = {1113         .sound_card = 0,1114         .devices = DEVICES_0,1115         .controls = rt5651_speaker_normal_controls,1116         .controls_count = sizeof(rt5651_speaker_normal_controls) / sizeof(struct config_control),1117     },......48 const struct config_control rt5651_speaker_normal_controls[] = {5657         {58             .ctl_name = "DAC MIXL INF1 Switch",59             .int_val = {on},60         },61         {62             .ctl_name = "DAC MIXR INF1 Switch",63             .int_val = {on},64         },65         {66             .ctl_name = "Stereo DAC MIXL DAC L1 Switch",67             .int_val = {on},68         },69         {70             .ctl_name = "Stereo DAC MIXR DAC R1 Switch",71             .int_val = {on},72         },73         {74             .ctl_name = "OUT MIXL DAC L1 Switch",75             .int_val = {on},76         },77         {78             .ctl_name = "OUT MIXR DAC R1 Switch",79             .int_val = {on},80         },81

HAL层会根据sound card name选择使用哪个table,如果没有匹配默认使用default_config.h

文件:./hardware/rockchip/audio/tinyalsa_hal/alsa_route.c89 /**90  * @brief route_init91  *92  * @returns93  */94 int route_init(void)95 {96     char soundCardID[20] = "";97     static FILE * fp;98     unsigned i, config_count = sizeof(sound_card_config_list) / sizeof(struct alsa_sound_card_config);99     size_t read_size;
100
101     ALOGV("route_init()");
102
103     fp = fopen("/proc/asound/card0/id", "rt"); //id是第0个声卡,串口执行cat /proc/asound/card0/id可以查看
104     if (!fp) {105         ALOGE("Open sound card0 id error!");
106     } else {107         read_size = fread(soundCardID, sizeof(char), sizeof(soundCardID), fp);
108         fclose(fp);
109
110         if (soundCardID[read_size - 1] == '\n') {111             read_size--;
112             soundCardID[read_size] = '\0';
113         }
114
115         ALOGV("Sound card0 is %s", soundCardID);
116
117         for (i = 0; i < config_count; i++) {118             if (!(sound_card_config_list + i) || !sound_card_config_list[i].sound_card_name ||
119                 !sound_card_config_list[i].route_table)
120                 continue;
121
122             if (strncmp(sound_card_config_list[i].sound_card_name, soundCardID, //根据sound card name选择使用哪个table
123                 read_size) == 0) {124                 route_table = sound_card_config_list[i].route_table;
125                 ALOGD("Get route table for sound card0 %s", soundCardID);
126             }
127         }
128     }
129
130     if (!route_table) {131         route_table = &default_config_table; //如果没有匹配默认使用default_config.h
132         ALOGD("Can not get config table for sound card0 %s, so get default config table.", soundCardID);
133     }
134
135     for (i = PCM_DEVICE0_PLAYBACK; i < PCM_MAX; i++)
136          mPcm[i] = NULL;
137
138     return 0;
139 }

HAL层声卡名称sound card name和配置表列表table的声明在 ./tinyalsa_hal/codec_config/config_list.h 文件中。Audio将获取config_route_table并根据声卡0(识别到的声卡列表的第一个)和sound_card_name的名称设置路由route。
rk3288:/ # cat /proc/asound/card0/id
realtekrt5651co

文件:./hardware/rockchip/audio/tinyalsa_hal/codec_config/config_list.h71 struct alsa_sound_card_config sound_card_config_list[] = {72     {73         .sound_card_name = "RKRK616",74         .route_table = &rk616_config_table,75     },76     {77         .sound_card_name = "RK29RT3224",78         .route_table = &rt3224_config_table,79     },80     {81         .sound_card_name = "rockchiprt5640c",82         .route_table = &rt5640_config_table,83     },84     {85         .sound_card_name = "rockchipes8396c",86         .route_table = &es8396_config_table,87     },88     {89         .sound_card_name = "RK29RT3261",90         .route_table = &rt3261_config_table,91     },92     {93         .sound_card_name = "RK29WM8960",94         .route_table = &wm8960_config_table,95     },96     {97         .sound_card_name = "RKRT3224",98         .route_table = &rt3224_config_table,99     },
100     {101         .sound_card_name = "RKRT3261",
102         .route_table = &rt3261_config_table,
103     },
104     {105         .sound_card_name = "RKWM8960",
106         .route_table = &wm8960_config_table,
107     },
108     {109         .sound_card_name = "RKRT5616",
110         .route_table = &rt5616_config_table,
111     },
112     {113         .sound_card_name = "realtekrt5651co",
114         .route_table = &rt5651_config_table,
115     },......

.route_table的引用对应在xxxx_config.h文件中有定义,例如.route_table = &rt5651_config_table在rt5651_config.h中。

 文件:/hardware/rockchip/audio/tinyalsa_hal/codec_config/rt5651_config.h
1143 const struct config_route_table rt5651_config_table = {1144     //speaker
1145     .speaker_normal = {1146         .sound_card = 0,
1147         .devices = DEVICES_0,
1148         .controls = rt5651_speaker_normal_controls,
1149         .controls_count = sizeof(rt5651_speaker_normal_controls) / sizeof(struct config_control),
1150     },
1151     .speaker_incall = {1152         .sound_card = 0,
1153         .devices = DEVICES_0,
1154         .controls = rt5651_speaker_incall_controls,
1155         .controls_count = sizeof(rt5651_speaker_incall_controls) / sizeof(struct config_control),
1156     },......

然后再在.controls当中配置ctl_name和int_val,例如rt5651_speaker_normal_controls的配置,对应在kernel层会获取到这里的设置。

const struct config_control rt5651_speaker_normal_controls[] = {99     {100         .ctl_name = "RT5651 ASRC Switch",101         .int_val = {1},102     },103104     {105         .ctl_name = "DAC MIXL INF1 Switch",106         .int_val = {on},107     },108     {109         .ctl_name = "DAC MIXR INF1 Switch",110         .int_val = {on},111     },112     {113         .ctl_name = "Stereo DAC MIXL DAC L1 Switch",114         .int_val = {on},115     },116     {117         .ctl_name = "Stereo DAC MIXR DAC R1 Switch",118         .int_val = {on},119     },120     {121         .ctl_name = "OUT MIXL DAC L1 Switch",122         .int_val = {on},123     },124     {125         .ctl_name = "OUT MIXR DAC R1 Switch",126         .int_val = {on},127     },128     {129         .ctl_name = "HPOVOL L Switch",130         .int_val = {on},131     },132     {133         .ctl_name = "HPOVOL R Switch",134         .int_val = {on},135     },136     {137         .ctl_name = "HPO MIX HPVOL Switch",138         .int_val = {on},139     },140     {141         .ctl_name = "HPO MIX HPVOL Switch",142         .int_val = {on},143     },144     {145         .ctl_name = "HPO L Playback Switch",146         .int_val = {on},147     },148     {149         .ctl_name = "HPO R Playback Switch",150         .int_val = {on},151     },156     {    .ctl_name = "LOUT MIX DAC L1 Switch",    .int_val = {on},    },157     {    .ctl_name = "LOUT MIX DAC R1 Switch",    .int_val = {on},    },158159     //   SPEAKER_NORMAL_ROUTE  HEADSET_NORMAL_ROUTE160     {    .ctl_name =   "LOUT MIX OUTVOL L Switch",    .int_val = {on},    },161     {    .ctl_name =   "LOUT MIX OUTVOL R Switch",    .int_val = {on},    },162163     {    .ctl_name = "LOUT L Playback Switch",    .int_val = {on},    },164     {    .ctl_name = "LOUT R Playback Switch",    .int_val = {on},    },165166     //{    .ctl_name = "OUT Playback Volume",    .int_val = {26, 26},    }, // 31 31167168     {    .ctl_name = "DAC1 Playback Volume",    .int_val = {128, 128},    }, // {136, 136} //这里是音量设置};

音量值调节:

hardware/rockchip/audio/tinyalsa_hal/codec_config/rt5651_config.h

 const struct config_control rt5651_bluetooth_voip_controls[] = {// init IN2p/n for line in input.const struct config_control  rt5651_line_in_capture_controls[] = {// try run it first, to fix conflict{    .ctl_name = "RECMIXL INL1 Switch",    .int_val = {on},    }, //Replace mic: conf for L.in.L used{    .ctl_name = "RECMIXR INR1 Switch",    .int_val = {on},    }, //Replace mic: conf for L.in.R used{    .ctl_name = "RECMIXL BST2 Switch",    .int_val = {off},    }, // close conf for micL used{    .ctl_name = "RECMIXR BST2 Switch",    .int_val = {off},    }, // close conf for micR used{    .ctl_name = "RECMIXL BST1 Switch",    .int_val = {off},    },{    .ctl_name = "RECMIXR BST1 Switch",    .int_val = {off},    },{    .ctl_name = "RECMIXL BST3 Switch",    .int_val = {off},    },{    .ctl_name = "RECMIXR BST3 Switch",    .int_val = {off},    },{    .ctl_name = "Stereo1 ADC L1 Mux",    .str_val = "ADC",    },{    .ctl_name = "Stereo1 ADC R1 Mux",    .str_val = "ADC",    },{    .ctl_name = "Stereo1 ADC MIXL ADC1 Switch",    .int_val = {on},    },{    .ctl_name = "Stereo1 ADC MIXR ADC1 Switch",    .int_val = {on},    },{    .ctl_name = "ADC Capture Switch",    .int_val = {on, on},    },{    .ctl_name = "IN2 Boost",    .int_val = {2},    },{    .ctl_name = "ADC Capture Volume",    .int_val = {47, 47},    },// if you feel vol is low/high, can adjust it from 37 to 80. [63 is copied from rt5616]{    .ctl_name = "ADC Capture Volume",    .int_val = {63, 63},    }, // {57, 57} {47, 47}   //这里调节音量值设置

音频打开调用流程:

####  route_pcm_open()
####    -> get_route_config(route)
####                -> route_set_controls()
####                    -> route_pcm_close()
####                        -> route_set_controls()->

如何debug

1、通过看 kernel log 确认 alsa sound card 有没有注册。

rk3288_mid:/ $ dmesg | grep ALSA -EC5
[    1.551902] I : [File] : drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c; [Line] : 417; [Func] : mali_module_init(); svn_rev_string_from_arm of this mali_ko is '-cf8da18', rk_ko_ver is '5', built at '11:19:29', on 'Jan 15 2020'.
[    1.553256] Mali: Mali device driver loaded
[    1.554211] of_get_named_gpiod_flags: parsed 'gpios' property of node '/rockchip-key/power-key[0]' - status (0)
[    1.554274] of_get_named_gpiod_flags: parsed 'gpios' property of node '/rockchip-key/power-key[0]' - status (0)
[    1.554741] input: rk29-keypad as /devices/platform/rockchip-key/input/input2
[    1.556689] ALSA device list:
[    1.556778]   #0: realtek,rt5651-codec
[    1.556977]   #1: rk,hdmiin-tc358749x-codec
[    1.557280]   #2: rockchip,hdmi
[    1.557312]   #3: rockchip-cdndp-sound
[    1.565498] mmc_host mmc2: Bus speed (slot 0) = 150000000Hz (slot req 150000000Hz, actual 150000000HZ div = 0)

2、确认 route 是否正常
声卡注册好之后确认 alsa route 是否正确
通过命令 logcat -s alsa_route

rk3288_mid:/ $ logcat -s alsa_route
--------- beginning of system
--------- beginning of main
01-01 01:19:51.274   255   324 D alsa_route: route_set_controls() set route 24
01-01 01:38:30.866   255   324 D alsa_route: route_info->sound_card 0, route_info->devices 0
01-01 01:38:30.866   255   324 D alsa_route: route_set_controls() set route 0
01-01 01:38:34.105   255   324 D alsa_route: route_set_controls() set route 24
01-01 01:38:35.655   255   324 D alsa_route: route_info->sound_card 0, route_info->devices 0
01-01 01:38:35.656   255   324 D alsa_route: route_set_controls() set route 0
01-01 01:39:23.035   255   324 D alsa_route: route_set_controls() set route 24

上面命令跑了两个路由 route 0 route 24。route的宏定义在alsa_audio.h中。

文件:hardware/rockchip/audio$ vi tinyalsa_hal/alsa_audio.h62 typedef enum _AudioRoute {63     SPEAKER_NORMAL_ROUTE = 0,64     SPEAKER_INCALL_ROUTE, // 165     SPEAKER_RINGTONE_ROUTE,66     SPEAKER_VOIP_ROUTE,6768     EARPIECE_NORMAL_ROUTE, // 469     EARPIECE_INCALL_ROUTE,70     EARPIECE_RINGTONE_ROUTE,71     EARPIECE_VOIP_ROUTE,7273     HEADPHONE_NORMAL_ROUTE, // 874     HEADPHONE_INCALL_ROUTE,75     HEADPHONE_RINGTONE_ROUTE,76     SPEAKER_HEADPHONE_NORMAL_ROUTE,77     SPEAKER_HEADPHONE_RINGTONE_ROUTE,78     HEADPHONE_VOIP_ROUTE,7980     HEADSET_NORMAL_ROUTE, // 1481     HEADSET_INCALL_ROUTE,82     HEADSET_RINGTONE_ROUTE,83     HEADSET_VOIP_ROUTE,8485     BLUETOOTH_NORMAL_ROUTE, // 1886     BLUETOOTH_INCALL_ROUTE,87     BLUETOOTH_VOIP_ROUTE,
......
}AudioRoute;

RK3288_Android7.1在HAL层audio音频通路小结相关推荐

  1. Android Audio音频通路(七)

    android audio 生产者与消费者 简介 全面接触生产者/消费者问题是在操作系统原理中,并发性原理讨论的问题 生产者/消费者问题.最近的工作偏向音频,接着上一篇文章,用生产者,消费者模型来理解 ...

  2. Qualcomm Audio HAL 音频通路设置

    1. 音频框图概述 | Front End PCMs | SoC DSP | Back End DAIs | Audio devices |************* PCM0 <------- ...

  3. RK Audio HAL 音频通路设置与Codec原理

    由 b178903294创建, 最后修改于3月 18, 2020 一个平板项目中采用螃蟹卡ALC56561 作为硬件codec.由于声音播放前后过程中有pop声,所以对其硬件原理和驱动控制做了一番研究 ...

  4. Qualcomm Audio HAL 音频通路设置(基于8996平台)

    1. 音频框图概述 | Front End PCMs | SoC DSP | Back End DAIs | Audio devices |************* PCM0 <------- ...

  5. Qualcomm Audio HAL 音频通路设置【转】

    本文转载自:https://blog.csdn.net/azloong/article/details/79383323 1. 音频框图概述 | Front End PCMs | SoC DSP | ...

  6. Android9 Audio模块Hal层加载流程及修改方法

    摘要:在Android9中Audio模块调用Hal一般有两种路径: 1.通过AudioFlinger调用到Hal,这是众多原生接口走的路径,一般我们不会在这里增加方法,但是会修改这里面的方法 2.如果 ...

  7. android音频hal层简介

    如下图为android音频hal层所处的位置: 从上图可以看出,HAL层下面使用TiniAlsa(Android下一个简约的Alsa版本).HAL层分为两部分,一部分为各种音频设备,每种音频设备由一个 ...

  8. Android Audio 服务层与HAL层之间的接口分析 Service<->interface<->HAL

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.AudioFlinger 二.服务层接口分析 2.1由DevicesFactoryHalInterface可以找到Dev ...

  9. <一>Android Audio音频框架

    目录 1.0 设备驱动 2.0  android hal层 3.0  选择设备的暗箱策略AudioPolicy 4.0  软件层面的混音,AudioFlinger 5.0 完整的对外接口 AudioS ...

  10. 理解 Audio 音频系统二 之 audioserver AudioPolicyService

    理解 Audio 音频系统二 之 AudioPolicyService 二.audioserver & AudioPolicyService + AudioPolicy 启动流程总结 1. A ...

最新文章

  1. MySQL优化篇:show profile进行SQL分析
  2. MFC调用批处理文件(.bat)
  3. 基于ARM的Qt Creator嵌入式开发环境搭建
  4. Careers support for Masters students cambridge
  5. 客户端本地存储的比较及使用window.name数据传输
  6. 自称比特币创造者中本聪,如今这人被法官怒怼作伪证!
  7. 再送 5000 份红包封面!
  8. 深入浅出 Python Iterators 迭代器
  9. 女生学计算机和遥感哪个好就业,遥感科学与技术有性别歧视吗知乎
  10. Jeecg-Boot 使用技巧
  11. linux etc xdg,Xdg-menu (简体中文)
  12. 关于常用第三方统计平台比较
  13. 天涯上拣来的爱情哲学
  14. openBSD安装桌面
  15. ajax发送put请求参数,请求参数和PUT方法(Request params and PUT method)
  16. python get pip.py_get-pip.py 安装
  17. Rainbow 开发 step1
  18. java编写购书系统
  19. 新加坡首富张勇的烦恼
  20. 大数据技术原理与应用作业七

热门文章

  1. 同步异步-阻塞非阻塞
  2. c++程序设计原理与实践 第二十四章部分答案
  3. enumerateObjectsUsingBlock 、for 、for(... in ...) 的区别 性能测试
  4. Delphi 正则表达式语法(2): 或者与重复
  5. 【往届已EI稳定检索】第二届计算机科学与管理科技国际学术会议,多主题征稿!...
  6. 字节跳动 AI Lab 21届校招启动啦!
  7. NLP基础—3.文本表示
  8. 深度学习2.0-26.Regularization减轻overfitting
  9. 深度学习2.0-12.神经网络与全连接层之数据集的加载
  10. 梯度消失与梯度爆炸原因剖析