主题 : Tiny210v2( S5PV210 )平台下理解ALSA框架: 编写WM8960驱动 复制链接 | 浏览器收藏 | 打印
级别: 骑士
UID: 5844
精华: 9
发帖: 64
金钱: 770 两
威望: 154 点
贡献值: 9 点
综合积分: 308 分
注册时间: 2009-05-11
最后登录: 2019-05-14
楼主  发表于: 2012-12-20 20:29

 Tiny210v2( S5PV210 )平台下理解ALSA框架: 编写WM8960驱动

管理提醒: 本帖被 xoom 执行加亮操作(2012-12-21)
    1. 内核配置文件
    2. 源文件的编译过程
    3. 源文件的功能说明
    4. wm8960.c
    5. mini210_wm8960.c
    6. 附加:用于逆向解析的内核LOG ( 第1次更新)
    7. 附加:反汇编完成的 mini210_wm8960.c ( 第2次更新)
    8. 附加:wm8960 驱动最终版 ( 第3次更新)


    为了在用户空间验证PCM数据的流向,我编写了一个简单的程序用于播放WAV文件。
    但由于我使用的是自己的内核配置文件,而TINY210v2光盘中Android 4的rootfs目录中的声音驱动是二进制文件,并且在我的环境中不能够正常工作。

    因此编写的那个程序无法运行,连基本的设备文件都打不开。

    于是就通过逆向工程写了一个WM8960的驱动,这个驱动基本上在初始化的过程中能够和光盘中那个驱动保持一直的LOG输出。
    将这个驱动编译好了以后,替换掉Android 4的/system/lib/modules/3.0.8-FriendlyARM/kernel/sound/soc/s5pv2xxx目录中的 snd-soc-mini210-wm8960.ko 和 snd-soc-wm8960.ko 两个驱动以后,Android 4重启以后能够出声。
    
    一共要编写两个文件 wm8960.c 和 mini210_wm8960.c。
    wm8960.c 这个文件拷贝自 linux-3.0.8/sound/soc/codecs/wm8960.*,感觉完成度比较高。
    mini210_wm8960.c 大部分通过逆向工程得到的代码结构,在 hw_params 的函数还没全部处理完。

    因此,目前的这个驱动,还只是可以替换掉原来的驱动完成最基本的播放。(可能只能播放固定采样率的文件)
    
    如果想要将这个驱动完善,还需要看 wm8960 和 s5pv210 的 datasheet,以及查看电路链接,从而确认 wm8960 的控制参数应该如何设置。
    在这里先将这个半罐子水的驱动公开出来,如果有了解这个部分的,可以直接回复,或者你自己修改好了直接公布出来。


1. 内核配置文件

    将 mini210_android_defconfig 这个文件拷贝到同目录中的 .config ,然后 make menuconfig。
复制代码
  1.     Device Drivers
  2.         -> Sound card support
  3.             -> Advanced Linux Sound Architecture
  4.                 -> ALSA for SoC audio support

    可以看到
            <*> Samsung S5P Audio Drivers
            <*> SoC I2S Audio support for WM8960 on MINI210

    这两个选项被选中了。

    查看 linux-3.0.8/sound/soc/s5pv2xx 的 Kconfig 文件,可以看到:
    
    <*> Samsung S5P Audio Drivers 会让下面的宏有效:

复制代码
  1.         CONFIG_SND_S5PV2XX_SOC


    <*> SoC I2S Audio support for WM8960 on MINI210 会让下面的宏有效:
复制代码
  1.         CONFIG_SND_S5PV2XX_SOC_WM8960
  2.         CONFIG_SND_S5PC1XX_I2S
  3.         CONFIG_SND_SOC_WM8960_MINI210

    
    再查看 linux-3.0.8/sound/soc 下面的 Makefile,会发现如下开关:
