先从kernel/sound/soc/codecs/wcd9310.c中的一行代码开始

static const struct snd_kcontrol_new tabla_snd_controls[] = {
    SOC_SINGLE_TLV("LINEOUT1 Volume", TABLA_A_RX_LINE_1_GAIN, 0, 12, 1,
        line_gain),
看一下snd_kcontrol_new这个结构体

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;
};
再看一下SOC_SINGLE_TLV宏定义

#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) }

这里最主要的是tlv.p(line_gain)和private_value(保存着寄存器相关的信息)。

tlv.p在kernel/sound/core/control.c中被snd_ctl_tlv_ioctl()<-snd_ctl_ioctl()调用,alsa lib中的alsa_mixer.c通过ioctl去调用。

另外tlv.p在kernel/sound/core/control.c中被snd_ctl_new1()调用。参考:snd_kcontrol的分析

private_value在wcd9311.c中被使用。

Logo

更多推荐