> 技术文档 > OpenHarmony5.0.2 音频audio适配_rk3568插入耳机无声

OpenHarmony5.0.2 音频audio适配_rk3568插入耳机无声


开发环境

OpenHarmony5.0.2 RK3568

音频芯片:rk809,音频芯片在核心板pmic中,rk809引出的耳机和喇叭

遇到问题

编译后耳机有声音,但喇叭没有,拔插入耳机扬声器也没声音

解决思路

采用默认ADM方式,没用ALSA方式,修改默认的寄存器配置,使扬声器和耳机同时有声,耳机插拔调用寄存器修改扬声器静音还是播放来进行控制。目前只是解决这两个问题,其他音频相关没测试,例如录音之类的功能,后续调试到再完善。

修改代码
1、修改SELinux系统权限

文件地址:base/security/selinux_adapter/selinux.gni

declare_args() { selinux_adapter_enforce = false}

hdc shell 执行 getenforce  命令 验证输出应为 Permissive  

修改权限避免引起的问题,查看日志

permissive=1        处于宽容模式,只告警不做访问拦截。

permissive=0     强制模式时,做拦截

2、修改设备树

耳机检测配置

rk_headset: rk-headset {compatible = \"rockchip_headset\";headset_gpio = ; //改成自己的gpiopinctrl-names = \"default\";pinctrl-0 = ;//io-channels = ;};

声卡配置

rk809_sound: rk809-sound {status = \"okay\";compatible = \"simple-audio-card\";simple-audio-card,format = \"i2s\";simple-audio-card,name = \"rockchip,rk809-codec\";simple-audio-card,mclk-fs = ;simple-audio-card,cpu {sound-dai = ;};simple-audio-card,codec {sound-dai = ;};};rk809_codec: codec {#sound-dai-cells = ;compatible = \"rockchip,rk809-codec\", \"rockchip,rk817-codec\";clocks = ;clock-names = \"mclk\";assigned-clocks = , ;assigned-clock-rates = ;assigned-clock-parents = , ;pinctrl-names = \"default\";pinctrl-0 = ;hp-volume = ;spk-volume = ;capture_volume = ;//use-ext-amplifier;//mic-in-differential;status = \"okay\";};
3、修改播放路径配置

该文件定义了 ‌不同音频场景下的硬件设备开关状态‌,用于控制音频信号的输入/输出路由,确保系统在不同使用场景下切换正确的音频路径,修改如下文件

drivers/peripheral/audio/config/audio_paths.json
vendor/hihope/default_core_system/hals/audio/audio_paths.json
vendor/hihope/rk3568/hals/audio/audio_paths.json

........ \"hdf_audio_codec_primary_dev0\": [ { \"deep-buffer-playback\": [ {  \"Headphones\": [ { \"name\": \"Speaker1 Switch\", \"value\": 1 //改1 }........

此文件修改后对于代码的解析地址

drivers/hdf_core/framework/model/audio/dispatch/src/audio_control_dispatch.c

对应的方法如下,查看输出日志如果修改后没变化,可以删除out目录重新编译。
static int32_t ControlHostElemWrite(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *reqData, struct HdfSBuf *rspData)

4、修改默认的寄存器配置

修改后删除out目录重新编译,不然不会生效

vendor/hihope/rk3568_mini_system/hdf_config/khdf/audio/analog_headset_config.hcs

root { platform { template headset_info { match_attr = \"\"; serviceName = \"\"; } headset :: headset_info {  headset_gpio = 60; //自己计算gpio  //hook_gpio = 0; //注释掉.........文档默认配置耳机检测的GPIO为Gpio3 RK_PC3Gpio3 RK_PC3bank =3group=2X=3number=2*8+3=19Pin=3*32+19=115

vendor/hihope/default_core_system/hdf_config/khdf/audio/codec_config.hcs
vendor/hihope/rk3568/hdf_config/khdf/audio/codec_config.hcs

..................... regConfig { /* reg, value */ initSeqConfig = [  0x38, 0x18, //修改  0x41, 0xf7, //修改.....................
5、修改​​​​​​​耳机检测相关代码

文件位置:

device/board/hihope/rk3568/audio_drivers/headset_monitor/src/analog_headset_core.c

方法static int32_t LinuxReadConfig(struct device_node *node, struct HeadsetPdata *pdata)

......... /* hook */ ret = of_get_named_gpio_flags(node, \"hook_gpio\", 0, &pdata->hookGpio); if (ret hookGpio = 0; /* adc mode */ //pdata->isHookAdcMode = true; pdata->isHookAdcMode = false;//修改后 } else { ret = of_property_read_u32(node, \"hook_down_type\", &pdata->hookDownType); if (ret hookhookDownType = 0; } // pdata->isHookAdcMode = false; pdata->isHookAdcMode = true;//修改后 }............

新增方法控制扬声器开关

device/board/hihope/rk3568/audio_drivers/codec/rk809_codec/include/rk809_codec_impl.h

新增接口

/*扬声器开关控制0=关1=开*/int32_t Rk809DeviceSpeakerControl(uint32_t val);

device/board/hihope/rk3568/audio_drivers/codec/rk809_codec/src/rk809_codec_impl.c

新增实现方法

//扬声器关闭static const struct RegDefaultVal g_rk817SpeakerCloseReg[] = { { RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa0 }, { RK817_CODEC_ACLASSD_CFG1, 0x69 }, { RK817_CODEC_ACLASSD_CFG2, 0x44 },};static const struct RegConfig g_rk817SpeakerCloseRegConfig = { .regVal = g_rk817SpeakerCloseReg, .size = ARRAY_SIZE(g_rk817SpeakerCloseReg),};//扬声器打开static const struct RegDefaultVal g_rk817SpeakerOpenReg[] = { /* CLASS D mode */ { RK817_CODEC_DDAC_MUTE_MIXCTL,0x18}, /* CLASS D enable */ { RK817_CODEC_ACLASSD_CFG1,0xa5}, /* restart CLASS D, OCPP/N */ { RK817_CODEC_ACLASSD_CFG2,0xf7},};static const struct RegConfig g_rk817SpeakerOpenRegConfig = { .regVal = g_rk817SpeakerOpenReg, .size = ARRAY_SIZE(g_rk817SpeakerOpenReg),};/*扬声器开关控制0=关1=开*/int32_t Rk809DeviceSpeakerControl(uint32_t val){ int32_t ret; if(val==0){ ret = RK809DeviceRegConfig(g_rk817SpeakerCloseRegConfig); if (ret != HDF_SUCCESS) { return HDF_FAILURE; } }else if(val==1){ ret = RK809DeviceRegConfig(g_rk817SpeakerOpenRegConfig); if (ret != HDF_SUCCESS) { return HDF_FAILURE; } }else{ return HDF_FAILURE; } return HDF_SUCCESS;}

device/board/hihope/rk3568/audio_drivers/headset_monitor/src/analog_headset_gpio.c

调用方法

/* 根据插入状态控制扬声器开关*/static void ControlSpeakerState(int32_t level){ if(level == HEADSET_IN){ //关扬声器 Rk809DeviceSpeakerControl(0); }else { //开扬声器 Rk809DeviceSpeakerControl(1); }}

CheckState方法调用

static int32_t CheckState(struct HeadsetPriv *hs, bool *beChange){.............. if (level2 < 0) { return HDF_FAILURE; }    /*  根据插入状态控制扬声器开关*/     ControlSpeakerState(level2);..................

修改默认驱动值

device/board/hihope/rk3568/audio_drivers/codec/rk809_codec/src/rk809_codec_linux_driver.c

static const struct reg_default rk817_reg_defaults[] = { ............. { RK817_CODEC_ADAC_CFG0, 0x00 }, { RK817_CODEC_ADAC_CFG1, PWD_DACBIAS_ON | PWD_DACD_ON | PWD_DACL_ON | PWD_DACR_ON }, //修改 { RK817_CODEC_DDAC_POPD_DACST, 0x82 }, { RK817_CODEC_DDAC_VOLL, 0x00 }, ............. { RK817_CODEC_DDAC_LMT2, 0x00 }, { RK817_CODEC_DDAC_MUTE_MIXCTL, 0x18 }, //修改 { RK817_CODEC_DDAC_RVOLL, 0xff }, ............. { RK817_CODEC_AHP_CFG0, 0x80 },//修改 { RK817_CODEC_AHP_CFG1, 0x1f }, { RK817_CODEC_AHP_CP, 0x11 }, //修改 { RK817_CODEC_ACLASSD_CFG1, 0xa5 }, //修改 { RK817_CODEC_ACLASSD_CFG2, 0xf7 }, //修改 { RK817_CODEC_APLL_CFG0, 0x04 }, .............

6、修改​​​​​​​耳机插入后设备优先级相关代码(改不改影响不大)

文件位置:

foundation/multimedia/audio_framework/services/audio_policy/server/include/service/manager/pnp_server/audio_pnp_param.h

增加定义常量.............#define UEVENT_STATE_ANALOG_HP0 \"HEADPHONE=0\"#define UEVENT_STATE_ANALOG_HP1 \"HEADPHONE=1\".............

修改业务判断

文件位置:

foundation/multimedia/audio_framework/services/audio_policy/server/src/service/manager/pnp_server/audio_socket_thread.cpp

修改方法,此处不能检测到耳机设备新增,只能是麦克,先注释掉麦克,后期调试麦克再观察。int32_t AudioSocketThread::SetAudioPnpServerEventValue(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent) .................... //if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS0) != NULL) { if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HP0) != NULL) {  audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE; } // else if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS1) != NULL) { else if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HP1) != NULL) { audioEvent->eventType = PNP_EVENT_DEVICE_ADD; } else{ ....................

添加默认设备

foundation/multimedia/audio_framework/services/audio_policy/server/src/service/audio_device_manager.cpp
 

void AudioDeviceManager::AddDefaultDevices(const sptr &devDesc){ DeviceType devType = devDesc->deviceType_; //if (devType == DEVICE_TYPE_EARPIECE) { if (devType == DEVICE_TYPE_EARPIECE || devType == DEVICE_TYPE_WIRED_HEADSET) { //修改 earpiece_ = devDesc; } else if (devType == DEVICE_TYPE_SPEAKER) { speaker_ = devDesc; //} else if (devType == DEVICE_TYPE_MIC) { } else if (devType == DEVICE_TYPE_MIC || devType == DEVICE_TYPE_WIRED_HEADSET) { //修改 defalutMic_ = devDesc; }}

7、备注

目前修改后,用自带播放器播放音乐扬声器正常有声,拔插入耳机后扬声器中断正常。其他情况未测试。注意:配置文件HCS之类的修改后删除out目录再次编译,不然不生效。目前只做到这个程度,后期有问题优化再更新。

ALSA适配参考:audio适配方案_逸薇 -Laval社区