+static int mx27vis_amp_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int value = ucontrol->value.integer.value[0];
+ unsigned int reg = mc->reg;
+ int max = mc->max;
+
+ if (value > max)
+ return -EINVAL;
+
+ switch (reg) {
+ case MX27VIS_AMP_GAIN:
+ gpio_set_value(MX27VIS_PIN_G0, value & 1);
+ gpio_set_value(MX27VIS_PIN_G1, value >> 1);
+ mx27vis_amp_gain = value;
+ break;
+ case MX27VIS_AMP_MUTE:
+ gpio_set_value(MX27VIS_PIN_SDL, value & 1);
+ gpio_set_value(MX27VIS_PIN_SDR, value >> 1);
+ mx27vis_amp_mute = value;
+ break;
+ }
+ return 0;
+}
+
+static int mx27vis_amp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+
+ switch (reg) {
+ case MX27VIS_AMP_GAIN:
+ ucontrol->value.integer.value[0] = mx27vis_amp_gain;
+ break;
+ case MX27VIS_AMP_MUTE:
+ ucontrol->value.integer.value[0] = mx27vis_amp_mute;
+ break;
+ }
+ return 0;
+}
+
+/* From 6dB to 24dB in steps of 6dB */
+static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0);
+
+static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = {
+ SOC_DAPM_PIN_SWITCH("External Mic"),
+ SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0,
+ mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv),
+ SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0,
+ mx27vis_amp_get, mx27vis_amp_set),
+};
+
+static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("External Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
+ {"Mic Bias", NULL, "External Mic"},
+ {"IN1_R", NULL, "Mic Bias"},
+ {"IN2_R", NULL, "Mic Bias"},
+ {"IN3_R", NULL, "Mic Bias"},
+ {"IN1_L", NULL, "Mic Bias"},
+ {"IN2_L", NULL, "Mic Bias"},
+ {"IN3_L", NULL, "Mic Bias"},
+};
+