<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>RTC唤醒引起的待机问题 on Luoj`s Markdown</title>
    <link>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/</link>
    <description>Recent content in RTC唤醒引起的待机问题 on Luoj`s Markdown</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Mon, 08 Jun 2026 16:32:00 +0800</lastBuildDate>
    <atom:link href="https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>0.系统待机状态被异常唤醒</title>
      <link>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/0.%E7%B3%BB%E7%BB%9F%E5%BE%85%E6%9C%BA%E7%8A%B6%E6%80%81%E8%A2%AB%E5%BC%82%E5%B8%B8%E5%94%A4%E9%86%92/</link>
      <pubDate>Mon, 08 Jun 2026 16:32:00 +0800</pubDate>
      <guid>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/0.%E7%B3%BB%E7%BB%9F%E5%BE%85%E6%9C%BA%E7%8A%B6%E6%80%81%E8%A2%AB%E5%BC%82%E5%B8%B8%E5%94%A4%E9%86%92/</guid>
      <description>&lt;h1 id=&#34;rtc-唤醒注入-key_power--代码路径分析&#34;&gt;RTC 唤醒注入 KEY_POWER — 代码路径分析&lt;/h1&gt;
&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;
&lt;p&gt;rtk-parker-aosp-squash-25q2.02-mirakulo项目&lt;/p&gt;
&lt;h2 id=&#34;概述&#34;&gt;概述&lt;/h2&gt;
&lt;p&gt;STB 待机时 RTC 定时唤醒，IR 驱动在 Resume 时从寄存器读到上一个按键（POWER）的 NEC 帧残留，因 KEY_E 不在键值表中导致查表失败，旧代码 fallback 注入 KEY_POWER，经 Android → CEC 触发电视开机。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;根因是两层问题叠加：&lt;/strong&gt; ① 键值表缺少 KEY_E 映射；② 旧代码在 KEY_E 查不到时无条件使用寄存器残留值调用 &lt;code&gt;rc_keydown()&lt;/code&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一待机前power-键的-nec-帧锁存在寄存器中&#34;&gt;一、待机前：POWER 键的 NEC 帧锁存在寄存器中&lt;/h2&gt;
&lt;p&gt;用户按遥控器 POWER 让 STB 待机。IR 硬件收到 NEC 帧后存入 ISO 寄存器 &lt;code&gt;0x65c&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;正常 ISR 路径（&lt;code&gt;rtk-ir-hw.c:100-139&lt;/code&gt;）读出并解码，发送按键。Suspend 时 ISR 已不再触发，但硬件寄存器继续锁存上次收到的数据。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rtk-ir-hw.c:76-86&lt;/code&gt; 的 suspend 路径只 drain FIFO，不清零数据寄存器，残留值保留。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二rtc-唤醒pm-notifier-读取寄存器&#34;&gt;二、RTC 唤醒：PM notifier 读取寄存器&lt;/h2&gt;
&lt;p&gt;RTC 到期 → SoC 唤醒 → PM notifier 回调 &lt;code&gt;rtk_ir_key_event()&lt;/code&gt;。&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.RTC时钟到期之后出现非预期的HDMI有输出</title>
      <link>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/1.rtc%E6%97%B6%E9%92%9F%E5%88%B0%E6%9C%9F%E4%B9%8B%E5%90%8E%E5%87%BA%E7%8E%B0%E9%9D%9E%E9%A2%84%E6%9C%9F%E7%9A%84hdmi%E6%9C%89%E8%BE%93%E5%87%BA/</link>
      <pubDate>Mon, 08 Jun 2026 16:32:00 +0800</pubDate>
      <guid>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/1.rtc%E6%97%B6%E9%92%9F%E5%88%B0%E6%9C%9F%E4%B9%8B%E5%90%8E%E5%87%BA%E7%8E%B0%E9%9D%9E%E9%A2%84%E6%9C%9F%E7%9A%84hdmi%E6%9C%89%E8%BE%93%E5%87%BA/</guid>
      <description>&lt;h1 id=&#34;hdmi-被-rtc-唤醒--代码路径分析&#34;&gt;HDMI 被 RTC 唤醒 — 代码路径分析&lt;/h1&gt;
