记录 音量按键波形异常 的问题现象、排查过程、修改方案和验证方法。
音量按键波形异常
MT8781 音量减按键异常:KPROW0 固定拉低 + KPCOL0 输入检测方案
1. 问题背景
MT8781 项目中出现 音量减按键异常 问题。
根据硬件原理图,音量减按键不是单独 GPIO 按键,而是 keypad 矩阵按键:
Volume Down = KPROW0 + KPCOL0
对应 MT8781/MT6789 平台 pinmux 关系:
GPIO68 = KPROW0
GPIO66 = KPCOL0
也就是说,音量减按键由两根 keypad 矩阵线组合实现:
2. 原始问题分析
正常 keypad 矩阵按键需要同时配置 row 和 column,通过 keypad 驱动扫描识别按键事件。
但当前项目中并没有采用完整的 keypad row/col 扫描方式,而是参考其他项目采用 workaround:
GPIO68 / KPROW0 固定输出低电平
GPIO66 / KPCOL0 作为输入检测
这样处理后,音量减按键按下时:
KPCOL0 与 KPROW0 导通
↓
KPROW0 已固定为低电平
↓
KPCOL0 被拉低
↓
keypad 驱动检测到按键事件
因此,本问题不是单纯配置 KPCOL0 就可以解决的。
因为硬件上音量减实际依赖:
KPROW0 + KPCOL0
如果只配置 GPIO66 = KPCOL0,而 GPIO68 = KPROW0 没有稳定电平,则按键按下后 KPCOL0 不一定能被有效拉低,可能导致音量减无效或波形异常。
3. DTS 修改方案
3.1 新增 gpio_key_rom pinctrl
在 &pio 节点中新增 gpio_key_rom,将 GPIO68 配置为普通 GPIO,并输出低电平。
&pio {
gpio_key_rom: key_low {
pins_cmd_dat {
pinmux = <PINMUX_GPIO68__FUNC_GPIO68>;
slew-rate = <1>;
output-low;
};
};
};
关键点:
3.2 panel 节点绑定 key_rom
在 panel 节点中绑定该 pinctrl 状态:
pinctrl-names = "key_rom";
pinctrl-0 = <&gpio_key_rom>;
如果 panel 节点原本已经存在其他 pinctrl,例如 LCM 电源、复位、bias 相关 GPIO,不能直接覆盖原有配置,而应该追加:
pinctrl-names = "xxx", "xxx", "key_rom";
pinctrl-x = <&gpio_key_rom>;
否则可能影响屏幕上电、复位或 bias 时序。
3.3 keypad 侧配置 KPCOL0
keypad 侧仅配置 GPIO66 为 KPCOL0,并作为输入检测:
&keypad {
pinctrl-names = "default";
pinctrl-0 = <&kpd_pins_default>;
};
&pio {
kpd_pins_default: kpdgpiodefault {
pins_cmd_dat {
pinmux = <PINMUX_GPIO66__FUNC_KPCOL0>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
input-enable;
input-schmitt-enable;
};
};
};
关键点:
4. panel 驱动修改方案
仅在 DTS 中定义 gpio_key_rom 不一定会自动生效。
需要在 panel 驱动中主动获取并选择该 pinctrl 状态。
在 panel probe 阶段增加如下逻辑:
ctx->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(ctx->pinctrl)) {
dev_info(dev, "cannot get panel pinctrl %ld\n",
PTR_ERR(ctx->pinctrl));
ctx->pinctrl = NULL;
} else {
ctx->gpio_key_rom = pinctrl_lookup_state(ctx->pinctrl, "key_rom");
if (IS_ERR(ctx->gpio_key_rom)) {
dev_info(dev, "cannot find pinctrl key_rom %ld\n",
PTR_ERR(ctx->gpio_key_rom));
ctx->gpio_key_rom = NULL;
} else {
pinctrl_select_state(ctx->pinctrl, ctx->gpio_key_rom);
}
}
作用:
panel probe
↓
获取 panel 节点的 pinctrl
↓
查找名为 key_rom 的 pinctrl state
↓
选择 key_rom 状态
↓
GPIO68 生效为普通 GPIO 输出低电平
5. 核心结论
本问题的本质是:
音量减硬件上由 KPROW0 + KPCOL0 构成
但当前方案没有使用完整 keypad row/col 扫描,而是采用 workaround:
GPIO68 / KPROW0 固定输出低电平
GPIO66 / KPCOL0 作为 keypad 输入
因此,最终按键检测路径为:
按下音量减
↓
KPROW0 与 KPCOL0 导通
↓
GPIO68 / KPROW0 已固定输出低电平
↓
GPIO66 / KPCOL0 被拉低
↓
keypad 驱动检测到音量减按键事件
6. 注意事项
6.1 GPIO68 不应再作为正常 KPROW0 扫描使用
本方案中 GPIO68 被配置为:
普通 GPIO 输出低电平
因此它不再作为标准 keypad row 扫描线使用。
如果后续要恢复完整 keypad 矩阵扫描,则需要重新配置:
GPIO68 = KPROW0
GPIO66 = KPCOL0
并由 keypad 驱动统一管理 row/col。
6.2 panel pinctrl 不要覆盖原有配置
如果 panel 节点已有其他 pinctrl 状态,例如:
lcm_rst_low
lcm_rst_high
bias_en_low
bias_en_high
新增 key_rom 时必须追加,而不是替换。
错误风险:
覆盖 panel 原有 pinctrl
↓
LCM 电源 / 复位 / bias 配置丢失
↓
可能导致屏幕不开机、白屏、花屏或上电时序异常
6.3 需要确认 pinctrl select 是否真正执行
DTS 中写了:
pinctrl-names = "key_rom";
pinctrl-0 = <&gpio_key_rom>;
但是否生效,取决于驱动是否调用:
pinctrl_select_state(ctx->pinctrl, ctx->gpio_key_rom);
建议通过 kernel log 确认是否有以下异常:
cannot get panel pinctrl
cannot find pinctrl key_rom
如果没有报错,并且音量减恢复正常,说明 key_rom 状态已正确生效。
7. 验证结果
合入修改后,音量减按键恢复正常。
验证结论:
GPIO68 固定输出低电平生效
GPIO66 KPCOL0 能够检测到按键低电平变化
音量减按键功能恢复
8. 推荐提交说明
dts: configure GPIO68 low to fix volume down key issue
或中文描述:
配置 GPIO68 输出低电平,修复音量减按键异常
更完整版本:
MT8781 音量减按键由 KPROW0 + KPCOL0 构成。
参考项目 workaround,将 GPIO68/KPROW0 配置为普通 GPIO 输出低电平,
GPIO66/KPCOL0 作为 keypad 输入检测。
按下音量减时 KPCOL0 被 GPIO68 拉低,从而恢复按键检测功能。