主题 : Tiny210v2( S5PV210 )平台下理解ALSA框架: 编写WM8960驱动 复制链接 | 浏览器收藏 | 打印
级别: 骑士
UID: 5844
精华: 9
发帖: 62
金钱: 760 两
威望: 152 点
贡献值: 9 点
综合积分: 304 分
注册时间: 2009-05-11
最后登录: 2016-11-28
楼主  发表于: 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: 5844
精华: 9
发帖: 62
金钱: 760 两
威望: 152 点
贡献值: 9 点
综合积分: 304 分
注册时间: 2009-05-11
最后登录: 2016-11-28
1楼  发表于: 2012-12-20 20:34
4. wm8960.c

    wm8960.c 和 wm8960.h 因为是对 wm8960 芯片的控制,除了 i2c 需要使用 platform 资源以后,其他部分非常独立。在后来的确认中,发现 wm8960.c 直接从 linux-3.0.8/sound/soc/codecs 拷贝过来就可以,基本没有变动。

代码放不到帖子里面,做成附件吧。



5. mini210_wm8960.c

    mini210_wm8960.c 主要是通过逆向解析 Android 4 的 rootfs 附带的 snd-soc-mini210-wm8960.ko 解析得来的。
    正常的步骤应该是看 datasheet ,并结合 Tiny210v2 的硬件连接情况进行编写。

    解析的方法为:
    A 通过arm-linux-objdump -d 反汇编 snd-soc-mini210-wm8960.ko ,查看它内部都有哪些函数,以及调用过哪些外部函数。
        内部函数,可以通过对比内核中其他文件的实现,主要通过查找 soc-audio 这个关键字。
        调用的外部函数比较少,大概就是这么几个:
            snd_soc_dai_set_fmt
            snd_soc_dai_set_sysclk
            snd_soc_codec_set_sysclk
            snd_soc_dai_set_clkdiv
            snd_soc_dapm_new_controls
            snd_soc_dapm_add_routes
            snd_soc_dapm_nc_pin
            snd_soc_dapm_disable_pin
            snd_soc_dapm_enable_pin

    B 在内核源代码中,针对上面的函数添加 log 打印出来 传递的参数是什么。
    C 用新的内核启动 Android 4,查看 wm8960 相关驱动的 LOG。
    D 结合 LOG 以及 反汇编 Android 4 的 wm8960 的驱动,尝试复原 wm8960 驱动源代码。
    E 当驱动源代码复原差不多的时候,将其编译成 ko,并替换掉 Android 4 的 wm8960 驱动进行确认。
    F 反复重复上面过程。。。

    下面是 未完全 好用的 mini210_wm8960.c :


