yoda24/DOC_MECHA_PRJ_NIC1_20260617_CASE_REGMAP_I2C

GitHub: yoda24/DOC_MECHA_PRJ_NIC1_20260617_CASE_REGMAP_I2C

该项目记录并修复了 MediaTek 平台上 TFA9890 音频放大器驱动因 I2C regmap 结构体类型转换导致的垃圾数据通信错误。

Stars: 0 | Forks: 0

## TFA98XX 驱动 - Mediatek I2C 扩展兼容性适配 ### TFA9890 音频放大器 - 关键规格 ### 概述 NXP TFA9890 是一款高性能 D 类音频放大器,集成了 DSP 和 DC-DC 升压转换器,专为移动微型扬声器设计。 ### 与驱动开发相关的主要特性 | 特性 | 详情 | |---|---| | 控制接口 | I2C(400 kHz 快速模式) | | DSP | NXP CoolFlux,嵌入式固件 | | 输出功率 | 3.6W RMS(8Ω,9.5V 升压) | | 供电电压 | 2.7V - 5.5V | | 采样率 | 8 kHz - 48 kHz | | I2S 输入 | 2(支持双音频源) | | 扬声器保护 | 自适应偏移控制,实时温度监控 | | 固件 | 基于容器(.cnt),包含音乐/语音配置文件 | ### 驱动需求 | 需求 | 实现方式 | |---|---| | I2C 通信 | 400 kHz 快速模式,16 位寄存器 | | 固件加载 | 通过 regmap 或直接 I2C 加载容器(.cnt) | | DSP 控制 | 启动/停止,配置文件切换(音乐/语音) | | 音频路由 | ALSA SoC codec 集成 | | 中断处理 | 扬声器错误,温度过高警告,削波检测 | | 电源管理 | 挂起/恢复,LDO 控制,GPIO 复位 | #### 主要错误([错误日志](./dev_log_main_err.txt)) ### 配置 ``` CONFIG_MTK_I2C_EXTENSION=y ``` ``` static struct i2c_algorithm mt_i2c_algorithm = { #ifdef CONFIG_MTK_I2C_EXTENSION .master_xfer = (pmaster_xfer)mtk_i2c_transfer, #else .master_xfer = standard_i2c_transfer, #endif .functionality = mt_i2c_functionality, }; ```

  

                     KERNEL LINUX (GENERIC)

                    ┌─────────────────────┐

                    │  i2c_transfer()     │

                    │  regmap, SMBus, dll │

                    └──────────┬──────────┘

                               │ struct i2c_msg (standar)

                               │ no timing

                               │ no ext_flag

                               ▼

              ┌────────────────────────────────┐

              │   CONFIG_MTK_I2C_EXTENSION?    │

              └────────┬───────────────┬───────┘

                       │               │

                       =y              =n

                       │               │

                       ▼               ▼

              ┌──────────────┐  ┌──────────────┐

              │ mt_i2c_msg   │  │ i2c_msg      │

              │ (custom MTK) │  │ (standard)   │

              │ * timing     │  │              │

              │ * ext_flag   │  │              │

              └──────────────┘  └──────────────┘



### 垃圾数据流错误


  

                                                 struct i2c_msg (12 BYTE)

        #include <linux/i2c.h>            ┌────────────────────────────────┐

        ─────────────────────────►        │ addr │ flags │ len  │ *buf     │

                                          └──────┴───────┴──────┴──────────┘

                                          no member timing

                                          no member ext_flag



                                                    │

                                                    │ CAST

                                                    ▼



        #include <linux/mt_i2c.h>        ┌────────────────────────────────────────────────────┐

        ─────────────────────────►       │ addr │ flags │ len  │ *buf     │ timing │ ext_flag │

                                         └──────┴───────┴──────┴──────────┴────────┴──────────┘

                                         has member timing (4 byte) → value 400 KHz

                                         has member  ext_flag (4 byte) → value 0





        ═══════════════════════════════════════════════════════════════════════════════════════

        COMPARING:

        <linux/i2c.h>                       <linux/mt_i2c.h>

        ┌────┬────┬────┬────┐               ┌────┬────┬────┬────┬────────┬──────────┐

        │addr│flg │len │*buf│               │addr│flg │len │*buf│ timing │ ext_flag │

        └────┴────┴────┴────┘               └────┴────┴────┴────┴──┬─────┴────┬─────┘

                                                                   │          │

              CAST ▼                                               │          │

        ┌────┬────┬────┬────┬────────┬──────────┐                  │          │

        │addr│flg │len │*buf│ ?????? │ ???????? │                  ▼          ▼

        └────┴────┴────┴────┴──┬─────┴────┬─────┘             400 KHz     0 (safe)

                               │          │

                         GARBAGE!    GARBAGE!

                         0x4DE6D418  0xFFFFFFC0

                         (54 MHz!)   (RND!)

                               │          │

                               ▼          ▼

                          ┌─────────────────────┐

                          │  ERROR!             │

                          │  speed too fast     │

                          │  probe FAILS        │

                          └─────────────────────┘

结果([日志 1](./LOG1.txt)):


```
		dev_err("Failed to read Revision register: -22")

		return -EIO;
```


### 修复结果([日志 2](./LOG2.txt))。


╔══════════════════════════════════════════════════════════════════════════════════════════╗

║                           COMPARE 3 METHODE I2C READ - TFA98XX                           ║

╠══════════════════════════════╦══════════════════════════════╦════════════════════════════╣

║  SMBus Byte                  ║  SMBus Word                  ║  Regmap Custom             ║

╠══════════════════════════════╬══════════════════════════════╬════════════════════════════╣

║                              ║                              ║                            ║

║  Func Name:                  ║  Func Name:                  ║  Func Name:                ║

