
两种kcontrol
1 2 3
|
static const struct wm8960_snd_controls[] = { SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0), };
|
1 2 3
|
static const struct wm8960_lin_boost[] = { SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0), };
|
观察两个宏
1 2 3 4 5
|
{ .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) }
|
1 2 3 4 5
|
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_soc_info_volsw, .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
区别只在于get和put方法上
snd_soc_put_volsw
直接写
1 2 3 4 5 6 7 8
|
int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) val = (ucontrol->value.integer.value[0] & mask); return snd_soc_update_bits_locked(codec, reg, val_mask, val); snd_soc_update_bits(codec, reg, mask, value); snd_soc_read(codec, reg); snd_soc_write(codec, reg, new);
|
snd_soc_dapm_put_volsw
调用dapm_power_widgets,触发一系列dapm方面流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) change = snd_soc_test_bits(widget->codec, reg, mask, val); old = snd_soc_read(codec, reg); new = (old & ~mask) | value; change = old != new; return change; if (change) { for (wi = 0; wi < wlist->num_widgets; wi++) { widget = wlist->widgets[wi];
widget->value = val;
update.kcontrol = kcontrol; update.widget = widget; update.reg = reg; update.mask = mask; update.val = val; widget->dapm->update = &update;
dapm_mixer_update_power(widget, kcontrol, connect); dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); dapm_widget_update(dapm); snd_soc_update_bits(w->codec, update->reg, update->mask, update->val); } }
|
近期评论