目录

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 根引脚,主要分成几类:

  1. TMDS 差分对(传输视频和音频数据)

    • 3 组数据通道:TMDS Data2±, TMDS Data1±, TMDS Data0±
    • 1 组时钟通道:TMDS Clock±
  2. DDC 通道(Display Data Channel)

    • I²C 接口 (SCL + SDA),用来在 Source(比如 PC/机顶盒)和 Sink(比如显示器/电视)之间传输 EDID 信息(显示器支持的分辨率、刷新率等)。
    • 所以 DDC 是一种 I²C 通信机制
  3. CEC 通道(Consumer Electronics Control)

    • 单根线(CEC),用于实现 HDMI 设备间的互相控制,例如:

      • 电视遥控器可以控制机顶盒播放
      • 打开蓝光机 → 电视自动切换到对应 HDMI 输入
    • CEC 协议是 HDMI 的特色之一。

  4. Hot Plug Detect (HPD)

    • 由 Sink 输出,告诉 Source “我已经接好,可以通信”。
  5. 电源与地

    • +5V Power(由 Source 提供,给 Sink 侧的 EDID/EEPROM 供电)。
    • 多根 GND(屏蔽和差分信号回路)。

2. HDMI 19-pin Type A 引脚定义(标准接口)

下面是 Type A(最常见的标准 HDMI 接口)引脚分布:

引脚号名称功能
1TMDS Data2+差分信号数据通道 2 正
2TMDS Data2 Shield通道 2 屏蔽/地
3TMDS Data2−差分信号数据通道 2 负
4TMDS Data1+通道 1 正
5TMDS Data1 Shield通道 1 屏蔽/地
6TMDS Data1−通道 1 负
7TMDS Data0+通道 0 正
8TMDS Data0 Shield通道 0 屏蔽/地
9TMDS Data0−通道 0 负
10TMDS Clock+时钟通道正
11TMDS Clock Shield时钟通道屏蔽/地
12TMDS Clock−时钟通道负
13CEC消费电子控制(单线总线)
14Reserved (N.C. 或 HEC Data− in HDMI 1.4+)保留/HDMI Ethernet Channel
15SCLDDC I²C 时钟
16SDADDC I²C 数据
17GND
18+5V Power由 Source 提供电源(50mA~55mA,供 EDID EEPROM 和检测用)
19Hot Plug DetectSink → 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算法实现、探测/移除函数,以及模块初始化信息。

主要函数及其作用

以下是代码中的主要函数,按逻辑顺序分析,每个函数的作用、参数和关键逻辑简述如下:

  1. 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用于设置时钟分频或传输模式。
  2. ddcm_trigger_mode
    • 作用:触发DDC控制器的特定模式(如START、WRITE_DATA、READ_DATA等),并等待操作完成。这是DDC协议的核心控制函数。
    • 参数:ddc(驱动结构体指针)、mode(模式值,如DDCM_START=0x1)。
    • 关键逻辑:设置模式寄存器(DDCMCTL1),置位TRI位触发操作,然后通过readl_poll_timeout轮询等待TRI位清零(表示操作完成)。超时为20ms。
    • 使用场景:在读写消息中调用,用于启动传输、发送数据、读取数据等步骤。
  3. 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时调用。
  4. 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场景。
  5. 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。
  6. mtk_hdmi_ddc_func
    • 作用:返回I2C适配器的功能标志,支持纯I2C和SMBUS仿真。
    • 返回:I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL。
    • 使用场景:I2C算法的functionality回调,用于上层查询驱动能力。
  7. mtk_hdmi_ddc_probe
    • 作用:平台设备探测函数,初始化驱动。
    • 参数:pdev(平台设备指针)。
    • 关键逻辑
      • 分配ddc结构体,获取时钟(“ddc-i2c”)。
      • 映射寄存器资源。
      • 启用时钟。
      • 设置I2C适配器属性(名称、算法、重试次数等)。
      • 添加I2C适配器到内核。
    • 返回:成功0,失败负错误码。
    • 使用场景:内核加载模块时调用,支持DT匹配"mediatek,mt8173-hdmi-ddc"。
  8. 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注册。