MTK-Linux-DRM分析三十五-MTK-mtk_hdmi_ddc.c
目录
MTK Linux DRM分析(三十五)- MTK mtk_hdmi_ddc.c
一、简介
1. HDMI 接口的功能引脚分类
HDMI(High Definition Multimedia Interface)是一个基于 TMDS(Transition Minimized Differential Signaling)的数字音视频接口。
标准 Type A HDMI 接口 一共有 19 根引脚,主要分成几类:
TMDS 差分对(传输视频和音频数据)
- 3 组数据通道:TMDS Data2±, TMDS Data1±, TMDS Data0±
- 1 组时钟通道:TMDS Clock±
DDC 通道(Display Data Channel)
- I²C 接口 (SCL + SDA),用来在 Source(比如 PC/机顶盒)和 Sink(比如显示器/电视)之间传输 EDID 信息(显示器支持的分辨率、刷新率等)。
- 所以 DDC 是一种 I²C 通信机制。
CEC 通道(Consumer Electronics Control)
单根线(CEC),用于实现 HDMI 设备间的互相控制,例如:
- 电视遥控器可以控制机顶盒播放
- 打开蓝光机 → 电视自动切换到对应 HDMI 输入
CEC 协议是 HDMI 的特色之一。
Hot Plug Detect (HPD)
- 由 Sink 输出,告诉 Source “我已经接好,可以通信”。
电源与地
- +5V Power(由 Source 提供,给 Sink 侧的 EDID/EEPROM 供电)。
- 多根 GND(屏蔽和差分信号回路)。
2. HDMI 19-pin Type A 引脚定义(标准接口)
下面是 Type A(最常见的标准 HDMI 接口)引脚分布:
引脚号 | 名称 | 功能 |
---|---|---|
1 | TMDS Data2+ | 差分信号数据通道 2 正 |
2 | TMDS Data2 Shield | 通道 2 屏蔽/地 |
3 | TMDS Data2− | 差分信号数据通道 2 负 |
4 | TMDS Data1+ | 通道 1 正 |
5 | TMDS Data1 Shield | 通道 1 屏蔽/地 |
6 | TMDS Data1− | 通道 1 负 |
7 | TMDS Data0+ | 通道 0 正 |
8 | TMDS Data0 Shield | 通道 0 屏蔽/地 |
9 | TMDS Data0− | 通道 0 负 |
10 | TMDS Clock+ | 时钟通道正 |
11 | TMDS Clock Shield | 时钟通道屏蔽/地 |
12 | TMDS Clock− | 时钟通道负 |
13 | CEC | 消费电子控制(单线总线) |
14 | Reserved (N.C. 或 HEC Data− in HDMI 1.4+) | 保留/HDMI Ethernet Channel |
15 | SCL | DDC I²C 时钟 |
16 | SDA | DDC I²C 数据 |
17 | GND | 地 |
18 | +5V Power | 由 Source 提供电源(50mA~55mA,供 EDID EEPROM 和检测用) |
19 | Hot Plug Detect | Sink → Source,通知连接状态 |
3. DDC vs CEC 区别总结
DDC
- 协议:I²C
- 作用:让 Source 读取 Sink 的 EDID 配置
- 走线:SCL(Pin15)+ SDA(Pin16)
CEC
- 协议:CEC 专用单总线
- 作用:HDMI 设备互相控制(遥控、开关机联动)
- 走线:CEC(Pin13)
✅ 总结:
- HDMI Type A = 19 个 pin
- DDC = I²C 通道(SCL+SDA,用于 EDID)
- CEC = 单线控制通道(遥控/联动控制)
二、代码分析
这个代码文件(mtk_hdmi_ddc.c)是一个Linux内核驱动模块,用于MediaTek(联发科)平台的HDMI DDC(Display Data Channel)接口。DDC是HDMI标准中的一个通道,主要通过I2C协议实现显示器与主机之间的通信,例如读取EDID(Extended Display Identification Data)信息以获取显示器分辨率、刷新率等参数。该驱动实现了I2C适配器,允许内核通过此接口进行DDC数据读写操作。代码基于GPL-2.0许可证,使用平台设备驱动框架,支持MT8173等芯片。
代码的主要作用包括:
- 初始化HDMI DDC硬件(寄存器配置、时钟启用)。
- 提供I2C传输接口,支持读写操作。
- 处理DDC协议的启动、停止、数据传输和ACK确认。
- 寄存器操作辅助函数,用于位级控制DDC控制器。
代码结构清晰,包括寄存器定义、辅助函数、I2C消息处理函数、I2C算法实现、探测/移除函数,以及模块初始化信息。
主要函数及其作用
以下是代码中的主要函数,按逻辑顺序分析,每个函数的作用、参数和关键逻辑简述如下:
- sif_set_bit / sif_clr_bit / sif_bit_is_set / sif_write_mask / sif_read_mask
- 作用:这些是寄存器操作的辅助函数,用于对DDC控制器的寄存器进行位级读写和检查。它们封装了ioread/iowrite操作,确保硬件寄存器的原子性修改。
- 关键逻辑:使用readl/writel访问内存映射的寄存器,支持设置/清除位、检查位状态、掩码写/读。
- 使用场景:贯穿整个驱动,用于配置DDC模式、时钟分频、ACK检查等。例如,sif_write_mask用于设置时钟分频或传输模式。
- ddcm_trigger_mode
- 作用:触发DDC控制器的特定模式(如START、WRITE_DATA、READ_DATA等),并等待操作完成。这是DDC协议的核心控制函数。
- 参数:ddc(驱动结构体指针)、mode(模式值,如DDCM_START=0x1)。
- 关键逻辑:设置模式寄存器(DDCMCTL1),置位TRI位触发操作,然后通过readl_poll_timeout轮询等待TRI位清零(表示操作完成)。超时为20ms。
- 使用场景:在读写消息中调用,用于启动传输、发送数据、读取数据等步骤。
- mtk_hdmi_ddc_read_msg
- 作用:处理I2C读消息,从设备读取数据,支持多字节读取和ACK确认。主要用于DDC读取EDID等信息。
- 参数:ddc、msg(I2C消息结构体,包含地址、缓冲区、长度)。
- 关键逻辑:
- 发送START和设备地址(带读位)。
- 分块读取数据(每块最多8字节),处理ACK(使用DDCM_READ_DATA_ACK或NO_ACK)。
- 检查ACK错误,如果NACK则返回错误。
- 数据从寄存器(DDCMD0/DDCMD1)读取到msg->buf。
- 返回:成功返回0,失败返回-ENXIO(无响应)或其他错误。
- 使用场景:在I2C传输中,当消息标志为I2C_M_RD时调用。
- mtk_hdmi_ddc_write_msg
- 作用:处理I2C写消息,向设备写入数据。主要用于DDC配置或写入命令。
- 参数:ddc、msg(包含地址、缓冲区)。
- 关键逻辑:
- 发送START和设备地址(带写位),然后写入数据字节。
- 设置页面长度(PGLEN=1,表示2字节:地址+数据)。
- 检查ACK,如果不匹配则返回-EIO。
- 返回:成功返回0,失败返回-EIO。
- 使用场景:在I2C传输中,当消息不带I2C_M_RD标志时调用。注意:代码中只支持单字节写入(msg->buf[0]),可能针对特定DDC场景。
- mtk_hdmi_ddc_xfer
- 作用:I2C主传输函数,实现多个消息的批量传输。这是I2C算法的核心入口。
- 参数:adapter(I2C适配器)、msgs(消息数组)、num(消息数量)。
- 关键逻辑:
- 配置DDC寄存器(启用SCL拉伸、SM0EN,禁用ODRAIN)。
- 检查总线是否忙碌,如果忙返回-EBUSY。
- 设置时钟分频(SIF1_CLOK=288)。
- 循环处理每个消息:读调用read_msg,写调用write_msg。
- 传输结束发送STOP。
- 返回:成功返回处理的消息数,失败返回负错误码。
- 使用场景:由I2C核心调用,实现I2C协议的master_xfer。
- mtk_hdmi_ddc_func
- 作用:返回I2C适配器的功能标志,支持纯I2C和SMBUS仿真。
- 返回:I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL。
- 使用场景:I2C算法的functionality回调,用于上层查询驱动能力。
- mtk_hdmi_ddc_probe
- 作用:平台设备探测函数,初始化驱动。
- 参数:pdev(平台设备指针)。
- 关键逻辑:
- 分配ddc结构体,获取时钟(“ddc-i2c”)。
- 映射寄存器资源。
- 启用时钟。
- 设置I2C适配器属性(名称、算法、重试次数等)。
- 添加I2C适配器到内核。
- 返回:成功0,失败负错误码。
- 使用场景:内核加载模块时调用,支持DT匹配"mediatek,mt8173-hdmi-ddc"。
- mtk_hdmi_ddc_remove
- 作用:平台设备移除函数,清理资源。
- 参数:pdev。
- 关键逻辑:删除I2C适配器,禁用时钟。
- 返回:0。
- 使用场景:卸载模块时调用。
其他关键点
- 结构体:mtk_hdmi_ddc 包含I2C适配器、时钟和寄存器基址。
- I2C算法:mtk_hdmi_ddc_algorithm 定义了xfer和func回调。
- 寄存器定义:如DDC_DDCMCTL0(控制时钟、状态)、DDC_DDCMCTL1(模式、ACK)、DDCMD0/1(数据缓冲)。
- 错误处理:常见错误包括ACK失败(NACK)、总线忙、超时,使用dev_err日志。
- 限制:写操作仅支持单字节数据;读操作支持多字节但分块处理;无互联网访问,仅硬件操作。
- 模块信息:作者Jie Qiu,描述"MediaTek HDMI DDC Driver",使用platform_driver注册。