rk3399

您所在的位置:网站首页 typec输出音频和35输出有什么区别 rk3399

rk3399

2023-07-23 16:44| 来源: 网络整理| 查看: 265

关于音频的输出通路,可以有多重选择:HDMI-out,喇叭,耳机,LINE-in,USB声卡,蓝牙等,切换不同的通路音频就从不同的通路输出或者录入,这里主要以HDMIin为例来简单说一下相关AUDIO通路方面的内容。

RK3399 HDMI IN声卡通路选择

当前RK3399有三路i2s通道,HDMIOUT音频通路芯片内置为i2s2。当前RK3399 开发板上的音频芯片还有蓝牙、rt5651、tc358749,音频通路配置如下:

RK3399 I2S2 没有使用来作为蓝牙通话,则可以 TC358749 I2S 接口接到 RK3399的单独一个 I2S 上(I2S/PCM 不能跟其他 I2S 设备共用,否则造成 I2S 信号的干扰,声音有杂音),另外的 I2S 接口接 codec 通过功放输出 ANDROID 系统声音。

RK3399 HDMI IN 声卡通路配置

通路1:HDMIIn –> RK3399 I2S1- > RK3399 HDMI TX -> HDMI 电视机 通路2:HDMIIn –> RK3399 I2S1- > RK3399 I2S0 -> CODEC ->hp/Speaker

TC358749 I2S 信号送给 RK3399 录音,然后 RK3399 在通过播放给 HDMI TX 输出,需要注册两个声卡,TC358749 声卡,以及HDMI audio out 声卡,系统默认已经有HDMI audio out 注册,需要dts中开启即可,TC358749 需要再重新写一个声卡驱动。 在这里插入图片描述

RK3399 HDMI IN内核实现方案

该部分的总体思路是,注册东芝 tc358749x 芯片(约定以下简称 749 侧)声卡,当声卡成功注册后,打开 hdmiin apk 时,能用 tinyalsa 工具正常的进行录(tinycap)播(tinyplay)时,此部分即可调通。 rk3399 具有三组I2S 控制器,所以在硬件上连接方式有所不同。根据应用场景的不同,当 749 侧的 I2S 连接到cpu 或 codec 的 I2S 时,需区分 I2S 的主从模式,一般来说,由于 749 侧只能作为 master 模式,所以当和 749 侧连接的另一侧,则需要配置为 slave 模式

在这里插入图片描述

Android 7.1/ kernel 4.4 的 的 I2S M/S

4.4 内核使用了 simple-card 通用的 machine 驱动进行声卡的注册,为了配置主控的 I2S为 slave 模式。

