Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b22b4821 authored by Matthew Ranostay's avatar Matthew Ranostay Committed by Jaroslav Kysela
Browse files

[ALSA] hda: Mono mux mixer support



Add support for the mono mux on several 92HD7xxx codecs.
Creates a dynamic mixer for the mux selection.

Signed-off-by: default avatarMatthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 02f21c9d
Loading
Loading
Loading
Loading
+82 −1
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ struct sigmatel_spec {
	hda_nid_t *pwr_nids;

	/* playback */
	struct hda_input_mux *mono_mux;
	unsigned int cur_mmux;
	struct hda_multi_out multiout;
	hda_nid_t dac_nids[5];

@@ -144,6 +146,7 @@ struct sigmatel_spec {
	hda_nid_t *dmux_nids;
	unsigned int num_dmuxes;
	hda_nid_t dig_in_nid;
	hda_nid_t mono_nid;

	/* pin widgets */
	hda_nid_t *pin_nids;
@@ -174,6 +177,7 @@ struct sigmatel_spec {
	struct snd_kcontrol_new *kctl_alloc;
	struct hda_input_mux private_dimux;
	struct hda_input_mux private_imux;
	struct hda_input_mux private_mono_mux;

	/* virtual master */
	unsigned int vmaster_tlv[4];
@@ -401,6 +405,34 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
				     spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
}

static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_info *uinfo)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	struct sigmatel_spec *spec = codec->spec;
	return snd_hda_input_mux_info(spec->mono_mux, uinfo);
}

static int stac92xx_mono_mux_enum_get(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	struct sigmatel_spec *spec = codec->spec;

	ucontrol->value.enumerated.item[0] = spec->cur_mmux;
	return 0;
}

static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	struct sigmatel_spec *spec = codec->spec;

	return snd_hda_input_mux_put(codec, spec->mono_mux, ucontrol,
				     spec->mono_nid, &spec->cur_mmux);
}

#define stac92xx_aloopback_info snd_ctl_boolean_mono_info

static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol,
@@ -603,6 +635,16 @@ static struct hda_verb stac9205_core_init[] = {
	{}
};

#define STAC_MONO_MUX \
	{ \
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
		.name = "Mono Mux", \
		.count = 1, \
		.info = stac92xx_mono_mux_enum_info, \
		.get = stac92xx_mono_mux_enum_get, \
		.put = stac92xx_mono_mux_enum_put, \
	}

#define STAC_INPUT_SOURCE(cnt) \
	{ \
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
@@ -714,6 +756,7 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {

static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
	STAC_INPUT_SOURCE(2),
	STAC_MONO_MUX,

	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
@@ -733,6 +776,7 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
	STAC_INPUT_SOURCE(2),
	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
	STAC_MONO_MUX,

	HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
	HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
@@ -1180,7 +1224,7 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {

static unsigned int ref92hd71bxx_pin_configs[10] = {
	0x02214030, 0x02a19040, 0x01a19020, 0x01014010,
	0x0181302e, 0x01114010, 0x01a19020, 0x90a000f0,
	0x0181302e, 0x01114010, 0x01019020, 0x90a000f0,
	0x90a000f0, 0x01452050,
};

@@ -2318,6 +2362,35 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
	return 0;
}

/* labels for mono mux outputs */
static const char *stac92xx_mono_labels[3] = {
	"DAC0", "DAC1", "Mixer"
};

/* create mono mux for mono out on capable codecs */
static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec)
{
	struct sigmatel_spec *spec = codec->spec;
	struct hda_input_mux *mono_mux = &spec->private_mono_mux;
	int i, num_cons;
	hda_nid_t con_lst[ARRAY_SIZE(stac92xx_mono_labels)];

	num_cons = snd_hda_get_connections(codec,
				spec->mono_nid,
				con_lst,
				HDA_MAX_NUM_INPUTS);
	if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
		return -EINVAL;

	for (i = 0; i < num_cons; i++) {
		mono_mux->items[mono_mux->num_items].label =
					stac92xx_mono_labels[i];
		mono_mux->items[mono_mux->num_items].index = i;
		mono_mux->num_items++;
	}
	return 0;
}

/* labels for dmic mux inputs */
static const char *stac92xx_dmic_labels[5] = {
	"Analog Inputs", "Digital Mic 1", "Digital Mic 2",
@@ -2532,6 +2605,12 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
	if (err < 0)
		return err;

	if (spec->mono_nid > 0) {
		err = stac92xx_auto_create_mono_output_ctls(codec);
		if (err < 0)
			return err;
	}

	if (spec->num_dmics > 0)
		if ((err = stac92xx_auto_create_dmic_input_ctls(codec,
						&spec->autocfg)) < 0)
@@ -2552,6 +2631,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
	spec->input_mux = &spec->private_imux;
	if (!spec->dinput_mux)
		spec->dinput_mux = &spec->private_dimux;
	spec->mono_mux = &spec->private_mono_mux;

	return 1;
}
@@ -3237,6 +3317,7 @@ again:

	spec->gpio_mask = spec->gpio_data = 0x00000001; /* GPIO0 High = EAPD */

	spec->mono_nid = 0x15;
	spec->mux_nids = stac92hd71bxx_mux_nids;
	spec->adc_nids = stac92hd71bxx_adc_nids;
	spec->dmic_nids = stac92hd71bxx_dmic_nids;