
简介面向联发科MediaTek平台的LT9611驱动开发资源聚焦显示链路中DSI转HDMI的桥接方案默认输出全高清画面适用于嵌入式设备、智能电视或商用显示产品的驱动移植与底层调试。压缩包体积仅21KB包含5个文件其中3个为C语言驱动源文件分别承担启动加载阶段与内核阶段的初始化及数据通路控制另2个为DWS配置描述文件用于板级引脚复用和显示参数编解码源码与配置分离便于在具体硬件上快速适配。结合标题中的stomachhcc来看该驱动大概率针对特定硬件配置或项目定制理解这一点有助于减少在相似平台间移植时的踩坑成本。目前已有964人学习适合具备一定驱动基础、正在调试联发科显示输出或HDMI桥接方案的工程师参考。通过阅读源码和配置可以掌握LT9611的寄存器初始化流程、DSI转HDMI的信号转换要点以及将输出分辨率锁定为全高清的具体方法为实际产品集成提供直接可用的基础代码与排错思路。1. 一份 MTK 平台 LT9611 驱动源码能拆出多少东西拿到mtk-lt9611_stomachhcc_lt9611_mtk这份源码包时第一反应是它不是一个完整工程而是一组散落在 LK、Kernel 和配置脚本里的关键文件lt9611_dsi2hdmi.c、codegen.dws、tb8735ap1_lr_ztk.dws。这意味着你面对的不是一份开箱即用的驱动而是一个已经跑通过的方案切片需要自己把它拼回目标工程里。LT9611 是 Lontium 的 MIPI DSI 转 HDMI 桥片在 MTK 平台上常见于平板、车载或商显方案默认输出 1080p。这里有个容易忽略的点桥片驱动写得好不好直接决定开机 Logo 是否闪烁、进系统后 HDMI 是否黑屏、以及dmesg里是否挂满hdmi_connector报错。源码包里出现lk路径说明这套方案连 Preloader 之后的 LK 阶段都做了 HDMI 初始化——这是很多只改 Kernel 的移植方案最容易漏掉的一环。我不会逐行贴源码而是从「这份源码包到底想让你解决什么问题」出发拆出四条线LK 阶段初始化、Kernel 驱动框架、codegen.dws配置、以及调试手段。2. LK 阶段为什么开机 Logo 能不能显示取决于lt9611_dsi2hdmi.c2.1 LK 里跑 HDMI 桥片的必要性MTK 平台的显示链路是Display模块通过 DSI 输出接到 LT9611 再转成 HDMI 信号给屏幕。在 LKLittle Kernel阶段bootloader 需要点亮屏幕显示开机 Logo如果此时只初始化了 DSI 而没初始化 LT9611HDMI 端就是黑的。源码包的lk目录下放着lt9611_dsi2hdmi.c正是为了在 LK 阶段完成桥片的寄存器配置和视频参数协商。阅读这份源码时先看它的初始化入口。通常会有一个类似lt9611_dsi2hdmi_init的函数内部做三件事复位桥片、配置 I2C 通道、写 DSI 视频时序参数。代码结构大致如下static int lt9611_dsi2hdmi_init(void) { /* 复位桥片等待电源稳定 */ lt9611_reset(); mdelay(20); /* 通过 I2C 读取 chip id 确认桥片在线 */ if (lt9611_read_reg(0x00) ! 0x61) { printf([LT9611] chip id mismatch\n); return -1; } /* 配置 DSI 输出时序1080p60 对应 HFP88, HBP148, VFP4, VBP36 */ lt9611_set_timing(1920, 1080, 88, 148, 4, 36); /* 使能 HDMI 输出 */ lt9611_sys_power(1); return 0; }这段代码里lt9611_reset通常是拉 GPIO 控制复位引脚复位时序要参考 LT9611 datasheet一般是低电平保持至少 10ms 再拉高。lt9611_read_reg(0x00)读回的 chip id 可以用来确认 I2C 地址是否正确——LT9611 的 7-bit 地址常见为 0x3b 或 0x39具体看硬件 design 时 SA0 引脚的高低电平。如果读不到正确 ID大概率是 I2C 地址配错或者布线问题。2.2 时序参数是怎么算出来的1080p60 的标准时序中HFPHorizontal Front Porch是 88HBPHorizontal Back Porch是 148VFPVertical Front Porch是 4VBPVertical Back Porch是 36。但 LK 阶段真正生效的是 DSI 的HSA、HBP、HACT等参数它们需要根据dbi或dpi接口类型换算。MTK LK 的 display 驱动里常见写法是直接查表源码包的tb8735ap1_lr_ztk.dws里就保存了这份面板参数。注意 LK 阶段的 DSI 输出频率。LT9611 作为桥片对 DSI clock 有上限要求如果配置过高会导致画面雪花或直接无输出。我用 1080p60 时DSI clock 通常设在594–660MHz范围内对应 4-lane MIPI。LK 阶段拿到的pll_clk值要配合clk_get_rate确认实际生效频率/* 从设备树或配置表获取 DSI PLL 频率 */ unsigned int dsi_clk mtk_dsi_get_clk_rate(); printf([LT9611] DSI clock: %u Hz\n, dsi_clk); /* 计算 lane 速率bit clock / 4 lanes */ unsigned int lane_rate dsi_clk / 4;这里除以 4 是 4-lane 的配置。如果用的 3-lane 甚至 1-lane要相应调整。很多 LK 阶段黑屏问题最后定位都是 lane 数配少了带宽不够。3. Kernel 驱动lt9611_dsi2hdmi.c的 DRM 接入与 I2C 通信3.1 DRM bridge 驱动结构Kernel 目录下的lt9611_dsi2hdmi.c是完整版的桥片驱动基于 DRMDirect Rendering Manager框架的drm_bridge接口实现。它的核心逻辑是接收 DSI 数据流转换成 HDMI 信号输出同时处理 HDCP、EDID 读取、音频透传等。MTK 平台的显示栈是mtk_drmLT9611 作为外置桥片通过 I2C 与 SoC 通信在 DRM 里注册成一个drm_bridge。先看驱动如何注册自身static const struct i2c_device_id lt9611_i2c_id[] { { lt9611, 0 }, { } }; static const struct of_device_id lt9611_of_match[] { { .compatible lontium,lt9611 }, { } }; static struct i2c_driver lt9611_driver { .driver { .name lt9611, .of_match_table lt9611_of_match, }, .probe lt9611_probe, .id_table lt9611_i2c_id, };compatible字符串要和设备树里的节点匹配常见写法是i2c3 { lt96113b { compatible lontium,lt9611; reg 0x3b; reset-gpio pio 45 0; interrupt-parent pio; interrupts 46 IRQ_TYPE_EDGE_FALLING; }; };注意reg 0x3b是 8-bit 地址而驱动里i2c传输时直接用这个值和 LK 阶段用的 7-bit 地址要区分开——这是一个很常见的坑。芯片 datasheet 标注的地址通常是 7-bit但设备树里写的是 8-bit左移一位后的值写错一个 bit 整个驱动 probe 不到设备。3.2 probe 函数里做了什么lt9611_probe不只注册 I2C 设备它要做以下几件事获取 GPIO 资源、复位桥片、初始化 I2C 通信、注册 DRM bridge、配置 HDMI 输出。static int lt9611_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct lt9611 *lt devm_kzalloc(client-dev, sizeof(*lt), GFP_KERNEL); struct device_node *np client-dev.of_node; int ret; lt-client client; i2c_set_clientdata(client, lt); /* 解析 GPIO 资源 */ lt-reset_gpio of_get_named_gpio(np, reset-gpio, 0); if (gpio_is_valid(lt-reset_gpio)) { ret devm_gpio_request_one(client-dev, lt-reset_gpio, GPIOF_OUT_INIT_LOW, lt9611-reset); } /* 复位流程拉低 20ms拉高 50ms */ gpio_set_value(lt-reset_gpio, 0); msleep(20); gpio_set_value(lt-reset_gpio, 1); msleep(50); /* 读取 chip id 验证通信 */ ret lt9611_read_byte(lt, 0x00); if (ret ! 0x61) { dev_err(client-dev, LT9611 chip id error: 0x%02x\n, ret); return -EPROBE_DEFER; } /* 注册 DRM bridge */ lt-bridge.funcs lt9611_bridge_funcs; lt-bridge.of_node np; drm_bridge_add(lt-bridge); return 0; }这段代码里有个值得注意的细节devm_gpio_request_one用GPIOF_OUT_INIT_LOW来申请并在 probe 时拉低复位脚这是为了确保驱动加载时先让桥片处于复位态后面再拉高。msleep(20)和msleep(50)是两个关键延时参数——有些方案为了省时间把这两个延时缩短结果 LT9611 上电后内部 PLL 还没锁死驱动读 chip id 失败。如果遇到-EPROBE_DEFER先查 I2C 地址是否正确再查复位时序。3.3 ATF 命令调试寄存器Kernel 跑起来后如果想确认 LT9611 的寄存器状态最快的方式是用 ADB 通过 I2C 直接读写。MTK 平台/sys/bus/i2c/devices/目录下能看到设备adb shell cd /sys/bus/i2c/devices/3-003b cat name如果name显示为lt9611说明 probe 成功。接下来可以用i2ctransfer工具直接访问寄存器# 读 0x3b 设备 0x00 寄存器 i2ctransfer -y -f 3 w10x3b 0x00 r1这里-y是跳过确认-f是强制访问w10x3b表示向地址 0x3b 写入 1 字节0x00是寄存器地址r1是读 1 字节。返回0x61说明通信正常返回0xff或报错则要检查硬件连接。注意如果设备树里节点挂在别的 I2C 总线上把3换成实际的 bus 号。4.codegen.dws里的 GPIO 复用与 I2C 总线分配4.1dws文件在 MTK 平台的作用codegen.dws和tb8735ap1_lr_ztk.dws是 MTK 的 DWSDevice Wire Settings文件由MediaTek Configuration Tool生成作用是配置 GPIO 复用、上下拉、驱动能力和 I2C 通道分配。LT9611 桥片的 I2C 引脚、复位 GPIO、中断 GPIO 都需要在.dws里先配置好Kernel 的 pinctrl 子系统才能正确申请引脚。打开codegen.dws会看到类似下面的配置段落[GPIO_SETTING] ; 配置 GPIO45 为复位脚默认输出低 GPIO45 0x001 ; 配置 GPIO46 为中断脚带上拉 GPIO46 0x101 [I2C_SETTING] ; 将 I2C3 的 SDA/SCL 复用为功能引脚 I2C3_SDA 0x011 I2C3_SCL 0x011这段配置的含义是GPIO45 设置为模式 0GPIO 模式方向为输出且默认低电平GPIO46 设置为输入、使能内部上拉I2C3 的两个引脚复用为 I2C 功能。配置错一个引脚模式轻则读不到设备重则 GPIO 冲突导致其他外设异常。4.2 修改.dws后如何生效.dws文件改完后需要用MediaTek Configuration Tool将其编译成对应的 header 文件替换到 kernel 工程中。不同平台的编译产物不一样MTK 平台上常见的做法是# 在 kernel 工程目录下 ./mk tb8735ap1_lr_ztk new # 或者只更新 dts 部分 ./mk tb8735ap1_lr_ztk kernel有些平台需要先执行make clean再全编译因为dws生成的cust_gpio_usage.h和cust_i2c.h会作为头文件编译进内核增量编译可能不识别修改。注意 I2C 总线的选择。LT9611 挂在 I2C3 上时.dws里如果同时还有其他 I2C 设备要检查总线地址是否有冲突。常见问题是在dws里把 I2C3 配成了 500KHz 的高速模式但 LT9611 在某些板卡上只能跑 100KHz——此时需要降速[I2C_SETTING] I2C3_SPEED 100000改完之后要确认 Kernel 的 dts 里clock-frequency也保持一致否则驱动起来后 I2C 通信会偶发超时。5. 实战验证从编译到点亮的完整排查路径5.1 LK 阶段验证视频链路编译完 LK 和 Kernel 后刷机进 Preloader 阶段先看串口日志。LK 阶段打印的[LT9611]信息会直接暴露桥片初始化状态/* LK 阶段判断初始化是否成功 */ int lt9611_dsi2hdmi_init(void) { if (lt9611_chip_id_check() ! 0) return -1; printf([LT9611] init ok\n); return 0; }刷机后如果能看到[LT9611] init ok但屏幕仍然黑屏下一步就要量 HDMI 端是否有信号。用示波器量 HDMI 的 TMDS clock 引脚Pin 16如果有 148.5MHz 的时钟信号说明桥片已经开始输出问题大概率在 EDID 协商阶段。此时在 Kernel 侧用cat /sys/class/drm/card0-HDMI-A-1/status看连接状态cat /sys/class/drm/card0-HDMI-A-1/status返回connected说明 EDID 读到了返回disconnected则停在 I2C 的 DDC 通道上。LT9611 的 DDC 引脚是独立的它通过内部 I2C 转换到 HDMI 的 DDC 线如果屏端 EDID 读取失败需要检查 HDMI 座子的 HPDHot Plug Detect引脚——用万用表量 HPD 是否被拉高这是判断显示器是否在线的最快方式# 查看 HPD 中断是否触发 cat /proc/interrupts | grep lt9611HPD 中断一直没有计数说明桥片没有把 HPD 状态变化上报给 SoC此时优先查 GPIO 中断配置。5.2 分辨率参数与帧率抖动排查进入系统后如果画面撕裂或帧率不稳回到源码里查lt9611_set_video_mode函数的设定。LT9611 的0x10寄存器控制输出格式常见配置是 RGB888 或 YCbCr444/* 配置视频格式为 RGB888 */ lt9611_write_reg(lt, 0x10, 0x80); /* 配置色深 24bit */ lt9611_write_reg(lt, 0x11, 0x00);注意0x11寄存器的 bit 值在不同版本 SDK 里含义有差异源码包里的lt9611_v1_3_MTK658_0628.c文件名里的v1_3就是桥片固件版本号不同版本的固件对某些寄存器位的定义不一样。改参数前先确认当前桥片固件版本和源码对应关系/* 读取固件版本 */ int version lt9611_read_reg(lt, 0x06); printf(LT9611 firmware v%d.%d\n, version 4, version 0x0F);如果版本号和源码注释不匹配建议先跑桥片厂商提供的固件升级工具再回来调驱动源码否则会浪费很多时间在寄存器和实际行为对不上的排障上。最后提一个参数LT9611 的数据通道 lane 映射可能不标准如果输出画面出现「颜色偏色但不花」的情况通常是0x05寄存器配置的 lane swap 顺序和硬件走线不一致按实际 PCB 布线翻转映射即可。本文还有配套的精品资源点击获取