复制代码
  1.         ifneq ($(CONFIG_SND_S5PV2XX_SOC),)
  2.         obj-$(CONFIG_SND_SOC)   += s5pv2xx/
  3.         else
  4.         obj-$(CONFIG_SND_SOC)   += samsung/
  5.         endif


    这也就是说,如果选择了 Samsung S5P Audio Drivers ,
    那么内核会去编译 linux-3.0.8/sound/soc/s5pv2xx 下面的文件。
    否则会编译 linux-3.0.8/sound/soc/samsung 下面的文件。
    
    也就是说我们只需要关注 linux-3.0.8/sound/soc/s5pv2xx 目录下的文件了。


2. 源文件的编译过程
        
    接下来我们继续确认 linux-3.0.8/sound/soc/s5pv2xx 的 Makefile 文件,可以看到:

复制代码
  1.         # Samsung Platform Support
  2.         snd-soc-s5pv2xx-objs := dma.o
  3.         snd-soc-s5pc1xx-i2s-objs := s5pc1xx-i2s.o
  4.         snd-soc-s5p-idma-objs := ss3c-dma-wrapper.o 3c-idma.o s5p-i2s_sec.o
  5.         
  6.         obj-$(CONFIG_SND_S5PV2XX_SOC) += snd-soc-s5pv2xx.o
  7.         obj-$(CONFIG_SND_S5PC1XX_I2S) += snd-soc-s5pc1xx-i2s.o
  8.         obj-$(CONFIG_S5P_INTERNAL_DMA) += snd-soc-s5p-idma.o
  9.         
  10.         # Codec support
  11.          snd-soc-wm8960-objs := wm8960.o
  12.         
  13.         ifneq ($(wildcard sound/soc/s5pv2xx/wm8960.c),)
  14.         ifeq ($(FA),1)
  15.         obj-$(CONFIG_SND_SOC_WM8960_MINI210) += snd-soc-wm8960.o
  16.         else
  17.         obj-m += snd-soc-wm8960.o
  18.         endif  #FA
  19.         endif
  20.         
  21.         # S5PV2XX Machine Support
  22.         snd-soc-mini210-wm8960-objs := mini210_wm8960.o
  23.         
  24.         ifneq ($(wildcard sound/soc/s5pv2xx/mini210_wm8960.c),)
  25.         ifeq ($(FA),1)
  26.         obj-$(CONFIG_SND_S5PV2XX_SOC_WM8960) += snd-soc-mini210-wm8960.o
  27.         else
  28.         obj-m += snd-soc-mini210-wm8960.o
  29.         endif  #FA
  30.         endif

    这里特别关注一下 wm8960 字样,大意是说如果有 wm8960.c 以及 mini210_wm8960.c 的话,就将他们编译成模块。
    但 TINY210v2 的光盘中,linux-3.0.8 没有提供这两个源代码,因此我们需要编写这两个文件。
    
    我新创建了这两个文件,但是是空文件,通过 make V=1 编译内核,看看内核的编译过程:


复制代码
  1.         make -f scripts/Makefile.build obj=sound/soc/s5pv2xx
  2.           arm-linux-gcc  -c -o sound/soc/s5pv2xx/s5pc1xx-i2s.o sound/soc/s5pv2xx/s5pc1xx-i2s.c
  3.           arm-linux-gcc  -c -o sound/soc/s5pv2xx/dma.o sound/soc/s5pv2xx/dma.c
  4.           arm-linux-ld -EL -r -o sound/soc/s5pv2xx/snd-soc-s5pv2xx.o sound/soc/s5pv2xx/dma.o
  5.           arm-linux-ld -EL -r -o sound/soc/s5pv2xx/snd-soc-s5pc1xx-i2s.o sound/soc/s5pv2xx/s5pc1xx-i2s.o
  6.           arm-linux-ld -EL -r -o sound/soc/s5pv2xx/built-in.o sound/soc/s5pv2xx/snd-soc-s5pv2xx.o sound/soc/s5pv2xx/snd-soc-s5pc1xx-i2s.o
  7.         
  8.           arm-linux-gcc  -c -o sound/soc/s5pv2xx/mini210_wm8960.o sound/soc/s5pv2xx/mini210_wm8960.c
  9.           arm-linux-gcc  -c -o sound/soc/s5pv2xx/wm8960.o sound/soc/s5pv2xx/wm8960.c
  10.           arm-linux-ld -EL    -r -o sound/soc/s5pv2xx/snd-soc-wm8960.o sound/soc/s5pv2xx/wm8960.o
  11.           arm-linux-ld -EL    -r -o sound/soc/s5pv2xx/snd-soc-mini210-wm8960.o sound/soc/s5pv2xx/mini210_wm8960.o
  12.         
  13.         (cat /dev/null;   echo kernel/sound/soc/s5pv2xx/snd-soc-wm8960.ko;   echo kernel/sound/soc/s5pv2xx/snd-soc-mini210-wm8960.ko;) > sound/soc/s5pv2xx/modules.order
  14.         
  15.           arm-linux-gcc -c -o sound/soc/s5pv2xx/snd-soc-mini210-wm8960.mod.o sound/soc/s5pv2xx/snd-soc-mini210-wm8960.mod.c
  16.           arm-linux-ld  -o sound/soc/s5pv2xx/snd-soc-mini210-wm8960.ko sound/soc/s5pv2xx/snd-soc-mini210-wm8960.o sound/soc/s5pv2xx/snd-soc-mini210-wm8960.mod.o
  17.           arm-linux-gcc -c -o sound/soc/s5pv2xx/snd-soc-wm8960.mod.o sound/soc/s5pv2xx/snd-soc-wm8960.mod.c
  18.           arm-linux-ld -o sound/soc/s5pv2xx/snd-soc-wm8960.ko sound/soc/s5pv2xx/snd-soc-wm8960.o sound/soc/s5pv2xx/snd-soc-wm8960.mod.o


    大致意思是说:
    s5pc1xx-i2s.c  --> s5pc1xx-i2s.o --> snd-soc-s5pc1xx-i2s.o --> built-in.o --> zImage
    dma.c --> dma.o --> snd-soc-s5pv2xx.o --> built-in.o --> zImage

    mini210_wm8960.c --> mini210_wm8960.o --> snd-soc-mini210-wm8960.o --> snd-soc-mini210-wm8960.ko
    wm8960.c --> wm8960.o --> snd-soc-wm8960.o --> snd-soc-wm8960.ko

    因此我们只需要关注 dma.c / s5pc1xx-i2s.c / wm8960.c / mini210_wm8960.c 这 4个文件以及相关的头文件就可以了。


3. 源文件的功能说明

    目前还没有完全解析,这里只概要说明一下大致功能,以后补充 。 TBD
    
    dma.c : CPU 测主动控制的 dma 用于搬运声音数据(PCM DATA ?),(我觉得这个可能需要和 CONFIG_S5P_INTERNAL_DMA 区分开,这个可能是 Audio Subsystem 用自己的 dma )
    s5pc1xx-i2s.c : TBD
    wm8960.c : TBD 通过 i2c 控制 wm8960 芯片的所有实现,这里面还包含了 wm8960 在ALSA 的抽象实现。
    mini210_wm8960.c : TBD 实现 ALSA card 抽象的实现,还包括对 wm8960 的设置部分也在这里,这个代码需要关注一下  soc-audio。
[ 此帖被happyzlz在2012-12-29 22:20重新编辑 ]
级别: 侠客
UID: 17217
精华: 0
发帖: 77
金钱: 390 两
威望: 78 点
贡献值: 0 点
综合积分: 154 分
注册时间: 2010-03-26
最后登录: 2017-11-10
1楼  发表于: 2012-12-23 20:30

 回 5楼(victorlinwen) 的帖子

.codec_name = "wm8960-codec.0-001a"  是codec->dai->name + i2c设备名称。一般是在codec.c即wm8960.c,i2c设备名称 = adapter(i2c adapter 0)+7bit地址(2字节格式输出。即001a).具体的科研soc-core.c