&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;
&lt;p&gt;rtk-parker-aosp-squash-25q2.02-mirakulo项目&lt;/p&gt;
&lt;p&gt;前置问题见：系统待机状态被异常唤醒.md&lt;/p&gt;
&lt;h2 id=&#34;概述&#34;&gt;概述&lt;/h2&gt;
&lt;p&gt;RTC 定时唤醒 STB 时，HDMI 会短暂输出信号导致电视黑屏，然后恢复无信号。&lt;/p&gt;
&lt;p&gt;根因：内核 PM 框架的 Resume 不判断唤醒源，无条件恢复所有设备，HDMI 驱动在 resume 时无条件打开 PHY。&lt;/p&gt;
&lt;p&gt;修复方向：在 &lt;code&gt;rtk_drm_resume()&lt;/code&gt; 和 &lt;code&gt;rtk_hdmi_resume()&lt;/code&gt; 中判断唤醒源，RTC 后台唤醒时跳过显示/PHY 初始化。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一系统唤醒总入口&#34;&gt;一、系统唤醒总入口&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;kernel/power/suspend.c:490-529&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;suspend_devices_and_enter&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;suspend_state_t&lt;/span&gt; state)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ① suspend 所有设备
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;dpm_suspend_start&lt;/span&gt;(PMSG_SUSPEND);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ② SoC 深度睡眠
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;suspend_enter&lt;/span&gt;(state, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;wakeup);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resume_devices:                          &lt;span style=&#34;color:#75715e&#34;&gt;// ③ 被 RTC/IR/GPIO 唤醒后从这里开始
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;dpm_resume_end&lt;/span&gt;(PMSG_RESUME);         &lt;span style=&#34;color:#75715e&#34;&gt;// 恢复所有设备
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;醒来后 &lt;code&gt;dpm_resume_end()&lt;/code&gt; 是唯一出口，不管谁唤醒的都走这里。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二dpm_resume--无差别恢复所有设备&#34;&gt;二、dpm_resume — 无差别恢复所有设备&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;drivers/base/power/main.c:1001-1040&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dpm_resume&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;pm_message_t&lt;/span&gt; state)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;list_empty&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;dpm_suspended_list)) {     &lt;span style=&#34;color:#75715e&#34;&gt;// 遍历所有已 suspend 的设备
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        dev &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;to_device&lt;/span&gt;(dpm_suspended_list.next);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;device_resume&lt;/span&gt;(dev);                        &lt;span style=&#34;color:#75715e&#34;&gt;// 逐个恢复
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;dpm_suspended_list&lt;/code&gt; 是内核 PM 框架维护的全局链表，所有被 suspend 的设备都在上面。HDMI 设备在 suspend 时被加入链表，resume 时必然被取出恢复。&lt;/p&gt;</description>
    </item>
    <item>
      <title>2.待机状态下拔插HDMI问题</title>
      <link>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/2.%E5%BE%85%E6%9C%BA%E7%8A%B6%E6%80%81%E4%B8%8B%E6%8B%94%E6%8F%92hdmi%E9%97%AE%E9%A2%98/</link>
      <pubDate>Mon, 08 Jun 2026 16:32:00 +0800</pubDate>
      <guid>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/2.%E5%BE%85%E6%9C%BA%E7%8A%B6%E6%80%81%E4%B8%8B%E6%8B%94%E6%8F%92hdmi%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;h1 id=&#34;待机状态下拔插-hdmi-无输出问题&#34;&gt;待机状态下拔插 HDMI 无输出问题&lt;/h1&gt;
