Sound Mixer (Control 接口 1)

1,初始化函数:

snd_soc_add_controls(codec, wm9713_snd_ac97_controls,

ARRAY_SIZE(wm9713_snd_ac97_controls));

 

   首先wm9713_snd_ac97_controls结构体数组的实力化,这个过程是在编译的时候就决定的。是使用宏定义完成的。

1)涉及到两个结构体,一个是snd_kcontrol_new,另外一个是soc_mixer_control。这两个结构体中涉及的内容就是接下来通过宏定义来初始化的对象。

struct snd_kcontrol_new {

   snd_ctl_elem_iface_t iface; /* interface identifier */

   unsigned int device;        /* device/client number */

   unsigned int subdevice;     /* subdevice (substream) number */

   unsigned char *name;        /* ASCII name of item */

   unsigned int index;     /* index of item */

   unsigned int access;        /* access rights */

   unsigned int count;     /* count of same elements */

   snd_kcontrol_info_t *info;

   snd_kcontrol_get_t *get;

   snd_kcontrol_put_t *put;

   union {

       snd_kcontrol_tlv_rw_t *c;

       const unsigned int *p;

   } tlv;

   unsigned long private_value;

};

/* mixer control */

struct soc_mixer_control {

   int min, max, platform_max;

   unsigned int reg, rreg, shift, rshift, invert;

};

2)宏定义原型:

#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array)

{  

   .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,

   .name           = (xname),

   .access         = SNDRV_CTL_ELEM_ACCESS_TLV_READ|

SNDRV_CTL_ELEM_ACCESS_READWRITE,

   .tlv.p          = (tlv_array),

   .info           = snd_soc_info_volsw,

   .get            = snd_soc_get_volsw,

   .put            = snd_soc_put_volsw,

   .private_value = (unsigned long)&(struct soc_mixer_control)

   {

       .reg            = xreg,

       .shift          = shift_left,

       .rshift         = shift_right,

       .max            = xmax,

       .platform_max   = xmax,

       .invert         = xinvert

   }

}

 

static const unsigned int out_tlv[] = {

   TLV_DB_RANGE_HEAD(2),

   /* 0000000 - 0101111 = "Analogue mute" */

   0,

   48,

   TLV_DB_SCALE_ITEM(-25500, 0, 0),

   48,

   127,

   TLV_DB_SCALE_ITEM(-7300, 100, 0),

};

 

3)具体实现:

   取数组中的第一个成员,具体是怎么替代并且初始化:

SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv)

变形为:

.ifa           = SNDRV_CTL_ELEM_IFACE_MIXER,

.name          = Speaker Playback Volume,

.access        = SNDRV_CTL_ELEM_ACCESS_TLV_READ|

SNDRV_CTL_ELEM_ACCESS_READWRITE,

.tlv.p         = out_tlv,

.info          = snd_soc_info_volsw,

.get           = snd_soc_get_volsw,

.put           = snd_soc_put_volsw,

.private_value= (unsigned long)&(struct soc_mixer_control)

{

   .reg            = AC97_MASTER,

   .shift          = 8,

   .rshift         = 0,

   .max            = 1,

   .platform_max   = 1,

   .invert         = 31

}

2,初始化过程:

/**

 * snd_soc_add_controls - add an array of controls to a codec.

 * Convienience function to add a list of controls. Many codecs were

 * duplicating this code.

 *

 * @codec: codec to add controls to

 * @controls: array of controls to add

 * @num_controls: number of elements in the array

 *

 * Return 0 for success, else error.

 */

int snd_soc_add_controls(struct snd_soc_codec *codec,

                   const struct snd_kcontrol_new *controls, int num_controls)

参数codec          这个结构体指针是上级传下来的,主要用来找到card这个结构体。

参数controls       指针就是全局定义的wm9713_snd_ac97_controls

参数num_controls   是数组中实际的数组个数。

其实英语的注释中已经写的很清楚了这里只是简单的翻译一下,在后续分析中还会不断介绍到各自的作用。

函数内容for循环遍历说有的数组中的每一个成员,完成相应的操作。在这个for循环中使用的是:err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));

前面介绍了很多snd_kcontrol_new,这段代码中引入了snd_kcontrol。是这个结果在add函数中被使用。snd_soc_cnew这个函数就是分配一下内存空间,这个空间的对象就是snd_kcontrol,而后要注意的是在cardlist中链表中的结构是snd_kcontrol。函数中有这样的一句表述:list_add_tail(&kcontrol->list, &card->controls)。还有三个函数指针同样也要被初始化:

.info  = snd_soc_info_volsw,

.get   = snd_soc_get_volsw,

.put   = snd_soc_put_volsw,

   这样的函数作用就是和底层的硬件打交道,通过这些函数实现硬件的操作。其实在这层次中的函数还是进行了封装,目的就是参数再进一步提炼,到了最后调用read write等函数进行读写硬件的寄存器。同时再列出相同功能属性的操作函数:

   .info   = snd_soc_info_volsw_2r,

   .get    = snd_soc_get_volsw_2r,

.put   = snd_soc_put_volsw_2r,

   .info   = snd_soc_info_volsw_s8,

.get   = snd_soc_get_volsw_s8,

   .put    = snd_soc_put_volsw_s8,

   

    这样的函数操作集很多类型,针对不同的寄存器变量有不同的实现。

你可能感兴趣的:(arm_sound)