摘要做Android显示驱动最经典入门任务就是点亮一块新Panel。本篇完整梳理从屏幕手册阅读、上电时序、DTS编写、驱动适配到内核调试、屏幕点亮的全流程附带主线内核标准drm_panel驱动示例代码同时标注高频踩坑点。前言前面几篇我们初步搞懂了Android显示完整链路、DRM核心框架、MIPI-DSI协议。理论看懂之后第一个工程实战任务就是移植Panel驱动点亮屏幕。很多新手同学上手时直接上手改驱动代码最后卡在黑屏、上电时序错乱、DTS配置错误反复排查几天但在实际工程中根本不会给你很久的时间bringup几乎屏幕和主板到手当天就要亮起来因此需要后合理的策略进行bringup不仅技术角度还有其他主观客观因素后续篇章展开聊聊编者的理解。屏幕决定了后续其他模块同事的开发进度虽然可以通过投屏来操作屏幕但是会极大的降低开发进度。屏幕点亮本质上就两件核心事硬件上电时序DTS设备树描述再搭配PanelDDICDisplay Driver Integrated Circuit驱动的初始化序列。核心一句话DTS告诉内核这块屏幕硬件资源是什么上电时序保证DDIC在正确的电源、复位顺序下启动Panel驱动下发初始化命令最终屏幕正常上电、接收MIPI图像。一、前期准备拿到屏幕规格书移植第一步不是写代码而是读屏的datasheet提取关键信息电源VDD3.0V DDIC模拟电、VCI1.8V逻辑数字电、ELVSS-5.5V~-7V像素阴极负高压、ELVDD5.5V~7V像素阳极正高压等等电压每一路的电压值、上电/掉电顺序(OLED发光靠的就是ELVSS和ELVDD的大压差)复位引脚复位信号RST的高低电平、复位保持时间MIPI-DSI参数lane数量、传输速率、Video/Command模式、像素时序HSA/HBP/ACTIVE/HFPVSA/VBP/ACTIVE/VFP屏幕初始化命令序列DSI写寄存器指令屏幕最大分辨率、色深踩坑点不要随便抄别的屏DTS不同屏幕电源域、复位时序、时序参数完全不一样直接复制大概率黑屏。当然确定是同DDIC的阔以抄提高开发速度二、重中之重Panel上电/下电时序80%黑屏问题根源绝大多数点亮失败不是DRM或者MIPI代码问题而是上电顺序错误因为DRM框架层的code几乎不需要重新开发MTK或者Qcom已经提供较为完整可靠的source code。编者理解的一般标准MIPI屏上电流程供给数字电源 VCI数字先稳delay_ms(10)供给屏幕模拟电源VDDdelay_ms(10)等待电源稳定延时datasheet指定一般ms级高低高RST复位引脚保持复位一段时间释放复位拉高RST等待屏IC内部稳定ELVDD上电正高压先上再上负高压delay_ms(10)ELVSS上电delay_ms(10)DSI Host开启发送Panel初始化命令序列初始化完成开启MIPI视频流屏幕输出图像...下电时序休眠/关机同样重要顺序反过来关显示发0x28 0x10命令停止MIPI图像数据流ELVSS下电delay_ms(10)ELVDD下电delay_ms(10)拉低RST复位关闭VCI关闭VDDI常见错误复位释放太早、电源上电顺序颠倒、延时时间不足现象黑屏、偶尔能点亮、冷启动失败等等。三、DTS设备树编写描述屏幕硬件资源DTS的作用向内核描述硬件资源不需要修改内核C代码描述电源、复位引脚、DSI通道、屏幕时序。基础示例DTS里核心配置项/* 示例DTS片段主线开源内核风格仅用于演示 */panel: panel0 {compatible xxx,mipi-panel;reg 0;vsp-supply pmic_vsp;vsn-supply pmic_vsn;vddio-supply pmic_vddio;reset-gpios gpio 10 GPIO_ACTIVE_LOW;#address-cells 1;#size-cells 0;panel-timing {hactive 720;vactive 1280;hfront-porch 20;hback-porch 40;hsync-len 10;vfront-porch 10;vback-porch 10;vsync-len 2;};panel-init-sequence [/* DSI初始化指令根据屏规格书填充 */05 00 00 00 00 11,05 00 00 00 00 29,];};电源供应vsp-supply、vsn-supply、vddio-supply关联PMIC电源域复位引脚reset-gpios指定GPIO定义复位极性MIPI DSI配置data lanes数量、dsi时钟速率显示时序参数hactive、vactive以及前后消隐HBP/HSA/HFPVBP/VSA/VFP初始化命令序列panel-init-sequenceDSI发送的一系列寄存器指令电源、复位的延时参数对应datasheet时序简单理解内核MIPI DSI host驱动读到DTS配置就知道用哪个GPIO复位、打开哪几路PMIC电源、屏幕时序是多少、开机要发哪些初始化命令。调试小技巧DTS修改后重新单编译dtbo替换设备树如果Android全编译的话老慢了1h起步另外刷机后反编译看下dtbo里的参数是否是自己配置的否则容易导致修改不带入的风险优先核对DTS参数和屏幕手册不要先去修改panel驱动c文件。对于Qcom平台来说bringup阶段的参数配置大部分在dtsi文件对于MTK平台来说bringup阶段的参数配置大部分是driver的.c驱动文件当然也可重构到dtsi但目前主流是这么分的。四、Panel驱动代码适配drm_panel框架主线Linux开源代码片段说明下面代码取自Linux主线内核drm_panel示例模板开源通用框架不属于任何公司项目代码。 内核标准drm_panel驱动核心回调prepare(上电复位初始化)、enable(开启MIPI数据流)、disable、unprepare(下电)#include linux/module.h#include linux/of.h#include linux/gpio/consumer.h#include linux/regulator/consumer.h#include drm/drm_panel.h#include drm/drm_mipi_dsi.hstruct my_panel_data {struct drm_panel panel;struct mipi_dsi_device *dsi;struct regulator *vsp;struct regulator *vsn;struct regulator *vddio;struct gpio_desc *reset_gpio;bool prepared;};// 容器宏通过drm_panel结构体反向拿到自定义panel私有数据#define to_my_panel(p) container_of(p, struct my_panel_data, panel)// 【1】prepare上电、复位、发送初始化序列硬件准备阶段static int my_panel_prepare(struct drm_panel *panel){struct my_panel_data *pdata to_my_panel(panel);struct mipi_dsi_device *dsi pdata-dsi;int ret;if (pdata-prepared)return 0;// 1.上电按照datasheet时序打开三路电源ret regulator_enable(pdata-vsp);if (ret) goto err_vsp;ret regulator_enable(pdata-vsn);if (ret) goto err_vsn;ret regulator_enable(pdata-vddio);if (ret) goto err_vddio;msleep(20); // 等待电源稳定参考屏规格书// 硬件复位拉低复位保持延时再释放复位gpiod_set_value(pdata-reset_gpio, 0);msleep(10);gpiod_set_value(pdata-reset_gpio, 1);msleep(20);// 发送DTS中定义的panel初始化序列ret mipi_dsi_panel_init(dsi);if (ret) {dev_err(dsi-dev, panel init cmd failed\n);goto err_init;}pdata-prepared true;return 0;err_init:gpiod_set_value(pdata-reset_gpio, 0);regulator_disable(pdata-vddio);err_vddio:regulator_disable(pdata-vsn);err_vsn:regulator_disable(pdata-vsp);err_vsp:return ret;}// 【2】enable开启MIPI视频流输出像素画面static int my_panel_enable(struct drm_panel *panel){struct my_panel_data *pdata to_my_panel(panel);// 发送DSI指令开启显示输出return mipi_dsi_dcs_write(pdata-dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);}// 【3】disable关闭画面输出static int my_panel_disable(struct drm_panel *panel){struct my_panel_data *pdata to_my_panel(panel);return mipi_dsi_dcs_write(pdata-dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);}// 【4】unprepare下电关闭电源复位static int my_panel_unprepare(struct drm_panel *panel){struct my_panel_data *pdata to_my_panel(panel);if (!pdata-prepared)return 0;gpiod_set_value(pdata-reset_gpio, 0);regulator_disable(pdata-vddio);regulator_disable(pdata-vsn);regulator_disable(pdata-vsp);pdata-prepared false;return 0;}// 注册drm_panel回调函数表static const struct drm_panel_funcs my_panel_funcs {.prepare my_panel_prepare,.enable my_panel_enable,.disable my_panel_disable,.unprepare my_panel_unprepare,};// DSI设备probe解析DTS资源获取regulator、gpiostatic int my_panel_probe(struct mipi_dsi_device *dsi){struct my_panel_data *pdata;int ret;pdata devm_kzalloc(dsi-dev, sizeof(*pdata), GFP_KERNEL);if (!pdata)return -ENOMEM;pdata-dsi dsi;drm_panel_init(pdata-panel, dsi-dev, my_panel_funcs, DRM_PANEL_CONNECTOR);// 从DTS解析电源、复位GPIOpdata-vsp devm_regulator_get(dsi-dev, vsp);pdata-vsn devm_regulator_get(dsi-dev, vsn);pdata-vddio devm_regulator_get(dsi-dev, vddio);pdata-reset_gpio devm_gpiod_get(dsi-dev, reset, GPIOD_OUT_LOW);// 绑定DSI设备注册panelmipi_dsi_set_drvdata(dsi, pdata);drm_panel_add(pdata-panel);return 0;}static const struct of_device_id my_panel_of_match[] {{ .compatible xxx,mipi-panel },{ /* Sentinel */ }};MODULE_DEVICE_TABLE(of, my_panel_of_match);static struct mipi_dsi_driver my_panel_driver {.probe my_panel_probe,.driver {.name xxx_mipi_panel,.of_match_table my_panel_of_match,},};module_mipi_dsi_driver(my_panel_driver);MODULE_LICENSE(GPL);MODULE_DESCRIPTION(sslmDemo MIPI panel driver based on drm_panel);重点区分prepare与enable prepare上电、复位、发初始化命令硬件准备阶段 enable打开MIPI视频流输出像素画面 很多新手混淆这两个回调导致时序错乱开机先走probe函数原理后续拆细论述属于设备驱动开发基础知识。五、完整调试排错流程实战顺序先确认硬件供电、排线、硬件焊接用万用表测量各路电源电压、复位引脚电平确认硬件本身没问题检查DTS核对时序、电源、gpio极性dtbo是否成功替换打开内核log查看drm、mipi dsi驱动打印adbshelldmesg-w| grep -Edsi|panel|drm|lcm|disp|panel看probe是否成功有没有资源获取失败电源、gpio获取失败看prepare阶段上电、复位、初始化命令是否发送成功看时序参数是否被DRM校验通过atomic模式有没有报错最后看MIPI链路是否成功建立有没有MIPI报CRC错误高频故障现象与根因黑屏无任何屏幕初始化logDTS没加载成功 / 电源没打开背光有但无图像初始化命令发送失败 / MIPI时序参数错误冷启动黑屏热重启正常上电延时不足复位时序问题花屏MIPI速率、lane配置错误或者像素时序参数不对常见问题和排除思路后续新开篇章论述。六、新手学习建议先拿一块成熟可点亮的Panel驱动DTS作为参考对照屏幕手册逐行看懂每一个配置用已经bringup项目打开log开关不开可能抓不全乎抓重启开机log逐步梳理kernel log流程一步一步在code里和log打印对应明确代码流向。优先调试DTS与时序尽量不要一开始就大量修改C驱动代码每改一项单独测试不要一次性修改大量参数否则很难定位问题保存调试日志后续遇到同类黑屏问题可以快速复盘有空的话详细解构每行code逻辑结尾点亮Panel是显示驱动工程师的第一个实战关卡。 它不是单纯写代码而是硬件时序 设备树 DRMpaneldriver三者结合。 80%的黑屏问题根源都藏在上电时序和DTS配置里面而不是复杂的内核逻辑。更多详细笔记WeChat搜索素师良码 SEO 优化官网定制响应式建站教育培训建站