现在的位置: 首页 > 综合 > 正文

Linux ALSA声卡驱动之七:ASoC架构中的Codec

2013年10月11日 ⁄ 综合 ⁄ 共 5739字 ⁄ 字号 评论关闭

1.  Codec简介

在移动设备中,Codec的作用可以归结为4种,分别是:

  • 对PCM等信号进行D/A转换,把数字的音频信号转换为模拟信号
  • 对Mic、Linein或者其他输入源的模拟信号进行A/D转换,把模拟的声音信号转变CPU能够处理的数字信号
  • 对音频通路进行控制,比如播放音乐,收听调频收音机,又或者接听电话时,音频信号在codec内的流通路线是不一样的
  • 对音频信号做出相应的处理,例如音量控制,功率放大,EQ控制等等

ASoC对Codec的这些功能都定义好了一些列相应的接口,以方便地对Codec进行控制。ASoC对Codec驱动的一个基本要求是:驱动程序的代码必须要做到平台无关性,以方便同一个Codec的代码不经修改即可用在不同的平台上。以下的讨论基于wolfson的Codec芯片WM8994,kernel的版本3.3.x。


/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢!
/*****************************************************************************************************/

2.  ASoC中对Codec的数据抽象

描述Codec的最主要的几个数据结构分别是:snd_soc_codec,snd_soc_codec_driver,snd_soc_dai,snd_soc_dai_driver,其中的snd_soc_dai和snd_soc_dai_driver在ASoC的Platform驱动中也会使用到,Platform和Codec的DAI通过snd_soc_dai_link结构,在Machine驱动中进行绑定连接。下面我们先看看这几个结构的定义,这里我只贴出我要关注的字段,详细的定义请参照:/include/sound/soc.h。
snd_soc_codec:

[html] view
plain
copy

  1. /* SoC Audio Codec device */  
  2. struct snd_soc_codec {  
  3.     const char *name;  /* Codec的名字*/  
  4.     struct device *dev; /* 指向Codec设备的指针 */  
  5.     const struct snd_soc_codec_driver *driver; /* 指向该codec的驱动的指针 */  
  6.     struct snd_soc_card *card;    /* 指向Machine驱动的card实例 */  
  7.     int num_dai; /* 该Codec数字接口的个数,目前越来越多的Codec带有多个I2S或者是PCM接口 */  
  8.     int (*volatile_register)(...);  /* 用于判定某一寄存器是否是volatile */  
  9.     int (*readable_register)(...);  /* 用于判定某一寄存器是否可读 */  
  10.     int (*writable_register)(...);  /* 用于判定某一寄存器是否可写 */  
  11.   
  12.     /* runtime */  
  13.     ......  
  14.     /* codec IO */  
  15.     void *control_data; /* 该指针指向的结构用于对codec的控制,通常和read,write字段联合使用 */  
  16.     enum snd_soc_control_type control_type;/* 可以是SND_SOC_SPI,SND_SOC_I2C,SND_SOC_REGMAP中的一种 */  
  17.     unsigned int (*read)(struct snd_soc_codec *, unsigned int);  /* 读取Codec寄存器的函数 */  
  18.     int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);  /* 写入Codec寄存器的函数 */  
  19.     /* dapm */  
  20.     struct snd_soc_dapm_context dapm;  /* 用于DAPM控件 */  
  21. };  

snd_soc_codec_driver:

[html] view
plain
copy

  1. /* codec driver */  
  2. struct snd_soc_codec_driver {  
  3.     /* driver ops */  
  4.     int (*probe)(struct snd_soc_codec *);  /* codec驱动的probe函数,由snd_soc_instantiate_card回调 */  
  5.     int (*remove)(struct snd_soc_codec *);    
  6.     int (*suspend)(struct snd_soc_codec *);  /* 电源管理 */  
  7.     int (*resume)(struct snd_soc_codec *);  /* 电源管理 */  
  8.   
  9.     /* Default control and setup, added after probe() is run */  
  10.     const struct snd_kcontrol_new *controls;  /* 音频控件指针 */  
  11.     const struct snd_soc_dapm_widget *dapm_widgets;  /* dapm部件指针 */  
  12.     const struct snd_soc_dapm_route *dapm_routes;  /* dapm路由指针 */  
  13.   
  14.     /* codec wide operations */  
  15.     int (*set_sysclk)(...);  /* 时钟配置函数 */  
  16.     int (*set_pll)(...);  /* 锁相环配置函数 */  
  17.   
  18.     /* codec IO */  
  19.     unsigned int (*read)(...);  /* 读取codec寄存器函数 */  
  20.     int (*write)(...);  /* 写入codec寄存器函数 */  
  21.     int (*volatile_register)(...);  /* 用于判定某一寄存器是否是volatile */  
  22.     int (*readable_register)(...);  /* 用于判定某一寄存器是否可读 */  
  23.     int (*writable_register)(...);  /* 用于判定某一寄存器是否可写 */  
  24.   
  25.     /* codec bias level */  
  26.     int (*set_bias_level)(...);  /* 偏置电压配置函数 */  
  27.   
  28. };  

