static int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct adau *adau = snd_soc_codec_get_drvdata(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int stream = e->shift_l; unsigned int reg, val; int ret; if (stream == SNDRV_PCM_STREAM_PLAYBACK) reg = ADAU17X1_SERIAL_INPUT_ROUTE; else reg = ADAU17X1_SERIAL_OUTPUT_ROUTE; ret = regmap_read(adau->regmap, reg, &val); if (ret) return ret; if (val != 0) val = 1; ucontrol->value.enumerated.item[0] = val; return 0; }
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; }
/* * 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; }