您好,欢迎访问一九零五行业门户网

谈谈alsa-lib和驱动自身对kctl.info什么时候赋值的

谈谈 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, ... }; 内核层 sn
谈谈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 }
其它类似信息

推荐信息