snd_soc_dai:

[html] view
plain
copy

  1. /*  
  2.  * Digital Audio Interface runtime data.  
  3.  *  
  4.  * Holds runtime data for a DAI.  
  5.  */  
  6. struct snd_soc_dai {  
  7.     const char *name;  /* dai的名字 */  
  8.     struct device *dev;  /* 设备指针 */  
  9.   
  10.     /* driver ops */  
  11.     struct snd_soc_dai_driver *driver;  /* 指向dai驱动结构的指针 */  
  12.   
  13.     /* DAI runtime info */  
  14.     unsigned int capture_active:1;      /* stream is in use */  
  15.     unsigned int playback_active:1;     /* stream is in use */  
  16.   
  17.     /* DAI DMA data */  
  18.     void *playback_dma_data;  /* 用于管理playback dma */  
  19.     void *capture_dma_data;  /* 用于管理capture dma */  
  20.   
  21.     /* parent platform/codec */  
  22.     union {  
  23.         struct snd_soc_platform *platform;  /* 如果是cpu dai,指向所绑定的平台 */  
  24.         struct snd_soc_codec *codec;  /* 如果是codec dai指向所绑定的codec */  
  25.     };  
  26.     struct snd_soc_card *card;  /* 指向Machine驱动中的crad实例 */  
  27. };  

snd_soc_dai_driver:

[html] view
plain
copy

  1. /*  
  2.  * Digital Audio Interface Driver.  
  3.  *  
  4.  * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97  
  5.  * operations and capabilities. Codec and platform drivers will register this  
  6.  * structure for every DAI they have.  
  7.  *  
  8.  * This structure covers the clocking, formating and ALSA operations for each  
  9.  * interface.  
  10.  */  
  11. struct snd_soc_dai_driver {  
  12.     /* DAI description */  
  13.     const char *name;  /* dai驱动名字 */  
  14.   
  15.     /* DAI driver callbacks */  
  16.     int (*probe)(struct snd_soc_dai *dai);  /* dai驱动的probe函数,由snd_soc_instantiate_card回调 */  
  17.     int (*remove)(struct snd_soc_dai *dai);    
  18.     int (*suspend)(struct snd_soc_dai *dai);  /* 电源管理 */  
  19.     int (*resume)(struct snd_soc_dai *dai);    
  20.   
  21.     /* ops */  
  22.     const struct snd_soc_dai_ops *ops;  /* 指向本dai的snd_soc_dai_ops结构 */  
  23.   
  24.     /* DAI capabilities */  
  25.     struct snd_soc_pcm_stream capture;  /* 描述capture的能力 */  
  26.     struct snd_soc_pcm_stream playback;  /* 描述playback的能力 */  
  27. };  

snd_soc_dai_ops用于实现该dai的控制盒参数配置:

[html] view
plain
copy

  1. struct snd_soc_dai_ops {  
  2.     /*  
  3.      * DAI clocking configuration, all optional.  
  4.      * Called by soc_card drivers, normally in their hw_params.  
  5.      */  
  6.     int (*set_sysclk)(...);  
  7.     int (*set_pll)(...);  
  8.     int (*set_clkdiv)(...);  
  9.     /*  
  10.      * DAI format configuration  
  11.      * Called by soc_card drivers, normally in their hw_params.  
  12.      */  
  13.     int (*set_fmt)(...);  
  14.     int (*set_tdm_slot)(...);  
  15.     int (*set_channel_map)(...);  
  16.     int (*set_tristate)(...);  
  17.     /*  
  18.      * DAI digital mute - optional.  
  19.      * Called by soc-core to minimise any pops.  
  20.      */  
  21.     int (*digital_mute)(...);  
  22.     /*  
  23.      * ALSA PCM audio operations - all optional.  
  24.      * Called by soc-core during audio PCM operations.  
  25.      */  
  26.     int (*startup)(...);  
  27.     void (*shutdown)(...);  

抱歉!评论已关闭.