漫谈 Linux 声卡驱动开发的设备树与 I2S

最近在研究 Ubuntu 下的 ES8156 的声卡驱动,顺便学习了一下设备树(Device Tree)I2S 声卡的工作原理。首先要搞懂这两个概念,简单来说,把写驱动比作盖房子,盖房子之前,先要看懂设计图纸(设备树)和水电原理(I2S协议)。

下面用最通俗的方式为你拆解这两个核心概念:


🌳 什么是设备树 (Device Tree)?

在以前的 Linux 内核中,硬件信息(比如有几个 CPU、内存多大、GPIO 接了什么设备)是直接写死在 C 语言代码里的。这导致内核代码非常臃肿,同一个内核代码无法通用于不同配置的开发板。

设备树就是一份"硬件说明书"。

它的作用是告诉 Linux 内核:"嘿,我现在这台电脑(开发板)上,长什么样,有哪些外设。"

1. 核心比喻:树状结构

想象一棵树:

  • 树根 (Root):代表整个系统(SoC,也就是树莓派的芯片)。
  • 树枝 (Buses):代表连接方式,比如 I2C 总线、SPI 总线、I2S 总线。
  • 树叶 (Devices):代表具体的硬件,比如 ES8156 芯片。
2. 关键术语
  • DTS (Device Tree Source) :后缀为 .dts 的文本文件,人类可读,我们写的代码就是这个。
  • DTB (Device Tree Blob) :后缀为 .dtb 的二进制文件,由 DTS 编译而来,内核能读懂。
  • Node (节点):描述一个硬件对象。例如一个 I2C 控制器是一个节点,挂在这个控制器上的 ES8156 也是一个节点。
  • Property (属性) :节点的特征。例如 compatible(兼容性)、reg(寄存器地址/I2C地址)、clocks(时钟)。
3. 驱动匹配的"暗号"

这是最关键的一点:驱动程序是如何知道自己要控制哪个硬件的?

答案是:compatible 属性

  • 设备树 里,写:compatible = "everest,es8156";
  • 驱动源码 里,开发者也写了一个列表:{"everest,es8156", ...}
  • 内核启动时,会拿着设备树里的字符串去驱动列表里找。只要这两个字符串对上了,内核就把这个硬件分配给这个驱动来管理。

🔊 I2S 声卡的工作原理

I2S 全称是 Inter-IC Sound,是飞利浦公司制定的一种数字音频传输标准。它专门用来在芯片之间传输声音数据(比如 CPU 和 音频解码芯片之间)。

为什么不用 USB 或网络传输音频?因为 I2S 是纯数字、点对点、低延迟的,音质最纯净。

1. 三根核心线 (信号)

I2S 接口通常由 3-4 根线组成,它们就像乐队的指挥和乐手:

表格

信号线 全称 作用 比喻
BCLK Bit Clock (位时钟) 每传输 1 个 bit,它就跳变一次。频率非常高。 节拍器:每响一声,传一个音符。
LRCLK Left/Right Clock (声道时钟) 高电平代表右声道,低电平代表左声道。 指挥棒:指左边乐队奏,指右边乐队停。
DIN/DOUT Data In/Out (数据线) 真正传输声音波形数据的线路。 乐谱:上面写着具体要唱什么音。
MCLK Master Clock (主时钟) 通常是采样率的 256 或 384 倍,用于同步芯片内部振荡。 校准表:确保大家的表时间一致,不走音。
2. 数据是怎么传的?

想象你要传输一个立体声(左/右)的音乐:

  1. LRCLK 变成低电平(代表左声道开始)。
  2. BCLK 开始疯狂跳动(比如 2.3MHz)。
  3. DIN 上按照 BCLK 的节奏,一位一位地送出左声道的数字(比如 16 位或 24 位数据)。
  4. LRCLK 变成高电平(代表右声道开始)。
  5. BCLK 继续跳动,DIN 上送出右声道的数据。
  6. 如此循环,形成了连续的声音流。
3. 常见的"坑" (极性)

I2S 虽然标准,但不同芯片的厂商习惯不同。

  • 左对齐 (Left Justified) vs I2S 标准 (Philips Standard):数据是在 LRCLK 变化后的第一个时钟有效,还是第二个时钟有效?
  • LRCLK 极性:高电平到底是左声道还是右声道?
  • 解决方案 :这通常在设备树或驱动代码中通过 dai-format = "i2s";dai-format = "left_j"; 来配置。如果配置错了,你会听到噪音,或者只有单声道。

🛠️ 开发调试 ES8156 的具体步骤

结合前面的理论,现在要做的事情可以拆解为以下 5 个步骤:

第一步:硬件连接 (物理层)
  • 把树莓派的 GPIO 和 ES8156 的引脚焊对。
  • I2C 线:连接 SDA、SCL(用于发送"播放"、"静音"、"调音量"等指令)。
  • I2S 线:连接 BCLK、LRCLK、DIN/DOUT(用于传输真正的音乐数据流)。
  • 供电:检查 VCC 和 GND。
第二步:确认 I2C 通信 (控制层)
  • 在 Ubuntu 命令行输入 i2cdetect -y -1
  • 目的:确认电脑能看到 ES8156 这个"人"。如果扫到了地址(比如 0x1b),说明控制通道通了。
第三步:编写设备树 (描述层)
  • 创建一个 .dts 文件。
  • 内容
    1. 告诉内核:"我在 I2C 总线上挂了一个设备,地址是 0x1b,它的名字叫 everest,es8156"。
    2. 告诉内核:"请把简单的音频卡(Simple Card)配置好,CPU 端用 I2S,Codec 端用刚才那个 ES8156"。
第四步:加载与匹配 (软件层)
  • 编译设备树,重启或动态加载。
  • 输入 dmesg | grep es8156
  • 理想输出es8156_probe: entered。这意味着驱动程序的 probe 函数被调用了,说明设备树和驱动匹配成功
第五步:测试音频 (应用层)
  • 输入 aplay -l
  • 如果能看到声卡列表里多了一个设备,恭喜你,硬件和驱动都通了!接下来就是调音量和测试播放了。

📌 总结

  • 设备树 = 给内核看的 简历,告诉内核硬件长什么样。
  • I2S = 芯片间传输声音的 专用高速公路,有严格的时钟同步要求。
  • 调试核心 :先通 I2C(控制),再通 I2S(数据),靠 compatible 字符串牵线搭桥。

老徐,2026 0123

相关推荐
云栈开源日记2 小时前
Linux Kernel:云原生时代的操作系统内核
linux·运维·云原生
网硕互联的小客服2 小时前
Debian系统提示“Media change...”如何处理?
运维·debian
linweidong2 小时前
K8s节点保卫战:基于Node Local DNS架构的磁盘自愈系统设计
运维·docker·云原生·容器·架构·kubernetes·k8s
小手智联老徐2 小时前
Jetson Orin Nano 音频设置与开发之 DTS
linux·驱动开发·音视频
HalvmånEver2 小时前
Linux:信号捕捉上(信号三)
linux·运维·服务器
HIT_Weston2 小时前
108、【Ubuntu】【Hugo】搭建私人博客:搜索引擎
linux·ubuntu·搜索引擎
Gofarlic_OMS2 小时前
Fluent许可证使用合规性报告自动化生成系统
java·大数据·运维·人工智能·算法·matlab·自动化
很㗊2 小时前
奇技淫巧之花里胡哨的VIM---插件的添加与美化
linux·ubuntu·vim
Java后端的Ai之路2 小时前
【Python小知识】-self是什么?
linux·python··self