8、TSP功耗优化:休眠唤醒机制、低功耗模式、动态频率调整

各位做触控的同行,大家好。今天我们来聊聊TSP的功耗优化。说实话,功耗问题在手机整机调试中,往往是最后才被重视的——但一旦出了问题,就是大问题。我见过不少项目,功能都调通了,结果一测待机电流,多了好几毫安,查来查去,最后发现是触控IC没睡好。

功耗优化说白了就三件事:什么时候睡、怎么睡、醒了怎么跑。下面我们一个一个说。

8.1 休眠唤醒机制:让触控IC学会“闭眼”

触控IC的休眠唤醒,核心思路很简单:屏幕不亮的时候,IC就别全功率工作了。但这里有个矛盾——你睡着了,用户摸一下屏幕,你得能醒过来。所以休眠不是彻底断电,而是进入一种“半梦半醒”的状态。

我习惯把休眠唤醒分成三个等级:

  • 浅度休眠(Idle):扫描频率降低,比如从120Hz降到10Hz。手指放上去能快速唤醒,但功耗降得有限。
  • 深度休眠(Sleep):几乎停止所有扫描,只保留一个极低功耗的“唤醒检测”电路。功耗可以降到微安级别。
  • 关机(Power Down):彻底断电,唤醒需要系统重新初始化。这个一般不常用,因为唤醒太慢。

实际项目中,我们通常用深度休眠。我记得有一次调试一个项目,待机电流总是比竞品高0.5mA。查了半天,发现是触控IC在屏幕灭掉后,还在以30Hz的频率扫描。改成深度休眠后,电流直接降下来了。

关键点:休眠唤醒的触发时机,通常由系统框架控制。Android里通过early_suspendinput_suspend通知驱动。驱动收到通知后,调用触控IC的休眠指令。

驱动里大概是这样做的:

static int tsp_suspend(struct device *dev) {
    struct tsp_data *data = dev_get_drvdata(dev);
    // 通知IC进入深度休眠
    tsp_i2c_write(data->client, CMD_SLEEP, 0x01);
    // 关闭中断,避免误唤醒
    disable_irq(data->irq);
    return 0;
}

static int tsp_resume(struct device *dev) {
    struct tsp_data *data = dev_get_drvdata(dev);
    // 唤醒IC
    tsp_i2c_write(data->client, CMD_WAKEUP, 0x01);
    // 重新使能中断
    enable_irq(data->irq);
    return 0;
}

嗯,这里要注意:唤醒后一定要等IC稳定了再开中断。我曾经遇到过唤醒后立即上报误触,导致手机在口袋里自动拨号。后来加了个10ms的延迟,问题就解决了。

8.2 低功耗模式:精细化的“省电策略”

休眠唤醒是粗粒度的控制,低功耗模式则是细粒度的。说白了,就是在IC工作时,怎么让它更省电

常见的低功耗模式有这几种:

模式 原理 适用场景 功耗降低
间断扫描 扫描一阵,停一阵 待机、无操作 30%~50%
降电压 降低驱动电压 低噪声环境 10%~20%
降通道数 只扫描部分通道 边缘区域检测 20%~40%
降分辨率 降低ADC采样精度 非精确触摸场景 5%~10%

我个人习惯的做法是:根据场景动态切换。比如用户正在看视频,手指没动,那就用间断扫描+降电压。用户开始打字了,立刻切回全速模式。

小技巧:很多触控IC支持“手势唤醒”,比如双击亮屏。这种模式下,IC只扫描特定区域(比如屏幕中央),功耗极低。我建议在项目中尽量用这个功能,用户体验好,功耗也低。

8.3 动态频率调整:按需分配“算力”

动态频率调整,英文叫Dynamic Frequency Scaling,简称DFS。这个思路其实和CPU的调频很像——负载高的时候跑快点,负载低的时候跑慢点

触控IC的扫描频率,直接决定了功耗。120Hz扫描和60Hz扫描,功耗差一倍。但问题是,你不能一直用60Hz,因为用户滑动的时候会感觉卡顿。

所以我们需要一个策略:

  1. 无触摸时:降到最低频率(比如10Hz),只做唤醒检测。
  2. 有触摸但静止:用中等频率(比如60Hz),保证响应速度。
  3. 滑动/多点触摸:用最高频率(比如120Hz),保证流畅度。

驱动里实现这个逻辑,我一般用一个状态机:

enum tsp_freq_state {
    FREQ_IDLE,    // 无触摸
    FREQ_TOUCH,   // 有触摸
    FREQ_ACTIVE,  // 滑动/多点
};

static void tsp_update_freq(struct tsp_data *data) {
    switch (data->freq_state) {
        case FREQ_IDLE:
            tsp_set_scan_rate(data, 10); // 10Hz
            break;
        case FREQ_TOUCH:
            tsp_set_scan_rate(data, 60); // 60Hz
            break;
        case FREQ_ACTIVE:
            tsp_set_scan_rate(data, 120); // 120Hz
            break;
    }
}

这里有个坑:频率切换不能太频繁。你想想看,如果用户手指稍微抖一下,频率就从120Hz降到60Hz再升回去,反而会引入延迟。我一般会加一个滞回逻辑——比如连续100ms没有滑动,才降频。

避坑指南:我曾经在一个项目里,把频率切换阈值设得太灵敏。结果用户在玩游戏时,手指快速点击,频率一直在60Hz和120Hz之间跳,导致触摸响应忽快忽慢。后来改成“连续5个采样点无位移才降频”,问题就解决了。

8.4 知识体系总览

下面这张图,是我自己总结的TSP功耗优化整体框架。你可以把它当作一个检查清单:

TSP功耗优化知识体系 休眠唤醒机制 低功耗模式 动态频率调整 浅度休眠 / 深度休眠 / 关机 系统框架触发时机 中断使能/禁能控制 间断扫描 / 降电压 降通道数 / 降分辨率 手势唤醒(双击亮屏) 无触摸→10Hz 触摸静止→60Hz 滑动/多点→120Hz 核心原则:按需分配,动态切换,避免频繁跳变 —— 在功耗和性能之间找到最佳平衡点

这张图把三个模块的关系理清楚了。你实际做项目的时候,可以对照着看:休眠唤醒是“开关”,低功耗模式是“档位”,动态频率是“油门”。三者配合好了,功耗自然就降下来了。

好了,关于TSP功耗优化,我就讲这么多。记住一点:功耗优化不是一锤子买卖,它需要你在项目各个阶段反复调优。多测、多试、多总结,慢慢就有感觉了。


公众号:蓝海资料掘金营,微信deep3321