选择主题
☀️ 浅色
🌙 深色
🌿 护眼
Ctrl+K

0.系统待机状态被异常唤醒

RTC 唤醒注入 KEY_POWER — 代码路径分析 背景 rtk-parker-aosp-squash-25q2.02-mirakulo项目 概述 STB 待机时 RTC 定时唤醒,IR 驱动在 Resume 时从寄存器读到上一个按键(POWER)的 NEC 帧残留,因 KEY_E 不在键值表中导致查表失败,旧代码 fallback 注入 KEY_POWER,经 Android → CEC 触发电视开机。 根因是两层问题叠加: ① 键值表缺少 KEY_E 映射;② 旧代码在 KEY_E 查不到时无条件使用寄存器残留值调用 rc_keydown()。 一、待机前:POWER 键的 NEC 帧锁存在寄存器中 用户按遥控器 POWER 让 STB 待机。IR 硬件收到 NEC 帧后存入 ISO 寄存器 0x65c。 正常 ISR 路径(rtk-ir-hw.c:100-139)读出并解码,发送按键。Suspend 时 ISR 已不再触发,但硬件寄存器继续锁存上次收到的数据。 rtk-ir-hw.c:76-86 的 suspend 路径只 drain FIFO,不清零数据寄存器,残留值保留。 二、RTC 唤醒:PM notifier 读取寄存器 RTC 到期 → SoC 唤醒 → PM notifier 回调 rtk_ir_key_event()。 ...

June 8, 2026

1.RTC时钟到期之后出现非预期的HDMI有输出

HDMI 被 RTC 唤醒 — 代码路径分析 背景 rtk-parker-aosp-squash-25q2.02-mirakulo项目 前置问题见:系统待机状态被异常唤醒.md 概述 RTC 定时唤醒 STB 时,HDMI 会短暂输出信号导致电视黑屏,然后恢复无信号。 根因:内核 PM 框架的 Resume 不判断唤醒源,无条件恢复所有设备,HDMI 驱动在 resume 时无条件打开 PHY。 修复方向:在 rtk_drm_resume() 和 rtk_hdmi_resume() 中判断唤醒源,RTC 后台唤醒时跳过显示/PHY 初始化。 一、系统唤醒总入口 kernel/power/suspend.c:490-529 int suspend_devices_and_enter(suspend_state_t state) { // ① suspend 所有设备 dpm_suspend_start(PMSG_SUSPEND); // ② SoC 深度睡眠 suspend_enter(state, &wakeup); Resume_devices: // ③ 被 RTC/IR/GPIO 唤醒后从这里开始 dpm_resume_end(PMSG_RESUME); // 恢复所有设备 } 醒来后 dpm_resume_end() 是唯一出口,不管谁唤醒的都走这里。 二、dpm_resume — 无差别恢复所有设备 drivers/base/power/main.c:1001-1040 void dpm_resume(pm_message_t state) { while (!list_empty(&dpm_suspended_list)) { // 遍历所有已 suspend 的设备 dev = to_device(dpm_suspended_list.next); device_resume(dev); // 逐个恢复 } } dpm_suspended_list 是内核 PM 框架维护的全局链表,所有被 suspend 的设备都在上面。HDMI 设备在 suspend 时被加入链表,resume 时必然被取出恢复。 ...

June 8, 2026

2.待机状态下拔插HDMI问题

待机状态下拔插 HDMI 无输出问题 现象 STB 正常待机(suspend) 待机状态下拔掉 HDMI 线 解除待机(resume,如遥控器 IR 唤醒) 再次插入 HDMI 线 HDMI 无输出,电视显示无信号 复现步骤 待机 → 拔 HDMI → 唤醒 → 插 HDMI → 黑屏/无信号 根因:ALARM_EVENT 提前返回导致 IRQ 嵌套计数泄漏 disable_irq/enable_irq 是嵌套计数 Linux 内核的 disable_irq() / enable_irq() 使用深度计数器 desc->depth,不是布尔开关: // kernel/irq/manage.c void disable_irq(unsigned int irq) { irq_descs[irq]->depth++; } // depth > 0 → 中断屏蔽 void enable_irq(unsigned int irq) { irq_descs[irq]->depth--; } // depth == 0 → 中断打开 必须 一对一配对,否则 depth 永不归零,中断永久丢失。 旧代码的泄漏路径 rtk_hdmi_suspend() 无条件调用 disable_irq(hpd_irq)。rtk_hdmi_resume() 中,enable_irq(hpd_irq) 在 ALARM_EVENT 提前返回之后: ...

June 8, 2026

3.由于提前返回引起的待机状态下唤醒HDMI无输出

由于提前返回引起的待机状态下唤醒 HDMI 无输出 概述 为解决 RTC 定时唤醒(ALARM_EVENT)时 HDMI PHY 异常上电,在 rtk_drm_resume() 和 rtk_hdmi_resume() 中加入 ALARM_EVENT 判断后提前 return 0。这把 RTC 静默唤醒本身的 HDMI 上电问题解决了,但提前返回跳过了 resume 路径中的关键配对操作,导致跨 suspend/resume 周期的状态污染——下次手动唤醒时 HDMI 概率无输出。 经日志验证(等待一次RTC唤醒,然后重新进入待机后,手动退出待机后HDMI无输出.txt),问题稳定复现。 drm_mode_config_helper_resume() 源码 rtk_drm_resume() 通过调用此函数完成 DRM 层 resume。以下为内核源码(drm_modeset_helper.c),ALARM 路径的裸 return 0 跳过了这个函数的全部三步操作。同时贴上对应的 suspend 函数作为配对参考。 /* drm_modeset_helper.c L195-223 */ int drm_mode_config_helper_suspend(struct drm_device *dev) { struct drm_atomic_state *state; if (!dev) return 0; if (dev->mode_config.poll_enabled) drm_kms_helper_poll_disable(dev); // ③ 配对: poll_disable drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1); // ② 配对: fb→SUSPENDED state = drm_atomic_helper_suspend(dev); // ① 配对: 分配 state if (IS_ERR(state)) { drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0); if (dev->mode_config.poll_enabled) drm_kms_helper_poll_enable(dev); return PTR_ERR(state); } dev->mode_config.suspend_state = state; return 0; } /* drm_modeset_helper.c L240-263 */ int drm_mode_config_helper_resume(struct drm_device *dev) { int ret; if (!dev) return 0; if (WARN_ON(!dev->mode_config.suspend_state)) return -EINVAL; // 步骤 ①: 恢复原子状态 + 释放内存 ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state); if (ret) DRM_ERROR("Failed to resume (%d)\n", ret); dev->mode_config.suspend_state = NULL; // 步骤 ②: 恢复 fbdev drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0); // 步骤 ③: 恢复输出轮询 if (dev->mode_config.poll_enabled) drm_kms_helper_poll_enable(dev); return ret; } suspend 和 resume 的配对关系: ...

June 8, 2026