复制代码
  1.         /*
  2.          * mini_wm8960.c  --  WM8960 ALSA SoC Audio driver
  3.          *
  4.          * Author: happyzlz
  5.          *
  6.          * This program is free software; you can redistribute it and/or modify
  7.          * it under the terms of the GNU General Public License version 2 as
  8.          * published by the Free Software Foundation.
  9.          */
  10.         
  11.         #include <sound/soc.h>
  12.         #include "s5pc1xx-i2s.h"
  13.         #include "wm8960.h"
  14.         
  15.         
  16.         #define    CDCLK                    0x002
  17.         #define    CLKAUDIO                0x400
  18.         
  19.         
  20.         static struct snd_soc_card mini210_soc_card;
  21.         
  22.         static int mini210_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  23.         {
  24.             struct snd_soc_pcm_runtime *rtd = substream->private_data;
  25.             struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  26.             struct snd_soc_dai *codec_dai = rtd->codec_dai;
  27.             unsigned int pll_out;
  28.             int    ret;
  29.         
  30.             /* FIXME */
  31.             /* some value for setting should be checked from *params */
  32.             pll_out = 0;
  33.         
  34.             ret = snd_soc_dai_set_fmt( codec_dai, SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF|SND_SOC_DAIFMT_CBS_CFS );
  35.             if( ret < 0 ){
  36.                 printk( "%s: Codec DAI configuration error, %d\n", codec_dai->name, ret );
  37.                 return ret;
  38.             }
  39.         
  40.             ret = snd_soc_dai_set_fmt( cpu_dai, SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF|SND_SOC_DAIFMT_CBS_CFS );
  41.             if( ret < 0 ){
  42.                 printk( "%s: AP DAI configuration error, %d\n", cpu_dai->name, ret );
  43.                 return ret;
  44.             }
  45.         
  46.             /* FIXME */
  47.             ret = snd_soc_dai_set_sysclk( cpu_dai, CDCLK, 44100, SND_SOC_CLOCK_OUT );
  48.             if( ret < 0 ){
  49.                 printk( "%s: AP sycclk CDCLK setting error, %d\n", cpu_dai->name, ret );
  50.                 return ret;
  51.             }
  52.         
  53.             /* FIXME */
  54.             ret = snd_soc_dai_set_sysclk( cpu_dai, CLKAUDIO, 44100, SND_SOC_CLOCK_OUT );
  55.             if( ret < 0 ){
  56.                 printk( "%s: AP sysclk CLKAUDIO setting error, %d\n", cpu_dai->name, ret );
  57.                 return ret;
  58.             }
  59.             
  60.             /* FIXME */
  61.             ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_SYSCLKDIV, WM8960_SYSCLK_DIV_1 );
  62.             if( ret < 0 ){
  63.                 printk( "%s: Codec SYSCLKDIV setting error, %d\n", codec_dai->name, ret );
  64.                 return ret;
  65.             }
  66.             
  67.             /* FIXME */
  68.             ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_DACDIV, WM8960_DAC_DIV_1  );
  69.             if( ret < 0 ){
  70.                 printk( "%s: Codec DACDIV setting error, %d\n", codec_dai->name, ret );
  71.                 return ret;
  72.             }
  73.             
  74.             /* FIXME */
  75.             ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_DCLKDIV, 11289600  );
  76.             if( ret < 0 ){
  77.                 printk( "%s: Codec DCLKDIV setting error, %d\n", codec_dai->name, ret );
  78.                 return ret;
  79.             }
  80.             
  81.             /* FIXME */
  82.             ret = snd_soc_dai_set_clkdiv( cpu_dai, S3C64XX_DIV_PRESCALER, 5 );
  83.             if( ret < 0 ){
  84.                 printk( "%s: AP prescalar setting error, %d\n", cpu_dai->name, ret );
  85.                 return ret;
  86.             }
  87.         
  88.             /* FIXME */
  89.             ret = snd_soc_dai_set_clkdiv( cpu_dai, S3C64XX_DIV_RCLK, 256 );
  90.             if( ret < 0 ){
  91.                 printk( "%s: AP RFS setting error, %d\n", cpu_dai->name, ret );
  92.                 return ret;
  93.             }
  94.         
  95.             ret = snd_soc_dai_set_clkdiv( cpu_dai, S3C64XX_DIV_BCLK, 32 );
  96.             if( ret < 0 ){
  97.                 printk( "%s: AP BFS setting error, %d\n", cpu_dai->name, ret );
  98.                 return ret;
  99.             }
  100.         
  101.             return 0;
  102.         }
  103.         
  104.         static struct snd_soc_ops mini210_wm8960_ops = {
  105.             .hw_params = mini210_hw_params,
  106.         };
  107.         
  108.         static const struct snd_soc_dapm_widget mini210_dapm_capture_widgets[] = {
  109.             SND_SOC_DAPM_MIC(    "Mic Jack",            NULL ),
  110.             SND_SOC_DAPM_LINE(    "Line Input 3 (FM)",NULL ),
  111.         };
  112.         
  113.         static const struct snd_soc_dapm_widget mini210_dapm_playback_widgets[] = {
  114.             SND_SOC_DAPM_HP(    "Headphone Jack",    NULL ),
  115.             SND_SOC_DAPM_SPK(    "Speaker_L",        NULL ),
  116.             SND_SOC_DAPM_SPK(    "Speaker_R",        NULL ),
  117.         };
  118.         
  119.         static const struct snd_soc_dapm_route mini210_audio_map[] = {
  120.             { "Headphone Jack",    NULL,    "HP_L"        },
  121.             { "Headphone Jack",    NULL,     "HP_R"        },
  122.             { "Speaker_L",        NULL,     "SPK_LP"    },
  123.             { "Speaker_L",        NULL,     "SPK_LN"     },
  124.             { "Speaker_R",        NULL,     "SPK_RP"     },
  125.             { "Speaker_R",        NULL,     "SPK_RN"     },
  126.             { "LINPUT1",        NULL,     "MICB"        },
  127.             { "MICB",            NULL,     "Mic Jack"    },
  128.         };
  129.         
  130.         static int mini210_wm8960_init(struct snd_soc_pcm_runtime *rtd)
  131.         {
  132.             struct snd_soc_codec *codec = rtd->codec;
  133.             struct snd_soc_dapm_context *dapm = &codec->dapm;
  134.         
  135.             snd_soc_dapm_nc_pin(dapm, "RINPUT1");
  136.             snd_soc_dapm_nc_pin(dapm, "LINPUT2");
  137.             snd_soc_dapm_nc_pin(dapm, "RINPUT2");
  138.             snd_soc_dapm_nc_pin(dapm, "OUT3");
  139.             
  140.             snd_soc_dapm_new_controls( dapm, mini210_dapm_capture_widgets, ARRAY_SIZE( mini210_dapm_capture_widgets ) );
  141.             snd_soc_dapm_new_controls( dapm, mini210_dapm_playback_widgets, ARRAY_SIZE( mini210_dapm_playback_widgets ) );
  142.         
  143.             snd_soc_dapm_add_routes( dapm, mini210_audio_map, ARRAY_SIZE( mini210_audio_map ) );
  144.         
  145.             snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
  146.             snd_soc_dapm_enable_pin(dapm, "Mic Jack");
  147.             snd_soc_dapm_enable_pin(dapm, "Speaker_L");
  148.             snd_soc_dapm_enable_pin(dapm, "Speaker_R");
  149.             
  150.             snd_soc_dapm_disable_pin(dapm, "Line Input 3 (FM)");
  151.         
  152.             snd_soc_dapm_sync( dapm );
  153.         
  154.             return 0;
  155.         }
  156.         
  157.         static struct snd_soc_dai_link mini210_dai = {
  158.             .name = "MINI210",
  159.             .stream_name = "WM8960 HiFi",
  160.             .codec_name = "wm8960-codec.0-001a",
  161.             .platform_name = "samsung-audio",
  162.             .cpu_dai_name = "samsung-i2s.0",
  163.             .codec_dai_name = "wm8960-hifi",
  164.             .init = mini210_wm8960_init,
  165.             .ops = &mini210_wm8960_ops,
  166.         };
  167.         
  168.         static struct snd_soc_card mini210_soc_card = {
  169.             .name = "mini210",
  170.             .dai_link = &mini210_dai,
  171.             .num_links = 1,
  172.         };
  173.         
  174.         static struct platform_device *mini210_snd_device;
  175.         
  176.         static int __init mini210_audio_init(void)
  177.         {
  178.             int ret;
  179.         
  180.             mini210_snd_device = platform_device_alloc("soc-audio", -1);
  181.             if ( !mini210_snd_device ){
  182.                 return -ENOMEM;
  183.             }
  184.         
  185.             platform_set_drvdata( mini210_snd_device, &mini210_soc_card );
  186.         
  187.             ret = platform_device_add( mini210_snd_device );
  188.             if( ret ){
  189.                 platform_device_put( mini210_snd_device );
  190.             }
  191.         
  192.             return ret;
  193.         }
  194.         
  195.         static void __exit mini210_audio_exit(void)
  196.         {
  197.             platform_device_unregister( mini210_snd_device );
  198.         }
  199.         
  200.         
  201.         module_init( mini210_audio_init );
  202.         module_exit( mini210_audio_exit );
  203.         
  204.         MODULE_AUTHOR("zoulz, happyzlz@sohu.com");
  205.         MODULE_DESCRIPTION("ALSA SoC TINY210v2+WM8960");
  206.         MODULE_LICENSE("GPL");




6. 附加:用于逆向解析的内核LOG

    下面是 Andoird 4 的 wm8960 驱动在我的内核下的 debug log, 因为 Android 4 的默认内核是没有 debug log的。

