驱动开发硬核特训 · Day 30(下篇): 深入解析 lm48100q I2C 音频编解码器驱动模型(基于 i.MX8MP)

作者:嵌入式Jerry

视频教程请关注 B 站:"嵌入式Jerry"


一、背景与目标

在本篇中,我们围绕 TI 的 lm48100q 音频编解码器 展开,深入讲解其作为 I2C 外设如何集成至 Linux 内核音频子系统(ASoC),配合 i.MX8MP 平台上的 SAI 接口 实现音频回放功能。

目标包括:

  • 理解 lm48100q 的设备树绑定方式
  • 解析 codec 驱动与 machine 驱动的协同工作
  • 分析其 register map、音频路径、power domain 的实现方式
  • 展示 ASoC codec 驱动完整注册流程及常用结构体
  • 给出核心代码结构 + 注释 + 驱动关系图

在这里插入图片描述

二、设备树配置分析(i.MX8MP)

imx8mp-evk.dts 中:

dts 复制代码
&i2c2 {
    clock-frequency = <100000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c2>;
    status = "okay";

    lm48100q_codec: lm48100q@7d {
        compatible = "ti,lm48100q";
        reg = <0x7d>;
        #sound-dai-cells = <0>;
    };
};

解释:

  • i2c2 为 I2C 控制器,lm48100q 为挂载在 I2C 总线上的 codec,地址为 0x7d
  • #sound-dai-cells = <0>:表示 DAI(Digital Audio Interface)不接受参数,是一个单一 DAI。

对应的 sound-pcm1754 节点配置了该 codec:

dts 复制代码
sound-pcm1754 {
    compatible = "simple-audio-card";
    ...
    simple-audio-card,codec {
        sound-dai = <&lm48100q_codec>;
    };
};

三、Linux 驱动结构概览

lm48100q 采用标准的 ASoC codec 驱动模型,主要涉及三个部分:

  • lm48100q.c:codec 驱动本体(提供 DAI,电源,widget,路由定义)
  • simple-audio-card.c:machine 驱动(描述 CPU 和 codec 的连接关系)
  • fsl-sai.c:SAI 接口的 platform 驱动

整体结构如下图:

复制代码
       Userspace (aplay)
            ↓
     ALSA PCM Interface
            ↓
      ASoC Core Framework
       ↓            ↓
  Codec Driver   Platform Driver
   lm48100q.c       fsl-sai.c
       ↓              ↓
   I2C (regmap)     SAI (platform)
       ↓              ↓
  音频编解码芯片      i.MX SAI 控制器

四、lm48100q Codec 驱动详解

源码路径:sound/soc/codecs/lm48100q.c(或 TI 提供)

1. 模块入口与 of 绑定

c 复制代码
static const struct of_device_id lm48100q_of_match[] = {
    { .compatible = "ti,lm48100q" },
    {},
};
MODULE_DEVICE_TABLE(of, lm48100q_of_match);

绑定设备树节点中的 "ti,lm48100q"


2. I2C 驱动结构

c 复制代码
static struct i2c_driver lm48100q_i2c_driver = {
    .driver = {
        .name = "lm48100q",
        .of_match_table = lm48100q_of_match,
    },
    .probe = lm48100q_i2c_probe,
    .remove = lm48100q_i2c_remove,
};

3. codec 结构体注册

c 复制代码
static const struct regmap_config lm48100q_regmap = {
    .reg_bits = 8,
    .val_bits = 8,
    .max_register = LM48100Q_MAX_REG,
    .volatile_reg = lm48100q_volatile,
};

static int lm48100q_i2c_probe(struct i2c_client *i2c)
{
    struct regmap *regmap;

    regmap = devm_regmap_init_i2c(i2c, &lm48100q_regmap);
    ...
    return devm_snd_soc_register_component(&i2c->dev,
        &soc_component_dev_lm48100q, &lm48100q_dai, 1);
}
  • 使用 regmap 管理寄存器读写
  • 通过 snd_soc_register_component() 注册 codec

4. DAI 定义

c 复制代码
static struct snd_soc_dai_driver lm48100q_dai = {
    .name = "lm48100q-hifi",
    .playback = {
        .stream_name = "Playback",
        .channels_min = 2,
        .channels_max = 2,
        .rates = SNDRV_PCM_RATE_8000_192000,
        .formats = SNDRV_PCM_FMTBIT_S16_LE |
                   SNDRV_PCM_FMTBIT_S24_LE,
    },
    .ops = &lm48100q_dai_ops,
};