配置文件:arch/arm64/boot/dts/rockchip/rk3399-box-rev2-ne4000.dts tc358749x_sound:tc358749x-sound { compatible = "simple-audio-card"; simple-audio-card,format = "i2s"; simple-audio-card,name = "rockchip,tc358749x-codec"; simple-audio-card,bitclock-master = ; simple-audio-card,frame-master = ; simple-audio-card,cpu { sound-dai = ; sound-dai = ; }; sound0_master: simple-audio-card,codec { sound-dai = ; }; }; 对于rk3399具有多组 I2S 的平台,注册声卡的方式是把 749 和 codec注册成一张声卡,压缩包补丁默认是用这种方式注册的。 rt5651-sound { status = "disabled"; }; hdmiin-sound { compatible = "rockchip,rockchip-rt5651-tc358749x-sound"; rockchip,cpu = ; rockchip,codec = ; status = "okay"; }; 原dts中未对tc358749对应的i2s做配置,添加i2s1配置 +&i2s1 { status = "okay"; rockchip,i2s-broken-burst-len; rockchip,playback-channels = ; rockchip,capture-channels = ; #sound-dai-cells = ; }; 当前tc358749芯片挂在i2c1下面,在i2c1下面配置tc358749 tc358749x: tc358749x@0f { #sound-dai-cells = ; compatible = "toshiba,tc358749x"; reg = ; power-gpios = ; //GPIO4_A7 stanby-gpios = ; //GPIO3_C0 change to GPIO1_B5 reset-gpios = ; //GPIO3_D6 int-gpios = ; //GPIO4_A5 pinctrl-names = "default"; pinctrl-0 = ; status = "okay"; }; 添加当前音频配置方案,需修改音频驱动代码,根据RK提供修改方案进行修改

#测试驱动是否正常 1、tool & cmds : mmm external/tinyalsa/ [ tinymix tinyplay tinycap ] //从sdk源码中编译出tinyalsa测试工具

当前系统提供tinyalsa音频测试工具可直接用于音频测试 tinymix 音频通路配置 tinypcminfo 用于查看pcm通道的相关信息 tinyplay 播放音频 tinycap 录音(默认情况下该工具不安装,需在external/tinyalsa目录下编译才会生成) 录音:tinycap 001.wav -D 1 -d 1 001.wav 音频文件(tinycap只能录到wav格式的音频文件) -D 声卡 number -d pcm number 结束录音用 ctrl+c 组合键结束 播放: tinyplay 001.wav -D 0 -d 0 调试注意事项 在测试HDMI IN录音时出现无法录音的情况,检查后发现在i2s1的配置中出现GPIO口复用,需将复用的GPIO口注掉: i2s1 { i2s1_2ch_bus: i2s1-2ch-bus { rockchip,pins = , , //, ; //; }; }; 问题调试排查的一些方法

1、通过cat /proc/asound/cards确认声卡有没有注册上

rk3399_mid:/ # cat /proc/asound/cards 0 [rkhdmidpsound ]: rk-hdmi-dp-soun - rk-hdmi-dp-sound rk-hdmi-dp-sound 1 [realtekrt5651co]: realtekrt5651co - realtekrt5651codec_hdmiin realtekrt5651codec_hdmiin

2、查看当前声卡设备:

rk3399_mid:/ # ls /dev/snd/ controlC0 controlC1 pcmC0D0p pcmC1D0c pcmC1D0p pcmC1D1c timer p 播放设备 c 录音设备 HDMI out:pcmC0D0p codec : pcmC1D0c pcmC1D0p HDMI IN : pcmC1D1c

3、tc358749 连接到cpu的某组i2s,其对应的pcm设备在某声卡某pcm下,比如”pcmC1D0c”,说明749对应的pcm设备在声卡1,pcm号为0,则先打开 hdmiin apk,可以这样录音:

tinycap /sdcard/test.wav -D 1 -d 0 -c 2 -r 44100 -b 16

-D:声卡 number -d:pcm number

结束录音用 ctrl+c 组合键结束。 注:不能用 windows 的 cmd 命令窗口进行 ctrl+c 结束 。录音结束后,拷贝 test.wav 出来看看是否正常录到音。如果没有的话,确认声卡注册成功,用示波器量 tc358749 端的 i2s 信号,SDO 脚是否有信号,没有的找东芝的 FAE 咨询。

4、常用查看声卡状态和信息info 的命令操作:

cat /proc/asound/card*/pcm*/sub*/status |grep 'stat|close' -EC1 cat /proc/asound/card*/pcm*/sub*/info|grep id -C1|grep name -v cat /proc/asound/card*/pcm*/sub*/info rk3288:/ $ cat /proc/asound/card*/pcm*/sub*/info card: 0 device: 0 //输入设备类型 subdevice: 0 stream: CAPTURE //录音设备 id: RT5651 PCM rt5651-aif1-0 name: subname: subdevice #0 class: 0 subclass: 0 subdevices_count: 1 subdevices_avail: 1 card: 0 device: 0 //输出设备类型 subdevice: 0 stream: PLAYBACK //放音设备 id: RT5651 PCM rt5651-aif1-0 name: subname: subdevice #0 class: 0 subclass: 0 subdevices_count: 1 subdevices_avail: 1 RK3399 HDMIIN HAL层实现方案 HAL 层的实现是基于音频驱动已经调好的情况下来实现的,其基本思路是用 alsa-soc lib的API 来做的,主要API如下: 1. pcm_open 打开指定声卡下的 pcm 设备 2. pcm_frames_to_bytes 返回读回帧数的总大小用字节 3. pcm_read 读音频数据 4. pcm_wirte 写音频数据 5. pcm_close 关闭 pcm 设备

一般的编程步骤都是按 linux 的编程习惯统一调用界面来的,也即:pcm_open - > pcm_write/ pcm_read -> pcm_close 综上,HAL 层要做的便是按上面顺序进行的,pcm_read 从某声卡 pcm 设备读取音频数据,也即是对 749 声卡进行录音,pcm_write 把读到的音频数据写到某声卡中去,也即是把得到 749的音频数据通过这张声卡播放,具体的业务逻辑依据实际需求而定。

HAL层对HDMIIN的音频通路做了单独的处理,同时对上层apk进行了修改,根据RK提供的补丁处理上层音频通路

分析HAL层log

logcat -s AudioHardwareTiny audio_hw_hdmiin alsa_route RK3399 HDMIIN音频采样率

当前HDMIIN可读取的音频采样率为44.1khz,还无法适配其他采样率,当其他音频采样率接入时,录取的声音会出现断断续续的状态,根据RK提供的补丁进行修改

hal部分 相关函数说明

调试阶段,单独编译mmm hardware/rockchip/audio/tinyalsa_hal/ 得到 audio.primary.rk30board.so,push进机器验证即可。

out/target/product/rk3288/vendor/lib/hw/audio.primary.rk30board.so

hardware/rockchip/audio/tinyalsa_hal/audio_hw.c文件中start_output_stream函数为判断输出(声音输出)设备类型,选择音频输出通路: 根据out-> device 类型判断 if (out->device & (AUDIO_DEVICE_OUT_AUX_DIGITAL)

然后选择使用音频路由输出: card = adev->out_card[SND_OUT_SOUND_CARD_HDMI];

然后对应打开哪张声卡: out->pcm[SND_OUT_SOUND_CARD_HDMI]=pcm_open(card,PCM_DEVICE_HDMIOUT, PCM_OUT | PCM_MONOTONIC, &out->config);

hardware/rockchip/audio/tinyalsa_hal/audio_hw.c文件中start_input_stream函数为判断输入(声音录入)设备类型,选择音频输入通路。

audio_hw.c文件中read_in_sound_card 接口 //从节点获取声卡信息: file = fopen(SND_CARDS_NODE,“r”); while(get_line(file,buf,sizeof(buf)) >= 0){ if(is_mic_in_sound_card(buf)){ device->in_card[SND_IN_SOUND_CARD_MIC] = get_card_number(buf); }

audio_hw.c文件的 adev_set_parameters 函数会去获取一些属性参数,然后设置走哪个route,route的宏定义在alsa_audio.h文件。

然后在adev_set_parameters中调用str_parms_get_str获取对应字符串的属性(下面的例子是获取字符串HDMIin_enable的属性,该属性在apk中调用原生的接口

AudioManager.setParameters("HDMIin_enable=true")): 3060 /* HDMIin enable/disable */ 3061 val = str_parms_get_str(parms, "HDMIin_enable", value, sizeof(value)); 3062 if (0 3064 ALOGD("\n##[czd]%s:-------- HDMIin_enable(%s) ---------##\n\n", __func__, value); 3065 adev->hdmiin_state = true; 3066 //route_pcm_open(HDMI_IN_NORMAL_ROUTE); 3067 route_pcm_open(HDMI_IN_CAPTURE_ROUTE); 3068 ALOGD("Enable HDMIin"); 3069 } else if (strcmp(value, "false") == 0) { 3070 ALOGD("\n##[czd]%s:-------- HDMIin_disable(%s) ---------##\n\n", __func__, value); 3071 route_pcm_open(HDMI_IN_OFF_ROUTE); 3072 adev->hdmiin_state = false; 3073 ALOGD("Disable HDMIin"); 3074 } else { 3075 ALOGD("\n##[czd]%s:-------- HDMIin_enable(%s) ---------##\n\n", __func__, value); 3076 ALOGE("Unknown HDMIin state %s!!!", value); 3077 ret = -EINVAL; 3078 } 3079 }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3