&lt;h2 id=&#34;现象&#34;&gt;现象&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;STB 正常待机（suspend）&lt;/li&gt;
&lt;li&gt;待机状态下拔掉 HDMI 线&lt;/li&gt;
&lt;li&gt;解除待机（resume，如遥控器 IR 唤醒）&lt;/li&gt;
&lt;li&gt;再次插入 HDMI 线&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HDMI 无输出，电视显示无信号&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;复现步骤&#34;&gt;复现步骤&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;待机 → 拔 HDMI → 唤醒 → 插 HDMI → 黑屏/无信号
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;根因alarm_event-提前返回导致-irq-嵌套计数泄漏&#34;&gt;根因：ALARM_EVENT 提前返回导致 IRQ 嵌套计数泄漏&lt;/h2&gt;
&lt;h3 id=&#34;disable_irqenable_irq-是嵌套计数&#34;&gt;disable_irq/enable_irq 是嵌套计数&lt;/h3&gt;
&lt;p&gt;Linux 内核的 &lt;code&gt;disable_irq()&lt;/code&gt; / &lt;code&gt;enable_irq()&lt;/code&gt; 使用深度计数器 &lt;code&gt;desc-&amp;gt;depth&lt;/code&gt;，不是布尔开关：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// kernel/irq/manage.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;disable_irq&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; irq)  { irq_descs[irq]&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;depth&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;; }   &lt;span style=&#34;color:#75715e&#34;&gt;// depth &amp;gt; 0 → 中断屏蔽
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;enable_irq&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; irq)   { irq_descs[irq]&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;depth&lt;span style=&#34;color:#f92672&#34;&gt;--&lt;/span&gt;; }   &lt;span style=&#34;color:#75715e&#34;&gt;// depth == 0 → 中断打开
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;必须 &lt;strong&gt;一对一配对&lt;/strong&gt;，否则 depth 永不归零，中断永久丢失。&lt;/p&gt;
&lt;h3 id=&#34;旧代码的泄漏路径&#34;&gt;旧代码的泄漏路径&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rtk_hdmi_suspend()&lt;/code&gt; 无条件调用 &lt;code&gt;disable_irq(hpd_irq)&lt;/code&gt;。&lt;code&gt;rtk_hdmi_resume()&lt;/code&gt; 中，&lt;code&gt;enable_irq(hpd_irq)&lt;/code&gt; 在 &lt;code&gt;ALARM_EVENT&lt;/code&gt; 提前返回&lt;strong&gt;之后&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
    <item>
      <title>3.由于提前返回引起的待机状态下唤醒HDMI无输出</title>
      <link>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/3.%E7%94%B1%E4%BA%8E%E6%8F%90%E5%89%8D%E8%BF%94%E5%9B%9E%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E7%8A%B6%E6%80%81%E4%B8%8B%E5%94%A4%E9%86%92hdmi%E6%97%A0%E8%BE%93%E5%87%BA/</link>
      <pubDate>Mon, 08 Jun 2026 16:32:00 +0800</pubDate>
      <guid>https://luojmarkdown.pages.dev/posts/%E9%A1%B9%E7%9B%AE%E9%97%AE%E9%A2%98/rtc%E5%94%A4%E9%86%92%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E9%97%AE%E9%A2%98/3.%E7%94%B1%E4%BA%8E%E6%8F%90%E5%89%8D%E8%BF%94%E5%9B%9E%E5%BC%95%E8%B5%B7%E7%9A%84%E5%BE%85%E6%9C%BA%E7%8A%B6%E6%80%81%E4%B8%8B%E5%94%A4%E9%86%92hdmi%E6%97%A0%E8%BE%93%E5%87%BA/</guid>
      <description>&lt;h1 id=&#34;由于提前返回引起的待机状态下唤醒-hdmi-无输出&#34;&gt;由于提前返回引起的待机状态下唤醒 HDMI 无输出&lt;/h1&gt;
&lt;h2 id=&#34;概述&#34;&gt;概述&lt;/h2&gt;
&lt;p&gt;为解决 RTC 定时唤醒（ALARM_EVENT）时 HDMI PHY 异常上电，在 &lt;code&gt;rtk_drm_resume()&lt;/code&gt; 和 &lt;code&gt;rtk_hdmi_resume()&lt;/code&gt; 中加入 ALARM_EVENT 判断后提前 &lt;code&gt;return 0&lt;/code&gt;。这把 RTC 静默唤醒本身的 HDMI 上电问题解决了，但提前返回跳过了 resume 路径中的关键配对操作，导致&lt;strong&gt;跨 suspend/resume 周期的状态污染&lt;/strong&gt;——下次手动唤醒时 HDMI 概率无输出。&lt;/p&gt;
&lt;p&gt;经日志验证（&lt;code&gt;等待一次RTC唤醒，然后重新进入待机后，手动退出待机后HDMI无输出.txt&lt;/code&gt;），问题稳定复现。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;drm_mode_config_helper_resume-源码&#34;&gt;drm_mode_config_helper_resume() 源码&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rtk_drm_resume()&lt;/code&gt; 通过调用此函数完成 DRM 层 resume。以下为内核源码（&lt;code&gt;drm_modeset_helper.c&lt;/code&gt;），ALARM 路径的裸 &lt;code&gt;return 0&lt;/code&gt; 跳过了这个函数的全部三步操作。同时贴上对应的 suspend 函数作为配对参考。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/* drm_modeset_helper.c L195-223 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_mode_config_helper_suspend&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; drm_device &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;dev)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; drm_atomic_state &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;state;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;dev)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.poll_enabled)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_kms_helper_poll_disable&lt;/span&gt;(dev);                &lt;span style=&#34;color:#75715e&#34;&gt;// ③ 配对: poll_disable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_fb_helper_set_suspend_unlocked&lt;/span&gt;(dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;fb_helper, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// ② 配对: fb→SUSPENDED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    state &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_atomic_helper_suspend&lt;/span&gt;(dev);                &lt;span style=&#34;color:#75715e&#34;&gt;// ① 配对: 分配 state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;IS_ERR&lt;/span&gt;(state)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_fb_helper_set_suspend_unlocked&lt;/span&gt;(dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;fb_helper, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.poll_enabled)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_kms_helper_poll_enable&lt;/span&gt;(dev);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;PTR_ERR&lt;/span&gt;(state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.suspend_state &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; state;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/* drm_modeset_helper.c L240-263 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_mode_config_helper_resume&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; drm_device &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;dev)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;dev)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;WARN_ON&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.suspend_state))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;EINVAL;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 步骤 ①: 恢复原子状态 + 释放内存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ret &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_atomic_helper_resume&lt;/span&gt;(dev, dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.suspend_state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (ret)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;DRM_ERROR&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Failed to resume (%d)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, ret);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.suspend_state &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; NULL;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 步骤 ②: 恢复 fbdev
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_fb_helper_set_suspend_unlocked&lt;/span&gt;(dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;fb_helper, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 步骤 ③: 恢复输出轮询
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (dev&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mode_config.poll_enabled)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;drm_kms_helper_poll_enable&lt;/span&gt;(dev);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;suspend 和 resume 的配对关系：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