该 DAI 只支持 Playback,不支持录音。


5. 控件与路径配置(Widgets & Routes)

c 复制代码
static const struct snd_soc_dapm_widget lm48100q_dapm_widgets[] = {
    SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
    SND_SOC_DAPM_OUTPUT("HPOL"),
    SND_SOC_DAPM_OUTPUT("HPOR"),
};

static const struct snd_soc_dapm_route lm48100q_dapm_routes[] = {
    { "HPOL", NULL, "DAC" },
    { "HPOR", NULL, "DAC" },
};

定义音频组件的连接路径。


五、Machine 驱动部分(simple-audio-card)

无需用户实现,使用设备树进行配置:

dts 复制代码
sound-pcm1754 {
    compatible = "simple-audio-card";
    simple-audio-card,name = "pcm1754-audio";
    ...
    simple-audio-card,cpu {
        sound-dai = <&sai3>;
    };
    simple-audio-card,codec {
        sound-dai = <&lm48100q_codec>;
    };
};

ASoC core 解析 device tree 并自动注册 machine 驱动。


六、SAI 平台驱动(以 SAI3 为例)

路径:sound/soc/fsl/fsl_sai.c

它通过 platform_driver 提供 snd_soc_dai_driver,用于与 codec 的 DAI 建立连接关系。


七、应用层播放验证

音频配置好后,在根文件系统中可使用如下命令验证:

bash 复制代码
aplay -D plughw:0,0 test.wav

如果设备树、驱动、路径配置都正确,lm48100q 会响应并输出音频信号至耳机口。


八、完整调试技巧总结

1. 确认设备树生效:

bash 复制代码
dmesg | grep lm48100q
cat /proc/device-tree/soc@0/bus@30800000/i2c@30a20000/lm48100q@7d/compatible

2. 查看注册的声卡与 DAI:

bash 复制代码
cat /proc/asound/cards
cat /proc/asound/pcm

3. 检查 regmap:

bash 复制代码
i2cget -y 0 0x7d 0x01

九、小结

模块 类型 驱动入口
lm48100q Codec I2C + ASoC Codec
SAI3 Platform fsl-sai
Sound Card Machine simple-audio-card DT

lm48100q codec 的驱动模型是典型的 I2C + ASoC codec 类型,配合 i.MX 的 SAI 控制器,适用于嵌入式音频设备中的播放场景,具有较好的模块化与可移植性。


🔚 结语

至此,《驱动开发硬核特训 · Day 30》完整结束,我们已完整解析了两个典型的 I2C 总线驱动:at24 EEPROM 与 lm48100q 音频 codec,分别展示了 字符设备模型子系统型 Codec 驱动 的集成方式。


📌 技术平台 :嵌入式Jerry

📺 视频教程请关注 B 站:"嵌入式Jerry"

相关推荐
Kookoos11 分钟前
ABP vNext + Dapr 实现云原生微服务治理
微服务·云原生·架构·c#·.net
XiaoCCCcCCccCcccC15 分钟前
Linux网络基础 -- 局域网,广域网,网络协议,网络传输的基本流程,端口号,网络字节序
linux·c语言·网络·c++·网络协议
果子⌂15 分钟前
Linux系统入门第十二章 --Shell编程之正则表达式
linux·运维·服务器
随风奔跑的十八岁19 分钟前
java 破解aspose.words 18.6 使用
java·linux·word转pdf·aspose-words
微学AI22 分钟前
大模型的应用中A2A(Agent2Agent)架构的部署过程,A2A架构实现不同机器人之间的高效通信与协作
人工智能·架构·机器人·a2a
海尔辛32 分钟前
学习黑客5 分钟读懂Linux Filesystem Interaction Continued
linux·服务器·学习
是垚不是土1 小时前
Kolla-Ansible搭建与扩容OpenStack私有云平台
linux·运维·服务器·云计算·ansible·openstack
五花肉村长1 小时前
Linux-Ext系列文件系统
linux·运维·服务器·c++·笔记·visual studio
门前云梦2 小时前
VirtualBox中安装并运行ubuntu-24.04.2-desktop虚拟机
linux·ubuntu·虚拟机·virtualbox
FrozenLove_G2 小时前
硬件中断请求号和lspci命令查看到的device id有关系吗?
linux·微型计算机组成结构·内核学习