复制代码
  1.         # insmod  ./snd-soc-mini210-wm8960.ko
  2.         [   39.536162] soc-audio soc-audio: binding <乱码> at idx 0
  3.         [   39.536220] wm8960-codec 0-001a: Initializing flat cache for wm8960-codec.0-001a codec
  4.         [   39.536334] soc-audio soc-audio: probe mini210 dai link 0
  5.         [   39.536415] write f = 0
  6.         [   39.536581] write 1c = 9c
  7.         [   39.545002] read 19 => 0
  8.         [   39.545103] write 19 = 80
  9.         [   39.654707] write 19 = c0
  10.         [   39.654867] write 1c = 8
  11.         [   39.655020] read 19 => c0
  12.         [   39.655060] write 19 = 140
  13.         [   39.655213] read 0 => 97
  14.         [   39.655253] write 0 = 197
  15.         [   39.659007] read 1 => 97
  16.         [   39.663223] write 1 = 197
  17.         [   39.667754] read 15 => c3
  18.         [   39.672061] write 15 = 1c3
  19.         [   39.676755] read 16 => c3
  20.         [   39.680988] write 16 = 1c3
  21.         [   39.685606] read a => ff
  22.         [   39.689827] write a = 1ff
  23.         [   39.694361] read b => ff
  24.         [   39.698578] write b = 1ff
  25.         [   39.703111] read 2 => 0
  26.         [   39.707244] write 2 = 100
  27.         [   39.711779] read 3 => 0
  28.         [   39.715910] write 3 = 100
  29.         [   39.720440] read 28 => 0
  30.         [   39.724664] write 28 = 100
  31.         [   39.729283] read 29 => 0
  32.         [   39.733606] write 29 = 100
  33.         [   39.738119] write 9 = 40
  34.         
  35.         wm8960_probe->snd_soc_add_controls(codec, wm8960_snd_controls, ARRAY_SIZE(wm8960_snd_controls));
  36.         ==================================================
  37.         [   39.742456] ALSA: snd_soc_add_controls( codec dbf53600, controls bf000f88, num_controls 36 )
  38.         [   39.752571] ALSA: snd_ctl_add( Input Volume )
  39.         [   39.759939] ALSA: snd_ctl_add( Input Volume ZC Switch )
  40.         [   39.768171] ALSA: snd_ctl_add( Input Switch )
  41.         [   39.775532] ALSA: snd_ctl_add( Playback Volume )
  42.         [   39.783161] ALSA: snd_ctl_add( Headphone Playback Volume )
  43.         [   39.791651] ALSA: snd_ctl_add( Headphone Playback ZC Switch )
  44.         [   39.800406] ALSA: snd_ctl_add( Speaker Playback Volume )
  45.         [   39.808722] ALSA: snd_ctl_add( Speaker Playback ZC Switch )
  46.         [   39.817305] ALSA: snd_ctl_add( Speaker DC Volume )
  47.         [   39.825101] ALSA: snd_ctl_add( Speaker AC Volume )
  48.         [   39.833002] ALSA: snd_ctl_add( PCM Playback -6dB Switch )
  49.         [   39.841309] ALSA: snd_ctl_add( ADC Polarity )
  50.         [   39.848671] ALSA: snd_ctl_add( Playback De-emphasis )
  51.         [   39.856734] ALSA: snd_ctl_add( DAC Deemphasis Switch )
  52.         [   39.864877] ALSA: snd_ctl_add( ADC High Pass Filter Switch )
  53.         [   39.873547] ALSA: snd_ctl_add( DAC Polarity )
  54.         [   39.880908] ALSA: snd_ctl_add( 3D Filter Upper Cut-Off )
  55.         [   39.889230] ALSA: snd_ctl_add( 3D Filter Lower Cut-Off )
  56.         [   39.897546] ALSA: snd_ctl_add( 3D Volume )
  57.         [   39.904656] ALSA: snd_ctl_add( 3D Switch )
  58.         [   39.911759] ALSA: snd_ctl_add( ALC Function )
  59.         [   39.919125] ALSA: snd_ctl_add( ALC Max Gain )
  60.         [   39.926494] ALSA: snd_ctl_add( ALC Target )
  61.         [   39.933788] ALSA: snd_ctl_add( ALC Min Gain )
  62.         [   39.941052] ALSA: snd_ctl_add( ALC Hold Time )
  63.         [   39.948502] ALSA: snd_ctl_add( ALC Mode )
  64.         [   39.955522] ALSA: snd_ctl_add( ALC Decay )
  65.         [   39.962629] ALSA: snd_ctl_add( ALC Attack )
  66.         [   39.969820] ALSA: snd_ctl_add( Noise Gate Threshold )
  67.         [   39.977882] ALSA: snd_ctl_add( Noise Gate Switch )
  68.         [   39.985678] ALSA: snd_ctl_add( Capture Volume )
  69.         [   39.993220] ALSA: snd_ctl_add( MIC Boost Gain )
  70.         [   40.000757] ALSA: snd_ctl_add( Left Output Mixer Boost Bypass Volume )
  71.         [   40.010293] ALSA: snd_ctl_add( Left Output Mixer LINPUT3 Volume )
  72.         [   40.019389] ALSA: snd_ctl_add( Right Output Mixer Boost Bypass Volume )
  73.         [   40.029010] ALSA: snd_ctl_add( Right Output Mixer RINPUT3 Volume )
  74.         
  75.         wm8960_add_widgets->snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets, ARRAY_SIZE(wm8960_dapm_widgets));
  76.         ==================================================
  77.         [   40.038304] ALSA: snd_soc_dapm_new_controls( dapm dbf536cc, widget bf001648, num 30 )
  78.         [   40.047812] ALSA: snd_soc_dapm_new_control( LINPUT1 )
  79.         [   40.057085] ALSA: snd_soc_dapm_new_control( RINPUT1 )
  80.         [   40.066358] ALSA: snd_soc_dapm_new_control( LINPUT2 )
  81.         [   40.075629] ALSA: snd_soc_dapm_new_control( RINPUT2 )
  82.         [   40.084902] ALSA: snd_soc_dapm_new_control( LINPUT3 )
  83.         [   40.094172] ALSA: snd_soc_dapm_new_control( RINPUT3 )
  84.         [   40.103448] ALSA: snd_soc_dapm_new_control( MICB )
  85.         [   40.112459] ALSA: snd_soc_dapm_new_control( Left Input Mixer )
  86.         [   40.122512] ALSA: snd_soc_dapm_new_control( Right Input Mixer )
  87.         [   40.132651] ALSA: snd_soc_dapm_new_control( Left Boost Mixer )
  88.         [   40.142812] ALSA: snd_soc_dapm_new_control( Right Boost Mixer )
  89.         [   40.152843] ALSA: snd_soc_dapm_new_control( Left ADC )
  90.         [   40.162200] ALSA: snd_soc_dapm_new_control( Right ADC )
  91.         [   40.171647] ALSA: snd_soc_dapm_new_control( Left DAC )
  92.         [   40.181003] ALSA: snd_soc_dapm_new_control( Right DAC )
  93.         [   40.190451] ALSA: snd_soc_dapm_new_control( Left Output Mixer )
  94.         [   40.200588] ALSA: snd_soc_dapm_new_control( Right Output Mixer )
  95.         [   40.210818] ALSA: snd_soc_dapm_new_control( LOUT1 PGA )
  96.         [   40.220262] ALSA: snd_soc_dapm_new_control( ROUT1 PGA )
  97.         [   40.229705] ALSA: snd_soc_dapm_new_control( Left Speaker PGA )
  98.         [   40.239862] ALSA: snd_soc_dapm_new_control( Right Speaker PGA )
  99.         [   40.249896] ALSA: snd_soc_dapm_new_control( Right Speaker Output )
  100.         [   40.260299] ALSA: snd_soc_dapm_new_control( Left Speaker Output )
  101.         [   40.270608] ALSA: snd_soc_dapm_new_control( SPK_LP )
  102.         [   40.279796] ALSA: snd_soc_dapm_new_control( SPK_LN )
  103.         [   40.288981] ALSA: snd_soc_dapm_new_control( HP_L )
  104.         [   40.297991] ALSA: snd_soc_dapm_new_control( HP_R )
  105.         [   40.307007] ALSA: snd_soc_dapm_new_control( SPK_RP )
  106.         [   40.316189] ALSA: snd_soc_dapm_new_control( SPK_RN )
  107.         [   40.325378] ALSA: snd_soc_dapm_new_control( OUT3 )
  108.         
  109.         wm8960_add_widgets->snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
  110.         ==================================================
  111.         [   40.334490] ALSA: snd_soc_dapm_add_routes( dapm dbf536cc, route bf0022f0, num 34 )
  112.         [   40.343752] ALSA: snd_soc_dapm_add_route: { "Left Input Mixer", "LINPUT1 Switch", "LINPUT1" },
  113.         [   40.354153] read 20 => 100
  114.         [   40.358655] ALSA: snd_soc_dapm_add_route: { "Left Input Mixer", "LINPUT2 Switch", "LINPUT2" },
  115.         [   40.369054] read 20 => 100
  116.         [   40.373557] ALSA: snd_soc_dapm_add_route: { "Left Input Mixer", "LINPUT3 Switch", "LINPUT3" },
  117.         [   40.383961] read 20 => 100
  118.         [   40.388462] ALSA: snd_soc_dapm_add_route: { "Left Boost Mixer", "Boost Switch", "Left Input Mixer" },
  119.         [   40.399473] read 20 => 100
  120.         [   40.403974] ALSA: snd_soc_dapm_add_route: { "Left Boost Mixer", NULL,"LINPUT1" },
  121.         [   40.413252] ALSA: snd_soc_dapm_add_route: { "Left Boost Mixer", NULL,"LINPUT2" },
  122.         [   40.422520] ALSA: snd_soc_dapm_add_route: { "Left Boost Mixer", NULL,"LINPUT3" },
  123.         [   40.431796] ALSA: snd_soc_dapm_add_route: { "Right Input Mixer", "RINPUT1 Switch", "RINPUT1" },
  124.         [   40.442392] read 21 => 100
  125.         [   40.446785] ALSA: snd_soc_dapm_add_route: { "Right Input Mixer", "RINPUT2 Switch", "RINPUT2" },
  126.         [   40.457271] read 21 => 100
  127.         [   40.461775] ALSA: snd_soc_dapm_add_route: { "Right Input Mixer", "RINPUT3 Switch", "RINPUT3" },
  128.         [   40.472265] read 21 => 100
  129.         [   40.476766] ALSA: snd_soc_dapm_add_route: { "Right Boost Mixer", "Boost Switch", "Right Input Mixer" },
  130.         [   40.487950] read 21 => 100
  131.         [   40.492450] ALSA: snd_soc_dapm_add_route: { "Right Boost Mixer", NULL,"RINPUT1" },
  132.         [   40.501815] ALSA: snd_soc_dapm_add_route: { "Right Boost Mixer", NULL,"RINPUT2" },
  133.         [   40.511172] ALSA: snd_soc_dapm_add_route: { "Right Boost Mixer", NULL,"LINPUT3" },
  134.         [   40.525827] ALSA: snd_soc_dapm_add_route: { "Left ADC", NULL,"Left Boost Mixer" },
  135.         [   40.533606] ALSA: snd_soc_dapm_add_route: { "Right ADC", NULL,"Right Boost Mixer" },
  136.         [   40.545265] ALSA: snd_soc_dapm_add_route: { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
  137.         [   40.553145] read 22 => 50
  138.         [   40.554317] ALSA: snd_soc_dapm_add_route: { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer" },
  139.         [   40.572071] read 2d => 50
  140.         [   40.572115] ALSA: snd_soc_dapm_add_route: { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
  141.         [   40.581453] read 22 => 50
  142.         [   40.585872] ALSA: snd_soc_dapm_add_route: { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
  143.         [   40.596444] read 25 => 50
  144.         [   40.600860] ALSA: snd_soc_dapm_add_route: { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" },
  145.         [   40.612738] read 2e => 50
  146.         [   40.617152] ALSA: snd_soc_dapm_add_route: { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
  147.         [   40.628335] read 25 => 50
  148.         [   40.632749] ALSA: snd_soc_dapm_add_route: { "LOUT1 PGA", NULL,"Left Output Mixer" },
  149.         [   40.642395] ALSA: snd_soc_dapm_add_route: { "ROUT1 PGA", NULL,"Right Output Mixer" },
  150.         [   40.651904] ALSA: snd_soc_dapm_add_route: { "HP_L", NULL,"LOUT1 PGA" },
  151.         [   40.660312] ALSA: snd_soc_dapm_add_route: { "HP_R", NULL,"ROUT1 PGA" },
  152.         [   40.668715] ALSA: snd_soc_dapm_add_route: { "Left Speaker PGA", NULL,"Left Output Mixer" },
  153.         [   40.678900] ALSA: snd_soc_dapm_add_route: { "Right Speaker PGA", NULL,"Right Output Mixer" },
  154.         [   40.689168] ALSA: snd_soc_dapm_add_route: { "Left Speaker Output", NULL,"Left Speaker PGA" },
  155.         [   40.699481] ALSA: snd_soc_dapm_add_route: { "Right Speaker Output", NULL,"Right Speaker PGA" },
  156.         [   40.709967] ALSA: snd_soc_dapm_add_route: { "SPK_LN", NULL,"Left Speaker Output" },
  157.         [   40.719410] ALSA: snd_soc_dapm_add_route: { "SPK_LP", NULL,"Left Speaker Output" },
  158.         [   40.728858] ALSA: snd_soc_dapm_add_route: { "SPK_RN", NULL,"Right Speaker Output" },
  159.         [   40.738486] ALSA: snd_soc_dapm_add_route: { "SPK_RP", NULL,"Right Speaker Output" },
  160.         
  161.         wm8960_add_widgets->snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets_out3, ARRAY_SIZE(wm8960_dapm_widgets_out3));
  162.         ==================================================
  163.         [   40.747923] ALSA: snd_soc_dapm_new_controls( dapm dbf536cc, widget bf0025bc, num 1 )
  164.         [   40.757450] ALSA: snd_soc_dapm_new_control( Mono Output Mixer )
  165.         
  166.         wm8960_add_widgets->snd_soc_dapm_add_routes(dapm, audio_paths_out3,ARRAY_SIZE(audio_paths_out3));
  167.         ==================================================
  168.         [   40.767594] ALSA: snd_soc_dapm_add_routes( dapm dbf536cc, route bf002628, num 3 )
  169.         [   40.776862] ALSA: snd_soc_dapm_add_route: { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
  170.         [   40.787959] read 26 => 0
  171.         [   40.792287] ALSA: snd_soc_dapm_add_route: { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
  172.         [   40.803558] read 27 => 0
  173.         [   40.807884] ALSA: snd_soc_dapm_add_route: { "OUT3", NULL,"Mono Output Mixer" },
  174.         
  175.         mini210_wm8960_init
  176.         ==================================================
  177.         [   40.816996] ALSA: snd_soc_dapm_nc_pin( dapm dbf536cc, pin RINPUT1 )
  178.         [   40.825045] ALSA: snd_soc_dapm_nc_pin( dapm dbf536cc, pin LINPUT2 )
  179.         [   40.833105] ALSA: snd_soc_dapm_nc_pin( dapm dbf536cc, pin RINPUT2 )
  180.         [   40.841269] ALSA: snd_soc_dapm_nc_pin( dapm dbf536cc, pin OUT3 )
  181.         
  182.         mini210_wm8960_init->snd_soc_dapm_new_controls( dapm, mini210_dapm_capture_widgets, ARRAY_SIZE( mini210_dapm_capture_widgets ) );
  183.         ==================================================
  184.         [   40.848963] ALSA: snd_soc_dapm_new_controls( dapm dbf536cc, widget bf007438, num 2 )
  185.         [   40.858493] ALSA: snd_soc_dapm_new_control( dapm dbf536cc, widget->name Mic Jack )
  186.         [   40.867855] ALSA: snd_soc_dapm_new_control( dapm dbf536cc, widget->name Line Input 3 (FM) )
  187.         
  188.         mini210_wm8960_init->snd_soc_dapm_new_controls( dapm, mini210_dapm_playback_widgets, ARRAY_SIZE( mini210_dapm_playback_widgets ) );
  189.         ==================================================
  190.         [   40.877992] ALSA: snd_soc_dapm_new_controls( dapm dbf536cc, widget bf007510, num 3 )
  191.         [   40.887525] ALSA: snd_soc_dapm_new_control( dapm dbf536cc, widget->name Headphone Jack )
  192.         [   40.897409] ALSA: snd_soc_dapm_new_control( dapm dbf536cc, widget->name Speaker_L )
  193.         [   40.906853] ALSA: snd_soc_dapm_new_control( dapm dbf536cc, widget->name Speaker_R )
  194.         
  195.         mini210_wm8960_init->snd_soc_dapm_add_routes( dapm, mini210_audio_map, ARRAY_SIZE( mini210_audio_map ) );
  196.         ==================================================
  197.         [   40.916295] ALSA: snd_soc_dapm_add_routes( dapm dbf536cc, route bf007654, num 8 )
  198.         [   40.925568] ALSA: snd_soc_dapm_add_route: { "Headphone Jack", NULL,"HP_L" },
  199.         [   40.934406] ALSA: snd_soc_dapm_add_route: { "Headphone Jack", NULL,"HP_R" },
  200.         [   40.943355] ALSA: snd_soc_dapm_add_route: { "Speaker_L", NULL,"SPK_LP" },
  201.         [   40.951826] ALSA: snd_soc_dapm_add_route: { "Speaker_L", NULL,"SPK_LN" },
  202.         [   40.960406] ALSA: snd_soc_dapm_add_route: { "Speaker_R", NULL,"SPK_RP" },
  203.         [   40.968982] ALSA: snd_soc_dapm_add_route: { "Speaker_R", NULL,"SPK_RN" },
  204.         [   40.977564] ALSA: snd_soc_dapm_add_route: { "LINPUT1", NULL,"MICB" },
  205.         [   40.985796] ALSA: snd_soc_dapm_add_route: { "MICB", NULL,"Mic Jack" },
  206.         
  207.         mini210_wm8960_init
  208.         ==================================================
  209.         [   40.994117] ALSA: snd_soc_dapm_enable_pin( dapm dbf536cc, pin Headphone Jack )
  210.         [   41.003125] ALSA: snd_soc_dapm_enable_pin( dapm dbf536cc, pin Mic Jack )
  211.         [   41.011619] ALSA: snd_soc_dapm_enable_pin( dapm dbf536cc, pin Speaker_L )
  212.         [   41.020195] ALSA: snd_soc_dapm_enable_pin( dapm dbf536cc, pin Speaker_R )
  213.         [   41.028777] ALSA: snd_soc_dapm_disable_pin( dapm dbf536cc, pin Line Input 3 (FM) )
  214.         
  215.         [   41.038284] DAPM sequencing finished, waiting 500ms
  216.         [   41.541507] read 1a => 0
  217.         [   41.541591] read 31 => 37
  218.         [   41.541637] read 31 => 37
  219.         [   41.541682] read 1a => 0
  220.         [   41.541726] read 1a => 0
  221.         [   41.541770] read 1a => 0
  222.         [   41.545437] read 1a => 0
  223.         [   41.549799] read 2f => 0
  224.         [   41.554120] read 2f => 0
  225.         [   41.558434] read 1a => 0
  226.         [   41.562766] read 1a => 0
  227.         [   41.567103] read 19 => 140
  228.         [   41.571604] read 19 => 140
  229.         [   41.576118] read 19 => 140
  230.         [   41.580625] read 19 => 140
  231.         [   41.585145] read 2f => 0
  232.         [   41.589485] read 2f => 0
  233.         [   41.593791] read 19 => 140
  234.         [   41.598406] DAPM sequencing finished, waiting 500ms
  235.         [   42.103982] soc-audio soc-audio: registered pcm #0 (null) wm8960-hifi-0
  236.         [   42.104602] asoc: wm8960-hifi <-> samsung-i2s.0 mapping ok
  237.         [   42.118110] soc-audio soc-audio: Registered card 'mini210'


    当 Android 启动以后,任意点击一下 touchpanel,会看到有新的 LOG 输出,这个部分是 mini210_hw_params 的实现。
        
复制代码
  1.         [   93.516111] ..entering s5p_i2s_set_clk_enabled
  2.         [   93.516166] Inside..s5p_i2s_wr_startup..for playback stream
  3.         [   93.516220] asoc: wm8960-hifi <-> samsung-i2s.0 info:
  4.         [   93.516263] asoc: rate mask 0xfe
  5.         [   93.516291] asoc: min ch 2 max ch 2
  6.         [   93.516323] asoc: min rate 8000 max rate 48000
  7.         [   93.520055] wm8960-codec 0-001a: ALSA: snd_soc_dai_set_fmt( dai db48f480, fmt 12288 )
  8.         [   93.530735] wm8960-codec 0-001a: write 7 = 2
  9.         [   93.532129] samsung-i2s samsung-i2s.0: ALSA: snd_soc_dai_set_fmt( dai db54bb00, fmt 12288 )
  10.         [   93.540363] Entered s5p_i2s_set_fmt
  11.         [   93.543796] hw_params r: IISMOD: 200
  12.         [   93.547346] hw_params w: IISMOD: 200
  13.         [   93.551013] samsung-i2s samsung-i2s.0: ALSA: snd_soc_dai_set_sysclk( dai db54bb00, clk_id 2, freq 44100, dir 1 )
  14.         [   93.561056] samsung-i2s samsung-i2s.0: ALSA: snd_soc_dai_set_sysclk( dai db54bb00, clk_id 1024, freq 44100, dir 1 )
  15.         [   93.571485] EPLL Rate changes from 80000000 to 67738000
  16.         [   93.576654] wm8960-codec 0-001a: ALSA: snd_soc_dai_set_clkdiv( dai db48f480, div_id 0, div 0 )
  17.         [   93.585223] wm8960-codec 0-001a: read 4 => 0
  18.         [   93.589471] wm8960-codec 0-001a: write 4 = 0
  19.         [   93.593840] wm8960-codec 0-001a: ALSA: snd_soc_dai_set_clkdiv( dai db48f480, div_id 1, div 0 )
  20.         [   93.602297] wm8960-codec 0-001a: read 4 => 0
  21.         [   93.606719] wm8960-codec 0-001a: write 4 = 0
  22.         [   93.611028] wm8960-codec 0-001a: ALSA: snd_soc_dai_set_clkdiv( dai db48f480, div_id 3, div 11289600 )
  23.         [   93.619986] wm8960-codec 0-001a: read 8 => 1c0
  24.         [   93.624393] wm8960-codec 0-001a: write 8 = 1c0
  25.         [   93.629052] samsung-i2s samsung-i2s.0: ALSA: snd_soc_dai_set_clkdiv( dai db54bb00, div_id 3, div 5 )
  26.         [   93.637913] s5p_i2s_set_clkdiv(db54bb00, 3, 5)
  27.         [   93.642324] s5p_i2s_set_clkdiv: PSR=00008500
  28.         [   93.646586] samsung-i2s samsung-i2s.0: ALSA: snd_soc_dai_set_clkdiv( dai db54bb00, div_id 2, div 256 )
  29.         [   93.655963] s5p_i2s_set_clkdiv(db54bb00, 2, 256)
  30.         [   93.660436] s5p_i2s_set_clkdiv: MOD=00000600
  31.         [   93.664696] samsung-i2s samsung-i2s.0: ALSA: snd_soc_dai_set_clkdiv( dai db54bb00, div_id 1, div 32 )
  32.         [   93.673870] s5p_i2s_set_clkdiv(db54bb00, 1, 32)
  33.         [   93.678374] s5p_i2s_set_clkdiv: MOD=00000600
  34.         [   93.682633] wm8960-codec 0-001a: read 7 => 2
  35.         [   93.686872] wm8960-codec 0-001a: read 5 => 8
  36.         [   93.691113] wm8960-codec 0-001a: write 7 = 2
  37.         [   93.695476] Entered s3c2412_i2s_hw_params
  38.         [   93.699360] s3c2412_i2s_hw_params: r: IISMOD: 600
  39.         [   93.704026] s3c2412_i2s_hw_params: w: IISMOD: 600
  40.         [   93.710135] wm8960-codec 0-001a: widget Right DAC
  41.         [   93.710141]  Playback stream Playback event 1
  42.         [   93.717768] wm8960-codec 0-001a: widget Left DAC
  43.         [   93.717772]  Playback stream Playback event 1
  44.         [   93.726646] wm8960-codec 0-001a: widget Right ADC
  45.         [   93.726650]  Capture stream Playback event 1
  46.         [   93.735603] wm8960-codec 0-001a: widget Left ADC
  47.         [   93.735607]  Capture stream Playback event 1
  48.         [   93.744561] wm8960-codec 0-001a: read 5 => 8
  49.         [   93.748900] wm8960-codec 0-001a: write 5 = 0
  50.         [   93.753694] Entered s3c2412_i2s_trigger
  51.         [   93.756696] s3c2412_snd_txctrl(1)
  52.         [   93.759990] s3c2412_snd_txctrl: IIS: CON=8040cc81 MOD=600 FIC=40
  53.         [   93.765969] s3c2412_snd_txctrl: IIS: CON=8040cc85 MOD=600 FIC=40
  54.         [   96.783314] Entered s3c2412_i2s_trigger
  55.         [   96.783361] s3c2412_snd_txctrl(0)
  56.         [   96.783393] s3c2412_snd_txctrl: IIS: CON=8040c185 MOD=600 FIC=3f40
  57.         [   96.783447] s3c2412_snd_txctrl: IIS: CON=8040c1d1 MOD=500 FIC=3f40
  58.         [   96.783526] wm8960-codec 0-001a: read 5 => 0
  59.         [   96.784748] wm8960-codec 0-001a: write 5 = 8
  60.         [   96.789102] Inside s5p_i2s_wr_shutdown for playback stream
  61.         [   96.794452] ..entering s5p_i2s_set_clk_enabled
  62.         [   96.798870] I2S Audio Clock disabled and Registers stored...
  63.         [   96.804495] Inside s5p_i2s_wr_shutdown CLkGATE_IP3=0x8fc3b10c..
  64.         [  101.819714] pop wq checking: Playback status: inactive waiting: yes
  65.         [  101.819793] wm8960-codec 0-001a: widget Right DAC
  66.         [  101.819797]  Playback stream Playback event 2
  67.         [  101.819871] wm8960-codec 0-001a: widget Left DAC
  68.         [  101.819874]  Playback stream Playback event 2
  69.         [  101.821642] wm8960-codec 0-001a: widget Right ADC
  70.         [  101.821646]  Capture stream Playback event 2
  71.         [  101.830585] wm8960-codec 0-001a: widget Left ADC
  72.         [  101.830588]  Capture stream Playback event 2


  
[ 此帖被happyzlz在2012-12-20 20:43重新编辑 ]
级别: 骑士
UID: 5844
精华: 9
发帖: 62
金钱: 760 两
威望: 152 点
贡献值: 9 点
综合积分: 304 分
注册时间: 2009-05-11
最后登录: 2016-11-28
2楼  发表于: 2012-12-20 20:48
怎么上传不了东西呢,再试一试。  wm8960.c 和 wm8960.h  

wm8960.tar.gz (9 K) 下载次数:251
级别: 骑士
UID: 14419
精华: 1
发帖: 185
金钱: 995 两
威望: 199 点
贡献值: 1 点
综合积分: 390 分
注册时间: 2010-02-08
最后登录: 2014-04-13
3楼  发表于: 2012-12-20 21:37
收藏啦。。
级别: 新手上路
UID: 75609
精华: 0
发帖: 33
金钱: 165 两
威望: 33 点
贡献值: 0 点
综合积分: 66 分
注册时间: 2012-08-10
最后登录: 2014-10-12
4楼  发表于: 2012-12-21 12:15
顶,期待楼主更新。。
级别: 新手上路
UID: 28725
精华: 0
发帖: 19
金钱: 95 两
威望: 19 点
贡献值: 0 点
综合积分: 38 分
注册时间: 2010-09-15
最后登录: 2014-03-31
5楼  发表于: 2012-12-22 00:15
有个问题想请教楼主,alsa找不到声卡,跟进去是找不到codec,请问怎么解决,.codec_name = "wm8960-codec.0-001a",是怎么对应的?
级别: 骑士
UID: 5844
精华: 9
发帖: 62
金钱: 760 两
威望: 152 点
贡献值: 9 点
综合积分: 304 分
注册时间: 2009-05-11
最后登录: 2016-11-28
6楼  发表于: 2012-12-22 08:12
7. 附加:反汇编完成的 mini210_wm8960.c

在之前的基础上,完善了 hw_params 函数,objdump 后的 二进制,和 Andoid 4光盘中的 二进制基本一致。应该是一样的了。但目前板子不在身边,还没有确认。

另外, 光盘中的 驱动, 还需要 fa_codec_ctrl mini210 来进行设定,这个部分还需要解析一下如何对应。

但是 这个函数中,还有几个变量没有弄明白是什么意思,这就需要结合 芯片手册进行确认了。


复制代码
  1.     int div;
  2.     int r9;
  3.     int sl;    
  4.     unsigned int mul;
  5.     unsigned int clk_scale;


下面是变更后的代码:


复制代码
  1. /*
  2. * mini_wm8960.c  --  WM8960 ALSA SoC Audio driver
  3. *
  4. * Author: happyzlz
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <sound/soc.h>
  11. #include <sound/pcm.h>
  12. #include <sound/pcm_params.h>
  13. #include "s5pc1xx-i2s.h"
  14. #include "wm8960.h"
  15. #define    CDCLK                    0x002
  16. #define    CLKAUDIO                0x400
  17. static struct snd_soc_card mini210_soc_card;
  18. static int mini210_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  19. {
  20.     struct snd_soc_pcm_runtime *rtd = substream->private_data;
  21.     struct snd_soc_dai *codec_dai = rtd->codec_dai;
  22.     struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  23.     unsigned int rate = params_rate(params);
  24.     snd_pcm_format_t fmt = params_format( params );
  25.     int    ret = 0;
  26.     int div;
  27.     int r9;
  28.     int sl;    
  29.     unsigned int mul;
  30.     unsigned int clk_scale;
  31.     switch ( fmt ) {
  32.         case SNDRV_PCM_FORMAT_S16:
  33.             div = 32;
  34.             break;
  35.         case SNDRV_PCM_FORMAT_S20_3LE:
  36.         case SNDRV_PCM_FORMAT_S24:
  37.             div = 48;
  38.             break;
  39.         default:
  40.             return -EINVAL;
  41.     }
  42.     
  43.     switch ( rate ) {
  44.         case 8000:
  45.         case 11025:
  46.         case 12000:
  47.             if( div == 48 )
  48.                 r9 = 768;    //0x300
  49.             else
  50.                 r9 = 512;    //0x200
  51.             break;
  52.         case 16000:
  53.         case 22050:
  54.         case 24000:
  55.         case 32000:
  56.         case 44100:    //AC44
  57.         case 48000:
  58.         case 88200:
  59.         case 96000:
  60.             if( div == 48 )
  61.                 r9 = 384;    //0x180
  62.             else
  63.                 r9 = 256;    //0x100
  64.             break;
  65.         case 64000:
  66.             r9 = 384;        //0x180
  67.             break;
  68.         default:
  69.             return -EINVAL;
  70.     }
  71.     
  72.     ret = snd_soc_dai_set_fmt( codec_dai, SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF|SND_SOC_DAIFMT_CBS_CFS );
  73.     if( ret < 0 ){
  74.         printk( "%s: Codec DAI configuration error, %d\n", __func__, ret );
  75.         return ret;
  76.     }
  77.     ret = snd_soc_dai_set_fmt( cpu_dai, SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF|SND_SOC_DAIFMT_CBS_CFS );
  78.     if( ret < 0 ){
  79.         printk( "%s: AP DAI configuration error, %d\n", __func__, ret );
  80.         return ret;
  81.     }
  82.     ret = snd_soc_dai_set_sysclk( cpu_dai, CDCLK, rate, SND_SOC_CLOCK_OUT );    //44100
  83.     if( ret < 0 ){
  84.         printk( "%s: AP sycclk CDCLK setting error, %d\n", __func__, ret );
  85.         return ret;
  86.     }
  87.     ret = snd_soc_dai_set_sysclk( cpu_dai, CLKAUDIO, rate, SND_SOC_CLOCK_OUT );    //44100
  88.     if( ret < 0 ){
  89.         printk( "%s: AP sysclk CLKAUDIO setting error, %d\n", __func__, ret );
  90.         return ret;
  91.     }
  92.     if( rate & 0x0F )
  93.         sl = 0x04099990;
  94.     else
  95.         sl = 0x02ee0000;
  96.     ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_SYSCLKDIV, WM8960_SYSCLK_DIV_1 );
  97.     if( ret < 0 ){
  98.         printk( "%s: Codec SYSCLKDIV setting error, %d\n", __func__, ret );
  99.         return ret;
  100.     }
  101.     ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_DACDIV, WM8960_DAC_DIV_1  );
  102.     if( ret < 0 ){
  103.         printk( "%s: Codec DACDIV setting error, %d\n", __func__, ret );
  104.         return ret;
  105.     }
  106.     mul = rate * r9;
  107.     ret = snd_soc_dai_set_clkdiv( codec_dai, WM8960_DCLKDIV, mul );
  108.     if( ret < 0 ){
  109.         printk( "%s: Codec DCLKDIV setting error, %d\n", __func__, ret );
  110.         return ret;
  111.     }
  112.     
  113.     clk_scale =  sl / mul;
  114.     clk_scale--;
  115.     ret = snd_soc_dai_set_clkdiv( cpu_dai, S3C64XX_DIV_PRESCALER, clk_scale );
  116.     if( ret < 0 ){
  117.         printk( "%s: AP prescalar setting error, %d\n", __func__, ret );
  118.         return ret;
  119.     }
  120.     ret = snd_soc_dai_set_clkdiv( cpu_dai, S3C64XX_DIV_RCLK, r9 );
  121.     if( ret < 0 ){
  122.         printk( "%s: AP RFS setting error, %d\n", __func__, ret );
  123.         return ret;
  124.     }
  125.     ret = snd_soc_dai_set_clkdiv( cpu_dai, S3C64XX_DIV_BCLK, div );
  126.     if( ret < 0 ){
  127.         printk( "%s: AP BFS setting error, %d\n", __func__, ret );
  128.         return ret;
  129.     }
  130. // rate = 44100 = 0xAC44
  131. // div == 32
  132. // sl = 0x04099990 = 67738000
  133. // r9 = 256 = 0x100
  134. // mul ==  r9 * rate = 11289600 = 0xAC4400
  135. // clk_scale == sl /  mul - 1 = 5
  136.     return 0;
  137. }
  138. static struct snd_soc_ops mini210_wm8960_ops = {
  139.     .hw_params = mini210_hw_params,
  140. };
  141. static const struct snd_soc_dapm_widget mini210_dapm_capture_widgets[] = {
  142.     SND_SOC_DAPM_MIC(    "Mic Jack",            NULL ),
  143.     SND_SOC_DAPM_LINE(    "Line Input 3 (FM)",NULL ),
  144. };
  145. static const struct snd_soc_dapm_widget mini210_dapm_playback_widgets[] = {
  146.     SND_SOC_DAPM_HP(    "Headphone Jack",    NULL ),
  147.     SND_SOC_DAPM_SPK(    "Speaker_L",        NULL ),
  148.     SND_SOC_DAPM_SPK(    "Speaker_R",        NULL ),
  149. };
  150. static const struct snd_soc_dapm_route mini210_audio_map[] = {
  151.     { "Headphone Jack",    NULL,    "HP_L"        },
  152.     { "Headphone Jack",    NULL,     "HP_R"        },
  153.     { "Speaker_L",        NULL,     "SPK_LP"    },
  154.     { "Speaker_L",        NULL,     "SPK_LN"     },
  155.     { "Speaker_R",        NULL,     "SPK_RP"     },
  156.     { "Speaker_R",        NULL,     "SPK_RN"     },
  157.     { "LINPUT1",        NULL,     "MICB"        },
  158.     { "MICB",            NULL,     "Mic Jack"    },
  159. };
  160. static int mini210_wm8960_init(struct snd_soc_pcm_runtime *rtd)
  161. {
  162.     struct snd_soc_codec *codec = rtd->codec;
  163.     struct snd_soc_dapm_context *dapm = &codec->dapm;
  164.     snd_soc_dapm_nc_pin(dapm, "RINPUT1");
  165.     snd_soc_dapm_nc_pin(dapm, "LINPUT2");
  166.     snd_soc_dapm_nc_pin(dapm, "RINPUT2");
  167.     snd_soc_dapm_nc_pin(dapm, "OUT3");
  168.     
  169.     snd_soc_dapm_new_controls( dapm, mini210_dapm_capture_widgets, ARRAY_SIZE( mini210_dapm_capture_widgets ) );
  170.     snd_soc_dapm_new_controls( dapm, mini210_dapm_playback_widgets, ARRAY_SIZE( mini210_dapm_playback_widgets ) );
  171.     snd_soc_dapm_add_routes( dapm, mini210_audio_map, ARRAY_SIZE( mini210_audio_map ) );
  172.     snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
  173.     snd_soc_dapm_enable_pin(dapm, "Mic Jack");
  174.     snd_soc_dapm_enable_pin(dapm, "Speaker_L");
  175.     snd_soc_dapm_enable_pin(dapm, "Speaker_R");
  176.     
  177.     snd_soc_dapm_disable_pin(dapm, "Line Input 3 (FM)");
  178.     snd_soc_dapm_sync( dapm );
  179.     return 0;
  180. }
  181. static struct snd_soc_dai_link mini210_dai = {
  182.     .name = "MINI210",
  183.     .stream_name = "WM8960 HiFi",
  184.     .codec_name = "wm8960-codec.0-001a",
  185.     .platform_name = "samsung-audio",
  186.     .cpu_dai_name = "samsung-i2s.0",
  187.     .codec_dai_name = "wm8960-hifi",
  188.     .init = mini210_wm8960_init,
  189.     .ops = &mini210_wm8960_ops,
  190. };
  191. static struct snd_soc_card mini210_soc_card = {
  192.     .name = "mini210",
  193.     .dai_link = &mini210_dai,
  194.     .num_links = 1,
  195. };
  196. static struct platform_device *mini210_snd_device;
  197. static int __init mini210_audio_init(void)
  198. {
  199.     int ret;
  200.     mini210_snd_device = platform_device_alloc("soc-audio", -1);
  201.     if ( !mini210_snd_device ){
  202.         return -ENOMEM;
  203.     }
  204.     platform_set_drvdata( mini210_snd_device, &mini210_soc_card );
  205.     ret = platform_device_add( mini210_snd_device );
  206.     if( ret ){
  207.         platform_device_put( mini210_snd_device );
  208.     }
  209.     return ret;
  210. }
  211. static void __exit mini210_audio_exit(void)
  212. {
  213.     platform_device_unregister( mini210_snd_device );
  214. }
  215. module_init( mini210_audio_init );
  216. module_exit( mini210_audio_exit );
  217. MODULE_AUTHOR("zoulz, happyzlz@sohu.com");
  218. MODULE_DESCRIPTION("ALSA SoC TINY210v2+WM8960");
  219. MODULE_LICENSE("GPL");
级别: 骑士
UID: 5844
精华: 9
发帖: 62
金钱: 760 两
威望: 152 点
贡献值: 9 点
综合积分: 304 分
注册时间: 2009-05-11
最后登录: 2016-11-28
7楼  发表于: 2012-12-22 08:31

 回 5楼(victorlinwen) 的帖子

抱歉,我还没有看完ALSA这部分代码,影响中好象是在 注册 card 的时候填写到数据结构中的, 还好像记得 ALSA 的代码中,会为这部分添加特定后缀。 codec 的名字是 wm8960.c 的 i2c 驱动向  ALSA 内部注册 codec 的时候 决定的,叫做 wm8960-codec , ALSA 给他添加的后缀: .0-001a
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5407
金钱: 40120 两
威望: 17929 点
贡献值: 71 点
综合积分: 11054 分
注册时间: 2008-01-16
最后登录: 2014-11-22
8楼  发表于: 2012-12-22 09:05

 回 6楼(happyzlz) 的帖子

非常感谢你的分享!
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 28725
精华: 0
发帖: 19
金钱: 95 两
威望: 19 点
贡献值: 0 点
综合积分: 38 分
注册时间: 2010-09-15
最后登录: 2014-03-31
9楼  发表于: 2012-12-22 20:18
谢谢您,我现在在看这个,但是无从下手