static int txsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l; unsigned int mask = 1 << e->shift_l; unsigned int txpwr; if (val != 0 && val != mask) return -EINVAL; snd_soc_dapm_mutex_lock(dapm); if (snd_soc_test_bits(codec, e->reg, mask, val)) { /* save the current power state of the transmitter */ txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4; /* power down the transmitter */ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4); /* set the tx source */ snd_soc_update_bits(codec, e->reg, mask, val); /* restore the transmitter's configuration */ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr); } snd_soc_dapm_mutex_unlock(dapm); return 0; }
int arizona_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; unsigned int mask; struct snd_soc_dapm_update update; int wi; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; mask |= e->mask << e->shift_r; } change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 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 = e->reg; update.mask = mask; update.val = val; widget->dapm->update = &update; snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); widget->dapm->update = NULL; } } return change; }
/* * The MUX register for the Capture and Playback MUXs selects either DSP as * source/destination or one of the TDM slots. The TDM slot is selected via * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or * directly to the DAI interface with this control. */ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct snd_soc_dapm_update update; unsigned int stream = e->shift_l; unsigned int val, change; int reg; if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; switch (ucontrol->value.enumerated.item[0]) { case 0: val = 0; adau->dsp_bypass[stream] = false; break; default: val = (adau->tdm_slot[stream] * 2) + 1; adau->dsp_bypass[stream] = true; break; } if (stream == SNDRV_PCM_STREAM_PLAYBACK) reg = ADAU17X1_SERIAL_INPUT_ROUTE; else reg = ADAU17X1_SERIAL_OUTPUT_ROUTE; change = snd_soc_test_bits(codec, reg, 0xff, val); if (change) { update.kcontrol = kcontrol; update.mask = 0xff; update.reg = reg; update.val = val; snd_soc_dapm_mux_update_power(dapm, kcontrol, ucontrol->value.enumerated.item[0], e, &update); } return change; }