驱动开发硬核特训 · 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"

相关推荐
摇滚侠2 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
潜创微科技2 小时前
HDMI1.3 无线传输芯片方案 空旷 150 米量产级音视频方案
音视频
bush43 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
东方佑3 小时前
FRSM 规模效应与架构对比补充报告
架构
VidDown3 小时前
VidDown 工具站:免费、本地优先的开发者工具箱
javascript·编辑器·音视频·视频编解码·视频
换个昵称都难3 小时前
音频格式之WAV
音视频
载数而行5203 小时前
Linux 11 动态监控指令top
linux
AI创界者3 小时前
PilotTTS 一键整合包(Win/Mac):8G 显存畅跑,实测解锁情绪与副语言的精准控制
人工智能·macos·aigc·音视频
不会C语言的男孩4 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
u152109648495 小时前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频