这篇写什么?
一串看起来像「好多单」的投诉,其实都钉在同一条链上:HDMI ARC / eARC + Soundbar / AVR 不出声。
| 典型场景 |
|---|
| 待机 / 重启后 Soundbar 无声 |
| OOBE(开箱向导)过程中接 Soundbar 无声 |
| 大版本升级后 Soundbar 无声 |
| 播任意音频,Soundbar 仍无声 |
| HDMI1 播 4K Dongle + HDMI ARC/eARC 接 AVR,无声 |
| 笼统的 HDMI-ARC/eARC 无声 |
一轮合入从 Framework CEC、开机 OneTouchPlay,到 内核 eARC hold bus 一起加强。本文按「现象 → 分层修法」整理。
一句话:
无声 ≠ 只有 HAL 音量错
→ ARC 状态被误关掉 / 启动时 OTP 抢早
→ eARC 与 ARC CEC 互踩
→ 编码格式切换未按 HDMI 2.1 做 mute+hold bus
→ 分层修:状态、时序、消息过滤、总线保持

相关:Zoom + ARC 双无声、拔 ARC 音量飙最大。
一、为什么会「一整片」无声?
ARC/eARC 要同时稳住三件事:
| 层 | 职责 |
|---|---|
| CEC / 系统音频模式 | 谁是 Audio System、ARC 是否 Initiated、eARC 开时别再走旧 ARC 握手 |
| 启动 / 输入切换 | OneTouchPlay、OOBE 未完成时别乱切源 |
| 内核 eARC TX | 编码类型变化时按规范 mute + hold bus 再恢复 |
任一环在待机唤醒、首次插线、升级后冷启动时掉链子,听感都是同一个词:Soundbar 没声。
二、修法一:别把 ARC 状态误关掉(待机恢复)
文件示意: SetArcTransmissionStateAction.java
问题形态:从待机恢复后,声音从 ARC 掉回本机喇叭,外放变哑。
关键改动:
<Report ARC Initiated>发送失败时:日志从 debug 提到 warning- 去掉 失败分支里的
setArcStatus(false)
原先 NACK 一次就 setArcStatus(false),等于把 ARC 判死刑;待机抖动、瞬时 NACK 很常见,误关之后外放就没了。
修法:发送失败不要立刻拆掉 ARC 状态,避免「醒过来 ARC 已经 false」。
三、修法二:OneTouchPlay 等开机 / OOBE 完成(避免漏声道)
文件示意: InputChangeAdapter.java
问题形态:开机或 OOBE 未完成 时 Soundbar 已接上,OneTouchPlay / 输入切换过早,漏掉外放通路。
改动要点:
| 点 | 做法 |
|---|---|
| 启动未完成 | 先缓存 OTP 行为,boot complete 后再切 |
| OOBE | user_setup_complete 未完成则直接 return,不处理 |
| 前台已是 TV 输入 | 走广播切源;否则 startActivity 切到对应 passthrough input |
| Handler | 用延迟 / 投递保证时序,避免启动竞态 |
目标:启动向导和系统音频就绪之后,再响应 OneTouchPlay,Soundbar 声道不会被「太早的一次切源」弄丢。
四、修法三:CEC 上理顺 ARC / eARC,少静音、少冲突
涉及: HdmiCecLocalDevice(Tv).java、HdmiControlService.java、RequestArcInitiationAction.java 等。
1)eARC 已开时,别再当真处理一套 ARC CEC
例如在 eARC on 时:
- 忽略 / 不按旧逻辑处理
INITIATE_ARC、部分 System Audio 相关消息 - 避免 eARC 物理链路已通,CEC 又去 Terminate/Refuse ARC 把策略搅乱
2)ARC 尚未建立时,别乱触发音频切换
startArcAction 等路径增加保护:旧状态与新请求都是「关」时,干净落 setArcStatus(false) 并返回,减少无效动作。
收到 ReportArcInitiated 请求时,条件扩展为 isEarcOn() || mArcEstablished,eARC 场景也能正确回 Report ARC Initiated。
3)RequestArcInitiationAction 加重试
- 发送
<Request Arc Initiation>失败时 最多重试(如 2 次) - 超时同样可重试再 finish
- 收到对 Initiation 的 Feature Abort 时:不要 粗暴
disableArc(AVR 在 eARC / 切换瞬间 Abort 很常见)
提高「请求建 ARC」的成功率,减少「以为建好了其实没有」。
4)其它配套
handleReportShortAudioDescriptor等返回行为调整,避免短音频描述被直接丢掉- TV 侧消息分发走
dispatchMessage,保证待机 handler 与常规 CEC 路径一致 - System Audio 从 AVR 发起时,避开与
DeviceDiscoveryAction打架
五、修法四:内核 eARC——编码切换要 mute + hold bus
文件示意: earc.c / earc_hw.c
HDMI 2.1 对 eARC TX 在音频编码类型变化时,要求做足够的 总线保持与静音(规范侧常见表述含 至少约 100ms 量级的 hold;实现里用可调 delay_time,默认示例 40ms 起步,需按规范与联调拉齐)。
数据结构
struct work_struct tx_hold_bus_work;
enum audio_coding_types last_tx_audio_coding_type;
工作函数(示意)
tx_hold_bus_work_func:
earctx_dmac_mute_and_hold_bus(..., true);
msleep(delay_time);
earctx_dmac_mute_and_hold_bus(..., false);
在 aml_earctx_enable / earc_dai_trigger 里:当 tx_audio_coding_type 相对 last_* 变化 时 schedule_work(tx_hold_bus_work),并更新 last。
插拔 / probe 时把 last_tx_audio_coding_type 置为 UNDEFINED,避免沿用上一次编码类型。
硬件侧 earctx_dmac_mute_and_hold_bus:配 mute block、hold min time,再脉冲启动 / 恢复 biphase——保证 AVR/Soundbar 在格式切换窗不会吃到非法流而「整段哑火」。
六、场景 ↔ 修法对照
| 场景 | 更相关的修法 |
|---|---|
| 待机 / 重启后无声 | 勿因 Report 失败 setArcStatus(false);ARC 发起重试 |
| OOBE 中接 Soundbar 无声 | OTP 推迟 + user_setup_complete 门闩 |
| 升级后无声 | 启动时序 + eARC/ARC CEC 过滤 + hold bus |
| 任意播放无声 / Dongle+AVR | eARC 开时忽略冲突 ARC 消息;编码切换 hold bus |
| 笼统 ARC/eARC 无声 | 以上整包回归 |
七、验证建议
- 待机 → 唤醒,Soundbar / AVR 是否仍有声
- 冷启动、OOBE 未完成 / 完成后各插一次外放
- 纯 ARC 设备与 eARC 设备各测
- HDMI1 播 Dongle + ARC/eARC 播系统音
- 切换 PCM ↔ Bitstream(编码类型变化)听是否断流后能恢复
- log:hold bus finish、Request Arc Initiation retry、OTP deferred
八、小结
| 层 | 一句话 |
|---|---|
| ARC 状态 | 失败别轻易 setArcStatus(false) |
| 开机 OTP | 等 boot / OOBE,再切声道 |
| CEC | eARC 开着就别和旧 ARC 消息互殴;Initiation 可重试 |
| 内核 | 编码一变就 mute + hold bus,再恢复 |
口诀:外放无声,先分清是状态被关了、切源太早了、CEC 打架了,还是格式切换没 hold 住总线。
相关阅读
评论
还没有评论,来做第一个吧
读完了不评论,作者会以为你在沉思