int tse850_put_ana(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl); struct snd_soc_card *card = dapm->card; struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); struct soc_enum *e = (struct soc_enum *)kctrl->private_value; unsigned int uV = ucontrol->value.enumerated.item[0]; int ret; if (uV >= e->items) return -EINVAL; /* * Map enum zero (Low) to 2 volts on the regulator, do this since * the ana regulator is supplied by the system 12V voltage and * requesting anything below the system voltage causes the system * voltage to be passed through the regulator. Also, the ana * regulator induces noise when requesting voltages near the * system voltage. So, by mapping Low to 2V, that noise is * eliminated when all that is needed is 12V (the system voltage). */ if (uV) uV = 11000000 + (1000000 * uV); else uV = 2000000; ret = regulator_set_voltage(tse850->ana, uV, uV); if (ret < 0) return ret; return snd_soc_dapm_put_enum_double(kctrl, ucontrol); }
static int tse850_put_mux1(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl); struct snd_soc_card *card = dapm->card; struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card); struct soc_enum *e = (struct soc_enum *)kctrl->private_value; unsigned int val = ucontrol->value.enumerated.item[0]; if (val >= e->items) return -EINVAL; gpiod_set_value_cansleep(tse850->loop1, val); tse850->loop1_cache = val; return snd_soc_dapm_put_enum_double(kctrl, ucontrol); }
/* * When used with DAC outputs only the WM8993 charge pump supports * operation in class W mode, providing very low power consumption * when used with digital sources. Enable and disable this mode * automatically depending on the mixer configuration. * * Currently the only supported paths are the direct DAC->headphone * paths (which provide minimum power consumption anyway). */ static int class_w_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 wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); int ret; /* Turn it off if we're using the main output mixer */ if (ucontrol->value.integer.value[0] == 0) { if (wm8993->class_w_users == 0) { dev_dbg(codec->dev, "Disabling Class W\n"); snd_soc_update_bits(codec, WM8993_CLASS_W_0, WM8993_CP_DYN_FREQ | WM8993_CP_DYN_V, 0); } wm8993->class_w_users++; wm8993->hubs_data.class_w = true; } /* Implement the change */ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); /* Enable it if we're using the direct DAC path */ if (ucontrol->value.integer.value[0] == 1) { if (wm8993->class_w_users == 1) { dev_dbg(codec->dev, "Enabling Class W\n"); snd_soc_update_bits(codec, WM8993_CLASS_W_0, WM8993_CP_DYN_FREQ | WM8993_CP_DYN_V, WM8993_CP_DYN_FREQ | WM8993_CP_DYN_V); } wm8993->class_w_users--; wm8993->hubs_data.class_w = false; } dev_dbg(codec->dev, "Indirect DAC use count now %d\n", wm8993->class_w_users); return ret; }