║  i2c_smbus_read_byte_data()  ║  i2c_smbus_read_word_data()  ║  tfa98xx_regmap_read()     ║

║                              ║                              ║                            ║

╠══════════════════════════════╬══════════════════════════════╬════════════════════════════╣

║  PARAMS                      ║  PARAMS                      ║  PARAMS                    ║

║  ───────────────────────     ║  ───────────────────────     ║  ─────────────────────     ║

║  timing   = 0x0              ║  timing   = 0x0              ║  timing   = 0x0            ║

║  ext_flag = 0x0              ║  ext_flag = 0x0              ║  ext_flag = 0x0            ║

║  mode     = ST_MODE          ║  mode     = ST_MODE          ║  mode     = ST_MODE        ║

║  speed    = 100 KHz          ║  speed    = 100 KHz          ║  speed    = 100 KHz        ║

║  dma_en   = false            ║  dma_en   = false            ║  dma_en   = false          ║

║                              ║                              ║                            ║

╠══════════════════════════════╬══════════════════════════════╬════════════════════════════╣

║  TRANSFER                    ║  TRANSFER                    ║  TRANSFER                  ║

║  ───────────────────────     ║  ───────────────────────     ║  ─────────────────────     ║

║  Message : 1 (WRITE)         ║  Message : 1 (WRITE+READ)    ║  Message : 2 (WR + RD)     ║

║  Data    : 1 byte            ║  Data    : 2 byte            ║  Data    : 2 byte          ║

║  Protocol: SMBus             ║  Protocol: SMBus             ║  Protocol: I2C bare        ║

║                              ║                              ║                            ║

║  I2C Wire:                   ║  I2C Wire:                   ║  I2C Wire:                 ║

║  ┌──────────────────────┐    ║  ┌──────────────────────┐    ║  ┌──────────────────────┐  ║

║  │ S │ ADDR+W │ CMD │   │    ║  │ S │ ADDR+W │ CMD │   │    ║  │ S │ ADDR+W │ CMD │   │  ║

║  │   │        │0x03 │   │    ║  │   │        │0x03 │   │    ║  │   │        │0x03 │   │  ║

║  │   │ DATA_L │ STOP│   │    ║  │ Sr│ ADDR+R │     │   │    ║  │ Sr│ ADDR+R │     │   │  ║

║  │   │  0x00  │     │   │    ║  │   │ DATA_L │DTA_H│   │    ║  │   │ DATA_H │DTA_L│   │  ║

║  └──────────────────────┘    ║  │   │  0x00  │0x80 │   │    ║  │   │  0x00  │0x80 │   │  ║

║                              ║  │   │ STOP   │     │   │    ║  │   │ STOP   │     │   │  ║

║                              ║  └──────────────────────┘    ║  └──────────────────────┘  ║

║                              ║                              ║                            ║

╠══════════════════════════════╬══════════════════════════════╬════════════════════════════╣

║  Result                      ║  Result                      ║  Result                    ║

║  ───────────────────────     ║  ───────────────────────     ║  ─────────────────────     ║

║  Raw Data: 0x00              ║  Raw Data: 0x8000            ║  Raw Data: 0x00 0x80       ║

║  Value   : 0x00              ║  Value   : 0x8000            ║  Value   : 0x0080          ║

║                              ║                              ║                            ║

║  Only LOW byte               ║  Byte Order Swap             ║  HIGH=0x00, LOW=0x80       ║

║  8-bit                       ║                              ║  Revision = 0x80           ║

║                              ║                              ║  TFA9890 detected          ║

║                              ║                              ║                            ║

║                              ║                              ║                            ║

╠══════════════════════════════╩══════════════════════════════╩════════════════════════════╣

║                                                                                          ║

║  Result:                                                                                 ║

║  ──────────────────────────────────────────────────────────────────────────────────────  ║

║  SMBus Byte  = 8-bit, not enough for register 16-bit                                     ║

║  SMBus Word  = 16-bit byte order swap (little-endian vs big-endian)                      ║

║  Regmap Custom = 16-bit, byte order valid, flexible (support DMA, change speed)          ║

║                                                                                          ║

╚══════════════════════════════════════════════════════════════════════════════════════════╝



╔════════════════════════════════════════════════════════╗

║               COMPARE 3 METHODE READ 0x03                ║

╠══════════════════════╦═══════════════════════════════════╣

║ SMBus byte           ║ 0x00        Only 1 byte           ║

║ SMBus word           ║ 0x8000      Byte order swap       ║

║ Regmap Custom        ║ 0x0080      Valid                 ║

╚══════════════════════╩═══════════════════════════════════╝

### 最终结果([最终日志](./console-ramoops_DEV_Final_Log))。

通过以下方式成功解决了 TFA98XX 驱动集成问题:

1. **修复不兼容的 I2C 结构体** - 通过正确初始化 `timing` 和 `ext_flag` 字段,将标准 Linux `struct i2c_msg`(12 字节)适配为 Mediatek 的 `struct mt_i2c_msg`(24 字节),消除了导致“速度过快”错误的垃圾数据。
2. **探测芯片** - 在总线 0 上的 I2C 地址 0x35 处检测到 TFA9890 版本 0x80。
3. **固件安装** - 成功加载容器固件 `tfa98xx.cnt`(4761 字节),注册了 DSP 实例(句柄 0),并创建了 3 个音频配置文件:
- MUSIC_44100 (44.1 kHz)
- MUSIC_48000 (48 kHz)
- VOICE_16000 (16 kHz)

尚未进行音频播放测试。后续更新待定。
标签:ALSA, DSP固件, I2C通信, Linux驱动, MediaTek, 安全渗透, 音频放大器