Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15529820
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2010-06-06 18:56:03

谈谈kctl.info什么时候赋值为snd_ctl_elem_user_info的

可以是alsa-lib库调用接口添加
应用层
static const snd_ctl_ops_t snd_ctl_hw_ops = {
    ...
.element_add = snd_ctl_hw_elem_add,
.element_replace = snd_ctl_hw_elem_replace,
    ...
};
内核层
snd_ctl_elem_add_user
snd_ctl_elem_add
kctl.info = snd_ctl_elem_user_info;

也可以是kernel自动添加,其中wm8991_snd_controls就是使用下面的SOC_SINGLE,SOC_SINGLE_TLV等宏定义的数组
snd_ctl_add(codec->card, snd_soc_cnew(&wm8991_snd_controls[i],codec, NULL));
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
    void *data, char *long_name);
==> snd_ctl_new1
===> kctl.info = ncontrol->info;

下面都有内置的.info方法实现
/*
 * Convenience kcontrol builders
 */
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
    ((unsigned long)&(struct soc_mixer_control) \
    {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
    .invert = xinvert})
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
    ((unsigned long)&(struct soc_mixer_control) \
    {.reg = xreg, .max = xmax, .invert = xinvert})
#define SOC_SINGLE(xname, reg, shift, max, invert) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
    .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
    .put = snd_soc_put_volsw, \
    .private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, 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 =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
    .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, .invert = xinvert} }
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
    .info = snd_soc_info_volsw_2r, \
    .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
    .private_value = (unsigned long)&(struct soc_mixer_control) \
        {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
        .max = xmax, .invert = xinvert} }
#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, .invert = xinvert} }
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, 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_2r, \
    .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
    .private_value = (unsigned long)&(struct soc_mixer_control) \
        {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
        .max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, 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_s8, .get = snd_soc_get_volsw_s8, \
    .put    = snd_soc_put_volsw_s8, \
    .private_value = (unsigned long)&(struct soc_mixer_control) \
        {.reg = xreg, .min = xmin, .max = xmax} }
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
{    .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
    .max = xmax, .texts = xtexts }
#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \
    SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts)
#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
{    .max = xmax, .texts = xtexts }
#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \
{    .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
    .mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues}
#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \
    SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues)
#define SOC_ENUM(xname, xenum) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
    .info = snd_soc_info_enum_double, \
    .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
    .private_value = (unsigned long)&xenum }
#define SOC_VALUE_ENUM(xname, xenum) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
    .info = snd_soc_info_enum_double, \
    .get = snd_soc_get_value_enum_double, \
    .put = snd_soc_put_value_enum_double, \
    .private_value = (unsigned long)&xenum }
#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
     xhandler_get, xhandler_put) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
    .info = snd_soc_info_volsw, \
    .get = xhandler_get, .put = xhandler_put, \
    .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
#define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\
     xhandler_get, xhandler_put) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
    .info = snd_soc_info_volsw, \
    .get = xhandler_get, .put = xhandler_put, \
    .private_value = (unsigned long)&(struct soc_mixer_control) \
        {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
         .max = xmax, .invert = xinvert} }
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
     xhandler_get, xhandler_put, 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 = xhandler_get, .put = xhandler_put, \
    .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
    .info = snd_soc_info_bool_ext, \
    .get = xhandler_get, .put = xhandler_put, \
    .private_value = xdata }
#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
{    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
    .info = snd_soc_info_enum_ext, \
    .get = xhandler_get, .put = xhandler_put, \
    .private_value = (unsigned long)&xenum }
阅读(5317) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~