完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
这里先说下rk3288 HDMIin音频通路:
hdmiin: HDMIIn声音直接通过codec输出到喇叭、耳机,不需要送到主控进行处理: TC358749XBG-》 alc5651 i2s2 -》 alc5651 dac -》 hp/lineout alsa HAL 层 RK平台 android 5.1 BOX MID的SDK之后统一使用这个目录下面的代码 hardwarerockchipaudiotinyalsa_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.h 1110 const struct config_route_table rt5651_config_table = { 1111 //speaker 1112 .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[] = { 56 57 { 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.c 89 /** 90 * @brief route_init 91 * 92 * @returns 93 */ 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] = ‘ ’; 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.h 71 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 }, 103 104 { 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}, }, 158 159 // SPEAKER_NORMAL_ROUTE HEADSET_NORMAL_ROUTE 160 { .ctl_name = “LOUT MIX OUTVOL L Switch”, .int_val = {on}, }, 161 { .ctl_name = “LOUT MIX OUTVOL R Switch”, .int_val = {on}, }, 162 163 { .ctl_name = “LOUT L Playback Switch”, .int_val = {on}, }, 164 { .ctl_name = “LOUT R Playback Switch”, .int_val = {on}, }, 165 166 //{ .ctl_name = “OUT Playback Volume”, .int_val = {26, 26}, }, // 31 31 167 168 { .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.h 62 typedef enum _AudioRoute { 63 SPEAKER_NORMAL_ROUTE = 0, 64 SPEAKER_INCALL_ROUTE, // 1 65 SPEAKER_RINGTONE_ROUTE, 66 SPEAKER_VOIP_ROUTE, 67 68 EARPIECE_NORMAL_ROUTE, // 4 69 EARPIECE_INCALL_ROUTE, 70 EARPIECE_RINGTONE_ROUTE, 71 EARPIECE_VOIP_ROUTE, 72 73 HEADPHONE_NORMAL_ROUTE, // 8 74 HEADPHONE_INCALL_ROUTE, 75 HEADPHONE_RINGTONE_ROUTE, 76 SPEAKER_HEADPHONE_NORMAL_ROUTE, 77 SPEAKER_HEADPHONE_RINGTONE_ROUTE, 78 HEADPHONE_VOIP_ROUTE, 79 80 HEADSET_NORMAL_ROUTE, // 14 81 HEADSET_INCALL_ROUTE, 82 HEADSET_RINGTONE_ROUTE, 83 HEADSET_VOIP_ROUTE, 84 85 BLUETOOTH_NORMAL_ROUTE, // 18 86 BLUETOOTH_INCALL_ROUTE, 87 BLUETOOTH_VOIP_ROUTE, 。..。.. }AudioRoute; |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
827 浏览 2 评论
rk1126实现BT601输入,输入不带IIC接口的驱动程序
2446 浏览 0 评论
2088 浏览 1 评论
3298 浏览 3 评论
RK3568 Android11让系统ntp校准时间生效,需要设置些什么
3596 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-4 22:14 , Processed in 0.609379 second(s), Total 73, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191